Skip to content

fix: route /aidlc park and team-board to the orchestrator instead of the freeform funnel - #1112

Open
mahezsh wants to merge 1 commit into
awslabs:mainfrom
mahezsh:fix/park-slash-routing
Open

mahezsh wants to merge 1 commit into
awslabs:mainfrom
mahezsh:fix/park-slash-routing

Conversation

@mahezsh

@mahezsh mahezsh commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

Summary

Routes the orchestrator's two public verbs from the /aidlc command surface to the engine instead of into the freeform funnel. Closes #1109.

Changes

  • parseNextFlags recognises a sole leading park and a leading team-board; handleNext gains Branch 1c beside Branch 1b and emits a print directive naming aidlc park (run, then act on the parked directive) or aidlc team-board (read-only, print and stop). Both run before state inspection, like the existing terminal branches.
  • team-board forwards only --snapshot, --space <name>, and --intent <name>, the same allowlist discipline --doctor uses; any other token is a usage error. Selector values must match the shared name grammars (SPACE_NAME_REGEX, and a new INTENT_SELECTOR_REGEX for record dir, slug, or uuid), since both become path segments downstream; both the engine route and the direct team-board handler parse the full argv through one shared parseTeamBoardArgs, so stray tokens, duplicates, missing values, and --space ../../tmp are refused identically on both paths. Both authored ROUTES entries for the orchestrator list the team-board form with its selectors, so aidlc engine --help shows it; the hidden engine orchestrate noun previously omitted team-board altogether.
  • park is sole-token, mirroring the help rule, because parking mutates state. park inside a longer sentence stays freeform.
  • A sole unpark returns an error pointing at /aidlc --resume, the public spelling.
  • ORCHESTRATOR_VERBS is exported from aidlc-lib.ts beside READ_ONLY_FLAGS and WORKSPACE_VERBS. classifyTerminalCommand returns null for a leading orchestrator verb so the Kiro verb-intercept seam never runs them off-band (park mutates; team-board lives on the orchestrator, not aidlc-utility), and the Kiro tool-call guard exempts them from the bare-next backstop the way it exempts compose. The Branch 0 latch and the --review incompatibility list treat the verbs as deliberate moves. team-board does not touch the engine marker, so a board query stays a conversational turn for the Stop hook; park does, because the park it names mutates state.
  • CLI guide entries for /aidlc park (including the Unit-scoped checkout case, where the same command parks the Unit locally and leaves shared state alone) and /aidlc team-board, and a line in the session guide. No version, badge, or CHANGELOG change, per the Release Metadata Policy.

User experience

Before, over an active workflow:

/aidlc park
→ Work is already in progress on "…". You said: "park". Is this (1) part of that work;
  (2) a separate new piece of work - set it up alongside the current one; or (3) a change to the plan?

After:

/aidlc park
→ Workflow parked at "requirements-analysis". Resume with /aidlc --resume.

Checklist

  • I have reviewed the contributing guidelines
  • I have performed a self-review of this change
  • Changes have been tested
  • Changes are documented

Test plan

  • bun run check (package --check, typecheck, lint) and bun tests/gen-coverage-registry.ts --check are green. The one lint warning in t260 reproduces on untouched main.
  • t114 gains five cases: sole park on a fresh workspace and over an active one (print, never the new-work ask or a stage advance), park inside a sentence stays freeform, team-board with and without allowlisted args plus a stray-token usage error, and sole unpark. t114 also asserts team-board leaves the engine marker absent while park writes it. t178 pins ORCHESTRATOR_VERBS and that the classifier returns null for a leading verb even with a read-only flag after it.
  • Manual: on a scratch project with an active intent, next park returns the print directive, and running the named command parks the workflow and emits parked.
  • t27 cases 67 and 68 fail identically on untouched main (the stage question-flow precondition), unrelated to this change.

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.

Copilot AI lite review requested due to automatic review settings September 10, 2026 07:49
@github-actions github-actions Bot added the documentation Improvements or additions to documentation label Sep 10, 2026

Copilot AI 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.

🟡 Changes recommended

It updates release metadata surfaces (version constant/README badge/CHANGELOG entry) which repository policy reserves for a dedicated release-preparation PR, and there are a couple of smaller doc/comment inconsistencies to address.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR routes the orchestrator’s public verbs (park, team-board) from the /aidlc command surface to the orchestrator engine (instead of the freeform “new work” funnel), aligning behavior with documented CLI verbs and preventing accidental intent-creation prompts.

