| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
feat(FEAT-012): add Gherkin discovery-filtering acceptance harness - New tests/features/feat-012-discovery-filtering.feature: 7 scenarios (AC1-AC6 + AT-010 alias-aware unification) covering all six FEAT-012 acceptance criteria and EPIC AT-008/009/010 - New commands/epic_discovery_acceptance.rs: scenario-level cucumber worlds bound to live palette builder, live slash completion, and live dispatch; fail_on_skipped + non-zero passed-step assertions per scenario - Registered module in commands/mod.rs - docs/architecture/command-dispatch.md: module map row for shared discovery.rs owner - feat012 selector: 7/7 scenarios pass, zero skipped, non-zero steps each - Guards: discovery 13/13, palette 34/34, completion 24/24; strict clippy 0 warnings Generated with Claude Code | 1 个月前 | |
feat(tui)!: make agent the only model-visible sub-agent tool AGENTS.md says the model-facing sub-agent surface is `agent` only. It was not. `agents/list`, `agents/message`, `agents/followup`, `agents/interrupt`, `agents/coordinate`, and `agents/wait` never overrode `ToolSpec:: model_visible`, which defaults to true, so all six cleared the filter in `ToolRegistry::build_api_tools` and entered the model catalog. Being deferred did not hide them — deferral makes a tool discoverable via `tool_search`, and both matchers read the same catalog. The `agent` description then named five of them outright ("the narrow agents/list, agents/message, … tools expose the same semantics directly"), so the surface actively taught the second transport it claimed not to have. The fix follows the precedent already in this tree: `rlm` and `exec_shell` return false from `model_visible`, staying registered and executable by name so a persisted transcript replays against the same implementation while never being advertised. All six now do the same. Five were pure duplicates of an `agent` action. `agents/coordinate` was not. Its `claim` action is the only path to `SubAgentManager::expand_write_claim`, and write-scope enforcement fails closed — so hiding it without a replacement would have left the refusal message ("expand it first with agents/coordinate action=claim") pointing at a tool the model can no longer call, with no way to proceed. `agent` therefore gains exactly one action, `claim`, and no more: propose/accept/supersede/reconcile/inspect stay off the model surface because nothing fails closed without them. `claim` reuses the write-scope vocabulary `action=start` already speaks — `write_roots` advertised, `exact_files` and `coordination_contracts` parse-accepted — so one set of names describes a child's scope whether it is declared at launch or widened later. The translation to the coordinate wire is the load-bearing part and has its own documented function, because both ways of getting it wrong fail silently: the wire key is `roots`, and forwarding `write_roots` hands `expand_write_claim` three empty lists, which returns the unchanged claim with `Ok` — a success receipt for an expansion that never happened. The same no-op-success is why a scopeless claim is refused outright rather than passed through. Approval stays `Auto`, inheriting `agents/coordinate`'s rationale: gating a coordination record deadlocks autonomous fan-in, and `claim` can only widen the caller's own scope. Per-role gating had to be solved explicitly, and this is the part worth reviewing. Every capability gate here keys off a tool *name*, which is exactly what breaks when six tools become one, and `agent` is deliberately exempt from both: `posture_permits_tool` short-circuits it so delegation depth rather than write posture governs spawning, and `execution_envelope::is_delegation_tool` classifies it `Bounded` so a read-only member can still fan out read-only work. A capability folded into `agent` therefore inherits no gate at all. `agent_action_permitted` supplies one per action, reproducing the check the retired tool actually had — `agents/coordinate` declared `WritesFiles` and was kept off a read-only role's catalog by `envelope.write` — rather than inventing a new policy. It is applied when shaping the catalog and again at dispatch, because catalog shaping has never been the authority boundary here. The other seven actions keep exactly today's visibility; narrowing message/followup/interrupt for read-only roles would be an unrelated behavior change smuggled in behind a catalog cleanup. Making `agent` a `CANONICAL_ACTION_ALIASES` family would have reused the existing action-policy seam, but `canonical_action_alias` feeds `execution_envelope`, where the `agent` name is what earns the `Bounded` reclassification — so that route would have made `claim` demand write *and* shell authority. Contract changes, declared: the six tools leave the model catalog (wire shapes, schemas, and dispatch-by-name are unchanged); `agent` gains the `claim` action and its enum grows by one; the out-of-scope write refusal and the child's write-scope briefing now name `agent action=claim`; the frozen per-role surfaces drop the `agents/*` entries. Tests: the catalog test that asserted `agent` appears once now also asserts none of the six appear and that each stays registered and model-invisible; `tool_search` is exercised on both the regex and bm25 paths with queries aimed at the retired names and their descriptions; the `agent` description and schema are asserted to name none of them; the claim path is proven end to end by writing a file that was refused before the claim and admitted after it, which is what makes the wrong wire key fail here instead of in production. Every new test was confirmed to fail with its fix reverted. Implemented with agent assistance. Signed-off-by: Hunter Bown <hmbown@gmail.com> | 20 天前 | |
docs: make the tool-surface, subagent, and config references match the code docs/TOOL_SURFACE.md carried four claims the runtime's own tests contradict: 1. "The default-active policy contains exactly these ten names" listing `update_plan`. `DEFAULT_ACTIVE_NATIVE_TOOLS` (crates/tui/src/core/engine/tool_catalog.rs:44-58) has eight entries and `update_plan` is not among them — it appears nowhere in tool_catalog.rs. The policy is nine (those eight plus synthetic `tool_search`), eight with memory disabled. `update_plan` is registered (crates/tui/src/tools/plan.rs:401) but reachable only through `tool_search`; the tool table now says so. 2. "A memory-disabled or Moraine-fallback runtime". There is no Moraine fallback — docs/MEMORY.md:11-13 records the removal, and crates/tui/src/prompts.rs:2445-2449 is a test asserting MEMORY_GUIDANCE must not contain the word. 3. A "Replay-only aliases" table promising "saved transcripts, sessions, and recorded automation replay without migration" for 23 names, 16 of which are asserted REMOVED at crates/tui/src/tools/registry.rs:2066-2088 ("{retired} must stay removed") and 6 more at :2290-2304 ("{alias} must be removed"). Split into a "Removed spellings" section (with the registry.rs:313-316 note that resolve has no fuzzy step, so those calls fail rather than dispatch) and a "Replay-only aliases" section holding only what is still registered: apply_patch, task_*, github_*, automation_*, rlm_*, checklist_*/todo_*. 4. A "Release verification" block whose three cargo filters name tests that do not exist (`rg` finds those three strings only in that doc). `cargo test` exits 0 with "0 passed; N filtered out" on a filter that matches nothing, so a release engineer following it got three green checkmarks having verified nothing. Replaced with the real names — `shell_surface_contains_only_the_canonical_bash_tool` (registry.rs:2290) and `runtime_task_families_expose_only_canonical_tools` (registry.rs:2333) — plus the receipt test, and a warning about the silent-pass failure mode. docs/RUNTIME_SIMPLIFICATION_DESIGN.md repeats errors 1 and 3 and is designated authoritative by docs/TOOL_LIFECYCLE.md:3-7, but carries no status marker. Given a status banner naming both divergences and pointing at TOOL_SURFACE.md; the "Rejected alternatives" provenance is worth keeping, so not deleted. docs/SUBAGENTS.md: - "a bounded queue of up to 200 running plus queued sub-agents by default" — `MAX_SUBAGENT_ADMISSION` is 1024 (crates/tui/src/config/subagent_limits.rs:21), which is what docs/TOOL_SURFACE.md:182 already said. The 64/128 concurrency figures on the same page were correct and are untouched. - The memory section described a `memory.md` that does not exist and omitted the `scope` parameter. crates/tui/src/tools/remember.rs:165 states the legacy single-file path was removed in v0.9.4; writes go through `NativeMemoryStore::remember(scope, workspace_id, note)` (remember.rs:77-108). config.example.toml documented two key sets that do not exist. Neither struct has `deny_unknown_fields`, so both were silently discarded rather than rejected: - `[advisor] max_tool_pairs` / `system_prompt`. `AdvisorConfigToml` (crates/config/src/lib.rs:2369-2394) has enabled, max_tool_calls (default 10, clamped 1-50 — the doc said 8, max 32), rate_limit_secs, dedup_window_secs, and model. `model` was undocumented; now it is. - `[fleet.profiles.*.permissions] allow_tools` / `deny_tools`. `FleetProfilePermissions` (lib.rs:1966-1977) has allow_shell, trust, approval_required. `rg 'allow_tools|deny_tools' crates/` finds nothing. The example value was `"exec_shell"`, itself a removed tool name. docs/CONFIGURATION.md: deleted the "Parsed but currently unused" section. Its one entry, `tools_file`, is not parsed by anything — the field was removed in 346bfe3b6 and the doc bullet was orphaned. Repo-wide `rg` finds the string only in that section, and nothing links a #parsed-but-currently-unused anchor. docs/TTC_DESIGN.md said implementation "is deferred beyond v0.9.0". The `verify` tool shipped and is default-on (crates/tui/src/tools/verify.rs, features.rs:262, registry.rs:1040-1041 with verify_tool_enabled defaulted true). Retitled as landed-in-part; capability (B) is still genuinely deferred, so the doc stays. Its interface line said `with_verify(critic)`; the real signature is `with_verify_tool(client, model)` (registry.rs:886). docs/skills/README.md advertised `gh-plan-issues`, deleted in 18de2ebc0, and credited these skills to "the v0.8.61 release" at a 0.9.4 release. docs/architecture/provider-model-settings-v091.md pinned `provider_is_configured` to config.rs:8625-8669; it is at :10160 and that region is now unrelated code. Replaced with the symbol name, since config.rs is under active edit. docs/architecture/command-dispatch.md:133 claimed EPIC-002 was "ready for PR". The PR (#3706) merged and #2870 closed 2026-08-01. Line 145 was an empty "Current Evidence (Draft)" heading with no content; removed. .gitignore: `git check-ignore -v` attributes .claude/settings.json, scheduled_tasks.lock, worktrees/, and *.local.* to the blanket `.claude/` at line 126, not to the specific rules above them. Dropped the redundant ones and annotated why the HANDOFF_/CODEMAP_ patterns are deliberately kept. | 1 个月前 |
| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
| 1 个月前 | ||
| 20 天前 | ||
| 1 个月前 |