Skip to content

fix(fork): stop naming absent tools in model-facing text - #56

Merged
asto18089 merged 8 commits into
Pinvou:pinvou3-cleanfrom
asto18089:fix/skills-phantom-tool-text
Sep 17, 2026
Merged

asto18089 merged 8 commits into
Pinvou:pinvou3-cleanfrom
asto18089:fix/skills-phantom-tool-text

Conversation

@asto18089

@asto18089 asto18089 commented Sep 13, 2026 •

Copy link
Copy Markdown
Collaborator

Problem

Model-facing skills text named tools that are not in the executor's tool catalog:

  • The rendered skills-index Usage line told the model to call load_skill(name="list") directly, but load_skill is deferred and absent from the first-turn catalog unless the host force-loads it.
  • The subagent ## Skills block taught subagents to call load_skill, while the child wire catalog intentionally carries no load_skill (skills are discovered through tool_search there).

Observed effect (Pinvou "运动打卡" Work-card session, 2026-09): the model's reasoning loop stalled on "the index says to call load_skill, but it is not in my tool list".

Fix

Commit 1 (c34c3a430) — the incident sites:

  • Skills-index Usage: keep the load_skill guidance and add a one-line fallback — run tool_search first to activate load_skill when it is missing (covers hosts that do not force-load it, e.g. the upstream CLI).
  • Subagent skills block: teach tool_search-based skill discovery, matching the wire catalog subagents actually receive.
  • tools/skill.rs is untouched: the r1 line already carries no File-family reference.

Commit 2 (f81528358) — adversarial-review completion, same defect class:

  • mcp-discovery: registry_sync is deferred but tool_search-searchable on stock hosts, so a "not in your tool list ⇒ unavailable" gate surrendered a reachable capability. Step 1 now activates via tool_search first and declares unavailability only when that fails; it teaches a query-bearing call (the schema rejects empty input), states the eight-scored-matches contract instead of a "complete catalog" dump, and the preamble no longer claims an always-active tool surface. Step 3 gates start_registry_mcp_server (it can be absent while registry_sync is registered: pool init failure, tool-security mode).
  • Skills index: plugin-snapshot rows and the omitted-skills tail carry the same load_skill → tool_search fallback; the Usage/omitted lines stay honest for surfaces where tool_search is absent too (ACP, allowlist-restricted exec).
  • Subagent header: covers the third child class — explicit allowlists that keep tool_search but filter load_skill ("absent or does not surface").
  • Bundled pdf/help skills now cite read instead of the hidden File compatibility alias (absent from every catalog and from tool_search); best-of-n gates create_goal on availability (child registries remove the tool entirely).

Commit 3 (a2e21fcf9) — third adversarial pass: the two-stage pattern, applied consistently:

  • mcp-discovery step 3 now mirrors step 1 for start_registry_mcp_server: tool activation is per-name and does not follow from registry_sync's, so a visibility-only gate would surrender a reachable capability on every stock host. The preamble discloses that the start tool additionally needs the host's MCP pool initialized, and step 4 teaches re-activation for connected tools that re-defer on later turns.
  • best-of-n names the tool_search activation path for create_goal (deferred on every stock host, so the visibility gate alone always failed) and stays honest for subagent sessions where the tool is removed entirely.
  • The parent-context sub-agent hint (core/engine/context.rs) cites first-turn-active read/bash instead of the hidden File alias with a nonexistent list action; the pin is flipped and renamed into the forkguard set (forkguard_subagent_context_hint_names_active_tools).
  • The bundled-skills denylist drops the wrongly listed live tool list_dir (model-visible and searchable) and now covers the registry's remaining hidden aliases and canonical retired names; MAX_REGISTRY_MATCHES and the quoted "eight" wording are pinned together at compile time.

Commit 4 (18f7c7b15) — rider strip: the baseline gate repairs that rode in commit 1 (CHANGELOG slice resync, facts/web generated refresh, the map(Ok) clippy cleanup) moved to the dedicated CodeWhale #60 per the CONTRIBUTING changelog policy; this PR's net diff is topic-only.

Commit 5 (9f46ac5f0) — review round: dedupe the model-facing text, fix review nits:

  • Deferred-activation teaching becomes single-point: the skills-index Usage line and mcp-discovery step 1 keep the full fallback; plugin-snapshot rows, the omitted-skills tail, and mcp-discovery step 3 rely on them by reference (as in step 1) instead of repeating the sentence, and the subagent ## Skills header shrinks to the same one-sentence pattern. No information is lost; every session and child prompt gets shorter.
  • The mcp-discovery preamble is now precise: only the start tool needs the host's MCP pool initialized; registry_sync registers with MCP support alone.
  • The bundled-skills phantom list drops the speculative Read/Write/Edit entries (no registry table ever carried them), adds the missed git_diff/git_log/git_show/git_blame and agents/coordinate retired names, corrects the tracking comment, and discloses the BUNDLED_SKILLS sweep scope (v4-best-practices/feishu are not covered).
  • The remaining "eight" wording sides (MCP_REGISTRY_FIRST_INSTRUCTION and the registry_sync schema description) are pinned by test alongside the compile-time MAX_REGISTRY_MATCHES assert; the parent-context test comment no longer overclaims first-turn activity on "every stock host".

Known leftover (disclosed, not changed here): workflows/stopship.workflow.js briefs an explore child with the hidden File search_content alias. Review found the live behavior is harsher than first disclosed: the child step loop dispatches through execute_from_surface, which fails any name outside that child's policy-filtered catalog, and File is model_visible=false, so it never reaches any catalog — the call is rejected outright and the explore gate's first step cannot succeed today. Dispatch-by-alias only works below the catalog gate (e.g. replay tests calling registry.resolve directly). A bare rename to grep_files would not fix it either: that tool is deferred, so the brief needs a two-step tool_search activation teaching plus a response-budget re-measurement. That is a protocol rework of the release-acceptance fixture, now tracked as its own PR: CodeWhale#61 routes the scout through tool_search → grep_files with guards pinning both the scout surface and the fixture text.

