docs(runner): strip leaked generation wrappers, sync Phase 7 counts, guard against regressions

Remove trailing generation-wrapper markup (</content>, plus </invoke> in the
tutorial) that had leaked at EOF into eleven committed Phase 7 reference,
tutorial, evidence, and OKF-journal files.

Sync the stated suite counts in the current-state docs (tutorial,
scenario-explorer reference, verification-commands reference, and OKF journal)
to the verified results: test:phase7 49, test:browser:phase7 25,
docs:validate 73 files / 28 OKF concepts / 5 indexes. Drop a brittle wall-clock
timing from the journal. The dated 7F verification evidence and log.md milestone
entry keep their point-in-time 45/19 figures on purpose.

Add a wrapper-markup guard to docs:validate (via scripts/lib/doc-wrappers.mjs)
that fails with the exact file and line when generator envelope tags reappear,
plus a node:test regression suite wired into the package test script.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
DottaandClaude Opus 4.8 committed 2026-08-09 14:46:49 +00:00
1 parent 2cd4462e95
commit ab7b85878a
15 files changed
+82 -23

No files matched your search

@@ -96,4 +96,3 @@ prohibition, and the test-only, explicitly granted, allowlisted escape hatch.
- [Capability disposition](phase-07-capability-disposition.md)
- [Semantic tool catalog](phase-07-semantic-tools.md)
- [Scenario explorer](phase-07-scenario-explorer.md)
</content>
@@ -82,4 +82,3 @@ contract cannot silently fall out of sync.
- [Semantic tool catalog](phase-07-semantic-tools.md)
- [Authorization and exposure](phase-07-authorization-and-exposure.md)
- [Eval conformance](phase-07-eval-conformance.md)
</content>
@@ -80,4 +80,3 @@ OKF frontmatter). See the
- [Capability disposition](phase-07-capability-disposition.md)
- [Semantic tool catalog](phase-07-semantic-tools.md)
- [Scenario explorer](phase-07-scenario-explorer.md)
</content>
@@ -49,4 +49,3 @@ CTO approval at the Phase 7 checkpoint (`PAP-16908`). Until then:
- [Architecture and dependency boundary](architecture.md)
- [Mock ControlPlanePort](phase-07-mock-control-plane-port.md)
- [Capability disposition](phase-07-capability-disposition.md)
</content>
@@ -92,4 +92,3 @@ Nine tests, no npm alias of their own — they also run inside
- [Semantic tool catalog](phase-07-semantic-tools.md)
- [Authorization and exposure](phase-07-authorization-and-exposure.md)
- [Future binding boundary](phase-07-future-binding-boundary.md)
</content>
@@ -68,10 +68,10 @@ a time with zero horizontal overflow.
# Open the explorer on 127.0.0.1:4183.
pnpm --filter @paperclipai/paperclip-runner demo:phase7
# Scenario runtime, explorer components, and route determinism (45 tests).
# Scenario runtime, explorer components, and route determinism (49 tests).
pnpm --filter @paperclipai/paperclip-runner test:phase7
# Browser IA, determinism, evidence routes, boundary, a11y, responsive (19).
# Browser IA, determinism, evidence routes, boundary, a11y, responsive (25).
pnpm --filter @paperclipai/paperclip-runner test:browser:phase7
# Deterministic 24-image acceptance set (12 routes x 2 viewports).
@@ -83,4 +83,3 @@ pnpm --filter @paperclipai/paperclip-runner record:phase7
- [Eval conformance](phase-07-eval-conformance.md)
- [Verification commands](phase-07-verification-commands.md)
- [Phase 7F explorer verification](../knowledge/evidence/2026-08-09-phase-07f-explorer-verification.md)
</content>
@@ -84,4 +84,3 @@ that every optional group is present.
- [Authorization and exposure](phase-07-authorization-and-exposure.md)
- [Mock ControlPlanePort](phase-07-mock-control-plane-port.md)
- [Eval conformance](phase-07-eval-conformance.md)
</content>
@@ -14,10 +14,10 @@ acceptance record are in
| Semantic tools + authorization/redaction | `exec vitest run src/tools/phase7-semantic-tools.test.ts` | 9 tests pass |
| 106-case conformance | `test:phase7-evals` | 1 file (all 106 cases) passes |
| Fake-agent matrix + bounded Codex + parity report | `report:phase7-evals` | `Phase 7 eval conformance passed: 106 cases across 16 groups.` |
| Scenario runtime + explorer + routes | `test:phase7` | 45 tests pass |
| Browser IA, accessibility, determinism, boundary | `test:browser:phase7` | 19 Playwright tests pass |
| Scenario runtime + explorer + routes | `test:phase7` | 49 tests pass |
| Browser IA, accessibility, determinism, boundary | `test:browser:phase7` | 25 Playwright tests pass |
| Screenshot acceptance set | `record:phase7` | 24 deterministic images |
| Doc links + OKF bundle | `docs:validate` | 62 files, 26 OKF concepts, 5 indexes |
| Doc links + OKF bundle | `docs:validate` | 73 files, 28 OKF concepts, 5 indexes |
## Notes
@@ -39,4 +39,3 @@ acceptance record are in
- [Clean-start tutorial](tutorials/phase-07-scenario-explorer.md)
- [Eval conformance](phase-07-eval-conformance.md)
- [Scenario explorer](phase-07-scenario-explorer.md)
</content>
@@ -144,7 +144,7 @@ pnpm --filter @paperclipai/paperclip-runner exec vitest run \
pnpm --filter @paperclipai/paperclip-runner test:phase7-evals
pnpm --filter @paperclipai/paperclip-runner report:phase7-evals
# Scenario runtime, explorer components, and route determinism (45 tests).
# Scenario runtime, explorer components, and route determinism (49 tests).
pnpm --filter @paperclipai/paperclip-runner test:phase7
# Browser information architecture, accessibility, determinism, and boundary.
@@ -184,5 +184,3 @@ The exact results captured for the acceptance record are in the
(PAP-16903), 7F browser explorer (PAP-16904, UX gate PAP-16905), 7G docs and
evidence (PAP-16906), 7H clean-room QA (PAP-16907), Phase 7 checkpoint
(PAP-16908).
</content>
</invoke>
@@ -102,4 +102,3 @@ Results were captured on 2026-08-09 between 13:37Z and 13:39Z.
provider exercise is the bounded binding sample in `report:phase7-evals`.
- No Paperclip control plane, database, or provider is contacted anywhere in
Phase 7. Real integration is Phase 8 (ACPX) and requires separate approval.
</content>
@@ -56,15 +56,15 @@ All commands ran from the repository root, offline, on Node 22.22.2 / pnpm
152 skill/reference headings, 106 eval cases, 258 normative rows, and 41
legacy MCP aliases folded one-to-one.
- Mock control plane (9 tests), semantic tools and authorization/redaction
(9 tests), scenario runtime and explorer (45 tests), and the 106-case
(9 tests), scenario runtime and explorer (49 tests), and the 106-case
conformance suite all pass in-process.
- `report:phase7-evals` reports 106 cases across 16 groups, 18/18 fake-agent
operations, and the bounded Codex binding sample.
- `test:browser:phase7` passes 19 Playwright checks (6.8s) for information
- `test:browser:phase7` passes 25 Playwright checks for information
architecture, route determinism, evidence routes, the credential boundary,
accessibility, and responsive layout.
- On a clean tree `docs:validate` passes 62 documentation files and an OKF
bundle of 26 concepts across 5 indexes.
- On a clean tree `docs:validate` passes 73 documentation files and an OKF
bundle of 28 concepts across 5 indexes.
# Evidence
@@ -99,4 +99,3 @@ All commands ran from the repository root, offline, on Node 22.22.2 / pnpm
with generator-authored OKF frontmatter, or out of the bundle entirely?
- Which of the eight reference pages should the Phase 8 binding work extend
first when the real adapter lands behind the seam?
</content>
+1 -1
View File
@@ -36,7 +36,7 @@
"typecheck:typescript": "pnpm run check:protocol-types && tsc -p tsconfig.json --noEmit",
"typecheck:rust": "cargo check --manifest-path runner/Cargo.toml --locked --workspace",
"typecheck:browser": "tsc -p tsconfig.browser.json --noEmit",
"test": "pnpm run build:phase2-binaries && pnpm run test:typescript && pnpm run test:rust && node --test scripts/check-forbidden-imports.test.mjs scripts/record-phase4-evidence.test.mjs",
"test": "pnpm run build:phase2-binaries && pnpm run test:typescript && pnpm run test:rust && node --test scripts/check-forbidden-imports.test.mjs scripts/record-phase4-evidence.test.mjs scripts/validate-doc-links.test.mjs",
"test:typescript": "vitest run",
"test:rust": "cargo test --manifest-path runner/Cargo.toml --locked --workspace",
"test:browser": "pnpm run build:typescript && pnpm run build:phase2-binaries && pnpm run build:browser && playwright test --config devtools/browser/playwright.config.ts",
@@ -0,0 +1,21 @@
// Detects leaked model/tool generation-wrapper markup in documentation.
//
// When a generator writes its raw completion envelope into a file, tags such as
// a trailing `</content>` or `</invoke>` escape into the committed prose. Plain
// link and OKF validation do not notice them, so `docs:validate` scans every
// markdown file with this detector and fails on the exact file and line. Prose
// docs never legitimately contain these tags, so any match is a defect.
export const WRAPPER_MARKUP =
/<\/?(?:antml:[a-z0-9_-]+|content|invoke|parameter|function_calls|function_results)\b[^>]*>/i;
export function wrapperMarkupIn(markdown) {
const hits = [];
const lines = markdown.split("\n");
for (let index = 0; index < lines.length; index += 1) {
const match = lines[index].match(WRAPPER_MARKUP);
if (match) {
hits.push({ line: index + 1, tag: match[0] });
}
}
return hits;
}
@@ -2,6 +2,8 @@ import { access, readFile, readdir } from "node:fs/promises";
import { dirname, extname, relative, resolve } from "node:path";
import { fileURLToPath } from "node:url";
import { wrapperMarkupIn } from "./lib/doc-wrappers.mjs";
const packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), "..");
const documentationRoots = [
resolve(packageRoot, "README.md"),
@@ -80,6 +82,9 @@ const markdownFiles = (
for (const file of markdownFiles.sort()) {
const markdown = await readFile(file, "utf8");
for (const { line, tag } of wrapperMarkupIn(markdown)) {
errors.push(`${relative(packageRoot, file)}:${line} -> leaked generation-wrapper markup ${tag}`);
}
for (const rawLink of linksIn(markdown)) {
if (/^(?:https?:|mailto:|skill:)/.test(rawLink)) {
continue;
@@ -0,0 +1,45 @@
import assert from "node:assert/strict";
import { test } from "node:test";
import { wrapperMarkupIn } from "./lib/doc-wrappers.mjs";
test("clean prose reports no leaked generation-wrapper markup", () => {
const markdown = [
"# Title",
"",
"Body prose that talks about content and invoking tools without any tags.",
"",
"- [A link](other.md)",
"",
].join("\n");
assert.deepEqual(wrapperMarkupIn(markdown), []);
});
test("a trailing </content> wrapper is caught with its exact line", () => {
const markdown = ["# Title", "", "Body.", "</content>"].join("\n");
assert.deepEqual(wrapperMarkupIn(markdown), [{ line: 4, tag: "</content>" }]);
});
test("a tutorial's </invoke> wrapper is caught", () => {
const markdown = ["Body.", "</content>", "</invoke>"].join("\n");
assert.deepEqual(wrapperMarkupIn(markdown), [
{ line: 2, tag: "</content>" },
{ line: 3, tag: "</invoke>" },
]);
});
test("assorted generator envelope tags are all caught", () => {
for (const tag of [
"<content>",
"<invoke name=\"Bash\">",
"<parameter name=\"x\">",
"<function_calls>",
"</function_results>",
"<invoke>",
]) {
assert.deepEqual(wrapperMarkupIn(`prose\n${tag}\n`), [{ line: 2, tag }]);
}
});