Changes:

  • Add ORCHESTRATOR_VERBS and ensure leading park / team-board remain on the engine path (not off-band harness terminal routing).
  • Extend next flag parsing/dispatch to emit terminal print directives for park and team-board, and emit a usage error for unsupported team-board args / bare unpark.
  • Add/update unit tests and documentation entries for the new routing behavior.
File summaries
File Description
tests/unit/t178-classify-terminal-command.test.ts Adds coverage asserting orchestrator verbs stay on engine path and exports are pinned.
tests/unit/t114-orchestrate-next.test.ts Adds tests for next park, next team-board arg allowlist, and unpark error behavior.
tests/.coverage-registry.json Registers coverage unit for ORCHESTRATOR_VERBS.
tests/.coverage-ratchet.json Updates ratchet baseline for increased covered function count.
README.md Updates version badge to 2.8.3.
harness/kiro/hooks/aidlc-kiro-adapter.ts Exempts orchestrator verbs from the Kiro guard’s “bare-advancing” classification.
docs/guide/12-cli-commands.md Documents /aidlc park and /aidlc team-board in quick reference and detailed sections.
docs/guide/11-session-management.md Adds a session-management note pointing users to /aidlc park and /aidlc --resume.
core/tools/aidlc-version.ts Bumps framework version constant to 2.8.3.
core/tools/aidlc-orchestrate.ts Implements Branch routing for park / team-board and allowlisted args parsing.
core/tools/aidlc-lib.ts Exports ORCHESTRATOR_VERBS and keeps classifyTerminalCommand returning null for them.
CHANGELOG.md Adds a 2.8.3 changelog entry describing the behavior change and upgrade command.
Review details
  • Files reviewed: 12/12 changed files
  • Comments generated: 5
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread CHANGELOG.md Outdated
Comment thread README.md Outdated
Comment thread core/tools/aidlc-orchestrate.ts Outdated
Comment thread core/tools/aidlc-version.ts Outdated
Comment thread docs/guide/12-cli-commands.md Outdated
@mahezsh
mahezsh force-pushed the fix/park-slash-routing branch from a7515ff to ffff65b Compare September 10, 2026 09:01
Copilot AI review requested due to automatic review settings September 10, 2026 09:01

Copilot AI 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.

🟡 Changes recommended

team-board is read-only but currently still triggers the engine-touch marker (affecting Stop-hook behavior), and the new /aidlc park docs conflict with the current “unit scoped park” behavior.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details
  • Files reviewed: 9/9 changed files
  • Comments generated: 2
  • Review effort level: Lite

Comment thread core/tools/aidlc-orchestrate.ts
Comment thread docs/guide/12-cli-commands.md Outdated
@mahezsh
mahezsh force-pushed the fix/park-slash-routing branch from ffff65b to adfc3af Compare September 13, 2026 03:50
Copilot AI review requested due to automatic review settings September 13, 2026 03:50
@mahezsh
mahezsh marked this pull request as ready for review September 13, 2026 03:50

Copilot AI 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.

🟡 Changes recommended

An unresolved critical --space path-validation issue and moderate routing/guard parity issues remain.

Get a fresh assessment by requesting another Copilot review.

Review details

Suppressed comments (5)

core/tools/aidlc-lib.ts:1322

  • This unconditional early return disagrees with parseNextFlags for non-sole park forms such as ["park", "--status"]: the engine's parser scans the later read-only flag and routes --status through Branch 1, while this classifier returns null. That breaks the documented engine/classifier parity; only treat team-board (which owns all trailing args) and a sole park as orchestrator-owned here.
    core/tools/aidlc-orchestrate.ts:4310
  • These values come directly from the user's argv but are interpolated into the shell command without quoting. A value such as $(...) can execute during the conductor's follow-up command, and names containing spaces are split into extra arguments. Quote each non-flag value with the existing shellArg helper (or preserve the argv structurally) before joining the directive.
    const extra = flags.orchestratorVerbArgs && flags.orchestratorVerbArgs.length > 0
      ? ` ${flags.orchestratorVerbArgs.join(" ")}`
      : "";