Regression coverage: forkguard_skill_index_usage_names_tool_search_activation (also guards the single-point teaching: plugin rows and the omitted tail deliberately do not repeat the fallback; the separate omitted-tail test retired with the dedup), forkguard_subagent_skill_catalog_uses_tool_search_discovery, forkguard_mcp_discovery_skill_conditions_registry_commands, forkguard_registry_first_instruction_names_registered_tool_specs (also pins the "eight" wording in the instruction and the schema description), forkguard_bundled_skills_cite_no_hidden_or_retired_tool_names, forkguard_best_of_n_goal_tool_is_availability_gated, forkguard_subagent_context_hint_names_active_tools (flipped from the pre-existing summarization pin). Registered in the pinvou-agent fork-modifications doc (Pinvou/pinvou-agent#490) with sixteen active T3 fork-guard fingerprints (seventeen added, one retired with the dedup).

Base

Seven commits on top of the current r1 maintenance head ae7e3fb36 (parent gitlink at main), so the parent PR can advance the gitlink directly. Commit 1 originally carried disclosed baseline gate repairs; commit 4 strips them into CodeWhale #60, so nothing unrelated remains.

No-Issue: fork-side text fix; no separate CodeWhale issue is tracked for this change.

Commit 6 (be2b2fe92) — review-round completion, same defect class:

  • GOAL_CONTINUATION_PROMPT (prompts/text.rs) commanded update_goal, which is deferred on stock hosts — a goal created by a host-side /goal never activates it; the prompt now names the tool_search activation path.
  • The parent-context sub-agent hint (core/engine/context.rs) cited handle_read unconditionally; it now names the activation path too.
  • The skills-index Usage line and the subagent ## Skills header no longer over-claim "cannot load skills" when tool_search cannot surface load_skill — a registered deferred tool still hydrates on demand when called directly, so both now teach the direct-call fallback before declaring skills unavailable.
  • Test-only fixes: the mcp-discovery pin's empty-input attribution (the schema requires the query field; the host rejects an empty value) and the MAX_REGISTRY_MATCHES assert message (SKILL.md path prefix; the instruction side says "eight matches").
  • Under-pin repairs: the new direct-call fallback clauses are pinned in the Usage and subagent-header tests, an omitted-tail guard keeps the commit-5 dedup from silently regressing, and the goal-continuation activation teaching is pinned by forkguard_goal_continuation_names_tool_search_activation.

Verified: cargo fmt --check clean; cargo test -p codewhale-tui --lib with RUST_MIN_STACK=8388608 (matching CI) passes apart from three remote_control timing tests that are flaky on unmodified trees and pass in isolation. The forkguard sweep (57 tests, incl. the two new pins) is green.

Regression coverage added: forkguard_goal_continuation_names_tool_search_activation, forkguard_omitted_skills_line_stays_short. The pinvou-agent fork-modifications register (Hmbown#490) gained both new test names and the re-synced fingerprints for the reworded Usage line, subagent header, and context hint.

Commit 7 (4eb487cd3) — same-class closure from a fresh adversarial sweep:

  • MCP_REGISTRY_FIRST_INSTRUCTION (injected into the system prompt of every MCP-enabled session) commanded registry_sync and start_registry_mcp_server — both deferred on stock hosts — with no activation path and no availability gate; it now teaches the tool_search activation for both, degrades honestly to local tools when unreachable, and discloses that activating registry_sync does not activate the start tool.
  • REGISTRY_FIRST_PROMPT (attached to every registry_sync result) names the start-tool activation path.
  • Every worker-record prose site pairing a transcript handle with handle_read (takeover targets, the session projection, the transcript artifact description, and each handle_read-recommending status reason) carries one shared activation hint (HANDLE_READ_ACTIVATION_HINT); the duplicated takeover/projection sentence is extracted into a shared function.
  • The /agent dispatch brief and the bare /goal brief teach the handle_read/create_goal activation path.
  • GOAL_CONTINUATION_PROMPT and the parent-context hint keep a direct-call fallback beyond tool_search (allowed_tools-filtered sessions strip tool_search itself).
  • Web/fetch overflow metadata sets evidence_available: true so the engine auto-activates retrieve_tool_result — the recovery tool the overflow footer already names — under the same contract as the shell-truncation spillover.

New pins: forkguard_registry_first_prompt_teaches_start_tool_activation, forkguard_worker_record_hints_teach_handle_read_activation, forkguard_slash_agent_dispatch_teaches_handle_read_activation; the registry-first, goal-continuation, parent-context, bare-/goal, and web-overflow tests gain the new assertions. The pinvou-agent fork-modifications register (Hmbown#490) now carries thirty net-new T3 fingerprints (thirty-one added, one retired) and the candidate reads 66 forkguard_* tests against the 57 floor.

@github-actions

Copy link
Copy Markdown

Thanks @asto18089 for taking the time to contribute.

This repository is observing a maintainer-managed PR intake gate in dry-run mode, so this pull request is staying open. This note helps maintainers prepare the allowlist before any enforcement is considered.

Please read CONTRIBUTING.md for the expected contribution shape. A maintainer can grant recurring PR access by commenting /lgtm on a pull request.

asto18089 added a commit to Pinvou/pinvou-agent that referenced this pull request Sep 14, 2026
Model-facing text promised tools that were not in the model's actual
tool catalog, confusing the model (observed in a Work-card session):

- The base registry-first policy names registry_sync and
  start_registry_mcp_server; both are live foundation tools that were
  only missing from the Pinvou allowlist. Whitelist them (with
  first-turn visibility via ALWAYS_LOADED) instead of dropping the
  policy; the browser carve-out stays because the built-in browser is
  not in the registry.
- load_skill/file_search are deferred while the skills index and the
  work instructions name them directly; add them (plus the registry
  tools) to PINVOU3_ALWAYS_LOADED_TOOLS.
- mcp_pinvou3_present_artifact only exists while the builtin MCP
  server is connected: the artifact-card rule in the work instructions,
  the visual-design/gongwen/pptx/visualizer skills and the PPT scene
  payload are now conditional.
- The preview paragraph promised a 'retained compatibility control
  surface' Bash(action=..., background=true), but Bash is a
  model-invisible replay name in v0.9.12 and lowercase bash is
  foreground-only; the paragraph now directs background serving to
  terminal/run and states the honest fallback (present the artifact)
  when no background surface exists.
- Marketplace skills (government-writing, pptx, tencent-docs,
  visualizer) still taught retired write_file/exec_shell spellings on
  main; migrate them to canonical write/bash. The dingtalk NOTICE
  forward-guidance is updated so the next upstream sync does not
  replay the phantom File(action=...) syntax.

CodeWhale submodule advances to 2245a6c8 (Pinvou/CodeWhale#56):
skills-index Usage names the tool_search activation path for deferred
load_skill, and the subagent skills block teaches tool_search
discovery. Registered in docs/fork-modifications.md with fork-guard
fingerprints and two forkguard regression tests.

Signed-off-by: asto18089 <44870036+asto18089@users.noreply.github.com>
@asto18089
asto18089 force-pushed the fix/skills-phantom-tool-text branch 3 times, most recently from 41c8dcb to 4a0c82e Compare September 14, 2026 02:57
@asto18089
asto18089 changed the base branch from main to pinvou3-clean September 14, 2026 03:09
@asto18089
asto18089 force-pushed the fix/skills-phantom-tool-text branch from 4a0c82e to 83c0924 Compare September 14, 2026 03:10
The rendered skills index told the model to call load_skill with
name="list", but load_skill is a deferred tool that is not in the
first-turn catalog, and the subagent first-turn active set excludes
load_skill by design. Name the activation path instead: fall back to
tool_search when load_skill is missing (main sessions), and teach
subagents to discover skills through tool_search.

Extend the same treatment to the remaining phantom-naming sites found
in review: the bundled mcp-discovery skill now gates its registry_sync
command on tool availability and stops citing the retired exec_shell
alias (bash is the catalog name); the subagent ## Skills header stays
honest for tool-free children that also lack tool_search; the
omitted-skills tail carries the same tool_search fallback; and a new
engine regression pins MCP_REGISTRY_FIRST_INSTRUCTION to the registered
ToolSpec names so instruction/registration renames cannot drift apart
silently (the pinvou3-app allowlist coupling is documented in the test).

Regression coverage: forkguard_skill_index_usage_names_tool_search_activation,
forkguard_subagent_skill_catalog_uses_tool_search_discovery,
forkguard_omitted_skills_line_carries_tool_search_fallback,
forkguard_mcp_discovery_skill_conditions_registry_commands,
forkguard_registry_first_instruction_names_registered_tool_specs.

Also repair pre-existing baseline gate failures that this branch's first
CI run surfaced (they block the required gates but were not caused by
this fix): the clippy redundant closure in engine/tests.rs (new stable
lint), the crates/tui/CHANGELOG.md slice resync via
scripts/sync-changelog.sh, and the v0.9.11 -> v0.9.12 refresh of
web/data/latest-published-release.json plus
docs/public-surface-facts.json via web/scripts/sync-latest-release.mjs.
Release-note receipts for already-merged Hmbown#51/Hmbown#48/Hmbown#43/Hmbown#37 remain
advisory (check-versions exits 0) and must land before the next
release.

Signed-off-by: asto18089 <44870036+asto18089@users.noreply.github.com>
@asto18089
asto18089 force-pushed the fix/skills-phantom-tool-text branch from 83c0924 to c34c3a4 Compare September 14, 2026 05:07
asto18089 added a commit to Pinvou/pinvou-agent that referenced this pull request Sep 14, 2026
Model-facing text promised tools that were not in the model's actual
tool catalog, confusing the model (observed in a Work-card session):

- The base registry-first policy names registry_sync and
  start_registry_mcp_server; both are live foundation tools that were
  only missing from the Pinvou allowlist. Whitelist them (with
  first-turn visibility via ALWAYS_LOADED) instead of dropping the
  policy; the browser carve-out stays because the built-in browser is
  not in the registry.
- load_skill/file_search are deferred while the skills index and the
  work instructions name them directly; add them (plus the registry
  tools) to PINVOU3_ALWAYS_LOADED_TOOLS.
- mcp_pinvou3_present_artifact only exists while the builtin MCP
  server is connected: the artifact-card rule in the work instructions,
  the visual-design/gongwen/pptx/visualizer skills and the PPT scene
  payload are now conditional.
- The preview paragraph promised a 'retained compatibility control
  surface' Bash(action=..., background=true), but Bash is a
  model-invisible replay name in v0.9.12 and lowercase bash is
  foreground-only; the paragraph now directs background serving to
  terminal/run and states the honest fallback (present the artifact)
  when no background surface exists.
- Marketplace skills (government-writing, pptx, tencent-docs,
  visualizer) still taught retired write_file/exec_shell spellings on
  main; migrate them to canonical write/bash. The dingtalk NOTICE
  forward-guidance is updated so the next upstream sync does not
  replay the phantom File(action=...) syntax.
- The bundled mcp-discovery skill now gates its registry_sync command
  on tool availability (carried by the submodule commit below).

JS contract tests (canonical_tool_contract, browser_core_protocol)
are migrated from the deleted Bash compatibility surface to the new
contract, and the PPT scene payload uses the full
mcp_pinvou3_present_artifact catalog name.

CodeWhale submodule advances to c34c3a430 (Pinvou/CodeWhale#56,
pending merge): the skills-index Usage line names the tool_search
activation path for deferred load_skill, the subagent skills block
teaches tool_search discovery, and a new engine regression pins the
registry-first instruction to the registered ToolSpec names.
Registered in docs/fork-modifications(.en).md with six T3 fork-guard
fingerprints, a forkguard floor of 57, and refreshed drift counts.

The gitlink, EXPECTED_HEAD, and both registers deliberately point at
the #56 candidate until that PR lands and pinvou3-clean is advanced
to the same commit; verify-public-submodule.sh stays red by design
until that closure completes.

Signed-off-by: asto18089 <44870036+asto18089@users.noreply.github.com>
asto18089 added a commit to Pinvou/pinvou-agent that referenced this pull request Sep 14, 2026
Model-facing text promised tools that were not in the model's actual
tool catalog, confusing the model (observed in a Work-card session):

- The base registry-first policy names registry_sync and
  start_registry_mcp_server; both are live foundation tools that were
  only missing from the Pinvou allowlist. Whitelist them (with
  first-turn visibility via ALWAYS_LOADED) instead of dropping the
  policy; the browser carve-out stays because the built-in browser is
  not in the registry.
- load_skill/file_search are deferred while the skills index and the
  work instructions name them directly; add them (plus the registry
  tools) to PINVOU3_ALWAYS_LOADED_TOOLS.
- mcp_pinvou3_present_artifact only exists while the builtin MCP
  server is connected: the artifact-card rule in the work instructions,
  the visual-design/gongwen/pptx/visualizer skills and the PPT scene
  payload are now conditional.
- The preview paragraph promised a 'retained compatibility control
  surface' Bash(action=..., background=true), but Bash is a
  model-invisible replay name in v0.9.12 and lowercase bash is
  foreground-only; the paragraph now directs background serving to
  terminal/run and states the honest fallback (present the artifact)
  when no background surface exists.
- Marketplace skills (government-writing, pptx, tencent-docs,
  visualizer) still taught retired write_file/exec_shell spellings on
  main; migrate them to canonical write/bash. The dingtalk NOTICE
  forward-guidance is updated so the next upstream sync does not
  replay the phantom File(action=...) syntax.
- The bundled mcp-discovery skill now gates its registry_sync command
  on tool availability (carried by the submodule commit below).

JS contract tests (canonical_tool_contract, browser_core_protocol)
are migrated from the deleted Bash compatibility surface to the new
contract, and the PPT scene payload uses the full
mcp_pinvou3_present_artifact catalog name.

CodeWhale submodule advances to c34c3a430 (Pinvou/CodeWhale#56,
pending merge): the skills-index Usage line names the tool_search
activation path for deferred load_skill, the subagent skills block
teaches tool_search discovery, and a new engine regression pins the
registry-first instruction to the registered ToolSpec names.
Registered in docs/fork-modifications(.en).md with six T3 fork-guard
fingerprints, a forkguard floor of 57, and refreshed drift counts.

The gitlink and both registers point at the #56 candidate. fork-guard.sh
registers it as CANDIDATE_HEAD following the #408 candidate-period
convention: the registered EXPECTED_HEAD stays at the published
pinvou3-clean head ae7e3fb36 and layer 0 accepts either; the candidate
entry is retired once #56 lands and the public branch advances.
verify-public-submodule.sh stays red by design until that closure
completes.

Signed-off-by: asto18089 <44870036+asto18089@users.noreply.github.com>
Follow-up to the skills-index fix in c34c3a4 after an adversarial
review pass. Same defect class, same honest-availability treatment,
applied to the surfaces the first pass missed or got wrong:

- mcp-discovery: `registry_sync` is deferred but `tool_search`-
  searchable on stock hosts, so step 1's "not in your tool list =>
  Registry unavailable" surrendered a reachable capability and
  contradicted the load_skill treatment in the same change. Step 1 now
  activates via `tool_search` first and declares unavailability only if
  that fails, teaches a `query`-bearing call (the schema rejects empty
  input), states the eight-scored-matches contract instead of a
  "complete catalog" dump, and the preamble no longer claims an
  always-active tool surface. Step 3 gates `start_registry_mcp_server`,
  which can be absent while `registry_sync` is registered (pool init
  failure, tool-security mode).
- skills index: plugin-snapshot rows and the omitted-skills tail carry
  the `load_skill` -> `tool_search` fallback, and the Usage/omitted
  lines stay honest for surfaces where `tool_search` is absent too
  (ACP, allowlist-restricted exec).
- subagent ## Skills header: covers the third child class — explicit
  allowlists that keep `tool_search` but filter `load_skill` — with
  "absent or does not surface" instead of a binary premise.
- bundled pdf/help skills cited the `File` tool (`action: "read"`), a
  hidden compatibility alias no model-visible catalog or `tool_search`
  result can ever return; they now cite `read`. best-of-n gates
  `create_goal` on availability (child registries remove the tool
  entirely).

New regressions:
forkguard_bundled_skills_cite_no_hidden_or_retired_tool_names sweeps
every bundled body against hidden/retired names;
forkguard_best_of_n_goal_tool_is_availability_gated pins the gating.
The mcp-discovery and subagent pins were extended to the new wording.
Fingerprints, the guard CANDIDATE_HEAD, and the parent gitlink re-pin
ride in Pinvou/pinvou-agent#490.

Signed-off-by: asto18089 <44870036+asto18089@users.noreply.github.com>
@asto18089

Copy link
Copy Markdown
Collaborator Author

Pushed f81528358 (no force-push, c34c3a430 untouched): completes the phantom-tool sweep after an adversarial review pass. Highlights: mcp-discovery step 1 now activates registry_sync via tool_search before declaring unavailability (the tool is deferred-but-searchable on stock hosts, so the previous gate surrendered a reachable capability), teaches a query-bearing call (the schema rejects {}), and steps 1–3 are availability-gated consistently with the load_skill treatment; plugin-snapshot rows and the omitted-skills tail carry the tool_search fallback; the subagent header covers allowlist children that keep tool_search but filter load_skill; bundled pdf/help skills stop citing the hidden File alias (now read); best-of-n gates create_goal. Two new regressions: a bundled-skills sweep against hidden/retired names and the best-of-n gating pin. Local verification: skills:: 221 passed, forkguard 55 passed, subagent::tests 492 passed. Parent-side fingerprints/CANDIDATE_HEAD/gitlink re-pin ride in Hmbown#490 (Pinvou/pinvou-agent).

asto18089 added a commit to Pinvou/pinvou-agent that referenced this pull request Sep 14, 2026
Model-facing text promised tools that were not in the model's actual
tool catalog, confusing the model (observed in a Work-card session):

- The base registry-first policy names registry_sync and
  start_registry_mcp_server; both are live foundation tools that were
  only missing from the Pinvou allowlist. Whitelist them (with
  first-turn visibility via ALWAYS_LOADED) instead of dropping the
  policy; the browser carve-out stays because the built-in browser is
  not in the registry.
- load_skill/file_search are deferred while the skills index and the
  work instructions name them directly; add them (plus the registry
  tools) to PINVOU3_ALWAYS_LOADED_TOOLS.
- mcp_pinvou3_present_artifact only exists while the builtin MCP
  server is connected: the artifact-card rule in the work instructions,
  the visual-design/gongwen/pptx/visualizer skills and the PPT scene
  payload are now conditional.
- The preview paragraph promised a 'retained compatibility control
  surface' Bash(action=..., background=true), but Bash is a
  model-invisible replay name in v0.9.12 and lowercase bash is
  foreground-only; the paragraph now directs background serving to
  terminal/run and states the honest fallback (present the artifact)
  when no background surface exists.
- Marketplace skills (government-writing, pptx, tencent-docs,
  visualizer) still taught retired write_file/exec_shell spellings on
  main; migrate them to canonical write/bash. The dingtalk NOTICE
  forward-guidance is updated so the next upstream sync does not
  replay the phantom File(action=...) syntax.
- The bundled mcp-discovery skill now gates its registry_sync command
  on tool availability (carried by the submodule commit below).

JS contract tests (canonical_tool_contract, browser_core_protocol)
are migrated from the deleted Bash compatibility surface to the new
contract, and the PPT scene payload uses the full
mcp_pinvou3_present_artifact catalog name.

CodeWhale submodule advances to c34c3a430 (Pinvou/CodeWhale#56,
pending merge): the skills-index Usage line names the tool_search
activation path for deferred load_skill, the subagent skills block
teaches tool_search discovery, and a new engine regression pins the
registry-first instruction to the registered ToolSpec names.
Registered in docs/fork-modifications(.en).md with six T3 fork-guard
fingerprints, a forkguard floor of 57, and refreshed drift counts.

The gitlink and both registers point at the #56 candidate. fork-guard.sh
registers it as CANDIDATE_HEAD following the #408 candidate-period
convention: the registered EXPECTED_HEAD stays at the published
pinvou3-clean head ae7e3fb36 and layer 0 accepts either; the candidate
entry is retired once #56 lands and the public branch advances.
verify-public-submodule.sh stays red by design until that closure
completes.

Signed-off-by: asto18089 <44870036+asto18089@users.noreply.github.com>
A fresh adversarial pass over the branch found the sweep's own text
surrendering deferred-but-tool_search-searchable tools on visibility
gates alone, plus one phantom citation the sweep had missed:

- mcp-discovery step 3 now mirrors step 1: run tool_search first to
  activate start_registry_mcp_server (its activation does not follow
  from registry_sync's), and declare registry starts unavailable only
  when tool_search cannot surface it either. The preamble no longer
  overclaims registration (the start tool additionally needs the host's
  MCP pool initialized), and step 4 teaches re-activation for connected
  tools that re-defer on later turns.
- best-of-n now names the tool_search activation path for create_goal
  (deferred on every stock host, so the visibility gate alone always
  failed) and stays honest for subagent sessions where the tool is
  removed entirely.
- The bundled-skills denylist no longer lists list_dir, which is a
  live, model-visible, searchable tool; it now covers the registry's
  remaining hidden aliases and canonical retired names instead.
- The parent-context sub-agent hint cites `read` or `bash` (first-turn
  active) instead of the hidden `File` alias with a nonexistent
  `list` action; the pin is renamed into the forkguard set and flipped.
- MAX_REGISTRY_MATCHES is pinned to the quoted "eight" wording at
  compile time so the cap and the text cannot drift apart silently.

Disclosed, deliberately not changed here: workflows/stopship.workflow.js
briefs an explore child with the hidden `File` `search_content` alias. The
call dispatches by alias on every surface this fleet runs on, and a
rename to `grep_files` is behavior-changing (deferred hydration would
burn the scout's one-round response budget), so it needs its own
protocol rework rather than a drive-by edit.

Fingerprints and the parent gitlink re-pin ride in
Pinvou/pinvou-agent#490.

Signed-off-by: asto18089 <asto18089@126.com>
CodeWhale CONTRIBUTING.md writes changelog entries on main at merge
time and asks PRs carrying changelog hunks to strip them, and the
facts/web generated refreshes have no gate on the pinvou3-clean lane
(the web freshness checks run on master/main only). The CHANGELOG
slice resync, changelog.generated.ts, and the surface-facts trio move
to a dedicated chore PR; the clippy map(Ok) test-target cleanup moves
with them (fork-ci does not lint test targets). The net diff of this
branch is now the phantom-tool text fix only.

Signed-off-by: asto18089 <asto18089@126.com>
@asto18089 asto18089 changed the title fix(fork): stop naming absent tools in skills text fix(fork): stop naming absent tools in model-facing text Sep 14, 2026
@asto18089

Copy link
Copy Markdown
Collaborator Author

Pushed two more commits (both fast-forward, no force-push):

  • a2e21fcf9 — a third adversarial pass found the second commit's own gates repeating the defect class this PR fixes: mcp-discovery step 3 gated start_registry_mcp_server on visibility alone (activation is per-name, so the gate misfired on every stock host right after step 1's tool_search path), and best-of-n gated create_goal on visibility while the tool is deferred-but-searchable in main sessions. Both now teach the two-stage tool_search pattern; the preamble discloses the pool-init dependency, step 4 teaches re-activation for re-deferred connected tools, and the parent-context sub-agent hint (core/engine/context.rs) now cites read/bash instead of the hidden File alias (the old text was pinned by a test asserting the phantom wording — flipped and renamed into the forkguard set). The bundled-skills denylist drops the wrongly listed live tool list_dir and covers the registry's remaining hidden/retired names; MAX_REGISTRY_MATCHES is compile-time-pinned to the quoted "eight" wording.
  • 18f7c7b15 — strips the baseline gate repairs (CHANGELOG slice, facts/web generated files, map(Ok)) into the dedicated chore(baseline): resync the tui changelog slice, surface facts, and test clippy #60 per the CONTRIBUTING changelog policy; the net diff here is topic-only.

Disclosed, deliberately unchanged: workflows/stopship.workflow.js still briefs the scout with the hidden File search_content alias — it dispatches by alias on every surface this fleet runs on, and a grep_files rename would burn the scout's response budget on deferred hydration, so it needs a protocol rework, not a drive-by.

Local verification: forkguard 56/56, skills 221/221, tools::subagent::tests 492/492, fmt/clippy clean, parent fork-guard --fast green (62 behavior names, fingerprint layer pass). Fingerprint/gitlink re-pin rides in Pinvou/pinvou-agent#490 (54fa0c60).

Collapse the duplicated tool_search fallback teaching: the skills-index
Usage line and mcp-discovery step 1 stay the single teaching points; the
plugin rows, the omitted-skills tail, and mcp-discovery step 3 now rely
on them by reference instead of repeating the full fallback, and the
subagent ## Skills header shrinks to the same one-sentence pattern.

Make the mcp-discovery preamble precise: only the start tool needs the
host's MCP pool initialized; registry_sync registers with MCP support
alone.

Harden the bundled-skills phantom sweep: drop the speculative
`Read`/`Write`/`Edit` entries that no registry table ever carried,
add the missed `git_diff`/`git_log`/`git_show`/`git_blame` and
`agents/coordinate` retired names, correct the tracking comment, and
disclose the BUNDLED_SKILLS scope (v4-best-practices, feishu uncovered).

Pin the remaining "eight" wording sides (first-turn instruction and the
registry_sync schema description) to MAX_REGISTRY_MATCHES, and fix the
parent-context test comment that overclaimed first-turn activity on
"every stock host".

Fork-guard fingerprints for the changed text are re-synced in
Pinvou/pinvou-agent#490.

Signed-off-by: asto <asto18089@126.com>
@asto18089

Copy link
Copy Markdown
Collaborator Author

Full fresh re-review of head 9f46ac5f0 (commits 2–4 re-reviewed from scratch; commit 1 was covered earlier) with three parallel auditors plus main-line verification. Result: 0 blocking. All nine tool-fact claims verified against the registry/catalog code (deferred sets, the three child classes, required query, the 8-match cap, pool gating for the start tool, File as a hidden alias, create_goal removal in child registries). All forkguard tests pass; cargo check --all-targets and clippy --all-features --locked are clean.

Three minors and a disclosure fix from the review are applied as commit 5 (9f46ac5f0):

  1. Prompt dedup (context-budget round). The activation fallback was taught in full six times across surfaces. The skills-index Usage line and mcp-discovery step 1 are now the single teaching points; plugin rows, the omitted-skills tail, and step 3 reference them (as in step 1); the subagent ## Skills header shrank to the same one-sentence pattern. No information lost; per-session and per-child prompt cost goes down, and plugin-heavy sessions save per-row.
  2. stopship disclosure correction (main finding). The leftover was described as "dispatches by alias on every surface". Live child sessions dispatch through execute_from_surface, which fails any name outside the child's policy-filtered catalog, and File (model_visible=false) never reaches a catalog — the explore gate's first step already fails today, and a bare grep_files rename would not fix it (deferred ⇒ needs two-step activation teaching + budget re-measurement). Body and the fork-modifications doc now say so.
  3. Phantom-list hardening. Dropped the speculative Read/Write/Edit entries (no registry table ever carried them), added the missed git_diff/git_log/git_show/git_blame/agents/coordinate, corrected the tracking comment, disclosed the BUNDLED_SKILLS sweep scope.
  4. Pinning. The remaining "eight" wording sides (first-turn instruction, registry_sync schema description) are test-pinned alongside the compile-time assert; mcp-discovery preamble now states precisely that only the start tool needs the MCP pool; the "every stock host" test comment is corrected.

Parent-side registration re-synced in Pinvou/pinvou-agent#490: candidate re-pinned to 9f46ac5f0/33 commits, five fingerprints refreshed for the new wording, the omitted-tail fingerprint retired with its test, fork-guard --fast green (61 forkguard names, floor 57).

asto18089 added a commit to Pinvou/pinvou-agent that referenced this pull request Sep 14, 2026
Model-facing text promised tools that were not in the model's actual
tool catalog, confusing the model (observed in a Work-card session):

- The base registry-first policy names registry_sync and
  start_registry_mcp_server; both are live foundation tools that were
  only missing from the Pinvou allowlist. Whitelist them (with
  first-turn visibility via ALWAYS_LOADED) instead of dropping the
  policy; the browser carve-out stays because the built-in browser is
  not in the registry.
- load_skill/file_search are deferred while the skills index and the
  work instructions name them directly; add them (plus the registry
  tools) to PINVOU3_ALWAYS_LOADED_TOOLS.
- mcp_pinvou3_present_artifact only exists while the builtin MCP
  server is connected: the artifact-card rule in the work instructions,
  the visual-design/gongwen/pptx/visualizer skills and the PPT scene
  payload are now conditional.
- The preview paragraph promised a 'retained compatibility control
  surface' Bash(action=..., background=true), but Bash is a
  model-invisible replay name in v0.9.12 and lowercase bash is
  foreground-only; the paragraph now directs background serving to
  terminal/run and states the honest fallback (present the artifact)
  when no background surface exists.
- Marketplace skills (government-writing, pptx, tencent-docs,
  visualizer) still taught retired write_file/exec_shell spellings on
  main; migrate them to canonical write/bash. The dingtalk NOTICE
  forward-guidance is updated so the next upstream sync does not
  replay the phantom File(action=...) syntax.
- The bundled mcp-discovery skill now gates its registry_sync command
  on tool availability (carried by the submodule commit below).

JS contract tests (canonical_tool_contract, browser_core_protocol)
are migrated from the deleted Bash compatibility surface to the new
contract, and the PPT scene payload uses the full
mcp_pinvou3_present_artifact catalog name.

CodeWhale submodule advances to c34c3a430 (Pinvou/CodeWhale#56,
pending merge): the skills-index Usage line names the tool_search
activation path for deferred load_skill, the subagent skills block
teaches tool_search discovery, and a new engine regression pins the
registry-first instruction to the registered ToolSpec names.
Registered in docs/fork-modifications(.en).md with six T3 fork-guard
fingerprints, a forkguard floor of 57, and refreshed drift counts.

The gitlink and both registers point at the #56 candidate. fork-guard.sh
registers it as CANDIDATE_HEAD following the #408 candidate-period
convention: the registered EXPECTED_HEAD stays at the published
pinvou3-clean head ae7e3fb36 and layer 0 accepts either; the candidate
entry is retired once #56 lands and the public branch advances.
verify-public-submodule.sh stays red by design until that closure
completes.

Signed-off-by: asto18089 <44870036+asto18089@users.noreply.github.com>
asto18089 added a commit to Pinvou/pinvou-agent that referenced this pull request Sep 15, 2026
Model-facing text promised tools that were not in the model's actual
tool catalog, confusing the model (observed in a Work-card session):

- The base registry-first policy names registry_sync and
  start_registry_mcp_server; both are live foundation tools that were
  only missing from the Pinvou allowlist. Whitelist them (with
  first-turn visibility via ALWAYS_LOADED) instead of dropping the
  policy; the browser carve-out stays because the built-in browser is
  not in the registry.
- load_skill/file_search are deferred while the skills index and the
  work instructions name them directly; add them (plus the registry
  tools) to PINVOU3_ALWAYS_LOADED_TOOLS.
- mcp_pinvou3_present_artifact only exists while the builtin MCP
  server is connected: the artifact-card rule in the work instructions,
  the visual-design/gongwen/pptx/visualizer skills and the PPT scene
  payload are now conditional.
- The preview paragraph promised a 'retained compatibility control
  surface' Bash(action=..., background=true), but Bash is a
  model-invisible replay name in v0.9.12 and lowercase bash is
  foreground-only; the paragraph now directs background serving to
  terminal/run and states the honest fallback (present the artifact)
  when no background surface exists.
- Marketplace skills (government-writing, pptx, tencent-docs,
  visualizer) still taught retired write_file/exec_shell spellings on
  main; migrate them to canonical write/bash. The dingtalk NOTICE
  forward-guidance is updated so the next upstream sync does not
  replay the phantom File(action=...) syntax.
- The bundled mcp-discovery skill now gates its registry_sync command
  on tool availability (carried by the submodule commit below).

JS contract tests (canonical_tool_contract, browser_core_protocol)
are migrated from the deleted Bash compatibility surface to the new
contract, and the PPT scene payload uses the full
mcp_pinvou3_present_artifact catalog name.

CodeWhale submodule advances to c34c3a430 (Pinvou/CodeWhale#56,
pending merge): the skills-index Usage line names the tool_search
activation path for deferred load_skill, the subagent skills block
teaches tool_search discovery, and a new engine regression pins the
registry-first instruction to the registered ToolSpec names.
Registered in docs/fork-modifications(.en).md with six T3 fork-guard
fingerprints, a forkguard floor of 57, and refreshed drift counts.

The gitlink and both registers point at the #56 candidate. fork-guard.sh
registers it as CANDIDATE_HEAD following the #408 candidate-period
convention: the registered EXPECTED_HEAD stays at the published
pinvou3-clean head ae7e3fb36 and layer 0 accepts either; the candidate
entry is retired once #56 lands and the public branch advances.
verify-public-submodule.sh stays red by design until that closure
completes.

Signed-off-by: asto18089 <44870036+asto18089@users.noreply.github.com>
Adversarial review of this branch found the same phantom-tool defect
class at four more model-facing sites, plus two over-claims in the new
fallback wording:

- GOAL_CONTINUATION_PROMPT commanded `update_goal`, which is deferred
  on stock hosts (a goal created by a host-side /goal never activates
  it); the prompt now names the tool_search activation path.
- The parent-context sub-agent hint cited `handle_read`
  unconditionally; it now names the activation path too.
- The skills-index Usage line and the subagent ## Skills header
  declared skills unloadable when tool_search cannot surface
  load_skill, but a registered deferred tool still hydrates on demand
  when called directly; both now teach the direct-call fallback before
  declaring skills unavailable.
- Test-only fixes: the mcp-discovery pin's "rejects empty input"
  attribution (the schema requires the `query` field; the host rejects
  an empty value) and the MAX_REGISTRY_MATCHES assert message (SKILL.md
  path prefix, and the instruction side says "eight matches", not
  "eight scored matches").
- Under-pin repairs: pin the new direct-call fallback clauses in the
  Usage and subagent-header tests, add an omitted-tail guard so the
  commit-5 dedup cannot silently regress, and pin the
  goal-continuation activation teaching.

New regressions: forkguard_goal_continuation_names_tool_search_activation,
forkguard_omitted_skills_line_stays_short.

Verified: cargo fmt --check clean; cargo test -p codewhale-tui --lib
(RUST_MIN_STACK=8388608, matching CI) passes apart from three
remote_control timing tests that also fail intermittently on
unmodified trees and pass in isolation.

Fork-guard fingerprints for the changed text ride in
Pinvou/pinvou-agent#490 — that register also gains the two new test
names above.

Signed-off-by: asto18089 <asto18089@users.noreply.github.com>
asto18089 added a commit to Pinvou/pinvou-agent that referenced this pull request Sep 15, 2026
Model-facing text promised tools that were not in the model's actual
tool catalog, confusing the model (observed in a Work-card session):

- The base registry-first policy names registry_sync and
  start_registry_mcp_server; both are live foundation tools that were
  only missing from the Pinvou allowlist. Whitelist them (with
  first-turn visibility via ALWAYS_LOADED) instead of dropping the
  policy; the browser carve-out stays because the built-in browser is
  not in the registry.
- load_skill/file_search are deferred while the skills index and the
  work instructions name them directly; add them (plus the registry
  tools) to PINVOU3_ALWAYS_LOADED_TOOLS.
- mcp_pinvou3_present_artifact only exists while the builtin MCP
  server is connected: the artifact-card rule in the work instructions,
  the visual-design/gongwen/pptx/visualizer skills and the PPT scene
  payload are now conditional.
- The preview paragraph promised a 'retained compatibility control
  surface' Bash(action=..., background=true), but Bash is a
  model-invisible replay name in v0.9.12 and lowercase bash is
  foreground-only; the paragraph now directs background serving to
  terminal/run and states the honest fallback (present the artifact)
  when no background surface exists.
- Marketplace skills (government-writing, pptx, tencent-docs,
  visualizer) still taught retired write_file/exec_shell spellings on
  main; migrate them to canonical write/bash. The dingtalk NOTICE
  forward-guidance is updated so the next upstream sync does not
  replay the phantom File(action=...) syntax.
- The bundled mcp-discovery skill now gates its registry_sync command
  on tool availability (carried by the submodule commit below).

JS contract tests (canonical_tool_contract, browser_core_protocol)
are migrated from the deleted Bash compatibility surface to the new
contract, and the PPT scene payload uses the full
mcp_pinvou3_present_artifact catalog name.

CodeWhale submodule advances to c34c3a430 (Pinvou/CodeWhale#56,
pending merge): the skills-index Usage line names the tool_search
activation path for deferred load_skill, the subagent skills block
teaches tool_search discovery, and a new engine regression pins the
registry-first instruction to the registered ToolSpec names.
Registered in docs/fork-modifications(.en).md with six T3 fork-guard
fingerprints, a forkguard floor of 57, and refreshed drift counts.

The gitlink and both registers point at the #56 candidate. fork-guard.sh
registers it as CANDIDATE_HEAD following the #408 candidate-period
convention: the registered EXPECTED_HEAD stays at the published
pinvou3-clean head ae7e3fb36 and layer 0 accepts either; the candidate
entry is retired once #56 lands and the public branch advances.
verify-public-submodule.sh stays red by design until that closure
completes.

Signed-off-by: asto18089 <44870036+asto18089@users.noreply.github.com>
A fresh adversarial sweep found the same phantom-tool defect class at
five more model-facing sites, plus one evidence-contract gap:

- MCP_REGISTRY_FIRST_INSTRUCTION commanded `registry_sync` and
  `start_registry_mcp_server`, both deferred on stock hosts, with no
  activation path and no availability gate; it now teaches the
  `tool_search` activation for both, gates on reachability, and
  discloses that activating `registry_sync` does not activate the
  start tool.
- REGISTRY_FIRST_PROMPT (attached to every `registry_sync` result)
  commanded the start tool with no path; it now names the activation.
- The worker-record prose pairing `handle_read` with a transcript
  handle (takeover targets, session projection, the transcript artifact
  description, and every handle_read-recommending status reason) now
  carries one shared activation hint instead of commanding a tool
  absent from the first-turn catalog.
- The /agent dispatch brief and the bare /goal brief named
  `handle_read`/`create_goal` with no path; both now teach the
  activation.
- GOAL_CONTINUATION_PROMPT and the parent-context hint offered only the
  `tool_search` path, which allowed_tools-filtered sessions strip; both
  now keep the direct-call fallback (registered deferred tools hydrate
  when called by name).
- Web/fetch overflow metadata now sets `evidence_available: true` so
  the engine auto-activates `retrieve_tool_result` — the recovery tool
  the overflow footer already names — matching the shell-truncation
  spillover contract.

New pins: forkguard_registry_first_prompt_teaches_start_tool_activation,
forkguard_worker_record_hints_teach_handle_read_activation,
forkguard_slash_agent_dispatch_teaches_handle_read_activation; the
registry-first, goal-continuation, context-hint, bare-/goal, and web
overflow tests gain the new assertions.

Verified: cargo fmt --check clean; cargo clippy -p codewhale-tui --lib
--tests --locked clean apart from the pre-existing
engine/tests.rs CompleteOnceThenBlockModelClient closure that 18f7c7b
restored from base (fork-ci lints only non-test targets);
RUST_MIN_STACK=8388608 cargo test -p codewhale-tui --lib passes
11768/0.

Fork-guard fingerprints for the reworded registry-first instruction,
continuation prompt, context hint, and worker-record text ride in
Pinvou/pinvou-agent#490.

Signed-off-by: asto18089 <asto18089@users.noreply.github.com>
@asto18089

Copy link
Copy Markdown
Collaborator Author

Fresh adversarial review of the sixth-commit candidate (be2b2fe92), six verification tracks (deferred-tool mechanics ground truth, commit-6 defect hunt, scope purity, repo-wide missed-site sweep, dedupe coherence, local RUST_MIN_STACK=8388608 cargo test -p codewhale-tui --lib 11765/0):

Verified sound: all seven underlying tool-mechanics claims hold (first-turn active set read/write/edit/bash/agent/todo_write + synthetic tool_search; hydration keys off the model-facing catalog via a two-step receipt+retry; File never enters any catalog or tool_search result; create_goal/update_goal are removed from child registries; a host-side /goal never activates update_goal). Scope purity holds: the net diff is topic-only, the commit-4 rider strip left zero residue, and no contradictory "cannot load skills" text remains. The commit-6 direct-call fallback wording is behaviorally sound on every surface — the terminal "only if that call also fails" clause covers the allowlist corner where hydration cannot fire.

Found and fixed in commit 7 (4eb487cd3) — the same defect class survived at five more model-facing sites, plus one evidence-contract gap:

  1. MAJOR — MCP_REGISTRY_FIRST_INSTRUCTION (system prompt, every MCP-enabled session) commanded registry_sync/start_registry_mcp_server — both deferred on stock hosts — with no activation teaching and no availability gate; REGISTRY_FIRST_PROMPT (attached to every registry_sync result) had the same gap for the start tool. Fixed: both now teach the tool_search activation path, gate on reachability, and disclose per-name activation.
  2. MINOR — worker-record prose pairing handle_read with a transcript handle (takeover targets, the session projection, the transcript artifact description, each handle_read-recommending status reason) commanded the deferred tool; now carries one shared activation hint, with the duplicated takeover/projection sentence extracted into a shared function.
  3. MINOR — the /agent dispatch brief taught handle_read with no path; fixed.
  4. MINOR — the bare /goal brief commanded create_goal with no path; fixed.
  5. MINOR — the goal-continuation prompt and the parent-context hint offered only the tool_search path, which allowed_tools-filtered sessions strip (synthetic injection runs before the allow/deny retain); both now keep the direct-call fallback (registered deferred tools hydrate when called by name).
  6. MINOR — web/fetch overflow trailers named retrieve_tool_result but the metadata never set evidence_available, so the engine never auto-activated the named recovery tool; fixed to the shell-truncation spillover contract.

Housekeeping: the Base section now says seven commits, and the commit-6 register note is corrected (the Hmbown#490 re-sync had already landed).

Left as disclosed / out of scope: the stopship.workflow.js File-alias leftover stays with #61; the pre-existing map(|event| Ok(event)) closure restored by 18f7c7b15 is flagged by the current stable clippy under --all-targets, but fork-ci does not lint test targets, so it rides as-is; the PHANTOM_NAMES denylist stays manual (not registry-derived) by design.

Verification on 4eb487cd3: cargo fmt --check clean; cargo test -p codewhale-tui --lib 11768/0 (59 forkguard tests green); clippy -p codewhale-tui --lib --tests --locked clean apart from the pre-existing closure above. The parent register re-pin — gitlink + CANDIDATE_HEAD → 4eb487cd3, twelve new T3 fingerprints (18 → 30 net-new), the three new forkguard tests, floor 57 / actual 66 — is pushed to Pinvou/pinvou-agent#490 (5da767fc4), fork-guard --fast green there.

asto18089 added a commit to Pinvou/pinvou-agent that referenced this pull request Sep 16, 2026
Model-facing text promised tools that were not in the model's actual
tool catalog, confusing the model (observed in a Work-card session):

- The base registry-first policy names registry_sync and
  start_registry_mcp_server; both are live foundation tools that were
  only missing from the Pinvou allowlist. Whitelist them (with
  first-turn visibility via ALWAYS_LOADED) instead of dropping the
  policy; the browser carve-out stays because the built-in browser is
  not in the registry.
- load_skill/file_search are deferred while the skills index and the
  work instructions name them directly; add them (plus the registry
  tools) to PINVOU3_ALWAYS_LOADED_TOOLS.
- mcp_pinvou3_present_artifact only exists while the builtin MCP
  server is connected: the artifact-card rule in the work instructions,
  the visual-design/gongwen/pptx/visualizer skills and the PPT scene
  payload are now conditional.
- The preview paragraph promised a 'retained compatibility control
  surface' Bash(action=..., background=true), but Bash is a
  model-invisible replay name in v0.9.12 and lowercase bash is
  foreground-only; the paragraph now directs background serving to
  terminal/run and states the honest fallback (present the artifact)
  when no background surface exists.
- Marketplace skills (government-writing, pptx, tencent-docs,
  visualizer) still taught retired write_file/exec_shell spellings on
  main; migrate them to canonical write/bash. The dingtalk NOTICE
  forward-guidance is updated so the next upstream sync does not
  replay the phantom File(action=...) syntax.
- The bundled mcp-discovery skill now gates its registry_sync command
  on tool availability (carried by the submodule commit below).

JS contract tests (canonical_tool_contract, browser_core_protocol)
are migrated from the deleted Bash compatibility surface to the new
contract, and the PPT scene payload uses the full
mcp_pinvou3_present_artifact catalog name.

CodeWhale submodule advances to c34c3a430 (Pinvou/CodeWhale#56,
pending merge): the skills-index Usage line names the tool_search
activation path for deferred load_skill, the subagent skills block
teaches tool_search discovery, and a new engine regression pins the
registry-first instruction to the registered ToolSpec names.
Registered in docs/fork-modifications(.en).md with six T3 fork-guard
fingerprints, a forkguard floor of 57, and refreshed drift counts.

The gitlink and both registers point at the #56 candidate. fork-guard.sh
registers it as CANDIDATE_HEAD following the #408 candidate-period
convention: the registered EXPECTED_HEAD stays at the published
pinvou3-clean head ae7e3fb36 and layer 0 accepts either; the candidate
entry is retired once #56 lands and the public branch advances.
verify-public-submodule.sh stays red by design until that closure
completes.

Signed-off-by: asto18089 <44870036+asto18089@users.noreply.github.com>
asto18089 added a commit to Pinvou/pinvou-agent that referenced this pull request Sep 16, 2026
The CodeWhale#56 candidate gains a seventh commit (4eb487cd3) closing
the same-class phantom-text leftovers a fresh adversarial sweep found:
the registry-first system instruction and the per-result
REGISTRY_FIRST_PROMPT now teach the tool_search activation path for
their deferred commands; the worker-record handle_read prose carries a
shared activation hint; the /agent and bare /goal briefs teach
activation; the goal-continuation prompt and the parent-context hint
keep a direct-call fallback; and web/fetch overflow metadata sets
evidence_available so retrieve_tool_result auto-activates.

- advance the gitlink and CANDIDATE_HEAD to 4eb487cd3
  (CANDIDATE_COMMITS 34 -> 35, seven candidate commits)
- register twelve new T3 fingerprints (18 -> 30 net-new; 31 added,
  1 retired) and the three new forkguard tests
- refresh both fork registers (guard floor 57, actual 66; drift and
  section-11 counts restated for the seventh candidate commit)

./scripts/fork-guard.sh --fast on this head: exit 0, all layers green
(gitlink accepted as the registered candidate, floor 57 / actual 66);
python3 scripts/architecture-guard.py: pass.

Submodule-side evidence on Pinvou/CodeWhale#56 (candidate 4eb487cd3):
cargo fmt --check clean; RUST_MIN_STACK=8388608 cargo test -p
codewhale-tui --lib 11768/0; clippy -p codewhale-tui --lib --tests
clean apart from the pre-existing base-restored test closure that
fork-ci does not lint.

Signed-off-by: asto <asto18089@126.com>
A third independent review pass found no functional defects and no
remaining phantom-tool sites on stock hosts; it did surface small
consistency and honesty gaps, fixed here:

- The /agent dispatch brief and the bare /goal brief taught only the
  two-step `tool_search` activation. Explicit allowed_tools can strip
  `tool_search` itself - the exact corner the goal-continuation and
  parent-context pins already require the direct-call fallback for -
  so both briefs now carry the third tier and their pins assert it.
- The engine's parent-context hint re-typed the first two tiers of
  HANDLE_READ_ACTIVATION_HINT verbatim; the constant is pub(crate) now
  and the hint formats it in (rendered text byte-identical).
- fetch_url flags every artifact it writes as retrievable evidence,
  not just text overflows: binary PDF/media saves set evidence_available
  so the saved-artifact pointer line is actionable instead of a dead
  end. The behavior is kept; the comment and the assertion message
  claimed overflow-only and now describe the actual contract.
- The bundled-skills phantom denylist is a hand-maintained superset of
  the canonical retired and hidden-alias lists; it is now hoisted to
  module scope and anchored by a subset assertion against
  RETIRED_TOOL_NAMES/HIDDEN_COMPAT_TOOL_NAMES so a newly registered
  alias cannot silently skip the sweep.
- A test assertion message carried a fourteen-space line-continuation
  accident; whitespace only.

New pin: forkguard_phantom_denylist_covers_canonical_lists; the
slash-agent and bare-/goal pins gain the direct-call assertions.

Verified: cargo fmt --check clean; cargo clippy --workspace
--all-features --locked (fork-ci invocation) clean;
RUST_MIN_STACK=16777216 cargo test -p codewhale-tui --lib passes
11769/0 (one run reported two timing flakes that pass on immediate
rerun on the same tree); no Cargo.lock drift.

Fork-guard fingerprints for the new brief tiers and the denylist
anchor ride in Pinvou/pinvou-agent#490.

Signed-off-by: asto18089 <asto18089@users.noreply.github.com>
@asto18089
asto18089 force-pushed the fix/skills-phantom-tool-text branch from 6010098 to dc1f391 Compare September 16, 2026 14:32
asto18089 added a commit to Pinvou/pinvou-agent that referenced this pull request Sep 16, 2026
Third review round on Pinvou/CodeWhale#56 added one commit (the eighth,
dc1f391d6): the /agent and bare-/goal briefs gain the direct-call
fallback tier, HANDLE_READ_ACTIVATION_HINT becomes pub(crate) and is
reused by the parent-context hint (rendered text unchanged), the
fetch_url evidence_available comment now describes the actual contract
(binary PDF/media saves set it too), the bundled-skills phantom
denylist gains a canonical-list subset anchor, and one test-message
whitespace accident is fixed.

Re-pin the gitlink and CANDIDATE_HEAD to dc1f391d6 (CANDIDATE_COMMITS
36), add three T3 fingerprints (both brief tiers plus the denylist
anchor), refresh fork-modifications zh/en (round-seven narrative,
candidate head, drift 147 files +10708/-1343, guard count 67, and the
corrected list-action attribution), and register the new
forkguard_phantom_denylist_covers_canonical_lists test.

Verified: ./scripts/fork-guard.sh --fast green (fingerprint layer
passes, 67 forkguard names); python3 scripts/architecture-guard.py
green.

Signed-off-by: asto18089 <asto18089@users.noreply.github.com>
@asto18089

Copy link
Copy Markdown
Collaborator Author

Third independent review pass complete (six specialized audit tracks over the full diff, plus a whole-tree phantom sweep and mechanism re-verification against the engine code). Verdict: no BLOCKER, no MAJOR; the sweep is root-complete on stock hosts and the review round produced one follow-up commit, now pushed as dc1f391d6.

What the round verified clean: fmt / clippy (fork-ci invocation) / cargo test -p codewhale-tui --lib 11769/0; every mechanism claim in the taught ladders re-confirmed against code (deferred+searchable set, direct-call hydration, child-registry goal-tool removal, evidence_available contract parity with the shell-truncation spillover, MCP re-deferral, pool gating); all seven commits DCO-signed and on-theme in the net diff; Web confirmed a real catalog tool (WebTool), so the registry-first instruction carries no phantom.

Fixed in dc1f391d6 (round-three gaps, all minor):

  • The /agent dispatch brief and the bare /goal brief taught only the two-step tool_search activation; explicit allowed_tools can strip tool_search itself — the exact corner the goal-continuation and parent-context pins already require the direct-call fallback for. Both briefs now carry the third tier, and their pins assert it.
  • The engine's parent-context hint re-typed the first two tiers of HANDLE_READ_ACTIVATION_HINT verbatim; the constant is pub(crate) now and the hint reuses it (rendered text byte-identical).
  • fetch_url flags every artifact it writes as retrievable evidence — binary PDF/media saves set evidence_available too, not just text overflows. The behavior is kept (otherwise the saved-artifact pointer is a dead end); the comment and assertion message claimed overflow-only and now describe the actual contract.
  • The bundled-skills phantom denylist is hoisted to module scope and anchored by a subset assertion against the canonical RETIRED_TOOL_NAMES/HIDDEN_COMPAT_TOOL_NAMES lists (new pin forkguard_phantom_denylist_covers_canonical_lists), so a newly registered hidden alias can no longer silently skip the sweep.
  • One fourteen-space line-continuation accident in a test assertion message.

Disclosed, deliberately not changed: the handle.rs invalid-input messages and rlm.rs output note handle_read/retrieval without an activation ladder — both self-heal on stock hosts because a direct call to a registered deferred tool hydrates and retries; apply_patch in the implementer intro is feature-gated wording with graceful failure; the v4-best-practices asset keeps its retired-name citations because the file is the digest source for safe retirement (install_system_skills actively retires it) and is unreachable by models; the "nonexistent list action" misattribution in a2e21fcf9's historical message stands as history (the in-tree comments and the parent register now state the accurate form — list is a real FileTool action; the defect was the hidden alias itself).

Fork-guard registration rides in Pinvou/pinvou-agent#490 (6e8310b6c): gitlink + CANDIDATE_HEAD → dc1f391d6, three new T3 fingerprints, zh/en register refresh (round-seven narrative, drift, guard count 67, corrected list-action attribution).

Signed-off-by: asto18089 asto18089@users.noreply.github.com

@JensenChen28 JensenChen28 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.

已审查当前 head 对目标分支的实际差异,未发现需要阻塞合入的问题;提交前重新确认 required checks 通过。核对了模型可见工具名称、延迟加载提示与结果依赖标记。本轮以静态审查和远端门禁为依据,未在本机运行完整 Rust workspace 或所有平台测试。

@asto18089
asto18089 merged commit 72e98fd into Pinvou:pinvou3-clean Sep 17, 2026
5 checks passed
asto18089 added a commit to Pinvou/pinvou-agent that referenced this pull request Sep 17, 2026
Model-facing text promised tools that were not in the model's actual
tool catalog, confusing the model (observed in a Work-card session):

- The base registry-first policy names registry_sync and
  start_registry_mcp_server; both are live foundation tools that were
  only missing from the Pinvou allowlist. Whitelist them (with
  first-turn visibility via ALWAYS_LOADED) instead of dropping the
  policy; the browser carve-out stays because the built-in browser is
  not in the registry.
- load_skill/file_search are deferred while the skills index and the
  work instructions name them directly; add them (plus the registry
  tools) to PINVOU3_ALWAYS_LOADED_TOOLS.
- mcp_pinvou3_present_artifact only exists while the builtin MCP
  server is connected: the artifact-card rule in the work instructions,
  the visual-design/gongwen/pptx/visualizer skills and the PPT scene
  payload are now conditional.
- The preview paragraph promised a 'retained compatibility control
  surface' Bash(action=..., background=true), but Bash is a
  model-invisible replay name in v0.9.12 and lowercase bash is
  foreground-only; the paragraph now directs background serving to
  terminal/run and states the honest fallback (present the artifact)
  when no background surface exists.
- Marketplace skills (government-writing, pptx, tencent-docs,
  visualizer) still taught retired write_file/exec_shell spellings on
  main; migrate them to canonical write/bash. The dingtalk NOTICE
  forward-guidance is updated so the next upstream sync does not
  replay the phantom File(action=...) syntax.
- The bundled mcp-discovery skill now gates its registry_sync command
  on tool availability (carried by the submodule commit below).

JS contract tests (canonical_tool_contract, browser_core_protocol)
are migrated from the deleted Bash compatibility surface to the new
contract, and the PPT scene payload uses the full
mcp_pinvou3_present_artifact catalog name.

CodeWhale submodule advances to c34c3a430 (Pinvou/CodeWhale#56,
pending merge): the skills-index Usage line names the tool_search
activation path for deferred load_skill, the subagent skills block
teaches tool_search discovery, and a new engine regression pins the
registry-first instruction to the registered ToolSpec names.
Registered in docs/fork-modifications(.en).md with six T3 fork-guard
fingerprints, a forkguard floor of 57, and refreshed drift counts.

The gitlink and both registers point at the #56 candidate. fork-guard.sh
registers it as CANDIDATE_HEAD following the #408 candidate-period
convention: the registered EXPECTED_HEAD stays at the published
pinvou3-clean head ae7e3fb36 and layer 0 accepts either; the candidate
entry is retired once #56 lands and the public branch advances.
verify-public-submodule.sh stays red by design until that closure
completes.

Signed-off-by: asto18089 <44870036+asto18089@users.noreply.github.com>
asto18089 added a commit to Pinvou/pinvou-agent that referenced this pull request Sep 17, 2026
The CodeWhale#56 candidate gains a seventh commit (4eb487cd3) closing
the same-class phantom-text leftovers a fresh adversarial sweep found:
the registry-first system instruction and the per-result
REGISTRY_FIRST_PROMPT now teach the tool_search activation path for
their deferred commands; the worker-record handle_read prose carries a
shared activation hint; the /agent and bare /goal briefs teach
activation; the goal-continuation prompt and the parent-context hint
keep a direct-call fallback; and web/fetch overflow metadata sets
evidence_available so retrieve_tool_result auto-activates.

- advance the gitlink and CANDIDATE_HEAD to 4eb487cd3
  (CANDIDATE_COMMITS 34 -> 35, seven candidate commits)
- register twelve new T3 fingerprints (18 -> 30 net-new; 31 added,
  1 retired) and the three new forkguard tests
- refresh both fork registers (guard floor 57, actual 66; drift and
  section-11 counts restated for the seventh candidate commit)

./scripts/fork-guard.sh --fast on this head: exit 0, all layers green
(gitlink accepted as the registered candidate, floor 57 / actual 66);
python3 scripts/architecture-guard.py: pass.

Submodule-side evidence on Pinvou/CodeWhale#56 (candidate 4eb487cd3):
cargo fmt --check clean; RUST_MIN_STACK=8388608 cargo test -p
codewhale-tui --lib 11768/0; clippy -p codewhale-tui --lib --tests
clean apart from the pre-existing base-restored test closure that
fork-ci does not lint.

Signed-off-by: asto <asto18089@126.com>
asto18089 added a commit to Pinvou/pinvou-agent that referenced this pull request Sep 17, 2026
Third review round on Pinvou/CodeWhale#56 added one commit (the eighth,
dc1f391d6): the /agent and bare-/goal briefs gain the direct-call
fallback tier, HANDLE_READ_ACTIVATION_HINT becomes pub(crate) and is
reused by the parent-context hint (rendered text unchanged), the
fetch_url evidence_available comment now describes the actual contract
(binary PDF/media saves set it too), the bundled-skills phantom
denylist gains a canonical-list subset anchor, and one test-message
whitespace accident is fixed.

Re-pin the gitlink and CANDIDATE_HEAD to dc1f391d6 (CANDIDATE_COMMITS
36), add three T3 fingerprints (both brief tiers plus the denylist
anchor), refresh fork-modifications zh/en (round-seven narrative,
candidate head, drift 147 files +10708/-1343, guard count 67, and the
corrected list-action attribution), and register the new
forkguard_phantom_denylist_covers_canonical_lists test.

Verified: ./scripts/fork-guard.sh --fast green (fingerprint layer
passes, 67 forkguard names); python3 scripts/architecture-guard.py
green.

Signed-off-by: asto18089 <asto18089@users.noreply.github.com>
asto18089 added a commit to Pinvou/pinvou-agent that referenced this pull request Sep 19, 2026
Model-facing text promised tools that were not in the model's actual
tool catalog, confusing the model (observed in a Work-card session):

- The base registry-first policy names registry_sync and
  start_registry_mcp_server; both are live foundation tools that were
  only missing from the Pinvou allowlist. Whitelist them (with
  first-turn visibility via ALWAYS_LOADED) instead of dropping the
  policy; the browser carve-out stays because the built-in browser is
  not in the registry.
- load_skill/file_search are deferred while the skills index and the
  work instructions name them directly; add them (plus the registry
  tools) to PINVOU3_ALWAYS_LOADED_TOOLS.
- mcp_pinvou3_present_artifact only exists while the builtin MCP
  server is connected: the artifact-card rule in the work instructions,
  the visual-design/gongwen/pptx/visualizer skills and the PPT scene
  payload are now conditional.
- The preview paragraph promised a 'retained compatibility control
  surface' Bash(action=..., background=true), but Bash is a
  model-invisible replay name in v0.9.12 and lowercase bash is
  foreground-only; the paragraph now directs background serving to
  terminal/run and states the honest fallback (present the artifact)
  when no background surface exists.
- Marketplace skills (government-writing, pptx, tencent-docs,
  visualizer) still taught retired write_file/exec_shell spellings on
  main; migrate them to canonical write/bash. The dingtalk NOTICE
  forward-guidance is updated so the next upstream sync does not
  replay the phantom File(action=...) syntax.
- The bundled mcp-discovery skill now gates its registry_sync command
  on tool availability (carried by the submodule commit below).

JS contract tests (canonical_tool_contract, browser_core_protocol)
are migrated from the deleted Bash compatibility surface to the new
contract, and the PPT scene payload uses the full
mcp_pinvou3_present_artifact catalog name.

CodeWhale submodule advances to c34c3a430 (Pinvou/CodeWhale#56,
pending merge): the skills-index Usage line names the tool_search
activation path for deferred load_skill, the subagent skills block
teaches tool_search discovery, and a new engine regression pins the
registry-first instruction to the registered ToolSpec names.
Registered in docs/fork-modifications(.en).md with six T3 fork-guard
fingerprints, a forkguard floor of 57, and refreshed drift counts.

The gitlink and both registers point at the #56 candidate. fork-guard.sh
registers it as CANDIDATE_HEAD following the #408 candidate-period
convention: the registered EXPECTED_HEAD stays at the published
pinvou3-clean head ae7e3fb36 and layer 0 accepts either; the candidate
entry is retired once #56 lands and the public branch advances.
verify-public-submodule.sh stays red by design until that closure
completes.

Signed-off-by: asto18089 <44870036+asto18089@users.noreply.github.com>
asto18089 added a commit to Pinvou/pinvou-agent that referenced this pull request Sep 19, 2026
The CodeWhale#56 candidate gains a seventh commit (4eb487cd3) closing
the same-class phantom-text leftovers a fresh adversarial sweep found:
the registry-first system instruction and the per-result
REGISTRY_FIRST_PROMPT now teach the tool_search activation path for
their deferred commands; the worker-record handle_read prose carries a
shared activation hint; the /agent and bare /goal briefs teach
activation; the goal-continuation prompt and the parent-context hint
keep a direct-call fallback; and web/fetch overflow metadata sets
evidence_available so retrieve_tool_result auto-activates.

- advance the gitlink and CANDIDATE_HEAD to 4eb487cd3
  (CANDIDATE_COMMITS 34 -> 35, seven candidate commits)
- register twelve new T3 fingerprints (18 -> 30 net-new; 31 added,
  1 retired) and the three new forkguard tests
- refresh both fork registers (guard floor 57, actual 66; drift and
  section-11 counts restated for the seventh candidate commit)

./scripts/fork-guard.sh --fast on this head: exit 0, all layers green
(gitlink accepted as the registered candidate, floor 57 / actual 66);
python3 scripts/architecture-guard.py: pass.

Submodule-side evidence on Pinvou/CodeWhale#56 (candidate 4eb487cd3):
cargo fmt --check clean; RUST_MIN_STACK=8388608 cargo test -p
codewhale-tui --lib 11768/0; clippy -p codewhale-tui --lib --tests
clean apart from the pre-existing base-restored test closure that
fork-ci does not lint.

Signed-off-by: asto <asto18089@126.com>
asto18089 added a commit to Pinvou/pinvou-agent that referenced this pull request Sep 19, 2026
Third review round on Pinvou/CodeWhale#56 added one commit (the eighth,
dc1f391d6): the /agent and bare-/goal briefs gain the direct-call
fallback tier, HANDLE_READ_ACTIVATION_HINT becomes pub(crate) and is
reused by the parent-context hint (rendered text unchanged), the
fetch_url evidence_available comment now describes the actual contract
(binary PDF/media saves set it too), the bundled-skills phantom
denylist gains a canonical-list subset anchor, and one test-message
whitespace accident is fixed.

Re-pin the gitlink and CANDIDATE_HEAD to dc1f391d6 (CANDIDATE_COMMITS
36), add three T3 fingerprints (both brief tiers plus the denylist
anchor), refresh fork-modifications zh/en (round-seven narrative,
candidate head, drift 147 files +10708/-1343, guard count 67, and the
corrected list-action attribution), and register the new
forkguard_phantom_denylist_covers_canonical_lists test.

Verified: ./scripts/fork-guard.sh --fast green (fingerprint layer
passes, 67 forkguard names); python3 scripts/architecture-guard.py
green.

Signed-off-by: asto18089 <asto18089@users.noreply.github.com>
asto18089 added a commit to Pinvou/pinvou-agent that referenced this pull request Sep 20, 2026
Model-facing text promised tools that were not in the model's actual
tool catalog, confusing the model (observed in a Work-card session):

- The base registry-first policy names registry_sync and
  start_registry_mcp_server; both are live foundation tools that were
  only missing from the Pinvou allowlist. Whitelist them (with
  first-turn visibility via ALWAYS_LOADED) instead of dropping the
  policy; the browser carve-out stays because the built-in browser is
  not in the registry.
- load_skill/file_search are deferred while the skills index and the
  work instructions name them directly; add them (plus the registry
  tools) to PINVOU3_ALWAYS_LOADED_TOOLS.
- mcp_pinvou3_present_artifact only exists while the builtin MCP
  server is connected: the artifact-card rule in the work instructions,
  the visual-design/gongwen/pptx/visualizer skills and the PPT scene
  payload are now conditional.
- The preview paragraph promised a 'retained compatibility control
  surface' Bash(action=..., background=true), but Bash is a
  model-invisible replay name in v0.9.12 and lowercase bash is
  foreground-only; the paragraph now directs background serving to
  terminal/run and states the honest fallback (present the artifact)
  when no background surface exists.
- Marketplace skills (government-writing, pptx, tencent-docs,
  visualizer) still taught retired write_file/exec_shell spellings on
  main; migrate them to canonical write/bash. The dingtalk NOTICE
  forward-guidance is updated so the next upstream sync does not
  replay the phantom File(action=...) syntax.
- The bundled mcp-discovery skill now gates its registry_sync command
  on tool availability (carried by the submodule commit below).

JS contract tests (canonical_tool_contract, browser_core_protocol)
are migrated from the deleted Bash compatibility surface to the new
contract, and the PPT scene payload uses the full
mcp_pinvou3_present_artifact catalog name.

CodeWhale submodule advances to c34c3a430 (Pinvou/CodeWhale#56,
pending merge): the skills-index Usage line names the tool_search
activation path for deferred load_skill, the subagent skills block
teaches tool_search discovery, and a new engine regression pins the
registry-first instruction to the registered ToolSpec names.
Registered in docs/fork-modifications(.en).md with six T3 fork-guard
fingerprints, a forkguard floor of 57, and refreshed drift counts.

The gitlink and both registers point at the #56 candidate. fork-guard.sh
registers it as CANDIDATE_HEAD following the #408 candidate-period
convention: the registered EXPECTED_HEAD stays at the published
pinvou3-clean head ae7e3fb36 and layer 0 accepts either; the candidate
entry is retired once #56 lands and the public branch advances.
verify-public-submodule.sh stays red by design until that closure
completes.

Signed-off-by: asto18089 <44870036+asto18089@users.noreply.github.com>
asto18089 added a commit to Pinvou/pinvou-agent that referenced this pull request Sep 20, 2026
The CodeWhale#56 candidate gains a seventh commit (4eb487cd3) closing
the same-class phantom-text leftovers a fresh adversarial sweep found:
the registry-first system instruction and the per-result
REGISTRY_FIRST_PROMPT now teach the tool_search activation path for
their deferred commands; the worker-record handle_read prose carries a
shared activation hint; the /agent and bare /goal briefs teach
activation; the goal-continuation prompt and the parent-context hint
keep a direct-call fallback; and web/fetch overflow metadata sets
evidence_available so retrieve_tool_result auto-activates.

- advance the gitlink and CANDIDATE_HEAD to 4eb487cd3
  (CANDIDATE_COMMITS 34 -> 35, seven candidate commits)
- register twelve new T3 fingerprints (18 -> 30 net-new; 31 added,
  1 retired) and the three new forkguard tests
- refresh both fork registers (guard floor 57, actual 66; drift and
  section-11 counts restated for the seventh candidate commit)

./scripts/fork-guard.sh --fast on this head: exit 0, all layers green
(gitlink accepted as the registered candidate, floor 57 / actual 66);
python3 scripts/architecture-guard.py: pass.

Submodule-side evidence on Pinvou/CodeWhale#56 (candidate 4eb487cd3):
cargo fmt --check clean; RUST_MIN_STACK=8388608 cargo test -p
codewhale-tui --lib 11768/0; clippy -p codewhale-tui --lib --tests
clean apart from the pre-existing base-restored test closure that
fork-ci does not lint.

Signed-off-by: asto <asto18089@126.com>
asto18089 added a commit to Pinvou/pinvou-agent that referenced this pull request Sep 20, 2026
Third review round on Pinvou/CodeWhale#56 added one commit (the eighth,
dc1f391d6): the /agent and bare-/goal briefs gain the direct-call
fallback tier, HANDLE_READ_ACTIVATION_HINT becomes pub(crate) and is
reused by the parent-context hint (rendered text unchanged), the
fetch_url evidence_available comment now describes the actual contract
(binary PDF/media saves set it too), the bundled-skills phantom
denylist gains a canonical-list subset anchor, and one test-message
whitespace accident is fixed.

Re-pin the gitlink and CANDIDATE_HEAD to dc1f391d6 (CANDIDATE_COMMITS
36), add three T3 fingerprints (both brief tiers plus the denylist
anchor), refresh fork-modifications zh/en (round-seven narrative,
candidate head, drift 147 files +10708/-1343, guard count 67, and the
corrected list-action attribution), and register the new
forkguard_phantom_denylist_covers_canonical_lists test.

Verified: ./scripts/fork-guard.sh --fast green (fingerprint layer
passes, 67 forkguard names); python3 scripts/architecture-guard.py
green.

Signed-off-by: asto18089 <asto18089@users.noreply.github.com>
asto18089 added a commit to Pinvou/pinvou-agent that referenced this pull request Sep 20, 2026
Model-facing text promised tools that were not in the model's actual
tool catalog, confusing the model (observed in a Work-card session):

- The base registry-first policy names registry_sync and
  start_registry_mcp_server; both are live foundation tools that were
  only missing from the Pinvou allowlist. Whitelist them (with
  first-turn visibility via ALWAYS_LOADED) instead of dropping the
  policy; the browser carve-out stays because the built-in browser is
  not in the registry.
- load_skill/file_search are deferred while the skills index and the
  work instructions name them directly; add them (plus the registry
  tools) to PINVOU3_ALWAYS_LOADED_TOOLS.
- mcp_pinvou3_present_artifact only exists while the builtin MCP
  server is connected: the artifact-card rule in the work instructions,
  the visual-design/gongwen/pptx/visualizer skills and the PPT scene
  payload are now conditional.
- The preview paragraph promised a 'retained compatibility control
  surface' Bash(action=..., background=true), but Bash is a
  model-invisible replay name in v0.9.12 and lowercase bash is
  foreground-only; the paragraph now directs background serving to
  terminal/run and states the honest fallback (present the artifact)
  when no background surface exists.
- Marketplace skills (government-writing, pptx, tencent-docs,
  visualizer) still taught retired write_file/exec_shell spellings on
  main; migrate them to canonical write/bash. The dingtalk NOTICE
  forward-guidance is updated so the next upstream sync does not
  replay the phantom File(action=...) syntax.
- The bundled mcp-discovery skill now gates its registry_sync command
  on tool availability (carried by the submodule commit below).

JS contract tests (canonical_tool_contract, browser_core_protocol)
are migrated from the deleted Bash compatibility surface to the new
contract, and the PPT scene payload uses the full
mcp_pinvou3_present_artifact catalog name.

CodeWhale submodule advances to c34c3a430 (Pinvou/CodeWhale#56,
pending merge): the skills-index Usage line names the tool_search
activation path for deferred load_skill, the subagent skills block
teaches tool_search discovery, and a new engine regression pins the
registry-first instruction to the registered ToolSpec names.
Registered in docs/fork-modifications(.en).md with six T3 fork-guard
fingerprints, a forkguard floor of 57, and refreshed drift counts.

The gitlink and both registers point at the #56 candidate. fork-guard.sh
registers it as CANDIDATE_HEAD following the #408 candidate-period
convention: the registered EXPECTED_HEAD stays at the published
pinvou3-clean head ae7e3fb36 and layer 0 accepts either; the candidate
entry is retired once #56 lands and the public branch advances.
verify-public-submodule.sh stays red by design until that closure
completes.

Signed-off-by: asto18089 <44870036+asto18089@users.noreply.github.com>
asto18089 added a commit to Pinvou/pinvou-agent that referenced this pull request Sep 20, 2026
The CodeWhale#56 candidate gains a seventh commit (4eb487cd3) closing
the same-class phantom-text leftovers a fresh adversarial sweep found:
the registry-first system instruction and the per-result
REGISTRY_FIRST_PROMPT now teach the tool_search activation path for
their deferred commands; the worker-record handle_read prose carries a
shared activation hint; the /agent and bare /goal briefs teach
activation; the goal-continuation prompt and the parent-context hint
keep a direct-call fallback; and web/fetch overflow metadata sets
evidence_available so retrieve_tool_result auto-activates.

- advance the gitlink and CANDIDATE_HEAD to 4eb487cd3
  (CANDIDATE_COMMITS 34 -> 35, seven candidate commits)
- register twelve new T3 fingerprints (18 -> 30 net-new; 31 added,
  1 retired) and the three new forkguard tests
- refresh both fork registers (guard floor 57, actual 66; drift and
  section-11 counts restated for the seventh candidate commit)

./scripts/fork-guard.sh --fast on this head: exit 0, all layers green
(gitlink accepted as the registered candidate, floor 57 / actual 66);
python3 scripts/architecture-guard.py: pass.

Submodule-side evidence on Pinvou/CodeWhale#56 (candidate 4eb487cd3):
cargo fmt --check clean; RUST_MIN_STACK=8388608 cargo test -p
codewhale-tui --lib 11768/0; clippy -p codewhale-tui --lib --tests
clean apart from the pre-existing base-restored test closure that
fork-ci does not lint.

Signed-off-by: asto <asto18089@126.com>
asto18089 added a commit to Pinvou/pinvou-agent that referenced this pull request Sep 20, 2026
Third review round on Pinvou/CodeWhale#56 added one commit (the eighth,
dc1f391d6): the /agent and bare-/goal briefs gain the direct-call
fallback tier, HANDLE_READ_ACTIVATION_HINT becomes pub(crate) and is
reused by the parent-context hint (rendered text unchanged), the
fetch_url evidence_available comment now describes the actual contract
(binary PDF/media saves set it too), the bundled-skills phantom
denylist gains a canonical-list subset anchor, and one test-message
whitespace accident is fixed.

Re-pin the gitlink and CANDIDATE_HEAD to dc1f391d6 (CANDIDATE_COMMITS
36), add three T3 fingerprints (both brief tiers plus the denylist
anchor), refresh fork-modifications zh/en (round-seven narrative,
candidate head, drift 147 files +10708/-1343, guard count 67, and the
corrected list-action attribution), and register the new
forkguard_phantom_denylist_covers_canonical_lists test.

Verified: ./scripts/fork-guard.sh --fast green (fingerprint layer
passes, 67 forkguard names); python3 scripts/architecture-guard.py
green.

Signed-off-by: asto18089 <asto18089@users.noreply.github.com>
asto18089 added a commit to Pinvou/pinvou-agent that referenced this pull request Sep 20, 2026
Model-facing text promised tools that were not in the model's actual
tool catalog, confusing the model (observed in a Work-card session):

- The base registry-first policy names registry_sync and
  start_registry_mcp_server; both are live foundation tools that were
  only missing from the Pinvou allowlist. Whitelist them (with
  first-turn visibility via ALWAYS_LOADED) instead of dropping the
  policy; the browser carve-out stays because the built-in browser is
  not in the registry.
- load_skill/file_search are deferred while the skills index and the
  work instructions name them directly; add them (plus the registry
  tools) to PINVOU3_ALWAYS_LOADED_TOOLS.
- mcp_pinvou3_present_artifact only exists while the builtin MCP
  server is connected: the artifact-card rule in the work instructions,
  the visual-design/gongwen/pptx/visualizer skills and the PPT scene
  payload are now conditional.
- The preview paragraph promised a 'retained compatibility control
  surface' Bash(action=..., background=true), but Bash is a
  model-invisible replay name in v0.9.12 and lowercase bash is
  foreground-only; the paragraph now directs background serving to
  terminal/run and states the honest fallback (present the artifact)
  when no background surface exists.
- Marketplace skills (government-writing, pptx, tencent-docs,
  visualizer) still taught retired write_file/exec_shell spellings on
  main; migrate them to canonical write/bash. The dingtalk NOTICE
  forward-guidance is updated so the next upstream sync does not
  replay the phantom File(action=...) syntax.
- The bundled mcp-discovery skill now gates its registry_sync command
  on tool availability (carried by the submodule commit below).

JS contract tests (canonical_tool_contract, browser_core_protocol)
are migrated from the deleted Bash compatibility surface to the new
contract, and the PPT scene payload uses the full
mcp_pinvou3_present_artifact catalog name.

CodeWhale submodule advances to c34c3a430 (Pinvou/CodeWhale#56,
pending merge): the skills-index Usage line names the tool_search
activation path for deferred load_skill, the subagent skills block
teaches tool_search discovery, and a new engine regression pins the
registry-first instruction to the registered ToolSpec names.
Registered in docs/fork-modifications(.en).md with six T3 fork-guard
fingerprints, a forkguard floor of 57, and refreshed drift counts.

The gitlink and both registers point at the #56 candidate. fork-guard.sh
registers it as CANDIDATE_HEAD following the #408 candidate-period
convention: the registered EXPECTED_HEAD stays at the published
pinvou3-clean head ae7e3fb36 and layer 0 accepts either; the candidate
entry is retired once #56 lands and the public branch advances.
verify-public-submodule.sh stays red by design until that closure
completes.

Signed-off-by: asto18089 <44870036+asto18089@users.noreply.github.com>
asto18089 added a commit to Pinvou/pinvou-agent that referenced this pull request Sep 20, 2026
The CodeWhale#56 candidate gains a seventh commit (4eb487cd3) closing
the same-class phantom-text leftovers a fresh adversarial sweep found:
the registry-first system instruction and the per-result
REGISTRY_FIRST_PROMPT now teach the tool_search activation path for
their deferred commands; the worker-record handle_read prose carries a
shared activation hint; the /agent and bare /goal briefs teach
activation; the goal-continuation prompt and the parent-context hint
keep a direct-call fallback; and web/fetch overflow metadata sets
evidence_available so retrieve_tool_result auto-activates.

- advance the gitlink and CANDIDATE_HEAD to 4eb487cd3
  (CANDIDATE_COMMITS 34 -> 35, seven candidate commits)
- register twelve new T3 fingerprints (18 -> 30 net-new; 31 added,
  1 retired) and the three new forkguard tests
- refresh both fork registers (guard floor 57, actual 66; drift and
  section-11 counts restated for the seventh candidate commit)

./scripts/fork-guard.sh --fast on this head: exit 0, all layers green
(gitlink accepted as the registered candidate, floor 57 / actual 66);
python3 scripts/architecture-guard.py: pass.

Submodule-side evidence on Pinvou/CodeWhale#56 (candidate 4eb487cd3):
cargo fmt --check clean; RUST_MIN_STACK=8388608 cargo test -p
codewhale-tui --lib 11768/0; clippy -p codewhale-tui --lib --tests
clean apart from the pre-existing base-restored test closure that
fork-ci does not lint.

Signed-off-by: asto <asto18089@126.com>
asto18089 added a commit to Pinvou/pinvou-agent that referenced this pull request Sep 20, 2026
Third review round on Pinvou/CodeWhale#56 added one commit (the eighth,
dc1f391d6): the /agent and bare-/goal briefs gain the direct-call
fallback tier, HANDLE_READ_ACTIVATION_HINT becomes pub(crate) and is
reused by the parent-context hint (rendered text unchanged), the
fetch_url evidence_available comment now describes the actual contract
(binary PDF/media saves set it too), the bundled-skills phantom
denylist gains a canonical-list subset anchor, and one test-message
whitespace accident is fixed.

