Skip to content

fix: resolve hook and directive commands through the launch seam - #1384

Merged
leandrodamascena merged 3 commits into
awslabs:mainfrom
taikis:fix/native-invocation-in-hook-directives
Sep 27, 2026
Merged

leandrodamascena merged 3 commits into
awslabs:mainfrom
taikis:fix/native-invocation-in-hook-directives

Conversation

@taikis

@taikis taikis commented Sep 24, 2026 •

Copy link
Copy Markdown
Contributor

Problem

Directive strings handed to the conductor hardcoded a bun <harness>/tools/aidlc-<tool>.ts prefix. harnessDir() resolved WHICH tree the tool lives in, but nothing resolved HOW to launch it.

A native install ships no .ts under the harness tree and requires no bun on PATH, so every one of these commands was unrunnable there. The Stop hook is the worst case: it blocks turn-end, so the conductor was told to proceed and handed a command that cannot run — a dead end.

This also contradicts the framework's own onboarding text: "Framework hooks run through the self-contained aidlc binary. No separate script runtime or executable bits are required."

It was masked in development because a source checkout has both the .ts projection under .claude/tools/ and bun on PATH.

Fix

Route all 14 sites through aidlcInvocation() / aidlcToolInvocation(), which already resolve aidlc engine <route> on a compiled install and bun <harness>/tools/aidlc-<tool>.ts on a copy install. The surrounding code already used this seam — these sites simply did not go through it.

File Sites
core/hooks/aidlc-continue-workflow.ts Stop hook's next, continue, park, report guidance (5)
core/tools/aidlc-orchestrate.ts steering continue, claim/release, knowledge, unpark, stale-cursor report, unit resume (×4), recompose (10)
core/tools/aidlc-state.ts blocking-sensor override log decision/log answer, report (3)
core/tools/aidlc-utility.ts plugin sync (×2), graph compile (3)

Substitution is verified in both projections:

  • dist/claude → bun .claude/tools/aidlc.ts → bun .claude/tools/aidlc-orchestrate.ts next
  • dist-release/claude → aidlc → aidlc engine orchestrate next

Why this survived

tests/unit/t153-engine-directive-harness-seam.test.ts inspects exactly this shape, but its regex only rejects a hardcoded harness-directory literal — its comment explicitly calls bun ${harnessDir()}/tools/ "the seam", i.e. the correct form. The bun launcher was never in scope.

t153 now guards both halves. The new check reads the same directive from the other side — any tree spelling, no bun launcher — and covers the split-literal form (run \bun " + hd + "/tools/...`) that a line-oriented scan cannot see, with a negative control pinning both shapes so the scan cannot pass by matching nothing.

t249 pinned the copy-channel spelling of a command that is now channel-dependent; its assertions were changed to match the verb (exactly one next steer, no continue steer) rather than the launcher.

Verification

  • bun scripts/package.ts --check (determinism), bun run typecheck, bun run lint — clean
  • smoke tier: RESULT PASS (14 files)
  • unit tier: run as 3 shards across isolated worktrees; shard 1 RESULT PASS
  • integration tier: 131 files, --parallel 4
  • Directly relevant files pass serially: t121-stop-hook-enforce (142 pass / 0 fail), t248-steering-content-delivery, t249-copilot-adapter (58 pass), t230-dispatcher-routes, t153 (new guard)

Remaining failures on the test machine were each reproduced on main at the same or worse rate, so none are attributable to this change: t37 and t-e2e-isolated-runner fail identically on main; t326 and t78 are budget timeouts that are worse on main (t326: 7 failing cases on main vs 3 here; t78: 22 vs 3); t-tui-tmux-compat needs tmux, which is not installed.

Reported by a user who hit the Stop hook dead end on a native install; the loadDelegate/TOOLS half of that report is already fixed by #1115.

Acknowledgment

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of the project license.

Directive strings handed to the conductor hardcoded a
`bun <harness>/tools/aidlc-<tool>.ts` prefix. harnessDir() resolved WHICH
tree the tool lives in, but nothing resolved HOW to launch it: a native
install ships no `.ts` under the harness tree and requires no bun on
PATH, so every one of these commands was unrunnable there. The Stop hook
is the worst case - it blocks turn-end, so the conductor was told to
proceed and handed a command that cannot run.

Route all 14 sites through aidlcInvocation()/aidlcToolInvocation(), which
already resolve `aidlc engine <route>` on a compiled install and
`bun <harness>/tools/aidlc-<tool>.ts` on a copy install:

- core/hooks/aidlc-continue-workflow.ts - the Stop hook's next, continue,
  park and report guidance
- core/tools/aidlc-orchestrate.ts - steering continue, claim/release,
  knowledge, unpark, stale-cursor report, unit resume (4 sites), recompose
- core/tools/aidlc-state.ts - blocking-sensor override log and report
- core/tools/aidlc-utility.ts - plugin sync (2 sites), graph compile

t153 gains the matching guard. It accepted `bun ${harnessDir()}/tools/`
as "the seam", which is why this survived: the existing scan only rejects
a hardcoded harness-directory literal. The new guard reads the same
directive from the other side - any tree spelling, no bun launcher - and
covers the split-literal form (`run \`bun " + hd + "/tools/...`) that hid
from a line-oriented scan, with a negative control pinning both shapes.
t249 pinned the copy-channel spelling (`orchestrate.ts next`) of a command
the hook now resolves per channel. The assertions read the same intent
either way once they match the verb rather than the launcher: exactly one
`next` steer, and no `continue` steer, whether the reason says
`bun <harness>/tools/aidlc-orchestrate.ts next` or
`aidlc engine orchestrate next`.
@taikis
taikis force-pushed the fix/native-invocation-in-hook-directives branch from a05acb3 to 1ba9a3d Compare September 25, 2026 00:02
Use the dispatcher invocation helper for recompose and plugin sync so the
commands emitted to the conductor retain their required engine namespace.

Execute the emitted recomposition and doctor recovery commands in both
copy and native installations. Exercise Stop recovery and steering through
the compiled release binary without Bun on PATH for all seven harnesses,
and register the added hook coverage.

@leandrodamascena leandrodamascena left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, Taiki, for moving these commands onto the existing invocation helpers.

I reviewed the current head 9f1a1a1 against main 147a3cc. This restores the documented native-install contract without Bun and matches our agreed bug-fix scope.

I fixed the missing engine namespace in recomposition and both doctor plugin-sync remedies, and pushed 9f1a1a1. Regression tests execute the emitted commands in copy and native installations and cover native Stop recovery across all seven harnesses.

Required CI, security scans, Markdownlint, 52 native build gates, 60 Copilot tests, packaging determinism, typecheck, lint and coverage checks passed. No blocking findings remain. Validation used Linux; macOS/Windows and live-model journeys were not run. Automated AI review was skipped.

Proposed event: APPROVE.

@leandrodamascena
leandrodamascena added this pull request to the merge queue Sep 27, 2026
Merged via the queue into awslabs:main with commit 3d14803 Sep 27, 2026
32 checks passed
apackeer added a commit that referenced this pull request Sep 27, 2026
…ettings

* origin/main:
  fix: resolve hook and directive commands through the launch seam (#1384)
  fix: resolve compiled hook and adapter routes from packaged files (#1424)

# Conflicts:
#	core/tools/aidlc-orchestrate.ts
@taikis
taikis deleted the fix/native-invocation-in-hook-directives branch September 27, 2026 06:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants