Skip to content

fix: route compiled gate-sensor dispatch through the engine namespace - #1166

Merged
wowzoo merged 1 commit into
awslabs:mainfrom
chiliec:fix/gate-sensor-engine-namespace
Sep 16, 2026
Merged

wowzoo merged 1 commit into
awslabs:mainfrom
chiliec:fix/gate-sensor-engine-namespace

Conversation

@chiliec

@chiliec chiliec commented Sep 13, 2026

Copy link
Copy Markdown
Contributor

Summary

Closes #1165. In native/compiled installs, fireGateSensors() in core/tools/aidlc-state.ts spawned aidlc sensor fire …, but sensor is an engine-namespaced route, so the dispatcher exits with error: unknown command 'sensor'. Blocking gate sensors therefore always failed closed at the gate; advisory ones failed silently (the severity check happens before result.error/result.status are inspected).

Changes

  • core/tools/aidlc-state.ts: the compiled branch now spawns [executable, "engine", "sensor", ...args], matching how the sibling orchestrate dispatch in the same file already spawns [executable, "engine", "orchestrate", ...]. The bun (source) branch is unchanged.
  • tests/integration/t311-gate-sensor-enforcement.test.ts: new case "compiled dispatch fires sensors through the engine namespace" — points AIDLC_COMPILED_EXECUTABLE at a stub that logs its argv and execs the real dispatcher, then asserts both fires arrive as engine sensor fire gate-probe …, SENSOR_FIRED is recorded twice, and the gate opens.

User experience

Before: with a fire_on: gate / default_severity: blocking sensor on a native 2.8.2 install, aidlc engine orchestrate report --result awaiting-approval always refuses the gate with a dispatcher error, and advisory gate sensors never actually run.

After: gate sensors execute through aidlc engine sensor fire …, record their verdict, and the gate proceeds or blocks according to that verdict.

Checklist

  • I have reviewed the contributing guidelines
  • I have performed a self-review of this change
  • Changes have been tested
  • Changes are documented
  • If this change adds an input to any fingerprint, epoch, or receipt identity, the description names the human-visible change it detects

Test plan

Run locally (bun 1.4.2, Linux):

  • bun scripts/package.ts && bun scripts/package.ts --check — deterministic across all harnesses.
  • bun test tests/integration/t311-gate-sensor-enforcement.test.ts — 10 pass, 0 fail.
  • RED→GREEN: with the new test in place and the one-line source change reverted in the packaged dist/claude copy, the new test fails (gate exits 1, dispatcher rejects sensor); with the fix restored it passes.
  • bun test tests/unit/t94-sensor-fire-hook.test.ts tests/integration/t95-sensor-fire-hook-feature.test.ts — 40 pass.
  • bun x biome check --error-on-warnings on both touched files — clean; tsc --noEmit -p tsconfig.json and -p tsconfig.tests.json — clean.
  • Full bun tests/run-tests.ts: 422 files, 10472 assertions, 1 failed assertion — t276-cursor-adapter case 33 (expect(process.env.USER ?? process.env.LOGNAME).toBeTruthy()), which fails identically on a clean main checkout in my shell because $USER/$LOGNAME are unset there, and passes on this branch with USER exported. Environment-only, outside this diff; 25 live-Claude files skipped as designed.

No version / changelog changes per the release metadata policy.

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.

Native installs spawned `aidlc sensor fire ...`, which the dispatcher rejects
(`unknown command 'sensor'`) because sensor is an engine-namespaced route.
Blocking gate sensors therefore always failed closed; advisory failures were
silently ignored. Spawn `aidlc engine sensor fire ...` like the sibling
orchestrate dispatch does.

Closes awslabs#1165

Signed-off-by: Vladimir Babin <vovababin@gmail.com>
@wowzoo wowzoo self-assigned this Sep 16, 2026

@wowzoo wowzoo left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thank you for the fix and the regression test. The one-line routing change is what #1165 named, but the test is what keeps it fixed: it records the command the compiled dispatcher actually receives and asserts that gate sensors arrive as engine sensor fire, which is the thing that drifted silently.

Verified on this head