Re-pin the gitlink and CANDIDATE_HEAD to dc1f391d6 (CANDIDATE_COMMITS
36), add three T3 fingerprints (both brief tiers plus the denylist
anchor), refresh fork-modifications zh/en (round-seven narrative,
candidate head, drift 147 files +10708/-1343, guard count 67, and the
corrected list-action attribution), and register the new
forkguard_phantom_denylist_covers_canonical_lists test.

Verified: ./scripts/fork-guard.sh --fast green (fingerprint layer
passes, 67 forkguard names); python3 scripts/architecture-guard.py
green.

Signed-off-by: asto18089 <asto18089@users.noreply.github.com>
asto18089 added a commit to Pinvou/pinvou-agent that referenced this pull request Sep 20, 2026
Model-facing text promised tools that were not in the model's actual
tool catalog, confusing the model (observed in a Work-card session):

- The base registry-first policy names registry_sync and
  start_registry_mcp_server; both are live foundation tools that were
  only missing from the Pinvou allowlist. Whitelist them (with
  first-turn visibility via ALWAYS_LOADED) instead of dropping the
  policy; the browser carve-out stays because the built-in browser is
  not in the registry.
- load_skill/file_search are deferred while the skills index and the
  work instructions name them directly; add them (plus the registry
  tools) to PINVOU3_ALWAYS_LOADED_TOOLS.