core/tools/aidlc-orchestrate.ts:1657

  • These checks accept any non-flag token as a selector and preserve it verbatim. The new /aidlc path can therefore emit a command containing shell metacharacters, and --space ../../outside is later passed as selectedSpace into listIntents/path helpers, allowing traversal outside aidlc/spaces. Validate the space name with the shared slug validator before forwarding, and shell-quote both selector values in the generated command.
        const value = args[j + 1];
        if ((t === "--space" || t === "--intent") && value !== undefined && !value.startsWith("-")) {
          flags.orchestratorVerbArgs.push(t, value);

docs/guide/12-cli-commands.md:285

  • This says /aidlc park prints the checkout-local JSON object, but the routed command calls handlePark(), which captures spawnState() stdout and emits only the outer parked directive; the checkout_local result is discarded for a Unit-scoped checkout. Either relay that state result or document the directive that the command actually returns.
**Behavior:** The engine routes the verb to `aidlc park`, which emits `WORKFLOW_PARKED`, records the park marker in the state file, and reports the stage it parked at. No stage is advanced and nothing is marked complete. Parking is refused when no workflow is active or the workflow is already Completed. In a Unit-scoped team checkout (a Construction worktree carrying a Unit scope stamp) the same command parks that Unit locally instead: it writes a checkout-local Unit park marker, leaves the shared workflow state untouched, and prints `{"parked": true, "unit": ..., "checkout_local": true}`. Resume with `/aidlc --resume`, which clears whichever marker applies and continues. The verb is sole-token: `park` inside a longer sentence is treated as a description of work, so ask the conductor to park in prose or type the bare verb.

harness/kiro/hooks/aidlc-kiro-adapter.ts:504

  • This exempts every command whose first token is park, but parseNextFlags only treats a sole park as the orchestrator verb; next park <description> is intentionally freeform. With a fresh same-turn latch, the Kiro backstop will therefore let that bare advancing next through, allowing the freeform path to run instead of blocking the accidental follow-up. Restrict the exemption to a sole park (while keeping team-board leading-token based because its branch owns all trailing tokens).
    !ORCHESTRATOR_VERBS.has(nextArgs[0]) &&
  • Files reviewed: 9/9 changed files
  • Comments generated: 2
  • Review effort level: Lite

Comment thread core/tools/aidlc-orchestrate.ts Outdated
Comment thread docs/guide/12-cli-commands.md
Copilot AI review requested due to automatic review settings September 13, 2026 04:06
@mahezsh
mahezsh force-pushed the fix/park-slash-routing branch from adfc3af to ca0ed79 Compare September 13, 2026 04:06

Copilot AI 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.

🟡 Changes recommended

Unresolved findings remain in direct team-board argument validation and the Kiro park guard.

Get a fresh assessment by requesting another Copilot review.

Review details

Suppressed comments (1)

harness/kiro/hooks/aidlc-kiro-adapter.ts:504

  • This membership check exempts every command whose first freeform word is park, including next park the car, from the Kiro same-turn roll-forward guard. The engine only treats a sole park as the park route; longer descriptions intentionally remain freeform, so a freeform request can bypass the guard after a read-only latch and advance instead of being blocked. Restrict the exemption to the actual sole-token park route (while retaining team-board's leading-token route), or share the engine's parser predicate.
    !ORCHESTRATOR_VERBS.has(nextArgs[0]) &&
  • Files reviewed: 10/10 changed files
  • Comments generated: 1
  • Review effort level: Lite

Comment thread core/tools/aidlc-orchestrate.ts Outdated
Copilot AI review requested due to automatic review settings September 13, 2026 04:11
@mahezsh
mahezsh force-pushed the fix/park-slash-routing branch from ca0ed79 to a236316 Compare September 13, 2026 04:11

Copilot AI 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.

🔵 Needs a closer look

The direct team-board path must reject unknown and positional arguments before approval.

Review details

Suppressed comments (1)

core/tools/aidlc-orchestrate.ts:9175

  • The direct aidlc-orchestrate team-board path still ignores arbitrary trailing tokens: for example, team-board --bogus or team-board --space one junk reaches board rendering successfully, whereas the new next team-board parser rejects them. This violates the documented allowlist and lets malformed commands report success; parse the complete argv here (reject unknown/positional tokens and ambiguous duplicate selectors) before resolving the board.
  const flagValue = (name: string, grammar: RegExp): string | undefined => {
    const index = args.indexOf(name);
    if (index < 0) return undefined;
    const value = args[index + 1];
    if (!value || value.startsWith("-")) {
      throw new Error(`team-board ${name} requires a value.`);
    }
    // The value is joined into record paths below; refuse anything outside the
    // name grammar so a selector cannot read outside aidlc/spaces.
    if (!grammar.test(value)) {
      throw new Error(`team-board ${name} "${value}" is not a valid name.`);
    }
  • Files reviewed: 10/10 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

Copilot AI review requested due to automatic review settings September 13, 2026 04:55
@mahezsh
mahezsh force-pushed the fix/park-slash-routing branch from a236316 to d540946 Compare September 13, 2026 04:55

Copilot AI 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.

🟡 Changes recommended

Three moderate review findings remain unresolved.

Get a fresh assessment by requesting another Copilot review.

Review details

Suppressed comments (2)

core/tools/aidlc-orchestrate.ts:4093

  • This marker exclusion does not make a valid /aidlc team-board turn conversational for the transcript-based Stop hook. The public skill invokes this branch as aidlc-orchestrate.ts next team-board; isEngineToolCall still classifies that next segment as workflow engagement because isTerminalUtilityNext/isEngineEngagementSegment have no team-board exemption. Claude/Codex can therefore block after a read-only board query even though this marker is absent. Extend the shared engagement classifier (and add a transcript regression) for the canonical next team-board form rather than relying only on the marker.
    flags.orchestratorVerb !== "team-board"

harness/kiro/hooks/aidlc-kiro-adapter.ts:504

  • This exemption only works when team-board is the first token in nextArgs, but the orchestrator entrypoint accepts and strips launcher options such as --project-dir before parsing. Thus a valid next --project-dir <dir> team-board reaches this guard with nextArgs[0] === "--project-dir"; after a same-turn read-only latch (for example, following --status), it is classified as bare advancing and blocked instead of being allowed through. Normalize the launcher options before applying the leading-verb exemption, using the same normalization as the engine entrypoint.
    !ORCHESTRATOR_VERBS.has(nextArgs[0]) &&
  • Files reviewed: 11/11 changed files
  • Comments generated: 1
  • Review effort level: Lite

Comment thread core/tools/aidlc-orchestrate.ts Outdated
Copilot AI review requested due to automatic review settings September 13, 2026 06:28
@mahezsh
mahezsh force-pushed the fix/park-slash-routing branch from d540946 to 4a0767b Compare September 13, 2026 06:28

Copilot AI 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.

🟡 Changes recommended

next team-board --config ... bypasses the shared parser and marker behavior, causing inconsistent handling of invalid arguments.

Get a fresh assessment by requesting another Copilot review.

Review details
  • Files reviewed: 11/11 changed files
  • Comments generated: 1
  • Review effort level: Lite

Comment thread core/tools/aidlc-orchestrate.ts Outdated
Copilot AI review requested due to automatic review settings September 16, 2026 16:07
@mahezsh
mahezsh force-pushed the fix/park-slash-routing branch from 4a0767b to c0cf2c8 Compare September 16, 2026 16:07

Copilot AI 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.

🟡 Changes recommended

Two moderate unresolved issues remain involving UUID handling and Stop-hook classification.

Get a fresh assessment by requesting another Copilot review.

Review details

Suppressed comments (1)

core/tools/aidlc-lib.ts:1969

  • INTENT_SELECTOR_REGEX accepts uppercase selectors because of the /i flag, but handleTeamBoard later compares intent.uuid === selectedIntent (unlike the shared resolver, which lowercases UUIDs). An uppercase form of an existing UUID therefore passes this parser and then fails to resolve; either make UUID matching case-insensitive or reject uppercase selectors instead of accepting them.
  • Files reviewed: 11/11 changed files
  • Comments generated: 1
  • Review effort level: Lite

Comment thread core/tools/aidlc-lib.ts
// public grammar promises leading-token semantics.
// A leading orchestrator verb owns the command and stays on the engine path
// (see ORCHESTRATOR_VERBS); a read-only flag after it is that command's argv.
if (ORCHESTRATOR_VERBS.has(args[0])) return null;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: /aidlc park and /aidlc team-board are misread as freeform work and offer to create a second intent

2 participants