docs: fix live drift in extension, responses API, and channel docs (doc-truth PR 1/5) - #7375
Conversation
The public tutorial taught the retired manifest v2 authoring format ([[host_api]] / [capability_provider.tools] / runtime_credentials), which the v3 parser hard-rejects, and never mentioned origin_gate_matrix; the Responses API page claimed temperature is rejected (accepted 0.0-2.0 and forwarded), claimed model must be "default" (any well-formed name <= 256 bytes), claimed max_output_tokens is rejected (accepted and ignored by DTO policy), and omitted the required model field from every request example; the channel tutorial pointed at two files that no longer exist. - docs/extensions/building-a-tool.md: rewrite manifest sections to the v3 [[tools]] / [[tools.credentials]] / [auth.<vendor>] shape, document origin_gate_matrix (origins, policies, ratchet), correct the hosted-MCP [mcp] section, packaging via ironclaw_extension_support package modules, and v3 test references; drop the nonexistent script runtime kind. - docs/api/responses.mdx: correct model/temperature/tools/tool_choice rejection rules, document unknown-field tolerance, add the required model field to all 15 request examples. - docs/channels/building-a-channel.mdx: replace dead crates/ironclaw_first_party_extensions + available_extensions.rs registration instructions with the current package-directory mechanism. - docs/reborn/contracts/extensions.md: state that production manifests author v3 (lowering into the v2 resolved model described there); label the v2 examples as legacy. - docs/reborn/how-to-port-tool-to-reborn.md: superseded banner pointing at the v3 guides. Part of #7317 (doc-truth pipeline, PR 1 of 5). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
This PR was not deployed automatically as @thisisjoshford does not have access to the Railway project. In order to get automatic PR deploys, please add @thisisjoshford to your workspace on Railway. |
📝 WalkthroughSummary by CodeRabbit
WalkthroughThe documentation updates revise Responses API request requirements and examples. They also update extension and channel guides for manifest v3, credentials, origin policies, hosted MCP, package registration, and Reborn v2 compatibility. ChangesAPI and extension documentation
Estimated code review effort: 3 (Moderate) | ~20 minutes Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 3 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (3 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
🧭 IronLoop Run · ReviewThis comment updates in place as the Run moves through its stages. 🟥 Final result · Could not complete
Automatic trigger · attempt 1 of 3 · failed after 10s IronLoop could not complete the review for this Run. Failure details
|
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/channels/building-a-channel.mdx`:
- Line 323: Update the installation-flow documentation around the host-bundled
and local-development paths to include WebUI Extensions imports, runtime
discovery via /system/extensions/<extension-id>/manifest.toml, and that ironclaw
extension search lists discovered packages while ironclaw extension install
accepts only an extension ID. Keep the local-development directory guidance
separate from the supported Reborn user installation flow.
In `@docs/extensions/building-a-tool.md`:
- Around line 256-264: Clarify the host-port guidance near the “Host ports are
derived from effects” text: state that HostPortCatalog is a validation
allowlist, not a runtime adapter registry, and that effects only select or
validate policy. Specify that host/runtime service crates create adapters only
after authorization and obligation preparation, never from manifests.
In `@docs/reborn/how-to-port-tool-to-reborn.md`:
- Around line 3-14: Update the decision tree in this guide so it no longer
directs authors to retired RuntimeKind::Script or RuntimeKind::Mcp targets.
Either rewrite the affected rows to use the v3 manifest format, including
top-level [mcp] where applicable, or clearly mark the entire decision tree as
historical and not an authoring reference.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 97033822-201e-4fac-8499-ca2fcb42fdc5
📒 Files selected for processing (5)
docs/api/responses.mdxdocs/channels/building-a-channel.mdxdocs/extensions/building-a-tool.mddocs/reborn/contracts/extensions.mddocs/reborn/how-to-port-tool-to-reborn.md
There was a problem hiding this comment.
Pull request overview
This documentation-only PR updates Reborn extension and OpenAI-compatible Responses API docs to match current shipped behavior and manifests, reducing “doc drift” that causes users to hit runtime/parser errors when following the guides.
Changes:
- Updates extension/tool docs to the
reborn.extension_manifest.v3authoring surface ([[tools]],[auth.<vendor>],[mcp],origin_gate_matrix) and removes legacy v2 authoring guidance. - Refreshes Responses API documentation and examples to reflect current request validation/acceptance behavior (notably
modelrequired andtemperaturesupported). - Fixes channel installation guidance to the current host-bundled package +
ironclaw_extension_supportmechanism, and marks a legacy porting guide as superseded.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| docs/reborn/how-to-port-tool-to-reborn.md | Adds a “superseded” banner clarifying the guide’s legacy status and pointing to current v3 authoring docs. |
| docs/reborn/contracts/extensions.md | Corrects the manifest schema version guidance (v3 authoring that lowers into v2 resolved model). |
| docs/extensions/building-a-tool.md | Rewrites the manifest/tutorial sections to v3 ([[tools]], [auth.<vendor>], [mcp], origin_gate_matrix) and updates packaging/runtime lane guidance. |
| docs/channels/building-a-channel.mdx | Fixes host-bundled channel install steps to use crates/extensions/packages/<id>/ + ironclaw_extension_support PACKAGES. |
| docs/api/responses.mdx | Updates supported fields/rules and fixes request examples to include required model. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| - `temperature` (configure via settings) | ||
| - `max_output_tokens` (not yet wired) | ||
| - Any `model` other than `"default"` | ||
| - `tool_choice` (always — there is no per-request tool-choice surface) |
There was a problem hiding this comment.
Verified and fixed in 889f4b3. You're right: validate_responses_supported_fields rejects tool_choice unconditionally (responses_workflow.rs:1179), but the external-tools variant validate_responses_supported_fields_with_external_tools (responses_workflow.rs:1199-1222) never checks it, so with external tools wired tool_choice passes validation and is currently ignored. The bullet now says it is rejected only on deployments without external-tools support, and accepted-but-ignored otherwise.
- responses.mdx: tool_choice is rejected only without external-tools wiring; with external tools enabled it passes validation and is currently ignored (validate_responses_supported_fields_with_external_tools never checks it). - building-a-tool.md: clarify that effect-derived host ports are validation vocabulary against the HostPortCatalog allowlist; adapters are built by host-runtime services after authorization/obligations, never from manifests. - how-to-port-tool-to-reborn.md: mark the decision tree's RuntimeKind targets historical (v3 accepts only wasm|first_party; MCP is top-level [mcp]; process/CLI work is the sandbox lane). - building-a-channel.mdx: document the user install flow — virtual package root /system/extensions/<id>/manifest.toml, ironclaw extension search / install <extension-id> (ID, not path), WebUI Extensions lifecycle. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ce claim The rejection list was corrected in the previous commit (tool_choice is rejected only without external-tools wiring); the "Limits and quirks" bullet still said "not supported ... rejected with 400". Same claim, one wording. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/api/responses.mdx`:
- Around line 172-174: Update the tool_choice behavior documented near the
request error description to match the conditional contract already stated
nearby: reject it when external-tools support is unavailable, but accept and
currently ignore it when external-tools support is enabled. Remove the blanket
claim that every request containing tool_choice returns 400.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 8f7fc748-3f0e-405a-894f-db064d145e0b
📒 Files selected for processing (4)
docs/api/responses.mdxdocs/channels/building-a-channel.mdxdocs/extensions/building-a-tool.mddocs/reborn/how-to-port-tool-to-reborn.md
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.
Suppressed comments (1)
docs/api/responses.mdx:549
- The “Limits and quirks” summary says
tool_choiceis always rejected with 400, but earlier in this doc (and invalidate_responses_supported_fields_with_external_tools)tool_choiceis only rejected when external-tools support is disabled; with external tools enabled it is currently accepted and ignored. The summary should match that behavior to avoid reintroducing the earlier drift.
- **`tool_choice`**: rejected with `400` on deployments without external-tools support; with external tools enabled it is accepted but ignored. `max_output_tokens` and other unlisted OpenAI fields are accepted and ignored.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.
Suppressed comments (1)
docs/reborn/how-to-port-tool-to-reborn.md:12
- The inline code span for the v3 runtime kinds is split across two quoted lines, which breaks Markdown rendering (code spans can’t contain newlines). Keep the entire
[runtime] kind = ...snippet on a single line (or use a fenced code block).
> historical: v3 authoring accepts only `[runtime] kind = "wasm" |
> "first_party"`, hosted MCP servers use a top-level `[mcp]` section instead
A full code review of this PR against live code surfaced claims the original drift pass got wrong or missed; every fix below was re-verified against the cited source before editing: - responses.mdx: standard `ironclaw serve` deployments always wire external tools (OpenAiCompatRouteMountPorts requires the store/resume pair; mount.rs wires them unconditionally), so `tools` is accepted and `tool_choice` is accepted-and-ignored on shipped binaries — the conditional 400s apply only to custom compositions without the wiring (now a Note). temperature is validated and carried in the submitted turn payload but not applied as a provider sampling parameter. Non-streaming wait timeout is 30 s (DEFAULT_RESPONSES_WAIT_TIMEOUT), not 120. usage on retrieval is read best-effort from persisted run state incl. USD cost (read_run_usage), not always zero. - building-a-tool.md: the [auth.example] oauth2_code recipe gains the required token_response map (deny_unknown_fields rejects the example as previously written); Gmail/Google Calendar corrected to first_party runtimes (their manifests declare kind = "first_party"); the worked api_key recipe is github's, not slack's; the tail "Quick implementation checklist" and reference list were still v2-era (script lane, assets/<extension>/ path, "manifest v2", v2.rs pointer) and now teach the v3 shape; composition/CLI package-naming claim narrowed (the binary does link slack/telegram adapter crates). - contracts/extensions.md: legacy-format paragraph no longer claims host-bundled packages ship v2 (none do), and origin_gate_matrix is attributed to capability.rs + building-a-tool.md instead of extension-runtime/overview.md §3, which does not mention it. - how-to-port banner: `script` manifest authoring is retired; the RuntimeKind::Script symbol survives as the process-sandbox lane's kind. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
docs/extensions/building-a-tool.md (1)
310-323: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick winKeep optional v3 references optional.
Line 320 incorrectly makes
output_schema_refmandatory. The executable v3 contract accepts a tool withoutput_schema_ref = None.Line 322 also makes
prompt_doc_refmandatory.docs/reborn/contracts/extensions.mddefines it as optional lazy metadata.Update the field list and checklist. Require packaged assets only for references that the manifest declares.
Proposed wording
- `output_schema_ref`: relative path to JSON schema. - `prompt_doc_ref`: relative path to concise operation guidance. + `output_schema_ref`: optional relative path to JSON schema. + `prompt_doc_ref`: optional relative path to concise operation guidance. - bundled package assets include every manifest ref; + bundled package assets include every declared manifest ref;Also applies to: 696-703
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@docs/extensions/building-a-tool.md` around lines 310 - 323, Update the required tool-entry field list and the related checklist to make output_schema_ref and prompt_doc_ref optional, matching the v3 contract and lazy metadata behavior. Require packaged assets only when the manifest declares the corresponding references, while keeping declared references subject to validation.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/extensions/building-a-tool.md`:
- Around line 789-798: Before finalizing the documentation update in the Quick
implementation checklist, run both required checks from the docs directory: mint
dev and mint broken-links. Resolve any reported issues and confirm both checks
pass.
---
Outside diff comments:
In `@docs/extensions/building-a-tool.md`:
- Around line 310-323: Update the required tool-entry field list and the related
checklist to make output_schema_ref and prompt_doc_ref optional, matching the v3
contract and lazy metadata behavior. Require packaged assets only when the
manifest declares the corresponding references, while keeping declared
references subject to validation.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 08925847-7513-4d60-9b12-a1d1249fc559
📒 Files selected for processing (4)
docs/api/responses.mdxdocs/extensions/building-a-tool.mddocs/reborn/contracts/extensions.mddocs/reborn/how-to-port-tool-to-reborn.md
…drift Applies the verified findings from the PR #7376 code review: - The loop-exit and turn-runner contract docs claimed the deleted loop_driver_host checkpoint-rejection test had 'moved into the module'; it was deleted in #6696 and the fenced verification command could not run. Both now cite the real surviving pins (planned_driver.rs executor test + the ironclaw_turns projection test mapped in scripts/reborn-e2e-rust.sh), with runnable commands. - An unterminated comment now refuses at EOF like an unterminated fence; before, one typo'd closer silently un-scanned the rest of the file. - Markdown links in the re-included corpora are now checked as repo paths (they are never published, so the Mintlify-route rationale did not apply); this alone added ~165 verified references. - Each DOCS_REINCLUDED_PREFIXES entry must match at least one tracked page or discovery refuses, so the planned docs/reborn consolidation cannot silently drop the corpus from the scan. - The living extension-runtime spec pages (overview.md, standard-operations.md) and guidance-conventions.md join the scan; guidance-conventions.md now describes the docs surface and the MDX marker form, and its one dangling test path is repointed. - Floors comment corrected (57 rule globs, not 38). Also fixes four drifted claims from #7375's pages, verified against live code: the interleaved function_call_output example was rejected with 400 (resume input must be exclusively function_call_output items with previous_response_id); model is echoed only on create (GET/cancel report the 'reborn' placeholder); output_schema_ref is optional; and the unknown-fields claim now names the two deliberate exemptions. Self-tests: 43 pass (three new arms — unterminated comment refusal in both syntaxes, re-included links as repo claims, stale re-included prefix refusal). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…earai#7381) * docs(internal): record the doc-truth pipeline design (issue nearai#7317) The as-built design for keeping the public Mintlify docs in sync with released binaries: the problem evidence, the decisions of record (single doc tree deploying from a docs-live branch; deterministic gates only; human-curated changelog), the three enforcement layers (PR-time static gates, release-time cut/publish automation, human checklist), a surface-to-gate enforcement table, the deferred follow-ups (release-time live probes on the packaged binary, an openwiki-style non-blocking LLM fix-PR generator, flag-level CLI coverage, link integrity, zh freshness, contract-doc pinned-test re-verification), and the risk register. Part of nearai#7317 (doc-truth pipeline, PR 5 of 5). Companions: nearai#7375 nearai#7376 nearai#7378 nearai#7379. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs(internal): record review hardening in the doc-truth design Post-implementation review found five gaps; this records their resolutions where the design doc already claims the guarantees: planner routing so doc-fact tests run on docs-only PRs, the changelog entry landing on main before the Monday cut, a newest-stable-tag guard on publish-docs-live, the force-push allowance in the docs-live branch-protection shape, and the docs-hotfix repoint recipe. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…oc-truth PR 2/5) (nearai#7376) * docs: fix live drift in extension, responses API, and channel docs The public tutorial taught the retired manifest v2 authoring format ([[host_api]] / [capability_provider.tools] / runtime_credentials), which the v3 parser hard-rejects, and never mentioned origin_gate_matrix; the Responses API page claimed temperature is rejected (accepted 0.0-2.0 and forwarded), claimed model must be "default" (any well-formed name <= 256 bytes), claimed max_output_tokens is rejected (accepted and ignored by DTO policy), and omitted the required model field from every request example; the channel tutorial pointed at two files that no longer exist. - docs/extensions/building-a-tool.md: rewrite manifest sections to the v3 [[tools]] / [[tools.credentials]] / [auth.<vendor>] shape, document origin_gate_matrix (origins, policies, ratchet), correct the hosted-MCP [mcp] section, packaging via ironclaw_extension_support package modules, and v3 test references; drop the nonexistent script runtime kind. - docs/api/responses.mdx: correct model/temperature/tools/tool_choice rejection rules, document unknown-field tolerance, add the required model field to all 15 request examples. - docs/channels/building-a-channel.mdx: replace dead crates/ironclaw_first_party_extensions + available_extensions.rs registration instructions with the current package-directory mechanism. - docs/reborn/contracts/extensions.md: state that production manifests author v3 (lowering into the v2 resolved model described there); label the v2 examples as legacy. - docs/reborn/how-to-port-tool-to-reborn.md: superseded banner pointing at the v3 guides. Part of nearai#7317 (doc-truth pipeline, PR 1 of 5). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * ci(check-guidance): extend the reference gate to the docs/ surface The public Mintlify tree had no path-reference validation — a published tutorial told contributors to edit files that no longer exist and nothing caught it. check-guidance.py already owned the machinery (tracked-tree resolution, fence exclusion, suppress markers, shrink-only debt, fail-closed floors), so the docs surface joins the same gate rather than a fork. - discover_guidance() now collects every tracked docs/**.md|.mdx: published pages, the zh/ locale mirror, and the living contract corpus docs/reborn/contracts/. Dated archives (docs/internal/, the non-contract parts of docs/reborn/) are excluded as classes — measured 2026-08-07, 705 of 709 dangling docs references sat in those historical corpora, and forcing dated plans/ADRs to track today's tree would either rewrite history or drown KNOWN_MISSING. - docs/ files extract backticked inline paths only; Mintlify markdown link targets are site routes (extensionless pages, site-absolute /using/cli), a different namespace than the tracked tree, so the link extractor is off there by design. - _reference_lines learns MDX comments ({/* ... */}), including {/* check-guidance: path-ok */} as the .mdx suppress-marker form, with the same one-reference-per-marker and multi-line semantics as HTML comments. - Floors re-measured and re-dated (364 files / 2276 references; floors 180/1100), plus a dedicated MIN_DOCS_FILES=60 floor: the aggregate floors sit below the guidance-only remainder, so the docs branch of discovery silently breaking needs its own refusal. --json now reports docs_files. - Fixes the four real dangles the new scan found in docs/reborn/contracts/ (moved nested_dispatch_stream.rs test home, retired event-store migrations directory, loop_driver_host tests->src move). KNOWN_MISSING stays empty. - Self-tests: 8 new cases (dangling docs path fails; Mintlify links are not references; MDX marker suppresses exactly one reference; multi-line MDX comment hides content; zh discovered; archives excluded but contracts scanned; docs fence fails closed; docs floor refuses). - ws12_workflow_contracts.py: docs/api/responses.mdx and docs/zh/index.mdx join the has_guidance in-scope probes so a narrowed trigger regex cannot silently skip the gate for public docs. Part of nearai#7317 (doc-truth pipeline, PR 2 of 5); stacked on nearai#7375. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs: address Copilot and CodeRabbit review on doc-drift PR - responses.mdx: tool_choice is rejected only without external-tools wiring; with external tools enabled it passes validation and is currently ignored (validate_responses_supported_fields_with_external_tools never checks it). - building-a-tool.md: clarify that effect-derived host ports are validation vocabulary against the HostPortCatalog allowlist; adapters are built by host-runtime services after authorization/obligations, never from manifests. - how-to-port-tool-to-reborn.md: mark the decision tree's RuntimeKind targets historical (v3 accepts only wasm|first_party; MCP is top-level [mcp]; process/CLI work is the sandbox lane). - building-a-channel.mdx: document the user install flow — virtual package root /system/extensions/<id>/manifest.toml, ironclaw extension search / install <extension-id> (ID, not path), WebUI Extensions lifecycle. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs(responses): align the limits bullet with the corrected tool_choice claim The rejection list was corrected in the previous commit (tool_choice is rejected only without external-tools wiring); the "Limits and quirks" bullet still said "not supported ... rejected with 400". Same claim, one wording. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs: apply verified code-review findings on the drift PR A full code review of this PR against live code surfaced claims the original drift pass got wrong or missed; every fix below was re-verified against the cited source before editing: - responses.mdx: standard `ironclaw serve` deployments always wire external tools (OpenAiCompatRouteMountPorts requires the store/resume pair; mount.rs wires them unconditionally), so `tools` is accepted and `tool_choice` is accepted-and-ignored on shipped binaries — the conditional 400s apply only to custom compositions without the wiring (now a Note). temperature is validated and carried in the submitted turn payload but not applied as a provider sampling parameter. Non-streaming wait timeout is 30 s (DEFAULT_RESPONSES_WAIT_TIMEOUT), not 120. usage on retrieval is read best-effort from persisted run state incl. USD cost (read_run_usage), not always zero. - building-a-tool.md: the [auth.example] oauth2_code recipe gains the required token_response map (deny_unknown_fields rejects the example as previously written); Gmail/Google Calendar corrected to first_party runtimes (their manifests declare kind = "first_party"); the worked api_key recipe is github's, not slack's; the tail "Quick implementation checklist" and reference list were still v2-era (script lane, assets/<extension>/ path, "manifest v2", v2.rs pointer) and now teach the v3 shape; composition/CLI package-naming claim narrowed (the binary does link slack/telegram adapter crates). - contracts/extensions.md: legacy-format paragraph no longer claims host-bundled packages ship v2 (none do), and origin_gate_matrix is attributed to capability.rs + building-a-tool.md instead of extension-runtime/overview.md §3, which does not mention it. - how-to-port banner: `script` manifest authoring is retired; the RuntimeKind::Script symbol survives as the process-sandbox lane's kind. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs(contracts): repoint delivery_resolution.rs to its family directory PR nearai#7157 (merged to main 2026-08-07) cited crates/ironclaw_outbound/src/delivery_resolution.rs in the communication-delivery-resolution contract; the crate lives at crates/domains/ironclaw_outbound/. Caught by this branch's docs surface of check-guidance.py on the first merge of main after the gate landed — exactly the drift class it exists for. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * ci(check-guidance): harden the docs gate and fix review-surfaced doc drift Applies the verified findings from the PR nearai#7376 code review: - The loop-exit and turn-runner contract docs claimed the deleted loop_driver_host checkpoint-rejection test had 'moved into the module'; it was deleted in nearai#6696 and the fenced verification command could not run. Both now cite the real surviving pins (planned_driver.rs executor test + the ironclaw_turns projection test mapped in scripts/reborn-e2e-rust.sh), with runnable commands. - An unterminated comment now refuses at EOF like an unterminated fence; before, one typo'd closer silently un-scanned the rest of the file. - Markdown links in the re-included corpora are now checked as repo paths (they are never published, so the Mintlify-route rationale did not apply); this alone added ~165 verified references. - Each DOCS_REINCLUDED_PREFIXES entry must match at least one tracked page or discovery refuses, so the planned docs/reborn consolidation cannot silently drop the corpus from the scan. - The living extension-runtime spec pages (overview.md, standard-operations.md) and guidance-conventions.md join the scan; guidance-conventions.md now describes the docs surface and the MDX marker form, and its one dangling test path is repointed. - Floors comment corrected (57 rule globs, not 38). Also fixes four drifted claims from nearai#7375's pages, verified against live code: the interleaved function_call_output example was rejected with 400 (resume input must be exclusively function_call_output items with previous_response_id); model is echoed only on create (GET/cancel report the 'reborn' placeholder); output_schema_ref is optional; and the unknown-fields claim now names the two deliberate exemptions. Self-tests: 43 pass (three new arms — unterminated comment refusal in both syntaxes, re-included links as repo claims, stale re-included prefix refusal). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * ci(check-guidance): sync module docstring with re-included link checking CodeRabbit caught the docstring still claiming the link extractor is off for all of docs/** — stale since b172f69 enabled it for the re-included corpora. The docstring now states the exception and the current re-include set. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * ci(check-guidance): drop the docs/reborn re-include machinery after the docs/internal migration The docs-surface scan carried a double negative — exclude docs/reborn/ as an archive class, then re-include its living pages via DOCS_REINCLUDED_PREFIXES — because the old tree mixed dead archives with living specs. nearai#7559 moved everything under docs/internal/, so the structure is now: one excluded archive class (docs/internal/), and the living spec pages (the contract corpus, the two extension-runtime spec pages, guidance-conventions.md) named in INTERNAL_GUIDANCE_PREFIXES and scanned as first-class guidance files — full link checking, guarded by the same per-prefix zero-match refusal. The published-docs floor now counts only the Mintlify surface (measured 2026-08-13: 82 pages; floor re-halved to 40). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * ci(check-guidance): validate docs discovery against docs.json navigation instead of a count floor MIN_DOCS_FILES was an arbitrary magnitude tripwire (half of last measured, hand-re-dated) that only caught the docs branch of discovery losing ~half its pages. The published surface already has an independent definition — docs.json navigation, owned by docs_publication_boundary.py — so the gate now asserts every navigation page's source file is in the reference scan (reusing the boundary script's nav walker and OpenAPI pseudo-page filter). Discovery breaking refuses on the first missing published page, unreadable or page-less navigation refuses rather than passing vacuously, and there is no docs count floor left to tune. --json reports nav_pages_covered. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * ci(check-guidance): count the living internal spec pages in the docs_files metric CodeRabbit: docs_files under-reported the scan — the living internal spec pages are scanned docs files but were excluded from the count, a leftover of the deleted MIN_DOCS_FILES floor's published-only semantics. The metric now reports every scanned file under docs/ (131 at measurement); published surface health has its own signal in nav_pages_covered. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * ci(check-guidance): tighten comments and docstrings Same behavior; the docs-surface comments and test docstrings were carrying paragraph-length rationale better kept in the PR description. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…oc-truth PR 1/5) (nearai#7375) * docs: fix live drift in extension, responses API, and channel docs The public tutorial taught the retired manifest v2 authoring format ([[host_api]] / [capability_provider.tools] / runtime_credentials), which the v3 parser hard-rejects, and never mentioned origin_gate_matrix; the Responses API page claimed temperature is rejected (accepted 0.0-2.0 and forwarded), claimed model must be "default" (any well-formed name <= 256 bytes), claimed max_output_tokens is rejected (accepted and ignored by DTO policy), and omitted the required model field from every request example; the channel tutorial pointed at two files that no longer exist. - docs/extensions/building-a-tool.md: rewrite manifest sections to the v3 [[tools]] / [[tools.credentials]] / [auth.<vendor>] shape, document origin_gate_matrix (origins, policies, ratchet), correct the hosted-MCP [mcp] section, packaging via ironclaw_extension_support package modules, and v3 test references; drop the nonexistent script runtime kind. - docs/api/responses.mdx: correct model/temperature/tools/tool_choice rejection rules, document unknown-field tolerance, add the required model field to all 15 request examples. - docs/channels/building-a-channel.mdx: replace dead crates/ironclaw_first_party_extensions + available_extensions.rs registration instructions with the current package-directory mechanism. - docs/reborn/contracts/extensions.md: state that production manifests author v3 (lowering into the v2 resolved model described there); label the v2 examples as legacy. - docs/reborn/how-to-port-tool-to-reborn.md: superseded banner pointing at the v3 guides. Part of nearai#7317 (doc-truth pipeline, PR 1 of 5). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs: address Copilot and CodeRabbit review on doc-drift PR - responses.mdx: tool_choice is rejected only without external-tools wiring; with external tools enabled it passes validation and is currently ignored (validate_responses_supported_fields_with_external_tools never checks it). - building-a-tool.md: clarify that effect-derived host ports are validation vocabulary against the HostPortCatalog allowlist; adapters are built by host-runtime services after authorization/obligations, never from manifests. - how-to-port-tool-to-reborn.md: mark the decision tree's RuntimeKind targets historical (v3 accepts only wasm|first_party; MCP is top-level [mcp]; process/CLI work is the sandbox lane). - building-a-channel.mdx: document the user install flow — virtual package root /system/extensions/<id>/manifest.toml, ironclaw extension search / install <extension-id> (ID, not path), WebUI Extensions lifecycle. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs(responses): align the limits bullet with the corrected tool_choice claim The rejection list was corrected in the previous commit (tool_choice is rejected only without external-tools wiring); the "Limits and quirks" bullet still said "not supported ... rejected with 400". Same claim, one wording. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs: apply verified code-review findings on the drift PR A full code review of this PR against live code surfaced claims the original drift pass got wrong or missed; every fix below was re-verified against the cited source before editing: - responses.mdx: standard `ironclaw serve` deployments always wire external tools (OpenAiCompatRouteMountPorts requires the store/resume pair; mount.rs wires them unconditionally), so `tools` is accepted and `tool_choice` is accepted-and-ignored on shipped binaries — the conditional 400s apply only to custom compositions without the wiring (now a Note). temperature is validated and carried in the submitted turn payload but not applied as a provider sampling parameter. Non-streaming wait timeout is 30 s (DEFAULT_RESPONSES_WAIT_TIMEOUT), not 120. usage on retrieval is read best-effort from persisted run state incl. USD cost (read_run_usage), not always zero. - building-a-tool.md: the [auth.example] oauth2_code recipe gains the required token_response map (deny_unknown_fields rejects the example as previously written); Gmail/Google Calendar corrected to first_party runtimes (their manifests declare kind = "first_party"); the worked api_key recipe is github's, not slack's; the tail "Quick implementation checklist" and reference list were still v2-era (script lane, assets/<extension>/ path, "manifest v2", v2.rs pointer) and now teach the v3 shape; composition/CLI package-naming claim narrowed (the binary does link slack/telegram adapter crates). - contracts/extensions.md: legacy-format paragraph no longer claims host-bundled packages ship v2 (none do), and origin_gate_matrix is attributed to capability.rs + building-a-tool.md instead of extension-runtime/overview.md §3, which does not mention it. - how-to-port banner: `script` manifest authoring is retired; the RuntimeKind::Script symbol survives as the process-sandbox lane's kind. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…oc-truth PR 1/5) (nearai#7375) * docs: fix live drift in extension, responses API, and channel docs The public tutorial taught the retired manifest v2 authoring format ([[host_api]] / [capability_provider.tools] / runtime_credentials), which the v3 parser hard-rejects, and never mentioned origin_gate_matrix; the Responses API page claimed temperature is rejected (accepted 0.0-2.0 and forwarded), claimed model must be "default" (any well-formed name <= 256 bytes), claimed max_output_tokens is rejected (accepted and ignored by DTO policy), and omitted the required model field from every request example; the channel tutorial pointed at two files that no longer exist. - docs/extensions/building-a-tool.md: rewrite manifest sections to the v3 [[tools]] / [[tools.credentials]] / [auth.<vendor>] shape, document origin_gate_matrix (origins, policies, ratchet), correct the hosted-MCP [mcp] section, packaging via ironclaw_extension_support package modules, and v3 test references; drop the nonexistent script runtime kind. - docs/api/responses.mdx: correct model/temperature/tools/tool_choice rejection rules, document unknown-field tolerance, add the required model field to all 15 request examples. - docs/channels/building-a-channel.mdx: replace dead crates/ironclaw_first_party_extensions + available_extensions.rs registration instructions with the current package-directory mechanism. - docs/reborn/contracts/extensions.md: state that production manifests author v3 (lowering into the v2 resolved model described there); label the v2 examples as legacy. - docs/reborn/how-to-port-tool-to-reborn.md: superseded banner pointing at the v3 guides. Part of nearai#7317 (doc-truth pipeline, PR 1 of 5). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs: address Copilot and CodeRabbit review on doc-drift PR - responses.mdx: tool_choice is rejected only without external-tools wiring; with external tools enabled it passes validation and is currently ignored (validate_responses_supported_fields_with_external_tools never checks it). - building-a-tool.md: clarify that effect-derived host ports are validation vocabulary against the HostPortCatalog allowlist; adapters are built by host-runtime services after authorization/obligations, never from manifests. - how-to-port-tool-to-reborn.md: mark the decision tree's RuntimeKind targets historical (v3 accepts only wasm|first_party; MCP is top-level [mcp]; process/CLI work is the sandbox lane). - building-a-channel.mdx: document the user install flow — virtual package root /system/extensions/<id>/manifest.toml, ironclaw extension search / install <extension-id> (ID, not path), WebUI Extensions lifecycle. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs(responses): align the limits bullet with the corrected tool_choice claim The rejection list was corrected in the previous commit (tool_choice is rejected only without external-tools wiring); the "Limits and quirks" bullet still said "not supported ... rejected with 400". Same claim, one wording. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs: apply verified code-review findings on the drift PR A full code review of this PR against live code surfaced claims the original drift pass got wrong or missed; every fix below was re-verified against the cited source before editing: - responses.mdx: standard `ironclaw serve` deployments always wire external tools (OpenAiCompatRouteMountPorts requires the store/resume pair; mount.rs wires them unconditionally), so `tools` is accepted and `tool_choice` is accepted-and-ignored on shipped binaries — the conditional 400s apply only to custom compositions without the wiring (now a Note). temperature is validated and carried in the submitted turn payload but not applied as a provider sampling parameter. Non-streaming wait timeout is 30 s (DEFAULT_RESPONSES_WAIT_TIMEOUT), not 120. usage on retrieval is read best-effort from persisted run state incl. USD cost (read_run_usage), not always zero. - building-a-tool.md: the [auth.example] oauth2_code recipe gains the required token_response map (deny_unknown_fields rejects the example as previously written); Gmail/Google Calendar corrected to first_party runtimes (their manifests declare kind = "first_party"); the worked api_key recipe is github's, not slack's; the tail "Quick implementation checklist" and reference list were still v2-era (script lane, assets/<extension>/ path, "manifest v2", v2.rs pointer) and now teach the v3 shape; composition/CLI package-naming claim narrowed (the binary does link slack/telegram adapter crates). - contracts/extensions.md: legacy-format paragraph no longer claims host-bundled packages ship v2 (none do), and origin_gate_matrix is attributed to capability.rs + building-a-tool.md instead of extension-runtime/overview.md §3, which does not mention it. - how-to-port banner: `script` manifest authoring is retired; the RuntimeKind::Script symbol survives as the process-sandbox lane's kind. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…claims (doc-truth PR 3/5) (nearai#7378) * docs: fix live drift in extension, responses API, and channel docs The public tutorial taught the retired manifest v2 authoring format ([[host_api]] / [capability_provider.tools] / runtime_credentials), which the v3 parser hard-rejects, and never mentioned origin_gate_matrix; the Responses API page claimed temperature is rejected (accepted 0.0-2.0 and forwarded), claimed model must be "default" (any well-formed name <= 256 bytes), claimed max_output_tokens is rejected (accepted and ignored by DTO policy), and omitted the required model field from every request example; the channel tutorial pointed at two files that no longer exist. - docs/extensions/building-a-tool.md: rewrite manifest sections to the v3 [[tools]] / [[tools.credentials]] / [auth.<vendor>] shape, document origin_gate_matrix (origins, policies, ratchet), correct the hosted-MCP [mcp] section, packaging via ironclaw_extension_support package modules, and v3 test references; drop the nonexistent script runtime kind. - docs/api/responses.mdx: correct model/temperature/tools/tool_choice rejection rules, document unknown-field tolerance, add the required model field to all 15 request examples. - docs/channels/building-a-channel.mdx: replace dead crates/ironclaw_first_party_extensions + available_extensions.rs registration instructions with the current package-directory mechanism. - docs/reborn/contracts/extensions.md: state that production manifests author v3 (lowering into the v2 resolved model described there); label the v2 examples as legacy. - docs/reborn/how-to-port-tool-to-reborn.md: superseded banner pointing at the v3 guides. Part of nearai#7317 (doc-truth pipeline, PR 1 of 5). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * ci(check-guidance): extend the reference gate to the docs/ surface The public Mintlify tree had no path-reference validation — a published tutorial told contributors to edit files that no longer exist and nothing caught it. check-guidance.py already owned the machinery (tracked-tree resolution, fence exclusion, suppress markers, shrink-only debt, fail-closed floors), so the docs surface joins the same gate rather than a fork. - discover_guidance() now collects every tracked docs/**.md|.mdx: published pages, the zh/ locale mirror, and the living contract corpus docs/reborn/contracts/. Dated archives (docs/internal/, the non-contract parts of docs/reborn/) are excluded as classes — measured 2026-08-07, 705 of 709 dangling docs references sat in those historical corpora, and forcing dated plans/ADRs to track today's tree would either rewrite history or drown KNOWN_MISSING. - docs/ files extract backticked inline paths only; Mintlify markdown link targets are site routes (extensionless pages, site-absolute /using/cli), a different namespace than the tracked tree, so the link extractor is off there by design. - _reference_lines learns MDX comments ({/* ... */}), including {/* check-guidance: path-ok */} as the .mdx suppress-marker form, with the same one-reference-per-marker and multi-line semantics as HTML comments. - Floors re-measured and re-dated (364 files / 2276 references; floors 180/1100), plus a dedicated MIN_DOCS_FILES=60 floor: the aggregate floors sit below the guidance-only remainder, so the docs branch of discovery silently breaking needs its own refusal. --json now reports docs_files. - Fixes the four real dangles the new scan found in docs/reborn/contracts/ (moved nested_dispatch_stream.rs test home, retired event-store migrations directory, loop_driver_host tests->src move). KNOWN_MISSING stays empty. - Self-tests: 8 new cases (dangling docs path fails; Mintlify links are not references; MDX marker suppresses exactly one reference; multi-line MDX comment hides content; zh discovered; archives excluded but contracts scanned; docs fence fails closed; docs floor refuses). - ws12_workflow_contracts.py: docs/api/responses.mdx and docs/zh/index.mdx join the has_guidance in-scope probes so a narrowed trigger regex cannot silently skip the gate for public docs. Part of nearai#7317 (doc-truth pipeline, PR 2 of 5); stacked on nearai#7375. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * test(docs): pin CLI, manifest, and Responses doc claims to code Three deterministic doc-fact contract tests, each living in the crate that owns the truth it checks, so the drift nearai#7317 describes fails CI instead of shipping: - crates/app/ironclaw_cli/tests/docs_cli_reference.rs: parses the real binary's --help and cross-checks docs/using/cli.mdx table rows both ways (every visible subcommand documented, any alias form counting; every documented command real), with a fail-closed row floor. Doc gaps this surfaced are fixed here: ironhub had no rows at all, completion was fence-only, and the Trace Commons table lacked the `ironclaw` prefix the rest of the page uses. - crates/extensions/ironclaw_extension_registry/tests/ docs_manifest_schema_version.rs: walks the published docs tree (the frozen .mintignore fence mirrored as constants) and asserts zero occurrences of the retired reborn.extension_manifest.v2 literal, fenced code included; asserts building-a-tool.md names MANIFEST_SCHEMA_VERSION_V3 verbatim and documents origin_gate_matrix. - crates/product/ironclaw_openai_compat/tests/docs_responses_contract.rs: docs/api/responses.mdx now carries a machine-readable {/* doc-fact:responses-request-policy */} marker block (invisible when rendered); the test parses it and drives every claim through the same route-level seam as the sibling *_contract.rs suites — the marker's values parameterize the assertions (temperature accepted at the documented max and rejected just above it, model accepted at the byte cap and rejected past it, tool_choice always 400, tools 400 without / registered with external-tool wiring, empty tools treated as omitted, unknown fields like max_output_tokens accepted and ignored, and one request carrying every documented field accepted). Part of nearai#7317 (doc-truth pipeline, PR 3 of 5); stacked on nearai#7376. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs: address Copilot and CodeRabbit review on doc-drift PR - responses.mdx: tool_choice is rejected only without external-tools wiring; with external tools enabled it passes validation and is currently ignored (validate_responses_supported_fields_with_external_tools never checks it). - building-a-tool.md: clarify that effect-derived host ports are validation vocabulary against the HostPortCatalog allowlist; adapters are built by host-runtime services after authorization/obligations, never from manifests. - how-to-port-tool-to-reborn.md: mark the decision tree's RuntimeKind targets historical (v3 accepts only wasm|first_party; MCP is top-level [mcp]; process/CLI work is the sandbox lane). - building-a-channel.mdx: document the user install flow — virtual package root /system/extensions/<id>/manifest.toml, ironclaw extension search / install <extension-id> (ID, not path), WebUI Extensions lifecycle. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs(responses): align the limits bullet with the corrected tool_choice claim The rejection list was corrected in the previous commit (tool_choice is rejected only without external-tools wiring); the "Limits and quirks" bullet still said "not supported ... rejected with 400". Same claim, one wording. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * test(docs): tool_choice is conditionally rejected, not always Copilot review on the docs PR caught that validate_responses_supported_fields_with_external_tools never checks tool_choice — with external tools wired it is accepted and ignored, not 400'd. The doc-fact marker moves tool_choice into rejected_without_external_tools, and the dedicated test now proves both sides: 400 naming the param on the plain router, accepted-and-ignored (submit succeeds, nothing registers) with external-tool wiring. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs: apply verified code-review findings on the drift PR A full code review of this PR against live code surfaced claims the original drift pass got wrong or missed; every fix below was re-verified against the cited source before editing: - responses.mdx: standard `ironclaw serve` deployments always wire external tools (OpenAiCompatRouteMountPorts requires the store/resume pair; mount.rs wires them unconditionally), so `tools` is accepted and `tool_choice` is accepted-and-ignored on shipped binaries — the conditional 400s apply only to custom compositions without the wiring (now a Note). temperature is validated and carried in the submitted turn payload but not applied as a provider sampling parameter. Non-streaming wait timeout is 30 s (DEFAULT_RESPONSES_WAIT_TIMEOUT), not 120. usage on retrieval is read best-effort from persisted run state incl. USD cost (read_run_usage), not always zero. - building-a-tool.md: the [auth.example] oauth2_code recipe gains the required token_response map (deny_unknown_fields rejects the example as previously written); Gmail/Google Calendar corrected to first_party runtimes (their manifests declare kind = "first_party"); the worked api_key recipe is github's, not slack's; the tail "Quick implementation checklist" and reference list were still v2-era (script lane, assets/<extension>/ path, "manifest v2", v2.rs pointer) and now teach the v3 shape; composition/CLI package-naming claim narrowed (the binary does link slack/telegram adapter crates). - contracts/extensions.md: legacy-format paragraph no longer claims host-bundled packages ship v2 (none do), and origin_gate_matrix is attributed to capability.rs + building-a-tool.md instead of extension-runtime/overview.md §3, which does not mention it. - how-to-port banner: `script` manifest authoring is retired; the RuntimeKind::Script symbol survives as the process-sandbox lane's kind. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs(contracts): repoint delivery_resolution.rs to its family directory PR nearai#7157 (merged to main 2026-08-07) cited crates/ironclaw_outbound/src/delivery_resolution.rs in the communication-delivery-resolution contract; the crate lives at crates/domains/ironclaw_outbound/. Caught by this branch's docs surface of check-guidance.py on the first merge of main after the gate landed — exactly the drift class it exists for. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * ci(test-plan): route docs pages to the doc-fact tests that read them docs/ sat in IGNORED_PREFIXES as a pure-prose class, which this PR's doc-fact tests falsify: three cargo tests now read published pages, so a docs-only PR would have selected zero crate tests and merged green, leaving the failure to land on whichever unrelated change ran the full plan next. Published Markdown now selects the registry's schema-version sweep; docs/using/cli.mdx and docs/api/responses.mdx additionally select their owning crates. All selections are direct exact test targets — no reverse-dependency widening, since prose only changes the doc-fact assertions that read it. Fenced trees (docs/internal/, docs/reborn/, drafts) and non-page files keep the prose classification. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * ci(check-guidance): harden the docs gate and fix review-surfaced doc drift Applies the verified findings from the PR nearai#7376 code review: - The loop-exit and turn-runner contract docs claimed the deleted loop_driver_host checkpoint-rejection test had 'moved into the module'; it was deleted in nearai#6696 and the fenced verification command could not run. Both now cite the real surviving pins (planned_driver.rs executor test + the ironclaw_turns projection test mapped in scripts/reborn-e2e-rust.sh), with runnable commands. - An unterminated comment now refuses at EOF like an unterminated fence; before, one typo'd closer silently un-scanned the rest of the file. - Markdown links in the re-included corpora are now checked as repo paths (they are never published, so the Mintlify-route rationale did not apply); this alone added ~165 verified references. - Each DOCS_REINCLUDED_PREFIXES entry must match at least one tracked page or discovery refuses, so the planned docs/reborn consolidation cannot silently drop the corpus from the scan. - The living extension-runtime spec pages (overview.md, standard-operations.md) and guidance-conventions.md join the scan; guidance-conventions.md now describes the docs surface and the MDX marker form, and its one dangling test path is repointed. - Floors comment corrected (57 rule globs, not 38). Also fixes four drifted claims from nearai#7375's pages, verified against live code: the interleaved function_call_output example was rejected with 400 (resume input must be exclusively function_call_output items with previous_response_id); model is echoed only on create (GET/cancel report the 'reborn' placeholder); output_schema_ref is optional; and the unknown-fields claim now names the two deliberate exemptions. Self-tests: 43 pass (three new arms — unterminated comment refusal in both syntaxes, re-included links as repo claims, stale re-included prefix refusal). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * ci(check-guidance): sync module docstring with re-included link checking CodeRabbit caught the docstring still claiming the link extractor is off for all of docs/** — stale since b172f69 enabled it for the re-included corpora. The docstring now states the exception and the current re-include set. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * test(docs): drop the retired reborn/ entry from the publication-fence mirrors reborn/ left docs/.mintignore when nearai#7559 consolidated it into internal/; the fence mirrors in docs_manifest_schema_version.rs and reborn_pr_test_plan.py still listed it. Fixture paths follow the move. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * test(docs): tighten doc-fact comments and docstrings Same behavior; module docs and test docstrings trimmed to the point. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * test(docs): harden the doc-fact suites per CodeRabbit review - CLI: validate full documented command paths via `ironclaw <path> --help` (immediately caught and removed the nonexistent `extension activate` row) and match visible aliases as exact tokens, not substrings. - Responses: seed a real prior response so `previous_response_id` is actually submitted and accepted; document `metadata` in the visible table to match the marker. - Manifest sweep: parse the publication fence from docs/.mintignore instead of mirroring it, so a removed fence entry widens the scan with it. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(docs): correct the completion syntax and parse the fence in the planner Review findings (sub-agent /code-review): - docs/using/cli.mdx taught `ironclaw completion <shell>`; the binary only accepts `--shell <shell>`. The contract test stops extracting at flags, so it could not catch this. - The planner's doc-fact arm mirrored the .mintignore fence as constants — the same hand-maintained-mirror class the PR removes elsewhere. It now parses docs/.mintignore via docs_publication_boundary, and a .mintignore edit itself routes to the published sweep. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(test-plan): treat a missing docs/.mintignore as no fence, not a crash Matches docs_publication_boundary.find_violations(): fence gone means everything is published, so every page routes to the sweep. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * test(docs): replace the doc-fact count floors with derived anchors Same move as nearai#7376's MIN_DOCS_FILES removal: MIN_DOC_COMMAND_ROWS was redundant with the completeness check (the binary defines the expected set), and MIN_SCANNED_PAGES is now a docs.json nav-coverage assertion — every source-backed navigation route must be among the walked pages. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * test(docs): assert the current schema version instead of scanning for a retired literal Hardcoding `reborn.extension_manifest.v2` was backward-looking: retiring v3 would need a hand-edit or the test goes stale. The scan now extracts every `reborn.extension_manifest.<version>` mention in published pages and asserts it equals `MANIFEST_SCHEMA_VERSION_V3`, with the family prefix derived from the same constant — the next schema bump retargets the test by itself, and typo'd or older versions (v1, v33) are caught too. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…oc-truth PR 1/5) (nearai#7375) * docs: fix live drift in extension, responses API, and channel docs The public tutorial taught the retired manifest v2 authoring format ([[host_api]] / [capability_provider.tools] / runtime_credentials), which the v3 parser hard-rejects, and never mentioned origin_gate_matrix; the Responses API page claimed temperature is rejected (accepted 0.0-2.0 and forwarded), claimed model must be "default" (any well-formed name <= 256 bytes), claimed max_output_tokens is rejected (accepted and ignored by DTO policy), and omitted the required model field from every request example; the channel tutorial pointed at two files that no longer exist. - docs/extensions/building-a-tool.md: rewrite manifest sections to the v3 [[tools]] / [[tools.credentials]] / [auth.<vendor>] shape, document origin_gate_matrix (origins, policies, ratchet), correct the hosted-MCP [mcp] section, packaging via ironclaw_extension_support package modules, and v3 test references; drop the nonexistent script runtime kind. - docs/api/responses.mdx: correct model/temperature/tools/tool_choice rejection rules, document unknown-field tolerance, add the required model field to all 15 request examples. - docs/channels/building-a-channel.mdx: replace dead crates/ironclaw_first_party_extensions + available_extensions.rs registration instructions with the current package-directory mechanism. - docs/reborn/contracts/extensions.md: state that production manifests author v3 (lowering into the v2 resolved model described there); label the v2 examples as legacy. - docs/reborn/how-to-port-tool-to-reborn.md: superseded banner pointing at the v3 guides. Part of nearai#7317 (doc-truth pipeline, PR 1 of 5). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs: address Copilot and CodeRabbit review on doc-drift PR - responses.mdx: tool_choice is rejected only without external-tools wiring; with external tools enabled it passes validation and is currently ignored (validate_responses_supported_fields_with_external_tools never checks it). - building-a-tool.md: clarify that effect-derived host ports are validation vocabulary against the HostPortCatalog allowlist; adapters are built by host-runtime services after authorization/obligations, never from manifests. - how-to-port-tool-to-reborn.md: mark the decision tree's RuntimeKind targets historical (v3 accepts only wasm|first_party; MCP is top-level [mcp]; process/CLI work is the sandbox lane). - building-a-channel.mdx: document the user install flow — virtual package root /system/extensions/<id>/manifest.toml, ironclaw extension search / install <extension-id> (ID, not path), WebUI Extensions lifecycle. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs(responses): align the limits bullet with the corrected tool_choice claim The rejection list was corrected in the previous commit (tool_choice is rejected only without external-tools wiring); the "Limits and quirks" bullet still said "not supported ... rejected with 400". Same claim, one wording. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs: apply verified code-review findings on the drift PR A full code review of this PR against live code surfaced claims the original drift pass got wrong or missed; every fix below was re-verified against the cited source before editing: - responses.mdx: standard `ironclaw serve` deployments always wire external tools (OpenAiCompatRouteMountPorts requires the store/resume pair; mount.rs wires them unconditionally), so `tools` is accepted and `tool_choice` is accepted-and-ignored on shipped binaries — the conditional 400s apply only to custom compositions without the wiring (now a Note). temperature is validated and carried in the submitted turn payload but not applied as a provider sampling parameter. Non-streaming wait timeout is 30 s (DEFAULT_RESPONSES_WAIT_TIMEOUT), not 120. usage on retrieval is read best-effort from persisted run state incl. USD cost (read_run_usage), not always zero. - building-a-tool.md: the [auth.example] oauth2_code recipe gains the required token_response map (deny_unknown_fields rejects the example as previously written); Gmail/Google Calendar corrected to first_party runtimes (their manifests declare kind = "first_party"); the worked api_key recipe is github's, not slack's; the tail "Quick implementation checklist" and reference list were still v2-era (script lane, assets/<extension>/ path, "manifest v2", v2.rs pointer) and now teach the v3 shape; composition/CLI package-naming claim narrowed (the binary does link slack/telegram adapter crates). - contracts/extensions.md: legacy-format paragraph no longer claims host-bundled packages ship v2 (none do), and origin_gate_matrix is attributed to capability.rs + building-a-tool.md instead of extension-runtime/overview.md §3, which does not mention it. - how-to-port banner: `script` manifest authoring is retired; the RuntimeKind::Script symbol survives as the process-sandbox lane's kind. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…earai#7381) * docs(internal): record the doc-truth pipeline design (issue nearai#7317) The as-built design for keeping the public Mintlify docs in sync with released binaries: the problem evidence, the decisions of record (single doc tree deploying from a docs-live branch; deterministic gates only; human-curated changelog), the three enforcement layers (PR-time static gates, release-time cut/publish automation, human checklist), a surface-to-gate enforcement table, the deferred follow-ups (release-time live probes on the packaged binary, an openwiki-style non-blocking LLM fix-PR generator, flag-level CLI coverage, link integrity, zh freshness, contract-doc pinned-test re-verification), and the risk register. Part of nearai#7317 (doc-truth pipeline, PR 5 of 5). Companions: nearai#7375 nearai#7376 nearai#7378 nearai#7379. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs(internal): record review hardening in the doc-truth design Post-implementation review found five gaps; this records their resolutions where the design doc already claims the guarantees: planner routing so doc-fact tests run on docs-only PRs, the changelog entry landing on main before the Monday cut, a newest-stable-tag guard on publish-docs-live, the force-push allowance in the docs-live branch-protection shape, and the docs-hotfix repoint recipe. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…oc-truth PR 2/5) (nearai#7376) * docs: fix live drift in extension, responses API, and channel docs The public tutorial taught the retired manifest v2 authoring format ([[host_api]] / [capability_provider.tools] / runtime_credentials), which the v3 parser hard-rejects, and never mentioned origin_gate_matrix; the Responses API page claimed temperature is rejected (accepted 0.0-2.0 and forwarded), claimed model must be "default" (any well-formed name <= 256 bytes), claimed max_output_tokens is rejected (accepted and ignored by DTO policy), and omitted the required model field from every request example; the channel tutorial pointed at two files that no longer exist. - docs/extensions/building-a-tool.md: rewrite manifest sections to the v3 [[tools]] / [[tools.credentials]] / [auth.<vendor>] shape, document origin_gate_matrix (origins, policies, ratchet), correct the hosted-MCP [mcp] section, packaging via ironclaw_extension_support package modules, and v3 test references; drop the nonexistent script runtime kind. - docs/api/responses.mdx: correct model/temperature/tools/tool_choice rejection rules, document unknown-field tolerance, add the required model field to all 15 request examples. - docs/channels/building-a-channel.mdx: replace dead crates/ironclaw_first_party_extensions + available_extensions.rs registration instructions with the current package-directory mechanism. - docs/reborn/contracts/extensions.md: state that production manifests author v3 (lowering into the v2 resolved model described there); label the v2 examples as legacy. - docs/reborn/how-to-port-tool-to-reborn.md: superseded banner pointing at the v3 guides. Part of nearai#7317 (doc-truth pipeline, PR 1 of 5). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * ci(check-guidance): extend the reference gate to the docs/ surface The public Mintlify tree had no path-reference validation — a published tutorial told contributors to edit files that no longer exist and nothing caught it. check-guidance.py already owned the machinery (tracked-tree resolution, fence exclusion, suppress markers, shrink-only debt, fail-closed floors), so the docs surface joins the same gate rather than a fork. - discover_guidance() now collects every tracked docs/**.md|.mdx: published pages, the zh/ locale mirror, and the living contract corpus docs/reborn/contracts/. Dated archives (docs/internal/, the non-contract parts of docs/reborn/) are excluded as classes — measured 2026-08-07, 705 of 709 dangling docs references sat in those historical corpora, and forcing dated plans/ADRs to track today's tree would either rewrite history or drown KNOWN_MISSING. - docs/ files extract backticked inline paths only; Mintlify markdown link targets are site routes (extensionless pages, site-absolute /using/cli), a different namespace than the tracked tree, so the link extractor is off there by design. - _reference_lines learns MDX comments ({/* ... */}), including {/* check-guidance: path-ok */} as the .mdx suppress-marker form, with the same one-reference-per-marker and multi-line semantics as HTML comments. - Floors re-measured and re-dated (364 files / 2276 references; floors 180/1100), plus a dedicated MIN_DOCS_FILES=60 floor: the aggregate floors sit below the guidance-only remainder, so the docs branch of discovery silently breaking needs its own refusal. --json now reports docs_files. - Fixes the four real dangles the new scan found in docs/reborn/contracts/ (moved nested_dispatch_stream.rs test home, retired event-store migrations directory, loop_driver_host tests->src move). KNOWN_MISSING stays empty. - Self-tests: 8 new cases (dangling docs path fails; Mintlify links are not references; MDX marker suppresses exactly one reference; multi-line MDX comment hides content; zh discovered; archives excluded but contracts scanned; docs fence fails closed; docs floor refuses). - ws12_workflow_contracts.py: docs/api/responses.mdx and docs/zh/index.mdx join the has_guidance in-scope probes so a narrowed trigger regex cannot silently skip the gate for public docs. Part of nearai#7317 (doc-truth pipeline, PR 2 of 5); stacked on nearai#7375. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs: address Copilot and CodeRabbit review on doc-drift PR - responses.mdx: tool_choice is rejected only without external-tools wiring; with external tools enabled it passes validation and is currently ignored (validate_responses_supported_fields_with_external_tools never checks it). - building-a-tool.md: clarify that effect-derived host ports are validation vocabulary against the HostPortCatalog allowlist; adapters are built by host-runtime services after authorization/obligations, never from manifests. - how-to-port-tool-to-reborn.md: mark the decision tree's RuntimeKind targets historical (v3 accepts only wasm|first_party; MCP is top-level [mcp]; process/CLI work is the sandbox lane). - building-a-channel.mdx: document the user install flow — virtual package root /system/extensions/<id>/manifest.toml, ironclaw extension search / install <extension-id> (ID, not path), WebUI Extensions lifecycle. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs(responses): align the limits bullet with the corrected tool_choice claim The rejection list was corrected in the previous commit (tool_choice is rejected only without external-tools wiring); the "Limits and quirks" bullet still said "not supported ... rejected with 400". Same claim, one wording. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs: apply verified code-review findings on the drift PR A full code review of this PR against live code surfaced claims the original drift pass got wrong or missed; every fix below was re-verified against the cited source before editing: - responses.mdx: standard `ironclaw serve` deployments always wire external tools (OpenAiCompatRouteMountPorts requires the store/resume pair; mount.rs wires them unconditionally), so `tools` is accepted and `tool_choice` is accepted-and-ignored on shipped binaries — the conditional 400s apply only to custom compositions without the wiring (now a Note). temperature is validated and carried in the submitted turn payload but not applied as a provider sampling parameter. Non-streaming wait timeout is 30 s (DEFAULT_RESPONSES_WAIT_TIMEOUT), not 120. usage on retrieval is read best-effort from persisted run state incl. USD cost (read_run_usage), not always zero. - building-a-tool.md: the [auth.example] oauth2_code recipe gains the required token_response map (deny_unknown_fields rejects the example as previously written); Gmail/Google Calendar corrected to first_party runtimes (their manifests declare kind = "first_party"); the worked api_key recipe is github's, not slack's; the tail "Quick implementation checklist" and reference list were still v2-era (script lane, assets/<extension>/ path, "manifest v2", v2.rs pointer) and now teach the v3 shape; composition/CLI package-naming claim narrowed (the binary does link slack/telegram adapter crates). - contracts/extensions.md: legacy-format paragraph no longer claims host-bundled packages ship v2 (none do), and origin_gate_matrix is attributed to capability.rs + building-a-tool.md instead of extension-runtime/overview.md §3, which does not mention it. - how-to-port banner: `script` manifest authoring is retired; the RuntimeKind::Script symbol survives as the process-sandbox lane's kind. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs(contracts): repoint delivery_resolution.rs to its family directory PR nearai#7157 (merged to main 2026-08-07) cited crates/ironclaw_outbound/src/delivery_resolution.rs in the communication-delivery-resolution contract; the crate lives at crates/domains/ironclaw_outbound/. Caught by this branch's docs surface of check-guidance.py on the first merge of main after the gate landed — exactly the drift class it exists for. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * ci(check-guidance): harden the docs gate and fix review-surfaced doc drift Applies the verified findings from the PR nearai#7376 code review: - The loop-exit and turn-runner contract docs claimed the deleted loop_driver_host checkpoint-rejection test had 'moved into the module'; it was deleted in nearai#6696 and the fenced verification command could not run. Both now cite the real surviving pins (planned_driver.rs executor test + the ironclaw_turns projection test mapped in scripts/reborn-e2e-rust.sh), with runnable commands. - An unterminated comment now refuses at EOF like an unterminated fence; before, one typo'd closer silently un-scanned the rest of the file. - Markdown links in the re-included corpora are now checked as repo paths (they are never published, so the Mintlify-route rationale did not apply); this alone added ~165 verified references. - Each DOCS_REINCLUDED_PREFIXES entry must match at least one tracked page or discovery refuses, so the planned docs/reborn consolidation cannot silently drop the corpus from the scan. - The living extension-runtime spec pages (overview.md, standard-operations.md) and guidance-conventions.md join the scan; guidance-conventions.md now describes the docs surface and the MDX marker form, and its one dangling test path is repointed. - Floors comment corrected (57 rule globs, not 38). Also fixes four drifted claims from nearai#7375's pages, verified against live code: the interleaved function_call_output example was rejected with 400 (resume input must be exclusively function_call_output items with previous_response_id); model is echoed only on create (GET/cancel report the 'reborn' placeholder); output_schema_ref is optional; and the unknown-fields claim now names the two deliberate exemptions. Self-tests: 43 pass (three new arms — unterminated comment refusal in both syntaxes, re-included links as repo claims, stale re-included prefix refusal). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * ci(check-guidance): sync module docstring with re-included link checking CodeRabbit caught the docstring still claiming the link extractor is off for all of docs/** — stale since b172f69 enabled it for the re-included corpora. The docstring now states the exception and the current re-include set. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * ci(check-guidance): drop the docs/reborn re-include machinery after the docs/internal migration The docs-surface scan carried a double negative — exclude docs/reborn/ as an archive class, then re-include its living pages via DOCS_REINCLUDED_PREFIXES — because the old tree mixed dead archives with living specs. nearai#7559 moved everything under docs/internal/, so the structure is now: one excluded archive class (docs/internal/), and the living spec pages (the contract corpus, the two extension-runtime spec pages, guidance-conventions.md) named in INTERNAL_GUIDANCE_PREFIXES and scanned as first-class guidance files — full link checking, guarded by the same per-prefix zero-match refusal. The published-docs floor now counts only the Mintlify surface (measured 2026-08-13: 82 pages; floor re-halved to 40). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * ci(check-guidance): validate docs discovery against docs.json navigation instead of a count floor MIN_DOCS_FILES was an arbitrary magnitude tripwire (half of last measured, hand-re-dated) that only caught the docs branch of discovery losing ~half its pages. The published surface already has an independent definition — docs.json navigation, owned by docs_publication_boundary.py — so the gate now asserts every navigation page's source file is in the reference scan (reusing the boundary script's nav walker and OpenAPI pseudo-page filter). Discovery breaking refuses on the first missing published page, unreadable or page-less navigation refuses rather than passing vacuously, and there is no docs count floor left to tune. --json reports nav_pages_covered. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * ci(check-guidance): count the living internal spec pages in the docs_files metric CodeRabbit: docs_files under-reported the scan — the living internal spec pages are scanned docs files but were excluded from the count, a leftover of the deleted MIN_DOCS_FILES floor's published-only semantics. The metric now reports every scanned file under docs/ (131 at measurement); published surface health has its own signal in nav_pages_covered. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * ci(check-guidance): tighten comments and docstrings Same behavior; the docs-surface comments and test docstrings were carrying paragraph-length rationale better kept in the PR description. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…claims (doc-truth PR 3/5) (nearai#7378) * docs: fix live drift in extension, responses API, and channel docs The public tutorial taught the retired manifest v2 authoring format ([[host_api]] / [capability_provider.tools] / runtime_credentials), which the v3 parser hard-rejects, and never mentioned origin_gate_matrix; the Responses API page claimed temperature is rejected (accepted 0.0-2.0 and forwarded), claimed model must be "default" (any well-formed name <= 256 bytes), claimed max_output_tokens is rejected (accepted and ignored by DTO policy), and omitted the required model field from every request example; the channel tutorial pointed at two files that no longer exist. - docs/extensions/building-a-tool.md: rewrite manifest sections to the v3 [[tools]] / [[tools.credentials]] / [auth.<vendor>] shape, document origin_gate_matrix (origins, policies, ratchet), correct the hosted-MCP [mcp] section, packaging via ironclaw_extension_support package modules, and v3 test references; drop the nonexistent script runtime kind. - docs/api/responses.mdx: correct model/temperature/tools/tool_choice rejection rules, document unknown-field tolerance, add the required model field to all 15 request examples. - docs/channels/building-a-channel.mdx: replace dead crates/ironclaw_first_party_extensions + available_extensions.rs registration instructions with the current package-directory mechanism. - docs/reborn/contracts/extensions.md: state that production manifests author v3 (lowering into the v2 resolved model described there); label the v2 examples as legacy. - docs/reborn/how-to-port-tool-to-reborn.md: superseded banner pointing at the v3 guides. Part of nearai#7317 (doc-truth pipeline, PR 1 of 5). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * ci(check-guidance): extend the reference gate to the docs/ surface The public Mintlify tree had no path-reference validation — a published tutorial told contributors to edit files that no longer exist and nothing caught it. check-guidance.py already owned the machinery (tracked-tree resolution, fence exclusion, suppress markers, shrink-only debt, fail-closed floors), so the docs surface joins the same gate rather than a fork. - discover_guidance() now collects every tracked docs/**.md|.mdx: published pages, the zh/ locale mirror, and the living contract corpus docs/reborn/contracts/. Dated archives (docs/internal/, the non-contract parts of docs/reborn/) are excluded as classes — measured 2026-08-07, 705 of 709 dangling docs references sat in those historical corpora, and forcing dated plans/ADRs to track today's tree would either rewrite history or drown KNOWN_MISSING. - docs/ files extract backticked inline paths only; Mintlify markdown link targets are site routes (extensionless pages, site-absolute /using/cli), a different namespace than the tracked tree, so the link extractor is off there by design. - _reference_lines learns MDX comments ({/* ... */}), including {/* check-guidance: path-ok */} as the .mdx suppress-marker form, with the same one-reference-per-marker and multi-line semantics as HTML comments. - Floors re-measured and re-dated (364 files / 2276 references; floors 180/1100), plus a dedicated MIN_DOCS_FILES=60 floor: the aggregate floors sit below the guidance-only remainder, so the docs branch of discovery silently breaking needs its own refusal. --json now reports docs_files. - Fixes the four real dangles the new scan found in docs/reborn/contracts/ (moved nested_dispatch_stream.rs test home, retired event-store migrations directory, loop_driver_host tests->src move). KNOWN_MISSING stays empty. - Self-tests: 8 new cases (dangling docs path fails; Mintlify links are not references; MDX marker suppresses exactly one reference; multi-line MDX comment hides content; zh discovered; archives excluded but contracts scanned; docs fence fails closed; docs floor refuses). - ws12_workflow_contracts.py: docs/api/responses.mdx and docs/zh/index.mdx join the has_guidance in-scope probes so a narrowed trigger regex cannot silently skip the gate for public docs. Part of nearai#7317 (doc-truth pipeline, PR 2 of 5); stacked on nearai#7375. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * test(docs): pin CLI, manifest, and Responses doc claims to code Three deterministic doc-fact contract tests, each living in the crate that owns the truth it checks, so the drift nearai#7317 describes fails CI instead of shipping: - crates/app/ironclaw_cli/tests/docs_cli_reference.rs: parses the real binary's --help and cross-checks docs/using/cli.mdx table rows both ways (every visible subcommand documented, any alias form counting; every documented command real), with a fail-closed row floor. Doc gaps this surfaced are fixed here: ironhub had no rows at all, completion was fence-only, and the Trace Commons table lacked the `ironclaw` prefix the rest of the page uses. - crates/extensions/ironclaw_extension_registry/tests/ docs_manifest_schema_version.rs: walks the published docs tree (the frozen .mintignore fence mirrored as constants) and asserts zero occurrences of the retired reborn.extension_manifest.v2 literal, fenced code included; asserts building-a-tool.md names MANIFEST_SCHEMA_VERSION_V3 verbatim and documents origin_gate_matrix. - crates/product/ironclaw_openai_compat/tests/docs_responses_contract.rs: docs/api/responses.mdx now carries a machine-readable {/* doc-fact:responses-request-policy */} marker block (invisible when rendered); the test parses it and drives every claim through the same route-level seam as the sibling *_contract.rs suites — the marker's values parameterize the assertions (temperature accepted at the documented max and rejected just above it, model accepted at the byte cap and rejected past it, tool_choice always 400, tools 400 without / registered with external-tool wiring, empty tools treated as omitted, unknown fields like max_output_tokens accepted and ignored, and one request carrying every documented field accepted). Part of nearai#7317 (doc-truth pipeline, PR 3 of 5); stacked on nearai#7376. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs: address Copilot and CodeRabbit review on doc-drift PR - responses.mdx: tool_choice is rejected only without external-tools wiring; with external tools enabled it passes validation and is currently ignored (validate_responses_supported_fields_with_external_tools never checks it). - building-a-tool.md: clarify that effect-derived host ports are validation vocabulary against the HostPortCatalog allowlist; adapters are built by host-runtime services after authorization/obligations, never from manifests. - how-to-port-tool-to-reborn.md: mark the decision tree's RuntimeKind targets historical (v3 accepts only wasm|first_party; MCP is top-level [mcp]; process/CLI work is the sandbox lane). - building-a-channel.mdx: document the user install flow — virtual package root /system/extensions/<id>/manifest.toml, ironclaw extension search / install <extension-id> (ID, not path), WebUI Extensions lifecycle. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs(responses): align the limits bullet with the corrected tool_choice claim The rejection list was corrected in the previous commit (tool_choice is rejected only without external-tools wiring); the "Limits and quirks" bullet still said "not supported ... rejected with 400". Same claim, one wording. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * test(docs): tool_choice is conditionally rejected, not always Copilot review on the docs PR caught that validate_responses_supported_fields_with_external_tools never checks tool_choice — with external tools wired it is accepted and ignored, not 400'd. The doc-fact marker moves tool_choice into rejected_without_external_tools, and the dedicated test now proves both sides: 400 naming the param on the plain router, accepted-and-ignored (submit succeeds, nothing registers) with external-tool wiring. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs: apply verified code-review findings on the drift PR A full code review of this PR against live code surfaced claims the original drift pass got wrong or missed; every fix below was re-verified against the cited source before editing: - responses.mdx: standard `ironclaw serve` deployments always wire external tools (OpenAiCompatRouteMountPorts requires the store/resume pair; mount.rs wires them unconditionally), so `tools` is accepted and `tool_choice` is accepted-and-ignored on shipped binaries — the conditional 400s apply only to custom compositions without the wiring (now a Note). temperature is validated and carried in the submitted turn payload but not applied as a provider sampling parameter. Non-streaming wait timeout is 30 s (DEFAULT_RESPONSES_WAIT_TIMEOUT), not 120. usage on retrieval is read best-effort from persisted run state incl. USD cost (read_run_usage), not always zero. - building-a-tool.md: the [auth.example] oauth2_code recipe gains the required token_response map (deny_unknown_fields rejects the example as previously written); Gmail/Google Calendar corrected to first_party runtimes (their manifests declare kind = "first_party"); the worked api_key recipe is github's, not slack's; the tail "Quick implementation checklist" and reference list were still v2-era (script lane, assets/<extension>/ path, "manifest v2", v2.rs pointer) and now teach the v3 shape; composition/CLI package-naming claim narrowed (the binary does link slack/telegram adapter crates). - contracts/extensions.md: legacy-format paragraph no longer claims host-bundled packages ship v2 (none do), and origin_gate_matrix is attributed to capability.rs + building-a-tool.md instead of extension-runtime/overview.md §3, which does not mention it. - how-to-port banner: `script` manifest authoring is retired; the RuntimeKind::Script symbol survives as the process-sandbox lane's kind. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs(contracts): repoint delivery_resolution.rs to its family directory PR nearai#7157 (merged to main 2026-08-07) cited crates/ironclaw_outbound/src/delivery_resolution.rs in the communication-delivery-resolution contract; the crate lives at crates/domains/ironclaw_outbound/. Caught by this branch's docs surface of check-guidance.py on the first merge of main after the gate landed — exactly the drift class it exists for. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * ci(test-plan): route docs pages to the doc-fact tests that read them docs/ sat in IGNORED_PREFIXES as a pure-prose class, which this PR's doc-fact tests falsify: three cargo tests now read published pages, so a docs-only PR would have selected zero crate tests and merged green, leaving the failure to land on whichever unrelated change ran the full plan next. Published Markdown now selects the registry's schema-version sweep; docs/using/cli.mdx and docs/api/responses.mdx additionally select their owning crates. All selections are direct exact test targets — no reverse-dependency widening, since prose only changes the doc-fact assertions that read it. Fenced trees (docs/internal/, docs/reborn/, drafts) and non-page files keep the prose classification. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * ci(check-guidance): harden the docs gate and fix review-surfaced doc drift Applies the verified findings from the PR nearai#7376 code review: - The loop-exit and turn-runner contract docs claimed the deleted loop_driver_host checkpoint-rejection test had 'moved into the module'; it was deleted in nearai#6696 and the fenced verification command could not run. Both now cite the real surviving pins (planned_driver.rs executor test + the ironclaw_turns projection test mapped in scripts/reborn-e2e-rust.sh), with runnable commands. - An unterminated comment now refuses at EOF like an unterminated fence; before, one typo'd closer silently un-scanned the rest of the file. - Markdown links in the re-included corpora are now checked as repo paths (they are never published, so the Mintlify-route rationale did not apply); this alone added ~165 verified references. - Each DOCS_REINCLUDED_PREFIXES entry must match at least one tracked page or discovery refuses, so the planned docs/reborn consolidation cannot silently drop the corpus from the scan. - The living extension-runtime spec pages (overview.md, standard-operations.md) and guidance-conventions.md join the scan; guidance-conventions.md now describes the docs surface and the MDX marker form, and its one dangling test path is repointed. - Floors comment corrected (57 rule globs, not 38). Also fixes four drifted claims from nearai#7375's pages, verified against live code: the interleaved function_call_output example was rejected with 400 (resume input must be exclusively function_call_output items with previous_response_id); model is echoed only on create (GET/cancel report the 'reborn' placeholder); output_schema_ref is optional; and the unknown-fields claim now names the two deliberate exemptions. Self-tests: 43 pass (three new arms — unterminated comment refusal in both syntaxes, re-included links as repo claims, stale re-included prefix refusal). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * ci(check-guidance): sync module docstring with re-included link checking CodeRabbit caught the docstring still claiming the link extractor is off for all of docs/** — stale since b172f69 enabled it for the re-included corpora. The docstring now states the exception and the current re-include set. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * test(docs): drop the retired reborn/ entry from the publication-fence mirrors reborn/ left docs/.mintignore when nearai#7559 consolidated it into internal/; the fence mirrors in docs_manifest_schema_version.rs and reborn_pr_test_plan.py still listed it. Fixture paths follow the move. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * test(docs): tighten doc-fact comments and docstrings Same behavior; module docs and test docstrings trimmed to the point. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * test(docs): harden the doc-fact suites per CodeRabbit review - CLI: validate full documented command paths via `ironclaw <path> --help` (immediately caught and removed the nonexistent `extension activate` row) and match visible aliases as exact tokens, not substrings. - Responses: seed a real prior response so `previous_response_id` is actually submitted and accepted; document `metadata` in the visible table to match the marker. - Manifest sweep: parse the publication fence from docs/.mintignore instead of mirroring it, so a removed fence entry widens the scan with it. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(docs): correct the completion syntax and parse the fence in the planner Review findings (sub-agent /code-review): - docs/using/cli.mdx taught `ironclaw completion <shell>`; the binary only accepts `--shell <shell>`. The contract test stops extracting at flags, so it could not catch this. - The planner's doc-fact arm mirrored the .mintignore fence as constants — the same hand-maintained-mirror class the PR removes elsewhere. It now parses docs/.mintignore via docs_publication_boundary, and a .mintignore edit itself routes to the published sweep. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(test-plan): treat a missing docs/.mintignore as no fence, not a crash Matches docs_publication_boundary.find_violations(): fence gone means everything is published, so every page routes to the sweep. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * test(docs): replace the doc-fact count floors with derived anchors Same move as nearai#7376's MIN_DOCS_FILES removal: MIN_DOC_COMMAND_ROWS was redundant with the completeness check (the binary defines the expected set), and MIN_SCANNED_PAGES is now a docs.json nav-coverage assertion — every source-backed navigation route must be among the walked pages. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * test(docs): assert the current schema version instead of scanning for a retired literal Hardcoding `reborn.extension_manifest.v2` was backward-looking: retiring v3 would need a hand-edit or the test goes stale. The scan now extracts every `reborn.extension_manifest.<version>` mention in published pages and asserts it equals `MANIFEST_SCHEMA_VERSION_V3`, with the family prefix derived from the same constant — the next schema bump retargets the test by itself, and typo'd or older versions (v1, v33) are caught too. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Summary
docs/extensions/building-a-tool.mdto the currentreborn.extension_manifest.v3authoring format ([[tools]],[[tools.credentials]],[auth.<vendor>],[mcp]) — the page previously taught the legacy v2[[host_api]]/[capability_provider.tools]shape, which the v3 parser hard-rejects (crates/extensions/ironclaw_extension_registry/src/v3.rsusesdeny_unknown_fields), and never mentionedorigin_gate_matrix. This is the exact drift class called out in Proposal: Doc-Truth Verification Pipeline #7317.loop_run/product/automation), the five policies fromOriginGatePolicy, the forbidden-by-default rule, and thereborn_origin_gate_matrix_ratchet.rsshipping requirement.docs/api/responses.mdxagainstcrates/product/ironclaw_openai_compat:temperatureis accepted (0.0–2.0 inclusive, forwarded) not rejected;modelis required and any well-formed ≤256-byte name (not "must bedefault");max_output_tokensand other unknown fields are accepted-and-ignored by DTO policy, not rejected; non-emptytoolsis rejected only without external-tools wiring. Adds the requiredmodelfield to all 15 request examples (they would 400 as written — pinned bytests/dto_contract.rs).docs/channels/building-a-channel.mdxinstall instructions, which pointed atcrates/ironclaw_first_party_extensions/...andavailable_extensions.rsregistration — neither mechanism exists; replaced with the package-directory +ironclaw_extension_supportpackage-module mechanism.docs/reborn/contracts/extensions.mdclaim that production manifests use v2 (they author v3, which lowers into the v2 resolved model), and bannersdocs/reborn/how-to-port-tool-to-reborn.mdas superseded.Change Type
Linked Issue
Related #7317 — PR 1 of the 5-PR doc-truth pipeline plan (drift fixes land first so the follow-up gates land green). Follow-ups: docs path-reference gate (check-guidance), doc-fact contract tests, docs-live release automation + changelog, design doc.
Validation
python3 scripts/ci/docs_publication_boundary.py— every page published or fencedgrep -rn "extension_manifest.v2" docs/— hits remain only indocs/internal/(historical ADR/plans) and explicitly-labeled legacy examples in fenceddocs/reborn/crates/app/ironclaw_composition/src/mcp.rsreferences fixed tocrates/extensions/ironclaw_extension_host/src/mcp.rs)crates/extensions/packages/{github,notion-mcp,nearai-mcp}/manifest.toml) andRawManifestV3/RawToolV3/RawMcpV3struct fieldsvalidate_responses_supported_fields,validate_temperature,validate_model_name, and the DTO contract testsTest Strategy
User behavior: documentation-only; no runtime behavior changes.
Risk areas: none of the listed categories (docs only).
Tests added or updated:
What the tests prove: n/a (see follow-up PR).
Commands run:
python3 scripts/ci/docs_publication_boundary.py; greps above.Security Impact
None. Documentation only; the corrected text describes existing enforced behavior (origin gate matrix, credential mediation) more accurately than before.
Reborn Trust-Boundary Checklist
N/A — documentation-only change; no code, policy, or trust-bearing types touched.
🤖 Generated with Claude Code