- mcp_pinvou3_present_artifact only exists while the builtin MCP
  server is connected: the artifact-card rule in the work instructions,
  the visual-design/gongwen/pptx/visualizer skills and the PPT scene
  payload are now conditional.
- The preview paragraph promised a 'retained compatibility control
  surface' Bash(action=..., background=true), but Bash is a
  model-invisible replay name in v0.9.12 and lowercase bash is
  foreground-only; the paragraph now directs background serving to
  terminal/run and states the honest fallback (present the artifact)
  when no background surface exists.
- Marketplace skills (government-writing, pptx, tencent-docs,
  visualizer) still taught retired write_file/exec_shell spellings on
  main; migrate them to canonical write/bash. The dingtalk NOTICE
  forward-guidance is updated so the next upstream sync does not
  replay the phantom File(action=...) syntax.
- The bundled mcp-discovery skill now gates its registry_sync command
  on tool availability (carried by the submodule commit below).

JS contract tests (canonical_tool_contract, browser_core_protocol)
are migrated from the deleted Bash compatibility surface to the new
contract, and the PPT scene payload uses the full
mcp_pinvou3_present_artifact catalog name.

CodeWhale submodule advances to c34c3a430 (Pinvou/CodeWhale#56,
pending merge): the skills-index Usage line names the tool_search
activation path for deferred load_skill, the subagent skills block
teaches tool_search discovery, and a new engine regression pins the
registry-first instruction to the registered ToolSpec names.
Registered in docs/fork-modifications(.en).md with six T3 fork-guard
fingerprints, a forkguard floor of 57, and refreshed drift counts.