Base a0ee4415ec2b2d19f494b89348b6dfb2fdc77a49, head 6b52194399984602da22497dbf41175503f9bd7b.

  • The defect is present on the current default branch (09be7bddd35fd573f0bc7944af6bf6d8ea764198), not only on this pull request's base: core/tools/aidlc-state.ts:3040 still spawns [executable, "sensor", ...args].
  • sensor is engine-namespaced — core/tools/aidlc.ts:708-716 declares the route with namespace: "engine" and visibility: "hidden" — so the top-level form cannot resolve, and the message at core/tools/aidlc.ts:1505 is the error: unknown command 'sensor' in the report. On a binary built from this head, aidlc sensor fire … prints exactly that, while aidlc engine sensor fire … reaches the route and stops on the route's own projectRequirement refusal — the namespace is the whole difference.
  • The prefix matches the convention already in the same file at :2190 and :2277, which spawn [executable, "engine", "orchestrate", ...subargs].
  • fireGateSensors is the only dispatcher for gate sensors, and its three callers — gate-start, the approve revision backstop, and revise — all reach it, so the single line covers every path that fires them.

Control

Both arms on the current default branch, single-file runs, packager run before each:

arm result
your test applied, source unfixed 14 pass / 1 fail — the only failure is the new case, at expect(result.status).toBe(0), because the blocking gate refuses
same tree with the one-line fix 15 pass / 0 fail

On the head tree: t311 10/10, t92 + t94 + t95 89/89, gen-coverage-registry 37/37, and bun run check (packager, --check, three tsc projects, biome) clean. Measured with bun 1.4.0 on macOS; CI runs ubuntu, so CI is what adjudicates the full suite.

Nothing to change

No other sensor-route dispatch is left behind, and every compiled dispatch in core/ that omits engine is correct to omit it. Taking all 17 compiledExecutable() call sites in core/ on this head: core/tools/aidlc-metrics.ts:403 passes the --internal-metrics-send flag, which the dispatcher handles at core/tools/aidlc.ts:2891; core/tools/aidlc-utility.ts:657 builds its args at :646-650 already starting with engine; core/tools/aidlc-utility.ts:1771 passes team-board, a public verb of the route at core/tools/aidlc.ts:213-232; the three in core/tools/aidlc-lifecycle.ts are package-manager detection rather than dispatch; and the rest already carry the prefix. No prose in core/, harness/, docs/ or the generated tree instructs aidlc sensor fire without the namespace.

Closes #1165 is accurate: that issue's Expected Behavior section asks for the aidlc engine sensor fire … invocation, and this delivers it. The advisory-severity ordering the report mentions in passing — the default_severity !== "blocking" check at core/tools/aidlc-state.ts:3052 running before result.error at :3061 and result.status at :3075 — is a separate behaviour this change does not alter, and not one to fold in here.

Status

CI is green on 6b521943 — all 21 checks pass, including the four unit shards, the integration and e2e suite, smoke, and the contract job (determinism, typecheck, lint). The pull request now reports clean. Approving.

@wowzoo
wowzoo added this pull request to the merge queue Sep 16, 2026
Merged via the queue into awslabs:main with commit c97fa7b Sep 16, 2026
27 checks passed
wowzoo pushed a commit to wowzoo/aidlc-workflows that referenced this pull request Sep 16, 2026
apackeer added a commit that referenced this pull request Sep 17, 2026
* origin/main:
  fix: make compiled dispatch exhaustive over TOOLS so native review briefs route (#1070) (#1115)
  test: skip POSIX gate-sensor fixture on Windows (#1208)
  fix: make /aidlc compose scopes durable across an engine reinstall (#1159)
  fix: refuse orphaned positionals at intent-create instead of storing a truncated description (#1114) (#1195)
  fix: route compiled gate-sensor dispatch through the engine namespace (#1166)
  fix: name the accepted values in review-path refusals (#1082) (#1194)
  fix: discover stage-level summary questions when units are skipped (#1110)
  fix: keep a JSON-scalar gate reply instead of parsing it away (#1186)
  fix: resolve the zero-Unit code-generation location in the traceability sensor (#1179)
  fix(config): one quiet line for --show, and honest source options on a copy-channel refresh (#1185)
  test(t238): normalize walkFiles separators in the invocation-surface selector (#1184)
  fix(config): Kiro provides its own model access, so the provider section has nothing to ask (#1183)
  chore: prepare 2.9.0 release (#1181)
  feat!: classic scope v1 parity with scope-owned ceremony switches (#1151)
  fix: publish changed previews without a daily cap (#1178)
  fix: separate Bun copy and native installer runtimes (#1174)
  fix: publish next-patch previews nightly (#1169)
  fix: keep review bookkeeping out of the artifact, and out of the reviewer's findings (#1160)
  fix: measure the review budget against the engine's own ordinal, not the caller's (#1158)
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.

[Bug]: Blocking gate sensors fail in native CLI because dispatcher omits engine namespace

2 participants