The gitlink and both registers point at the #56 candidate. fork-guard.sh
registers it as CANDIDATE_HEAD following the #408 candidate-period
convention: the registered EXPECTED_HEAD stays at the published
pinvou3-clean head ae7e3fb36 and layer 0 accepts either; the candidate
entry is retired once #56 lands and the public branch advances.
verify-public-submodule.sh stays red by design until that closure
completes.

Signed-off-by: asto18089 <44870036+asto18089@users.noreply.github.com>
asto18089 added a commit to Pinvou/pinvou-agent that referenced this pull request Sep 20, 2026
The CodeWhale#56 candidate gains a seventh commit (4eb487cd3) closing
the same-class phantom-text leftovers a fresh adversarial sweep found:
the registry-first system instruction and the per-result
REGISTRY_FIRST_PROMPT now teach the tool_search activation path for
their deferred commands; the worker-record handle_read prose carries a
shared activation hint; the /agent and bare /goal briefs teach
activation; the goal-continuation prompt and the parent-context hint
keep a direct-call fallback; and web/fetch overflow metadata sets
evidence_available so retrieve_tool_result auto-activates.

- advance the gitlink and CANDIDATE_HEAD to 4eb487cd3
  (CANDIDATE_COMMITS 34 -> 35, seven candidate commits)
- register twelve new T3 fingerprints (18 -> 30 net-new; 31 added,
  1 retired) and the three new forkguard tests
- refresh both fork registers (guard floor 57, actual 66; drift and
  section-11 counts restated for the seventh candidate commit)

./scripts/fork-guard.sh --fast on this head: exit 0, all layers green
(gitlink accepted as the registered candidate, floor 57 / actual 66);
python3 scripts/architecture-guard.py: pass.

Submodule-side evidence on Pinvou/CodeWhale#56 (candidate 4eb487cd3):
cargo fmt --check clean; RUST_MIN_STACK=8388608 cargo test -p
codewhale-tui --lib 11768/0; clippy -p codewhale-tui --lib --tests
clean apart from the pre-existing base-restored test closure that
fork-ci does not lint.

Signed-off-by: asto <asto18089@126.com>
asto18089 added a commit to Pinvou/pinvou-agent that referenced this pull request Sep 20, 2026
Third review round on Pinvou/CodeWhale#56 added one commit (the eighth,
dc1f391d6): the /agent and bare-/goal briefs gain the direct-call
fallback tier, HANDLE_READ_ACTIVATION_HINT becomes pub(crate) and is
reused by the parent-context hint (rendered text unchanged), the
fetch_url evidence_available comment now describes the actual contract
(binary PDF/media saves set it too), the bundled-skills phantom
denylist gains a canonical-list subset anchor, and one test-message
whitespace accident is fixed.

Re-pin the gitlink and CANDIDATE_HEAD to dc1f391d6 (CANDIDATE_COMMITS
36), add three T3 fingerprints (both brief tiers plus the denylist
anchor), refresh fork-modifications zh/en (round-seven narrative,
candidate head, drift 147 files +10708/-1343, guard count 67, and the
corrected list-action attribution), and register the new
forkguard_phantom_denylist_covers_canonical_lists test.

Verified: ./scripts/fork-guard.sh --fast green (fingerprint layer
passes, 67 forkguard names); python3 scripts/architecture-guard.py
green.

Signed-off-by: asto18089 <asto18089@users.noreply.github.com>
qiuYliangM pushed a commit to qiuYliangM/pinvou-agent that referenced this pull request Sep 20, 2026
* fix: stop naming absent tools in model prompts

Model-facing text promised tools that were not in the model's actual
tool catalog, confusing the model (observed in a Work-card session):

- The base registry-first policy names registry_sync and
  start_registry_mcp_server; both are live foundation tools that were
  only missing from the Pinvou allowlist. Whitelist them (with
  first-turn visibility via ALWAYS_LOADED) instead of dropping the
  policy; the browser carve-out stays because the built-in browser is
  not in the registry.
- load_skill/file_search are deferred while the skills index and the
  work instructions name them directly; add them (plus the registry
  tools) to PINVOU3_ALWAYS_LOADED_TOOLS.
- mcp_pinvou3_present_artifact only exists while the builtin MCP
  server is connected: the artifact-card rule in the work instructions,
  the visual-design/gongwen/pptx/visualizer skills and the PPT scene
  payload are now conditional.
- The preview paragraph promised a 'retained compatibility control
  surface' Bash(action=..., background=true), but Bash is a
  model-invisible replay name in v0.9.12 and lowercase bash is
  foreground-only; the paragraph now directs background serving to
  terminal/run and states the honest fallback (present the artifact)
  when no background surface exists.
- Marketplace skills (government-writing, pptx, tencent-docs,
  visualizer) still taught retired write_file/exec_shell spellings on
  main; migrate them to canonical write/bash. The dingtalk NOTICE
  forward-guidance is updated so the next upstream sync does not
  replay the phantom File(action=...) syntax.
- The bundled mcp-discovery skill now gates its registry_sync command
  on tool availability (carried by the submodule commit below).

JS contract tests (canonical_tool_contract, browser_core_protocol)
are migrated from the deleted Bash compatibility surface to the new
contract, and the PPT scene payload uses the full
mcp_pinvou3_present_artifact catalog name.

CodeWhale submodule advances to c34c3a430 (Pinvou/CodeWhale#56,
pending merge): the skills-index Usage line names the tool_search
activation path for deferred load_skill, the subagent skills block
teaches tool_search discovery, and a new engine regression pins the
registry-first instruction to the registered ToolSpec names.
Registered in docs/fork-modifications(.en).md with six T3 fork-guard
fingerprints, a forkguard floor of 57, and refreshed drift counts.

The gitlink and both registers point at the Pinvou#56 candidate. fork-guard.sh
registers it as CANDIDATE_HEAD following the Pinvou#408 candidate-period
convention: the registered EXPECTED_HEAD stays at the published
pinvou3-clean head ae7e3fb36 and layer 0 accepts either; the candidate
entry is retired once Pinvou#56 lands and the public branch advances.
verify-public-submodule.sh stays red by design until that closure
completes.

Signed-off-by: asto18089 <44870036+asto18089@users.noreply.github.com>

* chore(guard): re-pin the Pinvou#56 candidate and its completion sweep

PR Pinvou#56 gained a second commit (f81528358) that finishes the
phantom-tool sweep after adversarial review: mcp-discovery step 1
activates registry_sync via tool_search before declaring unavailability
and teaches a query-bearing call; plugin-snapshot rows and the omitted
tail carry the tool_search fallback; the subagent header covers
allowlist children that keep tool_search but filter load_skill; the
bundled pdf/help skills cite read instead of the hidden File alias;
best-of-n gates create_goal on availability.

Re-pin CANDIDATE_HEAD/CANDIDATE_COMMITS (30) and the parent gitlink to
the candidate head, add seven T3 fingerprints (omitted-tail and
mcp-discovery test registrations, the tool_search-absent honesty
clause, the bundled-skills retired-name sweep, the best-of-n gating
pin, the pdf read citation, and the best-of-n gate text; backticks
escaped so the fingerprint layer can never silently command-substitute
a pattern), and align both fork-modification docs (13 new T3
fingerprints, 61 behavior names, SHA references).

Signed-off-by: asto18089 <44870036+asto18089@users.noreply.github.com>

* chore(guard): re-pin the Pinvou#56 sweep-closure candidate 18f7c7b15

PR Pinvou#56 gained two commits: a2e21fcf9 closes the two-stage activation
gaps its own second commit left (mcp-discovery step 3, best-of-n
create_goal), flips the parent-context hint to first-turn-active tool
names, corrects the bundled-skills denylist (list_dir is live), and
pins MAX_REGISTRY_MATCHES to the quoted wording; 18f7c7b15 strips the
baseline gate repairs into CodeWhale#60 per the changelog policy, so
the candidate's net diff is topic-only. CANDIDATE_HEAD advances to
18f7c7b15 (32 commits), the gitlink follows, and four T3 fingerprints
pin the new text (pool-init disclosure, step-3 two-stage gate,
best-of-n tool_search path, active-tool context hint). Docs refresh
the guard row to 62 behavior tests and the drift rows to the measured
145 files, +10301/-1235 (net +9,066), which also clears the stale
c34c3a430 publication cell and the 8897/8822 vintage mismatch.

Signed-off-by: asto18089 <asto18089@126.com>

* chore(guard): re-pin the Pinvou#56 dedupe candidate 9f46ac5f0

The phantom-tool PR gained a review round that dedupes the deferred-
activation teaching (Usage line and mcp-discovery step 1 are the single
teaching points; plugin rows, the omitted tail, and step 3 reference
them), precise-ifies the mcp-discovery pool preamble, hardens the
bundled-skills phantom list, and pins the remaining eight-wording sides.
Re-pin CANDIDATE_HEAD/COMMITS (33), refresh the five fingerprints whose
text changed, retire the omitted-tail fingerprint (its test merged into
the Usage-line guard), and correct the stopship leftover disclosure:
the aliased File call is rejected outright at the child catalog gate,
not dispatchable-by-alias.

Signed-off-by: asto <asto18089@126.com>

* chore(guard): advance gitlink to Pinvou#56 candidate 9f46ac5f

The dedupe re-pin (d1ebcb5) advanced CANDIDATE_HEAD and five T3
fingerprints to the dedupe candidate 9f46ac5f0 but left the CodeWhale
gitlink at the candidate's parent 18f7c7b15, so a fresh checkout
(submodule HEAD == gitlink) failed fork-guard layer 0 (head mismatch,
commit count 32 vs the registered 33, and the five refreshed
fingerprints whose wording only exists on 9f46ac5f0). Advance the
gitlink to 9f46ac5f0, which is exactly the current head of
Pinvou/CodeWhale PR Pinvou#56.

Sync both registers with the measured state at 9f46ac5f0: the English
T3 addendum and current-state table catch up to the five-commit
candidate (sixteen net T3 fingerprints, the corrected Pinvou#61 leftover
disclosure that the aliased File call is rejected outright at the child
catalog gate), and the section-0 tables stop registering the unmerged
squash merges, the parent gitlink rides the registered candidate (18
commits ahead of the r1 tag), drift is 145 files +10320/-1239 (net
+9,081), and the forkguard behavior-name count is 61 (55 default plus
6 benchmark-eval-controls). fork-guard's candidate comment and layer-0
banner now say five candidate commits and '13 registered + 1
candidate' respectively.

Verified on this tree: ./scripts/fork-guard.sh --fast exits 0 with the
submodule checked out at the new gitlink; architecture-guard passes;
node canonical_tool_contract (2) and browser_core_protocol (11) pass.

Signed-off-by: Pinvou Agent Review <review@pinvou.local>

* fix(review): honest NOTICE history, scoped comment

Review follow-ups for the phantom-tool sweep:

- NOTICE-dingtalk.md attributed the read_file -> read migration to PR
  Pinvou#231, but Pinvou#231 recorded it as File(action="read") (and the File.read
  shorthand); the canonical 'read' spelling arrived with the v0.9.12
  upgrade in PR Pinvou#453. The lark/wecom/tmeet NOTICEs keep the historical
  fact and add a reconciliation note instead of rewriting history, so
  align dingtalk with that pattern (attendance.md 6 occurrences,
  minutes.md 7 lines per the round-10 count correction).
- tool_policy.rs: the always-loaded admission comment claimed
  'everything else is deferred', but the base tool_search is never
  deferred (it stays active so the model can re-activate deferred
  tools); scope the claim to native tools.

Signed-off-by: Pinvou Agent Review <review@pinvou.local>

* fix: close residual phantom-tool gaps in skills

The same sweep this PR applies elsewhere missed one deterministic
instance: the ima connector skill orders a direct call to the native
`ima_openapi` tool, which matches no allowlist rule (the `mcp_*`
prefix only covers MCP-discovered names), so the per-turn catalog
strip made the skill teach a permanently absent tool. Admit the exact
name and teach the deferred-activation fallback in the skill text.

Also aligns the residual deferred-tool and retired-name mentions the
fresh sweep found:
- pptx/government-writing skills and the PPT scene route: connector
  tools stay deferred even when installed, so name the `tool_search`
  activation step before the unavailability branch.
- government-writing template: same teaching for the deferred
  `kb_search`.
- work instructions: `terminal/run` is deferred too, so the loopback
  preview's primary path was unreachable on a literal reading; teach
  the activation step.
- persona-card prompt: the prohibition cited the hidden replay names
  `File`/`Bash`; cite the canonical `read`/`write`/`bash`.
- contract test: widen the retired-name scan from bundle/ to all of
  resources/common so the marketplace skills stay guarded, and replace
  the tautological ALWAYS_LOADED array assertion with a real matcher
  check (an always-loaded name the allowlist strips is dead config).

Signed-off-by: Pinvou Agent Review <review@pinvou.local>

* chore(guard): re-pin the Pinvou#56 candidate be2b2fe92

CodeWhale#56 advanced again after the last re-pin: its sixth commit
rebuilds the omitted-tail guard under a new name, teaches the
direct-call hydration fallback in the Usage line and the subagent
skills header, and names the tool_search activation path in the
goal-continuation prompt and the parent-context hint.

Advance the gitlink and the candidate registration (CANDIDATE_HEAD
9f46ac5f0 -> be2b2fe92, CANDIDATE_COMMITS 33 -> 34), reword the two
Usage-line T3 anchors the rewording retired, register the two new
forkguard tests (18 net-new T3 fingerprints), and refresh both fork
registers: guard count 63, drift 145 files +10446/-1309 (net +9,137,
also reconciling the section-11 soft-limit paragraph that still said
9,066).

Signed-off-by: Pinvou Agent Review <review@pinvou.local>

* chore(guard): re-pin the Pinvou#56 candidate 4eb487cd3

The CodeWhale#56 candidate gains a seventh commit (4eb487cd3) closing
the same-class phantom-text leftovers a fresh adversarial sweep found:
the registry-first system instruction and the per-result
REGISTRY_FIRST_PROMPT now teach the tool_search activation path for
their deferred commands; the worker-record handle_read prose carries a
shared activation hint; the /agent and bare /goal briefs teach
activation; the goal-continuation prompt and the parent-context hint
keep a direct-call fallback; and web/fetch overflow metadata sets
evidence_available so retrieve_tool_result auto-activates.

- advance the gitlink and CANDIDATE_HEAD to 4eb487cd3
  (CANDIDATE_COMMITS 34 -> 35, seven candidate commits)
- register twelve new T3 fingerprints (18 -> 30 net-new; 31 added,
  1 retired) and the three new forkguard tests
- refresh both fork registers (guard floor 57, actual 66; drift and
  section-11 counts restated for the seventh candidate commit)

./scripts/fork-guard.sh --fast on this head: exit 0, all layers green
(gitlink accepted as the registered candidate, floor 57 / actual 66);
python3 scripts/architecture-guard.py: pass.

Submodule-side evidence on Pinvou/CodeWhale#56 (candidate 4eb487cd3):
cargo fmt --check clean; RUST_MIN_STACK=8388608 cargo test -p
codewhale-tui --lib 11768/0; clippy -p codewhale-tui --lib --tests
clean apart from the pre-existing base-restored test closure that
fork-ci does not lint.

Signed-off-by: asto <asto18089@126.com>

* chore(guard): re-pin the Pinvou#56 candidate dc1f391d6

Third review round on Pinvou/CodeWhale#56 added one commit (the eighth,
dc1f391d6): the /agent and bare-/goal briefs gain the direct-call
fallback tier, HANDLE_READ_ACTIVATION_HINT becomes pub(crate) and is
reused by the parent-context hint (rendered text unchanged), the
fetch_url evidence_available comment now describes the actual contract
(binary PDF/media saves set it too), the bundled-skills phantom
denylist gains a canonical-list subset anchor, and one test-message
whitespace accident is fixed.

Re-pin the gitlink and CANDIDATE_HEAD to dc1f391d6 (CANDIDATE_COMMITS
36), add three T3 fingerprints (both brief tiers plus the denylist
anchor), refresh fork-modifications zh/en (round-seven narrative,
candidate head, drift 147 files +10708/-1343, guard count 67, and the
corrected list-action attribution), and register the new
forkguard_phantom_denylist_covers_canonical_lists test.

Verified: ./scripts/fork-guard.sh --fast green (fingerprint layer
passes, 67 forkguard names); python3 scripts/architecture-guard.py
green.

Signed-off-by: asto18089 <asto18089@users.noreply.github.com>

* chore(guard): re-point the gitlink to the merged head

CodeWhale#56 landed upstream as squash 72e98fd89 and the rest of the
2026-09-17 batch (Pinvou#58/Pinvou#59/Pinvou#60/Pinvou#61) carried pinvou3-clean to 92427bd8d,
so the candidate-period registration is retired: EXPECTED_HEAD advances
to 92427bd8d (EXPECTED_COMMITS 28 -> 33), the CANDIDATE_HEAD/
CANDIDATE_COMMITS machinery is removed, and the T3 addendum plus the
state rows now describe landed state — gitlink = published head, 18
squash merges above the r1 tag, drift 167 files +11480/-1470, 72
forkguard behavior names. verify-public-submodule.sh is green again;
the registered candidate-period red ends with this commit.

Note: until Pinvou#408 lands, the rust-lint/cli-test lanes stay red on this
branch with E0027/E0063 on Op::SendMessage/Op::EditLastTurn — the Pinvou#58
submission_id echo needs the app-side adaptation that only Pinvou#408
carries. The re-pin to the published head is required by the fork
rules, so the compile breakage is disclosed here rather than papered
over with a duplicate partial adaptation.

Signed-off-by: asto18089 <asto18089@126.com>

* fix(review): teach kb tool activation, refresh register rows

- the KB agentic guide injected before every user message ordered a
  direct `kb_search` call, but kb_search/kb_open_source are deferred by
  default and absent from the first-turn tool list — the exact
  absent-tool shape this PR removes everywhere else; teach the
  tool_search activation step (same pattern as the marketplace skill
  migrations) and pin it in the guide test
- the section-0 heading still said 13 registered commits plus one
  pending candidate after the closure re-pin (zh and en)
- the Guard row said registered floor 54 while this branch's
  fork-guard.sh enforces 57, and repeated the wrong three-test
  benchmark-eval-controls count (actual: six); the en row also lost the
  consumer-PR dependency list
- the soft-limit paragraphs still cited the fifth-candidate net +9,137
  (candidates gone, landed drift is +10,010)
- the en Status bullet kept a stale "whose gitlink follows the
  registered candidate" clause (zh dropped it) with a lowercase
  sentence continuation

Signed-off-by: Pinvou Review <review@pinvou.local>

* fix(marketplace): gate native ima tool by package scope

The round-5 audit flagged a permission-boundary gap in 7a6e9af:
admitting ima_openapi to PINVOU3_ALLOWED_TOOLS made the tool
searchable and callable in every session, because the disabled
mapping only covers MCP manifests. Disabling or logging out of the
ima package hid the skill text but left the native tool admitted,
with locally retained credentials still usable.

Add a native-tool ownership table to the marketplace disabled
mapping: a native tool owned by a package is denied for a scope
whenever the package is uninstalled, or the owning package id is
disabled for that scope (the same availability rule the package's
skills follow, so an uninitialized DenyAll code scope denies with
no explicit toggle). Deny wins over the allowlist admission, so
first-turn catalog, tool_search results, and execution all reject.
ima connect/logout now hot-refresh the disallowed surface so live
engines flip without respawn.

Regression tests cover uninstalled, plain explicit disable, code
DenyAll default, and code explicit enable.

Signed-off-by: asto18089 <asto18089@126.com>

* fix(review): teach two-stage deferred activation

A fresh adversarial pass found that the PR's own conditional gates for
`mcp_pinvou3_present_artifact` and the `mcp_browser_*` family conflated
deferral with backend unavailability: every MCP tool not in the
always-loaded list is deferred, so those tools are absent from the
first-turn tool list even when their servers are healthy, and an
instruction-following model took the "backend unavailable" branch every
time (silently skipping the PPT scene's artifact card and the embedded
browser). The unconditional main-text path they replaced worked via
blind-call hydration.

Apply the PR's own two-stage pattern — absent from the list means
activate with `tool_search` first; only a failed `tool_search` means the
backend is unavailable — at every one-stage spot:

- instructions-work.md: artifact-card rule, the loopback-preview
  fallback, and the browser section (activate browser tools through
  tool_search; the unavailability branch now fires only when tool_search
  cannot surface them either)
- builtin visual-design, marketplace pptx / government-writing /
  visualizer skills and the visualizer design-system reference (the
  pptx and government-writing skills taught the two-stage pattern one
  line away from the one-stage artifact gate — internal contradiction)
- the PPT scene payload and its self-check line
- the ima module files (knowledge-base / notes) now carry the same
  activation teaching as the package root skill

Test parity: the runtime_bundle guard now requires the activation step
and the tool_search-gated browser branch (its old rationale misstated
the mechanism); the real-bridge regression asserts that every
always-loaded name in the live catalog ships non-deferred (membership
alone never proved first-turn visibility); the JS contract scan fails
loudly if either resources/common subtree stops contributing files;
the persona card rule states why `read` is covered (empty tool table).

Signed-off-by: asto18089 <asto18089@126.com>

* fix(marketplace): align native tool gate parity

Review follow-ups on the native-tool ownership gate:

- the gate now consults `unavailable_bundles_for` (disabled union
  hidden) instead of the switch-disabled set alone, so a scope-hidden
  but enabled package denies its native tool through the same rule its
  skills already follow — the doc comment's parity claim is now true,
  and the MCP channel and the native channel share one availability
  standard; pinned by a hidden-gate regression
- `uninstall_marketplace_skill` (and, for a uniform postcondition,
  `install_marketplace_skill` / `uninstall_marketplace_tool`) now call
  `pool.refresh_disallowed_tools()`: the deny list is snapshot state in
  live engines, and skill uninstall — unlike ima_logout — keeps the
  package's keyring credentials, so an owning package's native tool
  stayed admitted and executable until respawn
- new contract test pins the registered `ImaOpenApiTool` name across
  the engine registration, the allowlist, and NATIVE_PACKAGE_TOOLS:
  three independent literals where an allowlist-only rename failed open
  silently while every list-only test stayed green

Signed-off-by: asto18089 <asto18089@126.com>

* test: pin always-loaded membership and presence

A fresh adversarial review found the always-loaded list's membership
unpinned: the live-catalog regression iterates the same constant (and
silently skips absent names), while the contract loop here only checks
that listed names are admittable. Dropping one of the four text-named
tools from the constant would therefore re-create the first-turn-absent
phantom — the defect this PR removes — with a green suite.

- pin `load_skill` / `file_search` / `registry_sync` /
  `start_registry_mcp_server` membership in the allowlist contract
  (mutation-verified: removing one now reds)
- pin `registry_sync` / `start_registry_mcp_server` presence on the
  real-bridge catalog; their registration is conditional, so the
  always-loaded loop alone cannot catch the registration half
- assert the native `ima_openapi` stays out of the live catalog while
  its owning package is uninstalled — the end-to-end half of the
  ownership gate, which the marketplace unit tests (name mapping only)
  do not cover

Signed-off-by: asto18089 <asto18089@126.com>

* fix: teach tencent-docs deferred activation

The residual-sweep applied the two-stage deferred-activation pattern to
every marketplace skill that names deferred tools except this one: the
tencent-docs skill still taught direct invocation ("模型直接调用") of
the `mcp_tencent-docs_*` / `mcp_tdoc-*` tools with no `tool_search`
activation step, and its troubleshooting checklist judged availability
by tool prefix alone. Name the activation step at both spots, mirroring
the pptx/gongwen/visualizer wording: absent from the tool list →
activate with `tool_search`; only a failed `tool_search` means the
connector is unavailable this round.

Signed-off-by: asto18089 <asto18089@126.com>

* fix(marketplace): refresh deny list on installs

Complete the uniform refresh postcondition on the remaining install
paths: `install_marketplace_tool` and `import_skill_md_bytes` already
hot-refreshed the composed skills catalog and the permission rulesets
but not the deny snapshot. Install state flows into that snapshot in
both directions — the NATIVE_PACKAGE_TOOLS ownership gate and the
DenyAll scope syncs read it — so without this refresh live engines keep
the pre-install admission: a package's native tool stays denied, and a
newly installed connector's tools stay admitted in an initialized
DenyAll scope, until respawn.

Signed-off-by: asto18089 <asto18089@126.com>

---------

Signed-off-by: asto18089 <44870036+asto18089@users.noreply.github.com>
Signed-off-by: asto18089 <asto18089@126.com>
Signed-off-by: asto <asto18089@126.com>
Signed-off-by: Pinvou Agent Review <review@pinvou.local>
Signed-off-by: asto18089 <asto18089@users.noreply.github.com>
Signed-off-by: Pinvou Review <review@pinvou.local>
Co-authored-by: Pinvou Agent Review <review@pinvou.local>
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