diff --git a/.codex/skills/truthmark-check/SKILL.md b/.agents/skills/truthmark-check/SKILL.md similarity index 65% rename from .codex/skills/truthmark-check/SKILL.md rename to .agents/skills/truthmark-check/SKILL.md index e330fd0..b8b5902 100644 --- a/.codex/skills/truthmark-check/SKILL.md +++ b/.agents/skills/truthmark-check/SKILL.md @@ -3,26 +3,24 @@ name: truthmark-check description: Use when the user asks to audit repository truth health, routing, ownership, or canonical docs. Not for normal lint/test/typecheck/code-review verification, finish-time Sync, or silently rewriting docs. argument-hint: Optional area, doc path, or audit focus user-invocable: true -truthmark-version: 1.6.1 +truthmark-version: 2.1.0 --- # Truthmark Check Use this skill to audit repository truth health. - Invocations: OpenCode /skill truthmark-check; Codex /truthmark-check or $truthmark-check; Claude Code /truthmark-check; GitHub Copilot /truthmark-check; Gemini CLI /truthmark:check. Quick procedure: - Follow repository instruction files that exist in this checkout; do not assume any optional policy path exists. -- Inspect .truthmark/config.yml and configured route files (docs/truthmark/areas.md; docs/truthmark/areas/) only when they exist; then inspect canonical docs and relevant implementation directly. +- Inspect .truthmark/config.yml and configured route files (docs/truthmark/routes/areas.md; docs/truthmark/routes/areas/) only when they exist; then inspect canonical docs and relevant implementation directly. - Report issues and suggested fixes; do not silently rewrite unrelated files. -- Direct checkout inspection is valid even when local tooling is unavailable. - Read support/procedure.md before auditing details. -- Read support/subagents-and-leases.md before dispatching verifier subagents. +- Read support/subagents-and-leases.md only when dispatching verifier subagents. - Read support/report-template.md before the final report. Progressive disclosure: -- support/procedure.md -- support/report-template.md -- support/subagents-and-leases.md +- support/procedure.md — read before edits or detailed auditing; contains core quality gates +- support/report-template.md — read before the final report +- support/subagents-and-leases.md — read only when using subagents, leases, or accepting worker output diff --git a/.codex/skills/truthmark-check/agents/openai.yaml b/.agents/skills/truthmark-check/agents/openai.yaml similarity index 93% rename from .codex/skills/truthmark-check/agents/openai.yaml rename to .agents/skills/truthmark-check/agents/openai.yaml index 809b65f..7156cc6 100644 --- a/.codex/skills/truthmark-check/agents/openai.yaml +++ b/.agents/skills/truthmark-check/agents/openai.yaml @@ -7,5 +7,5 @@ policy: allow_implicit_invocation: false truthmark: - version: "1.6.1" + version: "2.1.0" refresh_command: "truthmark init" diff --git a/.codex/skills/truthmark-check/support/procedure.md b/.agents/skills/truthmark-check/support/procedure.md similarity index 84% rename from .codex/skills/truthmark-check/support/procedure.md rename to .agents/skills/truthmark-check/support/procedure.md index 72baa9b..6132ff9 100644 --- a/.codex/skills/truthmark-check/support/procedure.md +++ b/.agents/skills/truthmark-check/support/procedure.md @@ -1,6 +1,6 @@ # Truthmark Check Procedure -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. # Truthmark Check @@ -13,7 +13,7 @@ Truth Check is agent-led: - inspect .truthmark/config.yml and configured route files only when they exist; then inspect canonical docs and relevant implementation directly - Repository instruction files and explicitly configured policy docs remain instruction authority when present; do not assume a repository uses any particular policy path. Implementation code and canonical truth docs are inspected evidence for current behavior; they do not silently override workflow write boundaries. -- inspect the configured root route index at docs/truthmark/areas.md and relevant child route files under docs/truthmark/areas/ when they exist +- inspect the configured root route index at docs/truthmark/routes/areas.md and relevant child route files under docs/truthmark/routes/areas/ when they exist - check that current docs describe current code rather than historical plans - check that route files map code surfaces to canonical truth docs when route files exist - check for broad, catch-all, index-like, or mixed-owner truth docs and report them as topology issues requiring Truth Structure @@ -29,9 +29,9 @@ Evidence Gate: Truthmark hierarchy hints: - Config, when present: .truthmark/config.yml -- Root route index, when present: docs/truthmark/areas.md -- Area route files, when present: docs/truthmark/areas/**/*.md -- Truth docs, when present: docs/truth/**/*.md +- Root route index, when present: docs/truthmark/routes/areas.md +- Area route files, when present: docs/truthmark/routes/areas/**/*.md +- Truth docs, when present: docs/truthmark/truth/**/*.md Decision truth lives in the canonical doc it governs; date active decisions inline when added or changed. Do not create separate active-decision ADR/planning logs; replace the active decision and let Git history carry the audit trail. Update Product Decisions and Rationale when a decision changes behavior. diff --git a/.codex/skills/truthmark-check/support/report-template.md b/.agents/skills/truthmark-check/support/report-template.md similarity index 70% rename from .codex/skills/truthmark-check/support/report-template.md rename to .agents/skills/truthmark-check/support/report-template.md index 2ce828e..00a3453 100644 --- a/.codex/skills/truthmark-check/support/report-template.md +++ b/.agents/skills/truthmark-check/support/report-template.md @@ -1,6 +1,6 @@ # Truthmark Check Report Template -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Report completion in this shape: @@ -8,7 +8,7 @@ Report completion in this shape: Truth Check: completed Files reviewed: -- docs/truthmark/areas.md +- docs/truthmark/routes/areas.md Issues found: - none @@ -18,7 +18,7 @@ Fixes suggested: Evidence checked: - Finding: The root route index is present and maps repository truth owners. - Evidence: docs/truthmark/areas.md:1 + Evidence: docs/truthmark/routes/areas.md:1 Suggested fix: none Confidence: high diff --git a/.codex/skills/truthmark-check/support/subagents-and-leases.md b/.agents/skills/truthmark-check/support/subagents-and-leases.md similarity index 89% rename from .codex/skills/truthmark-check/support/subagents-and-leases.md rename to .agents/skills/truthmark-check/support/subagents-and-leases.md index 3c8b634..b55697f 100644 --- a/.codex/skills/truthmark-check/support/subagents-and-leases.md +++ b/.agents/skills/truthmark-check/support/subagents-and-leases.md @@ -1,6 +1,6 @@ # Truthmark Check Subagents And Leases -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Codex subagent mode: - use automatically when this workflow runs in Codex and the parent agent chooses bounded subagent fan-out diff --git a/.codex/skills/truthmark-document/SKILL.md b/.agents/skills/truthmark-document/SKILL.md similarity index 63% rename from .codex/skills/truthmark-document/SKILL.md rename to .agents/skills/truthmark-document/SKILL.md index 6e2469f..241a841 100644 --- a/.codex/skills/truthmark-document/SKILL.md +++ b/.agents/skills/truthmark-document/SKILL.md @@ -3,28 +3,27 @@ name: truthmark-document description: Use when the user asks to document existing implemented behavior, or Sync, Check, or Structure finds implemented behavior missing canonical truth. Not for functional-code changes, doc-first implementation, or topology repair that needs Structure. argument-hint: Optional implemented behavior, API endpoint, route, controller, package, or truth-doc area to document user-invocable: true -truthmark-version: 1.6.1 +truthmark-version: 2.1.0 --- # Truthmark Document Use this skill to document existing implemented behavior when no functional-code changes are required for the task. - Invocations: OpenCode /skill truthmark-document; Codex /truthmark-document or $truthmark-document; Claude Code /truthmark-document; GitHub Copilot /truthmark-document; Gemini CLI /truthmark:document. Quick procedure: - Follow repository instruction files that exist in this checkout; do not assume any optional policy path exists. -- Inspect .truthmark/config.yml and configured route files (docs/truthmark/areas.md; docs/truthmark/areas/) only when they exist; then inspect existing canonical docs, implementation code, and tests directly. +- Inspect .truthmark/config.yml and configured route files (docs/truthmark/routes/areas.md; docs/truthmark/routes/areas/) only when they exist; then inspect existing canonical docs, implementation code, and tests directly. - Document current implemented behavior; do not invent future behavior. - May write canonical truth docs and truth routing files only; must not write functional code. - Read support/procedure.md before editing truth docs. -- Read support/subagents-and-leases.md before dispatching or accepting worker output. +- Read support/subagents-and-leases.md only when dispatching or accepting worker output. - Read support/report-template.md before the final report. Progressive disclosure: -- support/procedure.md -- support/report-template.md -- support/subagents-and-leases.md -- helper-manifest.yml -- support/helper-policy.md +- support/procedure.md — read before edits or detailed auditing; contains core quality gates +- support/report-template.md — read before the final report +- support/subagents-and-leases.md — read only when using subagents, leases, or accepting worker output +- helper-manifest.yml — read only when invoking helper validators or validating helper registration +- support/helper-policy.md — read only when invoking helper validators or reporting helper status diff --git a/.codex/skills/truthmark-document/agents/openai.yaml b/.agents/skills/truthmark-document/agents/openai.yaml similarity index 93% rename from .codex/skills/truthmark-document/agents/openai.yaml rename to .agents/skills/truthmark-document/agents/openai.yaml index 12b9f89..1ed710a 100644 --- a/.codex/skills/truthmark-document/agents/openai.yaml +++ b/.agents/skills/truthmark-document/agents/openai.yaml @@ -7,5 +7,5 @@ policy: allow_implicit_invocation: false truthmark: - version: "1.6.1" + version: "2.1.0" refresh_command: "truthmark init" diff --git a/.codex/skills/truthmark-document/helper-manifest.yml b/.agents/skills/truthmark-document/helper-manifest.yml similarity index 86% rename from .codex/skills/truthmark-document/helper-manifest.yml rename to .agents/skills/truthmark-document/helper-manifest.yml index 2446476..175e1a0 100644 --- a/.codex/skills/truthmark-document/helper-manifest.yml +++ b/.agents/skills/truthmark-document/helper-manifest.yml @@ -1,8 +1,8 @@ -# Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +# Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. helpers: validate-document-report: optional: true - runner: truthmark>=1.6.1 + runner: truthmark>=2.1.0 command: argv: - truthmark @@ -17,7 +17,7 @@ helpers: fallback: manually validate support/report-template.md required sections and structured Evidence checked entries validate-write-lease: optional: true - runner: truthmark>=1.6.1 + runner: truthmark>=2.1.0 command: argv: - truthmark diff --git a/.codex/skills/truthmark-document/support/helper-policy.md b/.agents/skills/truthmark-document/support/helper-policy.md similarity index 86% rename from .codex/skills/truthmark-document/support/helper-policy.md rename to .agents/skills/truthmark-document/support/helper-policy.md index e545d84..2cb7bd6 100644 --- a/.codex/skills/truthmark-document/support/helper-policy.md +++ b/.agents/skills/truthmark-document/support/helper-policy.md @@ -1,6 +1,6 @@ # Optional Helper CLI Policy -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Optional helper CLI commands may collect deterministic checkout facts or validate artifacts. If the Truthmark CLI is unavailable or too old for a declared helper, continue manually using this procedure and report which helper was skipped. Helper output is derived evidence; it does not override direct checkout inspection, workflow write boundaries, or parent acceptance. @@ -11,8 +11,8 @@ Runner detection: - Do not fail the workflow solely because a helper cannot run. Available helpers: -- validate-document-report: optional truthmark>=1.6.1; manual fallback: manually validate support/report-template.md required sections and structured Evidence checked entries -- validate-write-lease: optional truthmark>=1.6.1; manual fallback: manually compare declared allowedWrites and forbiddenWrites with the actual changed files +- validate-document-report: optional truthmark>=2.1.0; manual fallback: manually validate support/report-template.md required sections and structured Evidence checked entries +- validate-write-lease: optional truthmark>=2.1.0; manual fallback: manually compare declared allowedWrites and forbiddenWrites with the actual changed files Final reports should include helper status when helpers are declared for this workflow: diff --git a/.codex/skills/truthmark-document/support/procedure.md b/.agents/skills/truthmark-document/support/procedure.md similarity index 93% rename from .codex/skills/truthmark-document/support/procedure.md rename to .agents/skills/truthmark-document/support/procedure.md index 3a38560..be8590f 100644 --- a/.codex/skills/truthmark-document/support/procedure.md +++ b/.agents/skills/truthmark-document/support/procedure.md @@ -1,6 +1,6 @@ # Truthmark Document Procedure -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. # Truthmark Document @@ -14,7 +14,7 @@ Truth Document is manual and implementation-first: - Repository instruction files and explicitly configured policy docs remain instruction authority when present; do not assume a repository uses any particular policy path. Implementation code and canonical truth docs are inspected evidence for current behavior; they do not silently override workflow write boundaries. - document current implemented behavior; do not invent future behavior or planned endpoints -- may write canonical truth docs and docs/truthmark/areas.md or relevant child route files only +- may write canonical truth docs and docs/truthmark/routes/areas.md or relevant child route files only - must not write functional code - when routing is missing, stale, broad, overloaded, catch-all, or cannot map the behavior to a bounded truth owner, run Truth Structure first when routing repair is safe and in scope - block and recommend Truth Structure when routing repair is unsafe, ambiguous, or outside the task boundary @@ -44,12 +44,12 @@ Evidence Gate: Repository intelligence artifacts are optional derived context: RepoIndex, RouteMap, ImpactSet, and ContextPack may guide routing, context selection, and verification planning when available. They do not override checkout evidence, canonical truth docs, route files, or workflow write boundaries. If unavailable, inspect any present Truthmark config, route files, source files, truth docs, and tests directly, then report that repository-intelligence artifacts were not generated. -When creating or updating a truth doc, inspect the routed truth kind and use the matching `docs/templates/-doc.md` template. +When creating or updating a truth doc, inspect the routed truth kind and use the matching template under the configured Truthmark templates root. Supported kinds: behavior, contract, architecture, workflow, operations, and test-behavior. Treat the HTML comments under each template section as normative authoring guidance for that section. Align existing docs to that template and write or repair section content so it satisfies the comment guidance while preserving accurate authored content. If the template is missing, use Scope, Product Decisions, Rationale, and the kind-specific current-truth section. -Teams may edit the template files under docs/templates/ to define their local truth-doc standards. +Teams may edit template files under the configured Truthmark templates root to define their local truth-doc standards. Truth-doc shape repair gate: - Truth Document may restructure only truth docs for the implemented behavior being documented. - repair shape in place only after the ownership gate confirms the doc is the right bounded owner @@ -61,9 +61,9 @@ Maintain architecture docs only for structure-level changes: system structure, m Keep ordinary behavior, endpoints, UI copy, validation rules, and bug fixes in behavior or contract docs unless they change those boundaries. Truthmark hierarchy hints: - Config, when present: .truthmark/config.yml -- Root route index, when present: docs/truthmark/areas.md -- Area route files, when present: docs/truthmark/areas/**/*.md -- Truth docs, when present: docs/truth/**/*.md +- Root route index, when present: docs/truthmark/routes/areas.md +- Area route files, when present: docs/truthmark/routes/areas/**/*.md +- Truth docs, when present: docs/truthmark/truth/**/*.md Decision truth lives in the canonical doc it governs; date active decisions inline when added or changed. Do not create separate active-decision ADR/planning logs; replace the active decision and let Git history carry the audit trail. Update Product Decisions and Rationale when a decision changes behavior. diff --git a/.codex/skills/truthmark-document/support/report-template.md b/.agents/skills/truthmark-document/support/report-template.md similarity index 61% rename from .codex/skills/truthmark-document/support/report-template.md rename to .agents/skills/truthmark-document/support/report-template.md index 39c8efc..5e38b92 100644 --- a/.codex/skills/truthmark-document/support/report-template.md +++ b/.agents/skills/truthmark-document/support/report-template.md @@ -1,6 +1,6 @@ # Truthmark Document Report Template -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Report completion in this shape: ```md @@ -10,23 +10,23 @@ Implementation reviewed: - src/routing/area-resolver.ts Ownership reviewed: -- docs/truthmark/areas.md +- docs/truthmark/routes/areas.md Truth docs created: -- docs/truth/contracts.md +- docs/truthmark/truth/contracts.md Truth docs updated: -- docs/truth/check-diagnostics.md +- docs/truthmark/truth/check-diagnostics.md Truth docs restructured: -- docs/truth/check-diagnostics.md +- docs/truthmark/truth/check-diagnostics.md Routing updated: -- docs/truthmark/areas.md +- docs/truthmark/routes/areas.md Evidence checked: - Claim: Route resolution behavior is documented in the contracts truth doc. - Evidence: src/routing/area-resolver.ts:14 / docs/truthmark/areas.md:9 + Evidence: src/routing/area-resolver.ts:14 / docs/truthmark/routes/areas.md:9 Result: supported Helper scripts: diff --git a/.codex/skills/truthmark-document/support/subagents-and-leases.md b/.agents/skills/truthmark-document/support/subagents-and-leases.md similarity index 94% rename from .codex/skills/truthmark-document/support/subagents-and-leases.md rename to .agents/skills/truthmark-document/support/subagents-and-leases.md index b91d76b..b15fea1 100644 --- a/.codex/skills/truthmark-document/support/subagents-and-leases.md +++ b/.agents/skills/truthmark-document/support/subagents-and-leases.md @@ -1,6 +1,6 @@ # Truthmark Document Subagents And Leases -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Codex subagent mode: - use automatically when this workflow runs in Codex and the parent agent chooses bounded subagent fan-out diff --git a/.codex/skills/truthmark-preview/SKILL.md b/.agents/skills/truthmark-preview/SKILL.md similarity index 73% rename from .codex/skills/truthmark-preview/SKILL.md rename to .agents/skills/truthmark-preview/SKILL.md index c9acc27..7db8d92 100644 --- a/.codex/skills/truthmark-preview/SKILL.md +++ b/.agents/skills/truthmark-preview/SKILL.md @@ -3,25 +3,24 @@ name: truthmark-preview description: Use when the user explicitly asks to preview likely workflow routing, target files, writes, or subagent use before edits. Not for validation, automatic gates, final correctness, or replacing Truth Check. argument-hint: Optional requested outcome, code area, doc path, or routing question user-invocable: true -truthmark-version: 1.6.1 +truthmark-version: 2.1.0 --- # Truthmark Preview Use this skill only when the user explicitly asks to preview Truthmark routing or workflow choice before edits. - Invocations: OpenCode /skill truthmark-preview; Codex /truthmark-preview or $truthmark-preview; Claude Code /truthmark-preview; GitHub Copilot /truthmark-preview; Gemini CLI /truthmark:preview. Quick procedure: - Follow repository instruction files that exist in this checkout; do not assume any optional policy path exists. -- Inspect .truthmark/config.yml and configured route files (docs/truthmark/areas.md; docs/truthmark/areas/) only when they exist; then inspect only the truth docs or implementation files needed to preview ownership. +- Inspect .truthmark/config.yml and configured route files (docs/truthmark/routes/areas.md; docs/truthmark/routes/areas/) only when they exist; then inspect only the truth docs or implementation files needed to preview ownership. - Truth Preview is read-only; this report is intended, not authorized. - must not edit files and must not issue write leases; do not run Truth Sync automatically, replace Truth Check, claim final correctness, or mutate code. - Use optional read-only route-auditor evidence only when it reduces context or clarifies ownership. - Hand off to the selected workflow after user approval. Progressive disclosure: -- support/procedure.md -- support/report-template.md -- support/subagents-and-leases.md +- support/procedure.md — read before edits or detailed auditing; contains core quality gates +- support/report-template.md — read before the final report +- support/subagents-and-leases.md — read only when using subagents, leases, or accepting worker output diff --git a/.codex/skills/truthmark-preview/agents/openai.yaml b/.agents/skills/truthmark-preview/agents/openai.yaml similarity index 94% rename from .codex/skills/truthmark-preview/agents/openai.yaml rename to .agents/skills/truthmark-preview/agents/openai.yaml index b3b0b0f..fc75934 100644 --- a/.codex/skills/truthmark-preview/agents/openai.yaml +++ b/.agents/skills/truthmark-preview/agents/openai.yaml @@ -7,5 +7,5 @@ policy: allow_implicit_invocation: false truthmark: - version: "1.6.1" + version: "2.1.0" refresh_command: "truthmark init" diff --git a/.codex/skills/truthmark-preview/support/procedure.md b/.agents/skills/truthmark-preview/support/procedure.md similarity index 80% rename from .codex/skills/truthmark-preview/support/procedure.md rename to .agents/skills/truthmark-preview/support/procedure.md index 2a3f60a..276926b 100644 --- a/.codex/skills/truthmark-preview/support/procedure.md +++ b/.agents/skills/truthmark-preview/support/procedure.md @@ -1,6 +1,6 @@ # Truthmark Preview Procedure -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Use this skill only when the user explicitly asks to preview Truthmark routing or workflow choice before edits. @@ -15,8 +15,8 @@ Purpose: Read: - .truthmark/config.yml, only when present -- docs/truthmark/areas.md, only when present -- relevant child route files under docs/truthmark/areas/, only when present +- docs/truthmark/routes/areas.md, only when present +- relevant child route files under docs/truthmark/routes/areas/, only when present - relevant truth docs and implementation files needed to preview ownership - Repository instruction files and explicitly configured policy docs remain instruction authority when present; do not assume a repository uses any particular policy path. Implementation code and canonical truth docs are inspected evidence for current behavior; they do not silently override workflow write boundaries. @@ -38,6 +38,6 @@ Suggested subagent use: Truthmark hierarchy hints: - Config, when present: .truthmark/config.yml -- Root route index, when present: docs/truthmark/areas.md -- Area route files, when present: docs/truthmark/areas/**/*.md -- Truth docs, when present: docs/truth/**/*.md +- Root route index, when present: docs/truthmark/routes/areas.md +- Area route files, when present: docs/truthmark/routes/areas/**/*.md +- Truth docs, when present: docs/truthmark/truth/**/*.md diff --git a/.codex/skills/truthmark-preview/support/report-template.md b/.agents/skills/truthmark-preview/support/report-template.md similarity index 81% rename from .codex/skills/truthmark-preview/support/report-template.md rename to .agents/skills/truthmark-preview/support/report-template.md index 2e63308..bff96a9 100644 --- a/.codex/skills/truthmark-preview/support/report-template.md +++ b/.agents/skills/truthmark-preview/support/report-template.md @@ -1,6 +1,6 @@ # Truthmark Preview Report Template -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Report completion in this shape: ```md @@ -18,15 +18,15 @@ Why this workflow: - forbidden adjacency considered: must not edit functional code Likely route owner: -- route file: docs/truthmark/areas.md -- truth doc: docs/truth/example.md +- route file: docs/truthmark/routes/areas.md +- truth doc: docs/truthmark/truth/example.md - confidence: medium Expected write classes: - truth docs Expected target files: -- docs/truth/example.md +- docs/truthmark/truth/example.md Suggested subagent use: - read-only verifiers: truth_route_auditor diff --git a/.codex/skills/truthmark-preview/support/subagents-and-leases.md b/.agents/skills/truthmark-preview/support/subagents-and-leases.md similarity index 89% rename from .codex/skills/truthmark-preview/support/subagents-and-leases.md rename to .agents/skills/truthmark-preview/support/subagents-and-leases.md index 900e28f..0b91ede 100644 --- a/.codex/skills/truthmark-preview/support/subagents-and-leases.md +++ b/.agents/skills/truthmark-preview/support/subagents-and-leases.md @@ -1,6 +1,6 @@ # Truthmark Preview Subagents And Leases -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Codex subagent mode: - use automatically when this workflow runs in Codex and the parent agent chooses bounded subagent fan-out diff --git a/.codex/skills/truthmark-realize/SKILL.md b/.agents/skills/truthmark-realize/SKILL.md similarity index 77% rename from .codex/skills/truthmark-realize/SKILL.md rename to .agents/skills/truthmark-realize/SKILL.md index afbe84c..8256b8e 100644 --- a/.codex/skills/truthmark-realize/SKILL.md +++ b/.agents/skills/truthmark-realize/SKILL.md @@ -3,24 +3,23 @@ name: truthmark-realize description: Use when the user explicitly asks to realize Truthmark truth docs into code, including /truthmark-realize, $truthmark-realize, or /truthmark:realize. Not for syncing docs after code changes, documenting existing code, topology repair, or truth audits. argument-hint: Optional truth doc path, area, or desired code behavior to realize user-invocable: true -truthmark-version: 1.6.1 +truthmark-version: 2.1.0 --- # Truthmark Realize Use this skill only when the user explicitly asks to realize truth docs into code. - Invocations: OpenCode /skill truthmark-realize; Codex /truthmark-realize or $truthmark-realize; Claude Code /truthmark-realize; GitHub Copilot /truthmark-realize; Gemini CLI /truthmark:realize. Quick procedure: - Follow repository instruction files that exist in this checkout; do not assume any optional policy path exists. -- Read the source truth docs, inspect .truthmark/config.yml and configured route files (docs/truthmark/areas.md; docs/truthmark/areas/) only when they exist, then inspect tests and relevant functional code directly. +- Read the source truth docs, inspect .truthmark/config.yml and configured route files (docs/truthmark/routes/areas.md; docs/truthmark/routes/areas/) only when they exist, then inspect tests and relevant functional code directly. - Truth docs lead; code follows. - may write functional code only; must not edit truth docs or truth routing while realizing those docs. - Read support/procedure.md before changing code. - Read support/report-template.md before the final report. Progressive disclosure: -- support/procedure.md -- support/report-template.md +- support/procedure.md — read before edits or detailed auditing; contains core quality gates +- support/report-template.md — read before the final report diff --git a/.codex/skills/truthmark-realize/agents/openai.yaml b/.agents/skills/truthmark-realize/agents/openai.yaml similarity index 93% rename from .codex/skills/truthmark-realize/agents/openai.yaml rename to .agents/skills/truthmark-realize/agents/openai.yaml index 8ce7276..b5bbffa 100644 --- a/.codex/skills/truthmark-realize/agents/openai.yaml +++ b/.agents/skills/truthmark-realize/agents/openai.yaml @@ -7,5 +7,5 @@ policy: allow_implicit_invocation: false truthmark: - version: "1.6.1" + version: "2.1.0" refresh_command: "truthmark init" diff --git a/.codex/skills/truthmark-realize/support/procedure.md b/.agents/skills/truthmark-realize/support/procedure.md similarity index 84% rename from .codex/skills/truthmark-realize/support/procedure.md rename to .agents/skills/truthmark-realize/support/procedure.md index 2deeaff..c419a77 100644 --- a/.codex/skills/truthmark-realize/support/procedure.md +++ b/.agents/skills/truthmark-realize/support/procedure.md @@ -1,6 +1,6 @@ # Truthmark Realize Procedure -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. # Truthmark Realize @@ -17,7 +17,7 @@ Truth Realize is doc-first: Workflow: 1. Read the updated truth docs named by the user, or infer the relevant docs from configured route files when present. -2. Inspect .truthmark/config.yml and configured route files (docs/truthmark/areas.md; docs/truthmark/areas/) only when they exist; then read tests and the relevant functional code. +2. Inspect .truthmark/config.yml and configured route files (docs/truthmark/routes/areas.md; docs/truthmark/routes/areas/) only when they exist; then read tests and the relevant functional code. 3. Repository instruction files and explicitly configured policy docs remain instruction authority when present; do not assume a repository uses any particular policy path. Implementation code and canonical truth docs are inspected evidence for current behavior; they do not silently override workflow write boundaries. Truth-doc ownership gate: @@ -31,9 +31,9 @@ Truth-doc ownership gate: 7. Report changed code files and verification steps. Truthmark hierarchy hints: - Config, when present: .truthmark/config.yml -- Root route index, when present: docs/truthmark/areas.md -- Area route files, when present: docs/truthmark/areas/**/*.md -- Truth docs, when present: docs/truth/**/*.md +- Root route index, when present: docs/truthmark/routes/areas.md +- Area route files, when present: docs/truthmark/routes/areas/**/*.md +- Truth docs, when present: docs/truthmark/truth/**/*.md Read and write boundaries: diff --git a/.codex/skills/truthmark-realize/support/report-template.md b/.agents/skills/truthmark-realize/support/report-template.md similarity index 62% rename from .codex/skills/truthmark-realize/support/report-template.md rename to .agents/skills/truthmark-realize/support/report-template.md index 6e887cc..b540f61 100644 --- a/.codex/skills/truthmark-realize/support/report-template.md +++ b/.agents/skills/truthmark-realize/support/report-template.md @@ -1,6 +1,6 @@ # Truthmark Realize Report Template -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Report completion in this shape: @@ -8,7 +8,7 @@ Report completion in this shape: Truth Realize: completed Truth docs used: -- docs/truth/authentication/session-timeout.md +- docs/truthmark/truth/authentication/session-timeout.md Code updated: - src/auth/session.ts diff --git a/.codex/skills/truthmark-structure/SKILL.md b/.agents/skills/truthmark-structure/SKILL.md similarity index 73% rename from .codex/skills/truthmark-structure/SKILL.md rename to .agents/skills/truthmark-structure/SKILL.md index c250fc2..4e0d2ab 100644 --- a/.codex/skills/truthmark-structure/SKILL.md +++ b/.agents/skills/truthmark-structure/SKILL.md @@ -3,25 +3,24 @@ name: truthmark-structure description: Use when routing or truth ownership is missing, stale, broad, overloaded, catch-all, unrouteable, mixed-owner, needs split/repair, or needs new area setup. Not for documenting implemented behavior, syncing a code diff, or realizing docs into code. argument-hint: Optional area, directory, or routing concern user-invocable: true -truthmark-version: 1.6.1 +truthmark-version: 2.1.0 --- # Truthmark Structure Use this skill to design or repair Truthmark area structure. - Invocations: OpenCode /skill truthmark-structure; Codex /truthmark-structure or $truthmark-structure; Claude Code /truthmark-structure; GitHub Copilot /truthmark-structure; Gemini CLI /truthmark:structure. Quick procedure: - Follow repository instruction files that exist in this checkout; do not assume any optional policy path exists. -- Inspect .truthmark/config.yml and configured route files (docs/truthmark/areas.md; docs/truthmark/areas/) only when they exist; then inspect current docs and relevant code directly. +- Inspect .truthmark/config.yml and configured route files (docs/truthmark/routes/areas.md; docs/truthmark/routes/areas/) only when they exist; then inspect current docs and relevant code directly. - Define areas by product or behavior ownership, not by mechanical directory mirroring. - Do not edit functional code. - Read support/procedure.md before writing route or starter truth-doc changes. - Read support/report-template.md before the final report. Progressive disclosure: -- support/procedure.md -- support/report-template.md -- support/subagents-and-leases.md +- support/procedure.md — read before edits or detailed auditing; contains core quality gates +- support/report-template.md — read before the final report +- support/subagents-and-leases.md — read only when using subagents, leases, or accepting worker output diff --git a/.codex/skills/truthmark-structure/agents/openai.yaml b/.agents/skills/truthmark-structure/agents/openai.yaml similarity index 94% rename from .codex/skills/truthmark-structure/agents/openai.yaml rename to .agents/skills/truthmark-structure/agents/openai.yaml index e1e73cc..3e5ec08 100644 --- a/.codex/skills/truthmark-structure/agents/openai.yaml +++ b/.agents/skills/truthmark-structure/agents/openai.yaml @@ -7,5 +7,5 @@ policy: allow_implicit_invocation: false truthmark: - version: "1.6.1" + version: "2.1.0" refresh_command: "truthmark init" diff --git a/.codex/skills/truthmark-structure/support/procedure.md b/.agents/skills/truthmark-structure/support/procedure.md similarity index 90% rename from .codex/skills/truthmark-structure/support/procedure.md rename to .agents/skills/truthmark-structure/support/procedure.md index bf91e44..5112d6e 100644 --- a/.codex/skills/truthmark-structure/support/procedure.md +++ b/.agents/skills/truthmark-structure/support/procedure.md @@ -1,6 +1,6 @@ # Truthmark Structure Procedure -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Use this skill to design or repair Truthmark area structure. Invocations: OpenCode /skill truthmark-structure; Codex /truthmark-structure or $truthmark-structure; Claude Code /truthmark-structure; GitHub Copilot /truthmark-structure; Gemini CLI /truthmark:structure. @@ -8,20 +8,20 @@ Truth Structure is agent-native: - inspect repository layout, current docs, Truthmark config and route files when present, and relevant code directly - Repository instruction files and explicitly configured policy docs remain instruction authority when present; do not assume a repository uses any particular policy path. Implementation code and canonical truth docs are inspected evidence for current behavior; they do not silently override workflow write boundaries. -- inspect the configured root route index at docs/truthmark/areas.md and relevant child route files under docs/truthmark/areas/ when they exist +- inspect the configured root route index at docs/truthmark/routes/areas.md and relevant child route files under docs/truthmark/routes/areas/ when they exist - define areas by product or behavior ownership, not by mechanical directory mirroring -- create or repair docs/truthmark/areas.md +- create or repair docs/truthmark/routes/areas.md - create starter truth docs when useful and when they belong in the canonical current-truth surface - Starter truth docs must use closed YAML frontmatter bounded by opening and closing --- lines; include status, doc_type, last_reviewed, and source_of_truth inside that frontmatter. - Starter truth docs must include ## Product Decisions and ## Rationale sections. -When creating or updating a truth doc, inspect the routed truth kind and use the matching `docs/templates/-doc.md` template. +When creating or updating a truth doc, inspect the routed truth kind and use the matching template under the configured Truthmark templates root. Supported kinds: behavior, contract, architecture, workflow, operations, and test-behavior. Treat the HTML comments under each template section as normative authoring guidance for that section. Align existing docs to that template and write or repair section content so it satisfies the comment guidance while preserving accurate authored content. If the template is missing, use Scope, Product Decisions, Rationale, and the kind-specific current-truth section. -Teams may edit the template files under docs/templates/ to define their local truth-doc standards. -- use docs/truth/**, docs/architecture/**, or docs/standards/** for current truth destinations +Teams may edit template files under the configured Truthmark templates root to define their local truth-doc standards. +- use docs/truthmark/truth/** for current truth destinations - use only canonical current-truth destinations for starter truth docs - keep active Product Decisions and Rationale in the canonical doc that owns the behavior - preserve unrelated authored content @@ -41,7 +41,7 @@ Do not: - do not create generic catch-all docs - do not treat README files as Sync targets ## Topology Governance -Truth Structure owns documentation topology. Do not depend on humans to manually organize docs/truth. Treat the configured truth root as a managed semantic root. +Truth Structure owns documentation topology. Do not depend on humans to manually organize docs/truthmark/truth. Treat the configured truth root as a managed semantic root. Inspect controllers, routes, handlers, services, packages, tests, existing truth docs, and route files; infer product and domain ownership from behavior boundaries, not from mechanical directory mirroring. When topology pressure exists, repair structure before creating or extending truth docs. Truth-doc ownership gate: @@ -62,7 +62,7 @@ Topology pressure signals: - the configured truth root has many direct non-index docs - a changed controller, route, or service cannot map to a specific behavior doc - Truth Sync would need to create a new generic truth doc because routing is too broad -- endpoint or controller names reveal domains missing from docs/truthmark/areas/** +- endpoint or controller names reveal domains missing from docs/truthmark/routes/areas/** Use these review thresholds as guidance: - more than 10 direct truth docs in one folder - more than 15 leaf areas in one child route file @@ -71,7 +71,7 @@ Use these review thresholds as guidance: Repair rules: - split broad, overloaded, or catch-all areas into behavior-owned child route files - split mixed-owner truth docs into bounded owner docs before adding new behavior claims -- create route files under docs/truthmark/areas/ when a product/domain boundary is clear +- create route files under docs/truthmark/routes/areas/ when a product/domain boundary is clear - create behavior truth docs under the configured truth root only when behavior lacks a current doc - README.md files are indexes, not Truth Sync targets - prefer bounded leaf truth docs at //.md @@ -102,9 +102,9 @@ Portable fallback: - Use a subagent only when the host supports that pattern; otherwise perform the topology repair inline. Truthmark hierarchy hints: - Config, when present: .truthmark/config.yml -- Root route index, when present: docs/truthmark/areas.md -- Area route files, when present: docs/truthmark/areas/**/*.md -- Truth docs, when present: docs/truth/**/*.md +- Root route index, when present: docs/truthmark/routes/areas.md +- Area route files, when present: docs/truthmark/routes/areas/**/*.md +- Truth docs, when present: docs/truthmark/truth/**/*.md Decision truth lives in the canonical doc it governs; date active decisions inline when added or changed. Do not create separate active-decision ADR/planning logs; replace the active decision and let Git history carry the audit trail. Update Product Decisions and Rationale when a decision changes behavior. diff --git a/.codex/skills/truthmark-structure/support/report-template.md b/.agents/skills/truthmark-structure/support/report-template.md similarity index 57% rename from .codex/skills/truthmark-structure/support/report-template.md rename to .agents/skills/truthmark-structure/support/report-template.md index 11efef7..1be260b 100644 --- a/.codex/skills/truthmark-structure/support/report-template.md +++ b/.agents/skills/truthmark-structure/support/report-template.md @@ -1,32 +1,32 @@ # Truthmark Structure Report Template -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Report completion in this shape: ```md Truth Structure: completed Topology reviewed: - controllers: src/auth/** -- docs root: docs/truth -- route files: docs/truthmark/areas.md +- docs root: docs/truthmark/truth +- route files: docs/truthmark/routes/areas.md Areas reviewed: - src/auth/** Routing updated: -- docs/truthmark/areas.md +- docs/truthmark/routes/areas.md Initial truth boundary: - Area: Authentication - Code: src/auth/** -- Truth owner: docs/truth/authentication/session.md +- Truth owner: docs/truthmark/truth/authentication/session.md - Scope: session behavior only Truth docs created: -- docs/truth/authentication/session.md +- docs/truthmark/truth/authentication/session.md Truth docs split: -- docs/truth/authentication/README.md -> docs/truth/authentication/session.md +- docs/truthmark/truth/authentication/README.md -> docs/truthmark/truth/authentication/session.md Truth docs restructured: -- docs/truth/authentication/README.md +- docs/truthmark/truth/authentication/README.md Evidence checked: - Claim: Session behavior belongs to a dedicated Authentication truth owner. - Evidence: src/auth/** / docs/truthmark/areas.md:7 + Evidence: src/auth/** / docs/truthmark/routes/areas.md:7 Result: supported Topology decisions: - Added an Authentication area because session behavior has a distinct code surface and truth owner. diff --git a/.codex/skills/truthmark-structure/support/subagents-and-leases.md b/.agents/skills/truthmark-structure/support/subagents-and-leases.md similarity index 89% rename from .codex/skills/truthmark-structure/support/subagents-and-leases.md rename to .agents/skills/truthmark-structure/support/subagents-and-leases.md index 4d177c6..a5b4f52 100644 --- a/.codex/skills/truthmark-structure/support/subagents-and-leases.md +++ b/.agents/skills/truthmark-structure/support/subagents-and-leases.md @@ -1,6 +1,6 @@ # Truthmark Structure Subagents And Leases -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Codex subagent mode: - use automatically when this workflow runs in Codex and the parent agent chooses bounded subagent fan-out diff --git a/.codex/skills/truthmark-sync/SKILL.md b/.agents/skills/truthmark-sync/SKILL.md similarity index 67% rename from .codex/skills/truthmark-sync/SKILL.md rename to .agents/skills/truthmark-sync/SKILL.md index 94278d7..ff1d4eb 100644 --- a/.codex/skills/truthmark-sync/SKILL.md +++ b/.agents/skills/truthmark-sync/SKILL.md @@ -3,29 +3,28 @@ name: truthmark-sync description: Use automatically at finish-time after functional code changes, or explicit /truthmark-sync, $truthmark-sync, or /truthmark:sync. Skip docs-only, formatting-only, behavior-preserving renames, missing config, and no-code changes. Not for doc-first realization or manual topology design. argument-hint: Optional changed-code area, truth-doc area, or sync focus user-invocable: true -truthmark-version: 1.6.1 +truthmark-version: 2.1.0 --- # Truthmark Sync Use this skill automatically before finishing when functional code changed since the last successful Truth Sync. Also run it immediately when the user explicitly invokes Truth Sync. - Invocations: OpenCode /skill truthmark-sync; Codex /truthmark-sync or $truthmark-sync; Claude Code /truthmark-sync; GitHub Copilot /truthmark-sync; Gemini CLI /truthmark:sync. Quick procedure: - Follow repository instruction files that exist in this checkout; do not assume any optional policy path exists. - Skip docs-only, formatting-only, behavior-preserving renames with no truth impact, missing config, and no-code changes. -- Inspect .truthmark/config.yml and configured route files (docs/truthmark/areas.md; docs/truthmark/areas/) only when they exist; then inspect relevant canonical docs directly. +- Inspect .truthmark/config.yml and configured route files (docs/truthmark/routes/areas.md; docs/truthmark/routes/areas/) only when they exist; then inspect relevant canonical docs directly. - direct checkout inspection is the canonical path; do not require the truthmark binary. - May write canonical truth docs and truth routing files only; must not rewrite functional code. - Read support/procedure.md before editing truth docs. -- Read support/subagents-and-leases.md before dispatching or accepting worker output. +- Read support/subagents-and-leases.md only when dispatching or accepting worker output. - Read support/report-template.md before the final report. Progressive disclosure: -- support/procedure.md -- support/report-template.md -- support/subagents-and-leases.md -- helper-manifest.yml -- support/helper-policy.md +- support/procedure.md — read before edits or detailed auditing; contains core quality gates +- support/report-template.md — read before the final report +- support/subagents-and-leases.md — read only when using subagents, leases, or accepting worker output +- helper-manifest.yml — read only when invoking helper validators or validating helper registration +- support/helper-policy.md — read only when invoking helper validators or reporting helper status diff --git a/.codex/skills/truthmark-sync/agents/openai.yaml b/.agents/skills/truthmark-sync/agents/openai.yaml similarity index 94% rename from .codex/skills/truthmark-sync/agents/openai.yaml rename to .agents/skills/truthmark-sync/agents/openai.yaml index c335b08..acb82ec 100644 --- a/.codex/skills/truthmark-sync/agents/openai.yaml +++ b/.agents/skills/truthmark-sync/agents/openai.yaml @@ -7,5 +7,5 @@ policy: allow_implicit_invocation: true truthmark: - version: "1.6.1" + version: "2.1.0" refresh_command: "truthmark init" diff --git a/.codex/skills/truthmark-sync/helper-manifest.yml b/.agents/skills/truthmark-sync/helper-manifest.yml similarity index 87% rename from .codex/skills/truthmark-sync/helper-manifest.yml rename to .agents/skills/truthmark-sync/helper-manifest.yml index 669b903..dd0153a 100644 --- a/.codex/skills/truthmark-sync/helper-manifest.yml +++ b/.agents/skills/truthmark-sync/helper-manifest.yml @@ -1,8 +1,8 @@ -# Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +# Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. helpers: validate-sync-report: optional: true - runner: truthmark>=1.6.1 + runner: truthmark>=2.1.0 command: argv: - truthmark @@ -17,7 +17,7 @@ helpers: fallback: "manually validate support/report-template.md and check Evidence checked entries match Claim, indented Evidence, and Result: supported | narrowed | removed | blocked" validate-write-lease: optional: true - runner: truthmark>=1.6.1 + runner: truthmark>=2.1.0 command: argv: - truthmark diff --git a/.codex/skills/truthmark-sync/support/helper-policy.md b/.agents/skills/truthmark-sync/support/helper-policy.md similarity index 86% rename from .codex/skills/truthmark-sync/support/helper-policy.md rename to .agents/skills/truthmark-sync/support/helper-policy.md index 78e8645..6c44128 100644 --- a/.codex/skills/truthmark-sync/support/helper-policy.md +++ b/.agents/skills/truthmark-sync/support/helper-policy.md @@ -1,6 +1,6 @@ # Optional Helper CLI Policy -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Optional helper CLI commands may collect deterministic checkout facts or validate artifacts. If the Truthmark CLI is unavailable or too old for a declared helper, continue manually using this procedure and report which helper was skipped. Helper output is derived evidence; it does not override direct checkout inspection, workflow write boundaries, or parent acceptance. @@ -11,8 +11,8 @@ Runner detection: - Do not fail the workflow solely because a helper cannot run. Available helpers: -- validate-sync-report: optional truthmark>=1.6.1; manual fallback: manually validate support/report-template.md and check Evidence checked entries match Claim, indented Evidence, and Result: supported | narrowed | removed | blocked -- validate-write-lease: optional truthmark>=1.6.1; manual fallback: manually compare declared allowedWrites and forbiddenWrites with the actual changed files +- validate-sync-report: optional truthmark>=2.1.0; manual fallback: manually validate support/report-template.md and check Evidence checked entries match Claim, indented Evidence, and Result: supported | narrowed | removed | blocked +- validate-write-lease: optional truthmark>=2.1.0; manual fallback: manually compare declared allowedWrites and forbiddenWrites with the actual changed files Final reports should include helper status when helpers are declared for this workflow: diff --git a/.codex/skills/truthmark-sync/support/procedure.md b/.agents/skills/truthmark-sync/support/procedure.md similarity index 95% rename from .codex/skills/truthmark-sync/support/procedure.md rename to .agents/skills/truthmark-sync/support/procedure.md index e839f8f..ff0f6f7 100644 --- a/.codex/skills/truthmark-sync/support/procedure.md +++ b/.agents/skills/truthmark-sync/support/procedure.md @@ -1,6 +1,6 @@ # Truthmark Sync Procedure -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Use this skill automatically before finishing when functional code changed since the last successful Truth Sync. Also run it immediately when the user explicitly invokes Truth Sync. Invocations: OpenCode /skill truthmark-sync; Codex /truthmark-sync or $truthmark-sync; Claude Code /truthmark-sync; GitHub Copilot /truthmark-sync; Gemini CLI /truthmark:sync. @@ -34,12 +34,12 @@ Product Decisions/Rationale preservation gate: - remove or narrow a decision or rationale only when checkout evidence shows it is stale or unsupported, and report the exact claim, evidence, and result - if ownership of a decision or rationale is unclear, block with manual-review files instead of deleting it or guessing - after the edit, verify every touched truth doc still has Product Decisions and Rationale sections and every pre-existing entry is preserved, moved, narrowed, removed with evidence, or blocked -When creating or updating a truth doc, inspect the routed truth kind and use the matching `docs/templates/-doc.md` template. +When creating or updating a truth doc, inspect the routed truth kind and use the matching template under the configured Truthmark templates root. Supported kinds: behavior, contract, architecture, workflow, operations, and test-behavior. Treat the HTML comments under each template section as normative authoring guidance for that section. Align existing docs to that template and write or repair section content so it satisfies the comment guidance while preserving accurate authored content. If the template is missing, use Scope, Product Decisions, Rationale, and the kind-specific current-truth section. -Teams may edit the template files under docs/templates/ to define their local truth-doc standards. +Teams may edit template files under the configured Truthmark templates root to define their local truth-doc standards. Truth-doc shape repair gate: - Truth Sync may restructure only truth docs impacted by the current functional-code change. - repair shape in place only after the ownership gate confirms the doc is the right bounded owner @@ -72,9 +72,9 @@ Helper status reporting: - Helper output is derived evidence and never replaces direct checkout inspection, evidence review, or parent acceptance. Truthmark hierarchy hints: - Config, when present: .truthmark/config.yml -- Root route index, when present: docs/truthmark/areas.md -- Area route files, when present: docs/truthmark/areas/**/*.md -- Truth docs, when present: docs/truth/**/*.md +- Root route index, when present: docs/truthmark/routes/areas.md +- Area route files, when present: docs/truthmark/routes/areas/**/*.md +- Truth docs, when present: docs/truthmark/truth/**/*.md Decision truth lives in the canonical doc it governs; date active decisions inline when added or changed. Do not create separate active-decision ADR/planning logs; replace the active decision and let Git history carry the audit trail. Update Product Decisions and Rationale when a decision changes behavior. diff --git a/.codex/skills/truthmark-sync/support/report-template.md b/.agents/skills/truthmark-sync/support/report-template.md similarity index 71% rename from .codex/skills/truthmark-sync/support/report-template.md rename to .agents/skills/truthmark-sync/support/report-template.md index 4cca036..4dfa42d 100644 --- a/.codex/skills/truthmark-sync/support/report-template.md +++ b/.agents/skills/truthmark-sync/support/report-template.md @@ -1,6 +1,6 @@ # Truthmark Sync Report Template -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Report completion in this shape: ```md @@ -10,14 +10,14 @@ Changed code reviewed: - src/auth/session.ts Ownership reviewed: -- docs/truthmark/areas.md +- docs/truthmark/routes/areas.md Truth docs updated: -- docs/truth/repository/overview.md +- docs/truthmark/truth/repository/overview.md Evidence checked: - Claim: Session timeout behavior is documented in the mapped repository truth doc. - Evidence: src/auth/session.ts:12 / docs/truthmark/areas.md:11 + Evidence: src/auth/session.ts:12 / docs/truthmark/routes/areas.md:11 Result: supported Helper scripts: @@ -34,7 +34,7 @@ Reason: - routing repair is not allowed Files requiring manual review: -- docs/truthmark/areas.md +- docs/truthmark/routes/areas.md Next action: - update routing metadata and rerun Truth Sync diff --git a/.codex/skills/truthmark-sync/support/subagents-and-leases.md b/.agents/skills/truthmark-sync/support/subagents-and-leases.md similarity index 94% rename from .codex/skills/truthmark-sync/support/subagents-and-leases.md rename to .agents/skills/truthmark-sync/support/subagents-and-leases.md index 275f158..d29ded4 100644 --- a/.codex/skills/truthmark-sync/support/subagents-and-leases.md +++ b/.agents/skills/truthmark-sync/support/subagents-and-leases.md @@ -1,6 +1,6 @@ # Truthmark Sync Subagents And Leases -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Codex subagent mode: - use automatically when this workflow runs in Codex and the parent agent chooses bounded subagent fan-out diff --git a/.claude/agents/truth-claim-verifier.md b/.claude/agents/truth-claim-verifier.md index 03280f0..8b64222 100644 --- a/.claude/agents/truth-claim-verifier.md +++ b/.claude/agents/truth-claim-verifier.md @@ -4,7 +4,7 @@ description: Read-only Truthmark claim verifier for checking canonical truth aga tools: Read, Grep, Glob, LS --- -# Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +# Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Manual invocation: use the truth-claim-verifier subagent. diff --git a/.claude/agents/truth-doc-reviewer.md b/.claude/agents/truth-doc-reviewer.md index e2e158b..c841e51 100644 --- a/.claude/agents/truth-doc-reviewer.md +++ b/.claude/agents/truth-doc-reviewer.md @@ -4,7 +4,7 @@ description: Read-only Truthmark doc reviewer for shape, decision, rationale, an tools: Read, Grep, Glob, LS --- -# Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +# Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Manual invocation: use the truth-doc-reviewer subagent. diff --git a/.claude/agents/truth-doc-writer.md b/.claude/agents/truth-doc-writer.md index 853efb9..6cd79d5 100644 --- a/.claude/agents/truth-doc-writer.md +++ b/.claude/agents/truth-doc-writer.md @@ -4,7 +4,7 @@ description: Write-capable Truthmark doc worker for one parent-leased truth-docu tools: Read, Grep, Glob, LS, Edit, MultiEdit --- -# Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +# Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Manual invocation: use the truth-doc-writer subagent with an explicit parent write lease. diff --git a/.claude/agents/truth-route-auditor.md b/.claude/agents/truth-route-auditor.md index 8b86603..9a194b6 100644 --- a/.claude/agents/truth-route-auditor.md +++ b/.claude/agents/truth-route-auditor.md @@ -4,7 +4,7 @@ description: Read-only Truthmark route auditor for bounded routing and ownership tools: Read, Grep, Glob, LS --- -# Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +# Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Manual invocation: use the truth-route-auditor subagent. diff --git a/.claude/skills/truthmark-check/SKILL.md b/.claude/skills/truthmark-check/SKILL.md index e330fd0..b8b5902 100644 --- a/.claude/skills/truthmark-check/SKILL.md +++ b/.claude/skills/truthmark-check/SKILL.md @@ -3,26 +3,24 @@ name: truthmark-check description: Use when the user asks to audit repository truth health, routing, ownership, or canonical docs. Not for normal lint/test/typecheck/code-review verification, finish-time Sync, or silently rewriting docs. argument-hint: Optional area, doc path, or audit focus user-invocable: true -truthmark-version: 1.6.1 +truthmark-version: 2.1.0 --- # Truthmark Check Use this skill to audit repository truth health. - Invocations: OpenCode /skill truthmark-check; Codex /truthmark-check or $truthmark-check; Claude Code /truthmark-check; GitHub Copilot /truthmark-check; Gemini CLI /truthmark:check. Quick procedure: - Follow repository instruction files that exist in this checkout; do not assume any optional policy path exists. -- Inspect .truthmark/config.yml and configured route files (docs/truthmark/areas.md; docs/truthmark/areas/) only when they exist; then inspect canonical docs and relevant implementation directly. +- Inspect .truthmark/config.yml and configured route files (docs/truthmark/routes/areas.md; docs/truthmark/routes/areas/) only when they exist; then inspect canonical docs and relevant implementation directly. - Report issues and suggested fixes; do not silently rewrite unrelated files. -- Direct checkout inspection is valid even when local tooling is unavailable. - Read support/procedure.md before auditing details. -- Read support/subagents-and-leases.md before dispatching verifier subagents. +- Read support/subagents-and-leases.md only when dispatching verifier subagents. - Read support/report-template.md before the final report. Progressive disclosure: -- support/procedure.md -- support/report-template.md -- support/subagents-and-leases.md +- support/procedure.md — read before edits or detailed auditing; contains core quality gates +- support/report-template.md — read before the final report +- support/subagents-and-leases.md — read only when using subagents, leases, or accepting worker output diff --git a/.claude/skills/truthmark-check/support/procedure.md b/.claude/skills/truthmark-check/support/procedure.md index 72baa9b..6132ff9 100644 --- a/.claude/skills/truthmark-check/support/procedure.md +++ b/.claude/skills/truthmark-check/support/procedure.md @@ -1,6 +1,6 @@ # Truthmark Check Procedure -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. # Truthmark Check @@ -13,7 +13,7 @@ Truth Check is agent-led: - inspect .truthmark/config.yml and configured route files only when they exist; then inspect canonical docs and relevant implementation directly - Repository instruction files and explicitly configured policy docs remain instruction authority when present; do not assume a repository uses any particular policy path. Implementation code and canonical truth docs are inspected evidence for current behavior; they do not silently override workflow write boundaries. -- inspect the configured root route index at docs/truthmark/areas.md and relevant child route files under docs/truthmark/areas/ when they exist +- inspect the configured root route index at docs/truthmark/routes/areas.md and relevant child route files under docs/truthmark/routes/areas/ when they exist - check that current docs describe current code rather than historical plans - check that route files map code surfaces to canonical truth docs when route files exist - check for broad, catch-all, index-like, or mixed-owner truth docs and report them as topology issues requiring Truth Structure @@ -29,9 +29,9 @@ Evidence Gate: Truthmark hierarchy hints: - Config, when present: .truthmark/config.yml -- Root route index, when present: docs/truthmark/areas.md -- Area route files, when present: docs/truthmark/areas/**/*.md -- Truth docs, when present: docs/truth/**/*.md +- Root route index, when present: docs/truthmark/routes/areas.md +- Area route files, when present: docs/truthmark/routes/areas/**/*.md +- Truth docs, when present: docs/truthmark/truth/**/*.md Decision truth lives in the canonical doc it governs; date active decisions inline when added or changed. Do not create separate active-decision ADR/planning logs; replace the active decision and let Git history carry the audit trail. Update Product Decisions and Rationale when a decision changes behavior. diff --git a/.claude/skills/truthmark-check/support/report-template.md b/.claude/skills/truthmark-check/support/report-template.md index 2ce828e..00a3453 100644 --- a/.claude/skills/truthmark-check/support/report-template.md +++ b/.claude/skills/truthmark-check/support/report-template.md @@ -1,6 +1,6 @@ # Truthmark Check Report Template -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Report completion in this shape: @@ -8,7 +8,7 @@ Report completion in this shape: Truth Check: completed Files reviewed: -- docs/truthmark/areas.md +- docs/truthmark/routes/areas.md Issues found: - none @@ -18,7 +18,7 @@ Fixes suggested: Evidence checked: - Finding: The root route index is present and maps repository truth owners. - Evidence: docs/truthmark/areas.md:1 + Evidence: docs/truthmark/routes/areas.md:1 Suggested fix: none Confidence: high diff --git a/.claude/skills/truthmark-check/support/subagents-and-leases.md b/.claude/skills/truthmark-check/support/subagents-and-leases.md index 141bb9a..29ad47b 100644 --- a/.claude/skills/truthmark-check/support/subagents-and-leases.md +++ b/.claude/skills/truthmark-check/support/subagents-and-leases.md @@ -1,6 +1,6 @@ # Truthmark Check Subagents And Leases -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Claude Code subagent mode: - use automatically when this workflow runs in Claude Code and the parent agent chooses bounded subagent fan-out diff --git a/.claude/skills/truthmark-document/SKILL.md b/.claude/skills/truthmark-document/SKILL.md index 6e2469f..241a841 100644 --- a/.claude/skills/truthmark-document/SKILL.md +++ b/.claude/skills/truthmark-document/SKILL.md @@ -3,28 +3,27 @@ name: truthmark-document description: Use when the user asks to document existing implemented behavior, or Sync, Check, or Structure finds implemented behavior missing canonical truth. Not for functional-code changes, doc-first implementation, or topology repair that needs Structure. argument-hint: Optional implemented behavior, API endpoint, route, controller, package, or truth-doc area to document user-invocable: true -truthmark-version: 1.6.1 +truthmark-version: 2.1.0 --- # Truthmark Document Use this skill to document existing implemented behavior when no functional-code changes are required for the task. - Invocations: OpenCode /skill truthmark-document; Codex /truthmark-document or $truthmark-document; Claude Code /truthmark-document; GitHub Copilot /truthmark-document; Gemini CLI /truthmark:document. Quick procedure: - Follow repository instruction files that exist in this checkout; do not assume any optional policy path exists. -- Inspect .truthmark/config.yml and configured route files (docs/truthmark/areas.md; docs/truthmark/areas/) only when they exist; then inspect existing canonical docs, implementation code, and tests directly. +- Inspect .truthmark/config.yml and configured route files (docs/truthmark/routes/areas.md; docs/truthmark/routes/areas/) only when they exist; then inspect existing canonical docs, implementation code, and tests directly. - Document current implemented behavior; do not invent future behavior. - May write canonical truth docs and truth routing files only; must not write functional code. - Read support/procedure.md before editing truth docs. -- Read support/subagents-and-leases.md before dispatching or accepting worker output. +- Read support/subagents-and-leases.md only when dispatching or accepting worker output. - Read support/report-template.md before the final report. Progressive disclosure: -- support/procedure.md -- support/report-template.md -- support/subagents-and-leases.md -- helper-manifest.yml -- support/helper-policy.md +- support/procedure.md — read before edits or detailed auditing; contains core quality gates +- support/report-template.md — read before the final report +- support/subagents-and-leases.md — read only when using subagents, leases, or accepting worker output +- helper-manifest.yml — read only when invoking helper validators or validating helper registration +- support/helper-policy.md — read only when invoking helper validators or reporting helper status diff --git a/.claude/skills/truthmark-document/helper-manifest.yml b/.claude/skills/truthmark-document/helper-manifest.yml index 2446476..175e1a0 100644 --- a/.claude/skills/truthmark-document/helper-manifest.yml +++ b/.claude/skills/truthmark-document/helper-manifest.yml @@ -1,8 +1,8 @@ -# Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +# Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. helpers: validate-document-report: optional: true - runner: truthmark>=1.6.1 + runner: truthmark>=2.1.0 command: argv: - truthmark @@ -17,7 +17,7 @@ helpers: fallback: manually validate support/report-template.md required sections and structured Evidence checked entries validate-write-lease: optional: true - runner: truthmark>=1.6.1 + runner: truthmark>=2.1.0 command: argv: - truthmark diff --git a/.claude/skills/truthmark-document/support/helper-policy.md b/.claude/skills/truthmark-document/support/helper-policy.md index e545d84..2cb7bd6 100644 --- a/.claude/skills/truthmark-document/support/helper-policy.md +++ b/.claude/skills/truthmark-document/support/helper-policy.md @@ -1,6 +1,6 @@ # Optional Helper CLI Policy -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Optional helper CLI commands may collect deterministic checkout facts or validate artifacts. If the Truthmark CLI is unavailable or too old for a declared helper, continue manually using this procedure and report which helper was skipped. Helper output is derived evidence; it does not override direct checkout inspection, workflow write boundaries, or parent acceptance. @@ -11,8 +11,8 @@ Runner detection: - Do not fail the workflow solely because a helper cannot run. Available helpers: -- validate-document-report: optional truthmark>=1.6.1; manual fallback: manually validate support/report-template.md required sections and structured Evidence checked entries -- validate-write-lease: optional truthmark>=1.6.1; manual fallback: manually compare declared allowedWrites and forbiddenWrites with the actual changed files +- validate-document-report: optional truthmark>=2.1.0; manual fallback: manually validate support/report-template.md required sections and structured Evidence checked entries +- validate-write-lease: optional truthmark>=2.1.0; manual fallback: manually compare declared allowedWrites and forbiddenWrites with the actual changed files Final reports should include helper status when helpers are declared for this workflow: diff --git a/.claude/skills/truthmark-document/support/procedure.md b/.claude/skills/truthmark-document/support/procedure.md index 3a38560..be8590f 100644 --- a/.claude/skills/truthmark-document/support/procedure.md +++ b/.claude/skills/truthmark-document/support/procedure.md @@ -1,6 +1,6 @@ # Truthmark Document Procedure -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. # Truthmark Document @@ -14,7 +14,7 @@ Truth Document is manual and implementation-first: - Repository instruction files and explicitly configured policy docs remain instruction authority when present; do not assume a repository uses any particular policy path. Implementation code and canonical truth docs are inspected evidence for current behavior; they do not silently override workflow write boundaries. - document current implemented behavior; do not invent future behavior or planned endpoints -- may write canonical truth docs and docs/truthmark/areas.md or relevant child route files only +- may write canonical truth docs and docs/truthmark/routes/areas.md or relevant child route files only - must not write functional code - when routing is missing, stale, broad, overloaded, catch-all, or cannot map the behavior to a bounded truth owner, run Truth Structure first when routing repair is safe and in scope - block and recommend Truth Structure when routing repair is unsafe, ambiguous, or outside the task boundary @@ -44,12 +44,12 @@ Evidence Gate: Repository intelligence artifacts are optional derived context: RepoIndex, RouteMap, ImpactSet, and ContextPack may guide routing, context selection, and verification planning when available. They do not override checkout evidence, canonical truth docs, route files, or workflow write boundaries. If unavailable, inspect any present Truthmark config, route files, source files, truth docs, and tests directly, then report that repository-intelligence artifacts were not generated. -When creating or updating a truth doc, inspect the routed truth kind and use the matching `docs/templates/-doc.md` template. +When creating or updating a truth doc, inspect the routed truth kind and use the matching template under the configured Truthmark templates root. Supported kinds: behavior, contract, architecture, workflow, operations, and test-behavior. Treat the HTML comments under each template section as normative authoring guidance for that section. Align existing docs to that template and write or repair section content so it satisfies the comment guidance while preserving accurate authored content. If the template is missing, use Scope, Product Decisions, Rationale, and the kind-specific current-truth section. -Teams may edit the template files under docs/templates/ to define their local truth-doc standards. +Teams may edit template files under the configured Truthmark templates root to define their local truth-doc standards. Truth-doc shape repair gate: - Truth Document may restructure only truth docs for the implemented behavior being documented. - repair shape in place only after the ownership gate confirms the doc is the right bounded owner @@ -61,9 +61,9 @@ Maintain architecture docs only for structure-level changes: system structure, m Keep ordinary behavior, endpoints, UI copy, validation rules, and bug fixes in behavior or contract docs unless they change those boundaries. Truthmark hierarchy hints: - Config, when present: .truthmark/config.yml -- Root route index, when present: docs/truthmark/areas.md -- Area route files, when present: docs/truthmark/areas/**/*.md -- Truth docs, when present: docs/truth/**/*.md +- Root route index, when present: docs/truthmark/routes/areas.md +- Area route files, when present: docs/truthmark/routes/areas/**/*.md +- Truth docs, when present: docs/truthmark/truth/**/*.md Decision truth lives in the canonical doc it governs; date active decisions inline when added or changed. Do not create separate active-decision ADR/planning logs; replace the active decision and let Git history carry the audit trail. Update Product Decisions and Rationale when a decision changes behavior. diff --git a/.claude/skills/truthmark-document/support/report-template.md b/.claude/skills/truthmark-document/support/report-template.md index 39c8efc..5e38b92 100644 --- a/.claude/skills/truthmark-document/support/report-template.md +++ b/.claude/skills/truthmark-document/support/report-template.md @@ -1,6 +1,6 @@ # Truthmark Document Report Template -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Report completion in this shape: ```md @@ -10,23 +10,23 @@ Implementation reviewed: - src/routing/area-resolver.ts Ownership reviewed: -- docs/truthmark/areas.md +- docs/truthmark/routes/areas.md Truth docs created: -- docs/truth/contracts.md +- docs/truthmark/truth/contracts.md Truth docs updated: -- docs/truth/check-diagnostics.md +- docs/truthmark/truth/check-diagnostics.md Truth docs restructured: -- docs/truth/check-diagnostics.md +- docs/truthmark/truth/check-diagnostics.md Routing updated: -- docs/truthmark/areas.md +- docs/truthmark/routes/areas.md Evidence checked: - Claim: Route resolution behavior is documented in the contracts truth doc. - Evidence: src/routing/area-resolver.ts:14 / docs/truthmark/areas.md:9 + Evidence: src/routing/area-resolver.ts:14 / docs/truthmark/routes/areas.md:9 Result: supported Helper scripts: diff --git a/.claude/skills/truthmark-document/support/subagents-and-leases.md b/.claude/skills/truthmark-document/support/subagents-and-leases.md index cb799ca..08313b3 100644 --- a/.claude/skills/truthmark-document/support/subagents-and-leases.md +++ b/.claude/skills/truthmark-document/support/subagents-and-leases.md @@ -1,6 +1,6 @@ # Truthmark Document Subagents And Leases -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Claude Code subagent mode: - use automatically when this workflow runs in Claude Code and the parent agent chooses bounded subagent fan-out diff --git a/.claude/skills/truthmark-preview/SKILL.md b/.claude/skills/truthmark-preview/SKILL.md index c9acc27..7db8d92 100644 --- a/.claude/skills/truthmark-preview/SKILL.md +++ b/.claude/skills/truthmark-preview/SKILL.md @@ -3,25 +3,24 @@ name: truthmark-preview description: Use when the user explicitly asks to preview likely workflow routing, target files, writes, or subagent use before edits. Not for validation, automatic gates, final correctness, or replacing Truth Check. argument-hint: Optional requested outcome, code area, doc path, or routing question user-invocable: true -truthmark-version: 1.6.1 +truthmark-version: 2.1.0 --- # Truthmark Preview Use this skill only when the user explicitly asks to preview Truthmark routing or workflow choice before edits. - Invocations: OpenCode /skill truthmark-preview; Codex /truthmark-preview or $truthmark-preview; Claude Code /truthmark-preview; GitHub Copilot /truthmark-preview; Gemini CLI /truthmark:preview. Quick procedure: - Follow repository instruction files that exist in this checkout; do not assume any optional policy path exists. -- Inspect .truthmark/config.yml and configured route files (docs/truthmark/areas.md; docs/truthmark/areas/) only when they exist; then inspect only the truth docs or implementation files needed to preview ownership. +- Inspect .truthmark/config.yml and configured route files (docs/truthmark/routes/areas.md; docs/truthmark/routes/areas/) only when they exist; then inspect only the truth docs or implementation files needed to preview ownership. - Truth Preview is read-only; this report is intended, not authorized. - must not edit files and must not issue write leases; do not run Truth Sync automatically, replace Truth Check, claim final correctness, or mutate code. - Use optional read-only route-auditor evidence only when it reduces context or clarifies ownership. - Hand off to the selected workflow after user approval. Progressive disclosure: -- support/procedure.md -- support/report-template.md -- support/subagents-and-leases.md +- support/procedure.md — read before edits or detailed auditing; contains core quality gates +- support/report-template.md — read before the final report +- support/subagents-and-leases.md — read only when using subagents, leases, or accepting worker output diff --git a/.claude/skills/truthmark-preview/support/procedure.md b/.claude/skills/truthmark-preview/support/procedure.md index 2a3f60a..276926b 100644 --- a/.claude/skills/truthmark-preview/support/procedure.md +++ b/.claude/skills/truthmark-preview/support/procedure.md @@ -1,6 +1,6 @@ # Truthmark Preview Procedure -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Use this skill only when the user explicitly asks to preview Truthmark routing or workflow choice before edits. @@ -15,8 +15,8 @@ Purpose: Read: - .truthmark/config.yml, only when present -- docs/truthmark/areas.md, only when present -- relevant child route files under docs/truthmark/areas/, only when present +- docs/truthmark/routes/areas.md, only when present +- relevant child route files under docs/truthmark/routes/areas/, only when present - relevant truth docs and implementation files needed to preview ownership - Repository instruction files and explicitly configured policy docs remain instruction authority when present; do not assume a repository uses any particular policy path. Implementation code and canonical truth docs are inspected evidence for current behavior; they do not silently override workflow write boundaries. @@ -38,6 +38,6 @@ Suggested subagent use: Truthmark hierarchy hints: - Config, when present: .truthmark/config.yml -- Root route index, when present: docs/truthmark/areas.md -- Area route files, when present: docs/truthmark/areas/**/*.md -- Truth docs, when present: docs/truth/**/*.md +- Root route index, when present: docs/truthmark/routes/areas.md +- Area route files, when present: docs/truthmark/routes/areas/**/*.md +- Truth docs, when present: docs/truthmark/truth/**/*.md diff --git a/.claude/skills/truthmark-preview/support/report-template.md b/.claude/skills/truthmark-preview/support/report-template.md index 2e63308..bff96a9 100644 --- a/.claude/skills/truthmark-preview/support/report-template.md +++ b/.claude/skills/truthmark-preview/support/report-template.md @@ -1,6 +1,6 @@ # Truthmark Preview Report Template -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Report completion in this shape: ```md @@ -18,15 +18,15 @@ Why this workflow: - forbidden adjacency considered: must not edit functional code Likely route owner: -- route file: docs/truthmark/areas.md -- truth doc: docs/truth/example.md +- route file: docs/truthmark/routes/areas.md +- truth doc: docs/truthmark/truth/example.md - confidence: medium Expected write classes: - truth docs Expected target files: -- docs/truth/example.md +- docs/truthmark/truth/example.md Suggested subagent use: - read-only verifiers: truth_route_auditor diff --git a/.claude/skills/truthmark-preview/support/subagents-and-leases.md b/.claude/skills/truthmark-preview/support/subagents-and-leases.md index 836d9c9..cfbffe3 100644 --- a/.claude/skills/truthmark-preview/support/subagents-and-leases.md +++ b/.claude/skills/truthmark-preview/support/subagents-and-leases.md @@ -1,6 +1,6 @@ # Truthmark Preview Subagents And Leases -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Claude Code subagent mode: - use automatically when this workflow runs in Claude Code and the parent agent chooses bounded subagent fan-out diff --git a/.claude/skills/truthmark-realize/SKILL.md b/.claude/skills/truthmark-realize/SKILL.md index afbe84c..8256b8e 100644 --- a/.claude/skills/truthmark-realize/SKILL.md +++ b/.claude/skills/truthmark-realize/SKILL.md @@ -3,24 +3,23 @@ name: truthmark-realize description: Use when the user explicitly asks to realize Truthmark truth docs into code, including /truthmark-realize, $truthmark-realize, or /truthmark:realize. Not for syncing docs after code changes, documenting existing code, topology repair, or truth audits. argument-hint: Optional truth doc path, area, or desired code behavior to realize user-invocable: true -truthmark-version: 1.6.1 +truthmark-version: 2.1.0 --- # Truthmark Realize Use this skill only when the user explicitly asks to realize truth docs into code. - Invocations: OpenCode /skill truthmark-realize; Codex /truthmark-realize or $truthmark-realize; Claude Code /truthmark-realize; GitHub Copilot /truthmark-realize; Gemini CLI /truthmark:realize. Quick procedure: - Follow repository instruction files that exist in this checkout; do not assume any optional policy path exists. -- Read the source truth docs, inspect .truthmark/config.yml and configured route files (docs/truthmark/areas.md; docs/truthmark/areas/) only when they exist, then inspect tests and relevant functional code directly. +- Read the source truth docs, inspect .truthmark/config.yml and configured route files (docs/truthmark/routes/areas.md; docs/truthmark/routes/areas/) only when they exist, then inspect tests and relevant functional code directly. - Truth docs lead; code follows. - may write functional code only; must not edit truth docs or truth routing while realizing those docs. - Read support/procedure.md before changing code. - Read support/report-template.md before the final report. Progressive disclosure: -- support/procedure.md -- support/report-template.md +- support/procedure.md — read before edits or detailed auditing; contains core quality gates +- support/report-template.md — read before the final report diff --git a/.claude/skills/truthmark-realize/support/procedure.md b/.claude/skills/truthmark-realize/support/procedure.md index 2deeaff..c419a77 100644 --- a/.claude/skills/truthmark-realize/support/procedure.md +++ b/.claude/skills/truthmark-realize/support/procedure.md @@ -1,6 +1,6 @@ # Truthmark Realize Procedure -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. # Truthmark Realize @@ -17,7 +17,7 @@ Truth Realize is doc-first: Workflow: 1. Read the updated truth docs named by the user, or infer the relevant docs from configured route files when present. -2. Inspect .truthmark/config.yml and configured route files (docs/truthmark/areas.md; docs/truthmark/areas/) only when they exist; then read tests and the relevant functional code. +2. Inspect .truthmark/config.yml and configured route files (docs/truthmark/routes/areas.md; docs/truthmark/routes/areas/) only when they exist; then read tests and the relevant functional code. 3. Repository instruction files and explicitly configured policy docs remain instruction authority when present; do not assume a repository uses any particular policy path. Implementation code and canonical truth docs are inspected evidence for current behavior; they do not silently override workflow write boundaries. Truth-doc ownership gate: @@ -31,9 +31,9 @@ Truth-doc ownership gate: 7. Report changed code files and verification steps. Truthmark hierarchy hints: - Config, when present: .truthmark/config.yml -- Root route index, when present: docs/truthmark/areas.md -- Area route files, when present: docs/truthmark/areas/**/*.md -- Truth docs, when present: docs/truth/**/*.md +- Root route index, when present: docs/truthmark/routes/areas.md +- Area route files, when present: docs/truthmark/routes/areas/**/*.md +- Truth docs, when present: docs/truthmark/truth/**/*.md Read and write boundaries: diff --git a/.claude/skills/truthmark-realize/support/report-template.md b/.claude/skills/truthmark-realize/support/report-template.md index 6e887cc..b540f61 100644 --- a/.claude/skills/truthmark-realize/support/report-template.md +++ b/.claude/skills/truthmark-realize/support/report-template.md @@ -1,6 +1,6 @@ # Truthmark Realize Report Template -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Report completion in this shape: @@ -8,7 +8,7 @@ Report completion in this shape: Truth Realize: completed Truth docs used: -- docs/truth/authentication/session-timeout.md +- docs/truthmark/truth/authentication/session-timeout.md Code updated: - src/auth/session.ts diff --git a/.claude/skills/truthmark-structure/SKILL.md b/.claude/skills/truthmark-structure/SKILL.md index c250fc2..4e0d2ab 100644 --- a/.claude/skills/truthmark-structure/SKILL.md +++ b/.claude/skills/truthmark-structure/SKILL.md @@ -3,25 +3,24 @@ name: truthmark-structure description: Use when routing or truth ownership is missing, stale, broad, overloaded, catch-all, unrouteable, mixed-owner, needs split/repair, or needs new area setup. Not for documenting implemented behavior, syncing a code diff, or realizing docs into code. argument-hint: Optional area, directory, or routing concern user-invocable: true -truthmark-version: 1.6.1 +truthmark-version: 2.1.0 --- # Truthmark Structure Use this skill to design or repair Truthmark area structure. - Invocations: OpenCode /skill truthmark-structure; Codex /truthmark-structure or $truthmark-structure; Claude Code /truthmark-structure; GitHub Copilot /truthmark-structure; Gemini CLI /truthmark:structure. Quick procedure: - Follow repository instruction files that exist in this checkout; do not assume any optional policy path exists. -- Inspect .truthmark/config.yml and configured route files (docs/truthmark/areas.md; docs/truthmark/areas/) only when they exist; then inspect current docs and relevant code directly. +- Inspect .truthmark/config.yml and configured route files (docs/truthmark/routes/areas.md; docs/truthmark/routes/areas/) only when they exist; then inspect current docs and relevant code directly. - Define areas by product or behavior ownership, not by mechanical directory mirroring. - Do not edit functional code. - Read support/procedure.md before writing route or starter truth-doc changes. - Read support/report-template.md before the final report. Progressive disclosure: -- support/procedure.md -- support/report-template.md -- support/subagents-and-leases.md +- support/procedure.md — read before edits or detailed auditing; contains core quality gates +- support/report-template.md — read before the final report +- support/subagents-and-leases.md — read only when using subagents, leases, or accepting worker output diff --git a/.claude/skills/truthmark-structure/support/procedure.md b/.claude/skills/truthmark-structure/support/procedure.md index bf91e44..5112d6e 100644 --- a/.claude/skills/truthmark-structure/support/procedure.md +++ b/.claude/skills/truthmark-structure/support/procedure.md @@ -1,6 +1,6 @@ # Truthmark Structure Procedure -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Use this skill to design or repair Truthmark area structure. Invocations: OpenCode /skill truthmark-structure; Codex /truthmark-structure or $truthmark-structure; Claude Code /truthmark-structure; GitHub Copilot /truthmark-structure; Gemini CLI /truthmark:structure. @@ -8,20 +8,20 @@ Truth Structure is agent-native: - inspect repository layout, current docs, Truthmark config and route files when present, and relevant code directly - Repository instruction files and explicitly configured policy docs remain instruction authority when present; do not assume a repository uses any particular policy path. Implementation code and canonical truth docs are inspected evidence for current behavior; they do not silently override workflow write boundaries. -- inspect the configured root route index at docs/truthmark/areas.md and relevant child route files under docs/truthmark/areas/ when they exist +- inspect the configured root route index at docs/truthmark/routes/areas.md and relevant child route files under docs/truthmark/routes/areas/ when they exist - define areas by product or behavior ownership, not by mechanical directory mirroring -- create or repair docs/truthmark/areas.md +- create or repair docs/truthmark/routes/areas.md - create starter truth docs when useful and when they belong in the canonical current-truth surface - Starter truth docs must use closed YAML frontmatter bounded by opening and closing --- lines; include status, doc_type, last_reviewed, and source_of_truth inside that frontmatter. - Starter truth docs must include ## Product Decisions and ## Rationale sections. -When creating or updating a truth doc, inspect the routed truth kind and use the matching `docs/templates/-doc.md` template. +When creating or updating a truth doc, inspect the routed truth kind and use the matching template under the configured Truthmark templates root. Supported kinds: behavior, contract, architecture, workflow, operations, and test-behavior. Treat the HTML comments under each template section as normative authoring guidance for that section. Align existing docs to that template and write or repair section content so it satisfies the comment guidance while preserving accurate authored content. If the template is missing, use Scope, Product Decisions, Rationale, and the kind-specific current-truth section. -Teams may edit the template files under docs/templates/ to define their local truth-doc standards. -- use docs/truth/**, docs/architecture/**, or docs/standards/** for current truth destinations +Teams may edit template files under the configured Truthmark templates root to define their local truth-doc standards. +- use docs/truthmark/truth/** for current truth destinations - use only canonical current-truth destinations for starter truth docs - keep active Product Decisions and Rationale in the canonical doc that owns the behavior - preserve unrelated authored content @@ -41,7 +41,7 @@ Do not: - do not create generic catch-all docs - do not treat README files as Sync targets ## Topology Governance -Truth Structure owns documentation topology. Do not depend on humans to manually organize docs/truth. Treat the configured truth root as a managed semantic root. +Truth Structure owns documentation topology. Do not depend on humans to manually organize docs/truthmark/truth. Treat the configured truth root as a managed semantic root. Inspect controllers, routes, handlers, services, packages, tests, existing truth docs, and route files; infer product and domain ownership from behavior boundaries, not from mechanical directory mirroring. When topology pressure exists, repair structure before creating or extending truth docs. Truth-doc ownership gate: @@ -62,7 +62,7 @@ Topology pressure signals: - the configured truth root has many direct non-index docs - a changed controller, route, or service cannot map to a specific behavior doc - Truth Sync would need to create a new generic truth doc because routing is too broad -- endpoint or controller names reveal domains missing from docs/truthmark/areas/** +- endpoint or controller names reveal domains missing from docs/truthmark/routes/areas/** Use these review thresholds as guidance: - more than 10 direct truth docs in one folder - more than 15 leaf areas in one child route file @@ -71,7 +71,7 @@ Use these review thresholds as guidance: Repair rules: - split broad, overloaded, or catch-all areas into behavior-owned child route files - split mixed-owner truth docs into bounded owner docs before adding new behavior claims -- create route files under docs/truthmark/areas/ when a product/domain boundary is clear +- create route files under docs/truthmark/routes/areas/ when a product/domain boundary is clear - create behavior truth docs under the configured truth root only when behavior lacks a current doc - README.md files are indexes, not Truth Sync targets - prefer bounded leaf truth docs at //.md @@ -102,9 +102,9 @@ Portable fallback: - Use a subagent only when the host supports that pattern; otherwise perform the topology repair inline. Truthmark hierarchy hints: - Config, when present: .truthmark/config.yml -- Root route index, when present: docs/truthmark/areas.md -- Area route files, when present: docs/truthmark/areas/**/*.md -- Truth docs, when present: docs/truth/**/*.md +- Root route index, when present: docs/truthmark/routes/areas.md +- Area route files, when present: docs/truthmark/routes/areas/**/*.md +- Truth docs, when present: docs/truthmark/truth/**/*.md Decision truth lives in the canonical doc it governs; date active decisions inline when added or changed. Do not create separate active-decision ADR/planning logs; replace the active decision and let Git history carry the audit trail. Update Product Decisions and Rationale when a decision changes behavior. diff --git a/.claude/skills/truthmark-structure/support/report-template.md b/.claude/skills/truthmark-structure/support/report-template.md index 11efef7..1be260b 100644 --- a/.claude/skills/truthmark-structure/support/report-template.md +++ b/.claude/skills/truthmark-structure/support/report-template.md @@ -1,32 +1,32 @@ # Truthmark Structure Report Template -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Report completion in this shape: ```md Truth Structure: completed Topology reviewed: - controllers: src/auth/** -- docs root: docs/truth -- route files: docs/truthmark/areas.md +- docs root: docs/truthmark/truth +- route files: docs/truthmark/routes/areas.md Areas reviewed: - src/auth/** Routing updated: -- docs/truthmark/areas.md +- docs/truthmark/routes/areas.md Initial truth boundary: - Area: Authentication - Code: src/auth/** -- Truth owner: docs/truth/authentication/session.md +- Truth owner: docs/truthmark/truth/authentication/session.md - Scope: session behavior only Truth docs created: -- docs/truth/authentication/session.md +- docs/truthmark/truth/authentication/session.md Truth docs split: -- docs/truth/authentication/README.md -> docs/truth/authentication/session.md +- docs/truthmark/truth/authentication/README.md -> docs/truthmark/truth/authentication/session.md Truth docs restructured: -- docs/truth/authentication/README.md +- docs/truthmark/truth/authentication/README.md Evidence checked: - Claim: Session behavior belongs to a dedicated Authentication truth owner. - Evidence: src/auth/** / docs/truthmark/areas.md:7 + Evidence: src/auth/** / docs/truthmark/routes/areas.md:7 Result: supported Topology decisions: - Added an Authentication area because session behavior has a distinct code surface and truth owner. diff --git a/.claude/skills/truthmark-structure/support/subagents-and-leases.md b/.claude/skills/truthmark-structure/support/subagents-and-leases.md index 782ee2c..b7af6fd 100644 --- a/.claude/skills/truthmark-structure/support/subagents-and-leases.md +++ b/.claude/skills/truthmark-structure/support/subagents-and-leases.md @@ -1,6 +1,6 @@ # Truthmark Structure Subagents And Leases -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Claude Code subagent mode: - use automatically when this workflow runs in Claude Code and the parent agent chooses bounded subagent fan-out diff --git a/.claude/skills/truthmark-sync/SKILL.md b/.claude/skills/truthmark-sync/SKILL.md index 94278d7..ff1d4eb 100644 --- a/.claude/skills/truthmark-sync/SKILL.md +++ b/.claude/skills/truthmark-sync/SKILL.md @@ -3,29 +3,28 @@ name: truthmark-sync description: Use automatically at finish-time after functional code changes, or explicit /truthmark-sync, $truthmark-sync, or /truthmark:sync. Skip docs-only, formatting-only, behavior-preserving renames, missing config, and no-code changes. Not for doc-first realization or manual topology design. argument-hint: Optional changed-code area, truth-doc area, or sync focus user-invocable: true -truthmark-version: 1.6.1 +truthmark-version: 2.1.0 --- # Truthmark Sync Use this skill automatically before finishing when functional code changed since the last successful Truth Sync. Also run it immediately when the user explicitly invokes Truth Sync. - Invocations: OpenCode /skill truthmark-sync; Codex /truthmark-sync or $truthmark-sync; Claude Code /truthmark-sync; GitHub Copilot /truthmark-sync; Gemini CLI /truthmark:sync. Quick procedure: - Follow repository instruction files that exist in this checkout; do not assume any optional policy path exists. - Skip docs-only, formatting-only, behavior-preserving renames with no truth impact, missing config, and no-code changes. -- Inspect .truthmark/config.yml and configured route files (docs/truthmark/areas.md; docs/truthmark/areas/) only when they exist; then inspect relevant canonical docs directly. +- Inspect .truthmark/config.yml and configured route files (docs/truthmark/routes/areas.md; docs/truthmark/routes/areas/) only when they exist; then inspect relevant canonical docs directly. - direct checkout inspection is the canonical path; do not require the truthmark binary. - May write canonical truth docs and truth routing files only; must not rewrite functional code. - Read support/procedure.md before editing truth docs. -- Read support/subagents-and-leases.md before dispatching or accepting worker output. +- Read support/subagents-and-leases.md only when dispatching or accepting worker output. - Read support/report-template.md before the final report. Progressive disclosure: -- support/procedure.md -- support/report-template.md -- support/subagents-and-leases.md -- helper-manifest.yml -- support/helper-policy.md +- support/procedure.md — read before edits or detailed auditing; contains core quality gates +- support/report-template.md — read before the final report +- support/subagents-and-leases.md — read only when using subagents, leases, or accepting worker output +- helper-manifest.yml — read only when invoking helper validators or validating helper registration +- support/helper-policy.md — read only when invoking helper validators or reporting helper status diff --git a/.claude/skills/truthmark-sync/helper-manifest.yml b/.claude/skills/truthmark-sync/helper-manifest.yml index 669b903..dd0153a 100644 --- a/.claude/skills/truthmark-sync/helper-manifest.yml +++ b/.claude/skills/truthmark-sync/helper-manifest.yml @@ -1,8 +1,8 @@ -# Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +# Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. helpers: validate-sync-report: optional: true - runner: truthmark>=1.6.1 + runner: truthmark>=2.1.0 command: argv: - truthmark @@ -17,7 +17,7 @@ helpers: fallback: "manually validate support/report-template.md and check Evidence checked entries match Claim, indented Evidence, and Result: supported | narrowed | removed | blocked" validate-write-lease: optional: true - runner: truthmark>=1.6.1 + runner: truthmark>=2.1.0 command: argv: - truthmark diff --git a/.claude/skills/truthmark-sync/support/helper-policy.md b/.claude/skills/truthmark-sync/support/helper-policy.md index 78e8645..6c44128 100644 --- a/.claude/skills/truthmark-sync/support/helper-policy.md +++ b/.claude/skills/truthmark-sync/support/helper-policy.md @@ -1,6 +1,6 @@ # Optional Helper CLI Policy -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Optional helper CLI commands may collect deterministic checkout facts or validate artifacts. If the Truthmark CLI is unavailable or too old for a declared helper, continue manually using this procedure and report which helper was skipped. Helper output is derived evidence; it does not override direct checkout inspection, workflow write boundaries, or parent acceptance. @@ -11,8 +11,8 @@ Runner detection: - Do not fail the workflow solely because a helper cannot run. Available helpers: -- validate-sync-report: optional truthmark>=1.6.1; manual fallback: manually validate support/report-template.md and check Evidence checked entries match Claim, indented Evidence, and Result: supported | narrowed | removed | blocked -- validate-write-lease: optional truthmark>=1.6.1; manual fallback: manually compare declared allowedWrites and forbiddenWrites with the actual changed files +- validate-sync-report: optional truthmark>=2.1.0; manual fallback: manually validate support/report-template.md and check Evidence checked entries match Claim, indented Evidence, and Result: supported | narrowed | removed | blocked +- validate-write-lease: optional truthmark>=2.1.0; manual fallback: manually compare declared allowedWrites and forbiddenWrites with the actual changed files Final reports should include helper status when helpers are declared for this workflow: diff --git a/.claude/skills/truthmark-sync/support/procedure.md b/.claude/skills/truthmark-sync/support/procedure.md index e839f8f..ff0f6f7 100644 --- a/.claude/skills/truthmark-sync/support/procedure.md +++ b/.claude/skills/truthmark-sync/support/procedure.md @@ -1,6 +1,6 @@ # Truthmark Sync Procedure -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Use this skill automatically before finishing when functional code changed since the last successful Truth Sync. Also run it immediately when the user explicitly invokes Truth Sync. Invocations: OpenCode /skill truthmark-sync; Codex /truthmark-sync or $truthmark-sync; Claude Code /truthmark-sync; GitHub Copilot /truthmark-sync; Gemini CLI /truthmark:sync. @@ -34,12 +34,12 @@ Product Decisions/Rationale preservation gate: - remove or narrow a decision or rationale only when checkout evidence shows it is stale or unsupported, and report the exact claim, evidence, and result - if ownership of a decision or rationale is unclear, block with manual-review files instead of deleting it or guessing - after the edit, verify every touched truth doc still has Product Decisions and Rationale sections and every pre-existing entry is preserved, moved, narrowed, removed with evidence, or blocked -When creating or updating a truth doc, inspect the routed truth kind and use the matching `docs/templates/-doc.md` template. +When creating or updating a truth doc, inspect the routed truth kind and use the matching template under the configured Truthmark templates root. Supported kinds: behavior, contract, architecture, workflow, operations, and test-behavior. Treat the HTML comments under each template section as normative authoring guidance for that section. Align existing docs to that template and write or repair section content so it satisfies the comment guidance while preserving accurate authored content. If the template is missing, use Scope, Product Decisions, Rationale, and the kind-specific current-truth section. -Teams may edit the template files under docs/templates/ to define their local truth-doc standards. +Teams may edit template files under the configured Truthmark templates root to define their local truth-doc standards. Truth-doc shape repair gate: - Truth Sync may restructure only truth docs impacted by the current functional-code change. - repair shape in place only after the ownership gate confirms the doc is the right bounded owner @@ -72,9 +72,9 @@ Helper status reporting: - Helper output is derived evidence and never replaces direct checkout inspection, evidence review, or parent acceptance. Truthmark hierarchy hints: - Config, when present: .truthmark/config.yml -- Root route index, when present: docs/truthmark/areas.md -- Area route files, when present: docs/truthmark/areas/**/*.md -- Truth docs, when present: docs/truth/**/*.md +- Root route index, when present: docs/truthmark/routes/areas.md +- Area route files, when present: docs/truthmark/routes/areas/**/*.md +- Truth docs, when present: docs/truthmark/truth/**/*.md Decision truth lives in the canonical doc it governs; date active decisions inline when added or changed. Do not create separate active-decision ADR/planning logs; replace the active decision and let Git history carry the audit trail. Update Product Decisions and Rationale when a decision changes behavior. diff --git a/.claude/skills/truthmark-sync/support/report-template.md b/.claude/skills/truthmark-sync/support/report-template.md index 4cca036..4dfa42d 100644 --- a/.claude/skills/truthmark-sync/support/report-template.md +++ b/.claude/skills/truthmark-sync/support/report-template.md @@ -1,6 +1,6 @@ # Truthmark Sync Report Template -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Report completion in this shape: ```md @@ -10,14 +10,14 @@ Changed code reviewed: - src/auth/session.ts Ownership reviewed: -- docs/truthmark/areas.md +- docs/truthmark/routes/areas.md Truth docs updated: -- docs/truth/repository/overview.md +- docs/truthmark/truth/repository/overview.md Evidence checked: - Claim: Session timeout behavior is documented in the mapped repository truth doc. - Evidence: src/auth/session.ts:12 / docs/truthmark/areas.md:11 + Evidence: src/auth/session.ts:12 / docs/truthmark/routes/areas.md:11 Result: supported Helper scripts: @@ -34,7 +34,7 @@ Reason: - routing repair is not allowed Files requiring manual review: -- docs/truthmark/areas.md +- docs/truthmark/routes/areas.md Next action: - update routing metadata and rerun Truth Sync diff --git a/.claude/skills/truthmark-sync/support/subagents-and-leases.md b/.claude/skills/truthmark-sync/support/subagents-and-leases.md index 682c265..12ac2c7 100644 --- a/.claude/skills/truthmark-sync/support/subagents-and-leases.md +++ b/.claude/skills/truthmark-sync/support/subagents-and-leases.md @@ -1,6 +1,6 @@ # Truthmark Sync Subagents And Leases -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Claude Code subagent mode: - use automatically when this workflow runs in Claude Code and the parent agent chooses bounded subagent fan-out diff --git a/.codex/agents/truth-claim-verifier.toml b/.codex/agents/truth-claim-verifier.toml index 4bcc18b..3ca3986 100644 --- a/.codex/agents/truth-claim-verifier.toml +++ b/.codex/agents/truth-claim-verifier.toml @@ -1,4 +1,4 @@ -# Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +# Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. name = "truth_claim_verifier" description = "Read-only Truthmark claim verifier for checking canonical truth against checkout evidence." sandbox_mode = "read-only" diff --git a/.codex/agents/truth-doc-reviewer.toml b/.codex/agents/truth-doc-reviewer.toml index 72adbcb..189d62b 100644 --- a/.codex/agents/truth-doc-reviewer.toml +++ b/.codex/agents/truth-doc-reviewer.toml @@ -1,4 +1,4 @@ -# Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +# Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. name = "truth_doc_reviewer" description = "Read-only Truthmark doc reviewer for shape, decision, rationale, and evidence hygiene." sandbox_mode = "read-only" diff --git a/.codex/agents/truth-doc-writer.toml b/.codex/agents/truth-doc-writer.toml index 41e90fd..a6a9607 100644 --- a/.codex/agents/truth-doc-writer.toml +++ b/.codex/agents/truth-doc-writer.toml @@ -1,4 +1,4 @@ -# Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +# Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. name = "truth_doc_writer" description = "Write-capable Truthmark doc worker for one parent-leased truth-document shard." sandbox_mode = "workspace-write" diff --git a/.codex/agents/truth-route-auditor.toml b/.codex/agents/truth-route-auditor.toml index c153627..54edecd 100644 --- a/.codex/agents/truth-route-auditor.toml +++ b/.codex/agents/truth-route-auditor.toml @@ -1,4 +1,4 @@ -# Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +# Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. name = "truth_route_auditor" description = "Read-only Truthmark route auditor for bounded routing and ownership verification." sandbox_mode = "read-only" diff --git a/.gemini/agents/truth-claim-verifier.md b/.gemini/agents/truth-claim-verifier.md index 41a2e1e..4fd99b5 100644 --- a/.gemini/agents/truth-claim-verifier.md +++ b/.gemini/agents/truth-claim-verifier.md @@ -5,7 +5,7 @@ kind: local tools: [read_file, grep_search] --- -# Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +# Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Manual invocation: @truth-claim-verifier diff --git a/.gemini/agents/truth-doc-reviewer.md b/.gemini/agents/truth-doc-reviewer.md index e9f5361..ca21e31 100644 --- a/.gemini/agents/truth-doc-reviewer.md +++ b/.gemini/agents/truth-doc-reviewer.md @@ -5,7 +5,7 @@ kind: local tools: [read_file, grep_search] --- -# Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +# Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Manual invocation: @truth-doc-reviewer diff --git a/.gemini/agents/truth-doc-writer.md b/.gemini/agents/truth-doc-writer.md index 7d03255..b41d60d 100644 --- a/.gemini/agents/truth-doc-writer.md +++ b/.gemini/agents/truth-doc-writer.md @@ -5,7 +5,7 @@ kind: local tools: [read_file, grep_search, write_file] --- -# Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +# Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Manual invocation: @truth-doc-writer with an explicit parent write lease. diff --git a/.gemini/agents/truth-route-auditor.md b/.gemini/agents/truth-route-auditor.md index 4e1e341..fcda8b2 100644 --- a/.gemini/agents/truth-route-auditor.md +++ b/.gemini/agents/truth-route-auditor.md @@ -5,7 +5,7 @@ kind: local tools: [read_file, grep_search] --- -# Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +# Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Manual invocation: @truth-route-auditor diff --git a/.gemini/commands/truthmark/check.toml b/.gemini/commands/truthmark/check.toml index 2f44c53..33cd2d6 100644 --- a/.gemini/commands/truthmark/check.toml +++ b/.gemini/commands/truthmark/check.toml @@ -5,7 +5,7 @@ name: truthmark-check description: Use when the user asks to audit repository truth health, routing, ownership, or canonical docs. Not for normal lint/test/typecheck/code-review verification, finish-time Sync, or silently rewriting docs. argument-hint: Optional area, doc path, or audit focus user-invocable: true -truthmark-version: 1.6.1 +truthmark-version: 2.1.0 --- # Truthmark Check @@ -19,7 +19,7 @@ Truth Check is agent-led: - inspect .truthmark/config.yml and configured route files only when they exist; then inspect canonical docs and relevant implementation directly - Repository instruction files and explicitly configured policy docs remain instruction authority when present; do not assume a repository uses any particular policy path. Implementation code and canonical truth docs are inspected evidence for current behavior; they do not silently override workflow write boundaries. -- inspect the configured root route index at docs/truthmark/areas.md and relevant child route files under docs/truthmark/areas/ when they exist +- inspect the configured root route index at docs/truthmark/routes/areas.md and relevant child route files under docs/truthmark/routes/areas/ when they exist - check that current docs describe current code rather than historical plans - check that route files map code surfaces to canonical truth docs when route files exist - check for broad, catch-all, index-like, or mixed-owner truth docs and report them as topology issues requiring Truth Structure @@ -35,9 +35,9 @@ Evidence Gate: Truthmark hierarchy hints: - Config, when present: .truthmark/config.yml -- Root route index, when present: docs/truthmark/areas.md -- Area route files, when present: docs/truthmark/areas/**/*.md -- Truth docs, when present: docs/truth/**/*.md +- Root route index, when present: docs/truthmark/routes/areas.md +- Area route files, when present: docs/truthmark/routes/areas/**/*.md +- Truth docs, when present: docs/truthmark/truth/**/*.md Decision truth lives in the canonical doc it governs; date active decisions inline when added or changed. Do not create separate active-decision ADR/planning logs; replace the active decision and let Git history carry the audit trail. Update Product Decisions and Rationale when a decision changes behavior. @@ -48,7 +48,7 @@ Report completion in this shape: Truth Check: completed Files reviewed: -- docs/truthmark/areas.md +- docs/truthmark/routes/areas.md Issues found: - none @@ -58,7 +58,7 @@ Fixes suggested: Evidence checked: - Finding: The root route index is present and maps repository truth owners. - Evidence: docs/truthmark/areas.md:1 + Evidence: docs/truthmark/routes/areas.md:1 Suggested fix: none Confidence: high diff --git a/.gemini/commands/truthmark/document.toml b/.gemini/commands/truthmark/document.toml index 41500cd..15fb447 100644 --- a/.gemini/commands/truthmark/document.toml +++ b/.gemini/commands/truthmark/document.toml @@ -5,7 +5,7 @@ name: truthmark-document description: Use when the user asks to document existing implemented behavior, or Sync, Check, or Structure finds implemented behavior missing canonical truth. Not for functional-code changes, doc-first implementation, or topology repair that needs Structure. argument-hint: Optional implemented behavior, API endpoint, route, controller, package, or truth-doc area to document user-invocable: true -truthmark-version: 1.6.1 +truthmark-version: 2.1.0 --- # Truthmark Document @@ -20,7 +20,7 @@ Truth Document is manual and implementation-first: - Repository instruction files and explicitly configured policy docs remain instruction authority when present; do not assume a repository uses any particular policy path. Implementation code and canonical truth docs are inspected evidence for current behavior; they do not silently override workflow write boundaries. - document current implemented behavior; do not invent future behavior or planned endpoints -- may write canonical truth docs and docs/truthmark/areas.md or relevant child route files only +- may write canonical truth docs and docs/truthmark/routes/areas.md or relevant child route files only - must not write functional code - when routing is missing, stale, broad, overloaded, catch-all, or cannot map the behavior to a bounded truth owner, run Truth Structure first when routing repair is safe and in scope - block and recommend Truth Structure when routing repair is unsafe, ambiguous, or outside the task boundary @@ -50,12 +50,12 @@ Evidence Gate: Repository intelligence artifacts are optional derived context: RepoIndex, RouteMap, ImpactSet, and ContextPack may guide routing, context selection, and verification planning when available. They do not override checkout evidence, canonical truth docs, route files, or workflow write boundaries. If unavailable, inspect any present Truthmark config, route files, source files, truth docs, and tests directly, then report that repository-intelligence artifacts were not generated. -When creating or updating a truth doc, inspect the routed truth kind and use the matching `docs/templates/-doc.md` template. +When creating or updating a truth doc, inspect the routed truth kind and use the matching template under the configured Truthmark templates root. Supported kinds: behavior, contract, architecture, workflow, operations, and test-behavior. Treat the HTML comments under each template section as normative authoring guidance for that section. Align existing docs to that template and write or repair section content so it satisfies the comment guidance while preserving accurate authored content. If the template is missing, use Scope, Product Decisions, Rationale, and the kind-specific current-truth section. -Teams may edit the template files under docs/templates/ to define their local truth-doc standards. +Teams may edit template files under the configured Truthmark templates root to define their local truth-doc standards. Truth-doc shape repair gate: - Truth Document may restructure only truth docs for the implemented behavior being documented. - repair shape in place only after the ownership gate confirms the doc is the right bounded owner @@ -67,9 +67,9 @@ Maintain architecture docs only for structure-level changes: system structure, m Keep ordinary behavior, endpoints, UI copy, validation rules, and bug fixes in behavior or contract docs unless they change those boundaries. Truthmark hierarchy hints: - Config, when present: .truthmark/config.yml -- Root route index, when present: docs/truthmark/areas.md -- Area route files, when present: docs/truthmark/areas/**/*.md -- Truth docs, when present: docs/truth/**/*.md +- Root route index, when present: docs/truthmark/routes/areas.md +- Area route files, when present: docs/truthmark/routes/areas/**/*.md +- Truth docs, when present: docs/truthmark/truth/**/*.md Decision truth lives in the canonical doc it governs; date active decisions inline when added or changed. Do not create separate active-decision ADR/planning logs; replace the active decision and let Git history carry the audit trail. Update Product Decisions and Rationale when a decision changes behavior. @@ -93,23 +93,23 @@ Implementation reviewed: - src/routing/area-resolver.ts Ownership reviewed: -- docs/truthmark/areas.md +- docs/truthmark/routes/areas.md Truth docs created: -- docs/truth/contracts.md +- docs/truthmark/truth/contracts.md Truth docs updated: -- docs/truth/check-diagnostics.md +- docs/truthmark/truth/check-diagnostics.md Truth docs restructured: -- docs/truth/check-diagnostics.md +- docs/truthmark/truth/check-diagnostics.md Routing updated: -- docs/truthmark/areas.md +- docs/truthmark/routes/areas.md Evidence checked: - Claim: Route resolution behavior is documented in the contracts truth doc. - Evidence: src/routing/area-resolver.ts:14 / docs/truthmark/areas.md:9 + Evidence: src/routing/area-resolver.ts:14 / docs/truthmark/routes/areas.md:9 Result: supported Helper scripts: diff --git a/.gemini/commands/truthmark/preview.toml b/.gemini/commands/truthmark/preview.toml index 8e3133f..f1f6322 100644 --- a/.gemini/commands/truthmark/preview.toml +++ b/.gemini/commands/truthmark/preview.toml @@ -5,7 +5,7 @@ name: truthmark-preview description: Use when the user explicitly asks to preview likely workflow routing, target files, writes, or subagent use before edits. Not for validation, automatic gates, final correctness, or replacing Truth Check. argument-hint: Optional requested outcome, code area, doc path, or routing question user-invocable: true -truthmark-version: 1.6.1 +truthmark-version: 2.1.0 --- Use this skill only when the user explicitly asks to preview Truthmark routing or workflow choice before edits. @@ -21,8 +21,8 @@ Purpose: Read: - .truthmark/config.yml, only when present -- docs/truthmark/areas.md, only when present -- relevant child route files under docs/truthmark/areas/, only when present +- docs/truthmark/routes/areas.md, only when present +- relevant child route files under docs/truthmark/routes/areas/, only when present - relevant truth docs and implementation files needed to preview ownership - Repository instruction files and explicitly configured policy docs remain instruction authority when present; do not assume a repository uses any particular policy path. Implementation code and canonical truth docs are inspected evidence for current behavior; they do not silently override workflow write boundaries. @@ -44,9 +44,9 @@ Suggested subagent use: Truthmark hierarchy hints: - Config, when present: .truthmark/config.yml -- Root route index, when present: docs/truthmark/areas.md -- Area route files, when present: docs/truthmark/areas/**/*.md -- Truth docs, when present: docs/truth/**/*.md +- Root route index, when present: docs/truthmark/routes/areas.md +- Area route files, when present: docs/truthmark/routes/areas/**/*.md +- Truth docs, when present: docs/truthmark/truth/**/*.md Report completion in this shape: ```md @@ -64,15 +64,15 @@ Why this workflow: - forbidden adjacency considered: must not edit functional code Likely route owner: -- route file: docs/truthmark/areas.md -- truth doc: docs/truth/example.md +- route file: docs/truthmark/routes/areas.md +- truth doc: docs/truthmark/truth/example.md - confidence: medium Expected write classes: - truth docs Expected target files: -- docs/truth/example.md +- docs/truthmark/truth/example.md Suggested subagent use: - read-only verifiers: truth_route_auditor diff --git a/.gemini/commands/truthmark/realize.toml b/.gemini/commands/truthmark/realize.toml index 9be5eb0..40c00f7 100644 --- a/.gemini/commands/truthmark/realize.toml +++ b/.gemini/commands/truthmark/realize.toml @@ -5,7 +5,7 @@ name: truthmark-realize description: Use when the user explicitly asks to realize Truthmark truth docs into code, including /truthmark-realize, $truthmark-realize, or /truthmark:realize. Not for syncing docs after code changes, documenting existing code, topology repair, or truth audits. argument-hint: Optional truth doc path, area, or desired code behavior to realize user-invocable: true -truthmark-version: 1.6.1 +truthmark-version: 2.1.0 --- # Truthmark Realize @@ -23,7 +23,7 @@ Truth Realize is doc-first: Workflow: 1. Read the updated truth docs named by the user, or infer the relevant docs from configured route files when present. -2. Inspect .truthmark/config.yml and configured route files (docs/truthmark/areas.md; docs/truthmark/areas/) only when they exist; then read tests and the relevant functional code. +2. Inspect .truthmark/config.yml and configured route files (docs/truthmark/routes/areas.md; docs/truthmark/routes/areas/) only when they exist; then read tests and the relevant functional code. 3. Repository instruction files and explicitly configured policy docs remain instruction authority when present; do not assume a repository uses any particular policy path. Implementation code and canonical truth docs are inspected evidence for current behavior; they do not silently override workflow write boundaries. Truth-doc ownership gate: @@ -37,9 +37,9 @@ Truth-doc ownership gate: 7. Report changed code files and verification steps. Truthmark hierarchy hints: - Config, when present: .truthmark/config.yml -- Root route index, when present: docs/truthmark/areas.md -- Area route files, when present: docs/truthmark/areas/**/*.md -- Truth docs, when present: docs/truth/**/*.md +- Root route index, when present: docs/truthmark/routes/areas.md +- Area route files, when present: docs/truthmark/routes/areas/**/*.md +- Truth docs, when present: docs/truthmark/truth/**/*.md Read and write boundaries: @@ -53,7 +53,7 @@ Report completion in this shape: Truth Realize: completed Truth docs used: -- docs/truth/authentication/session-timeout.md +- docs/truthmark/truth/authentication/session-timeout.md Code updated: - src/auth/session.ts diff --git a/.gemini/commands/truthmark/structure.toml b/.gemini/commands/truthmark/structure.toml index 2fe8827..af13bf4 100644 --- a/.gemini/commands/truthmark/structure.toml +++ b/.gemini/commands/truthmark/structure.toml @@ -5,7 +5,7 @@ name: truthmark-structure description: Use when routing or truth ownership is missing, stale, broad, overloaded, catch-all, unrouteable, mixed-owner, needs split/repair, or needs new area setup. Not for documenting implemented behavior, syncing a code diff, or realizing docs into code. argument-hint: Optional area, directory, or routing concern user-invocable: true -truthmark-version: 1.6.1 +truthmark-version: 2.1.0 --- Use this skill to design or repair Truthmark area structure. @@ -14,20 +14,20 @@ Truth Structure is agent-native: - inspect repository layout, current docs, Truthmark config and route files when present, and relevant code directly - Repository instruction files and explicitly configured policy docs remain instruction authority when present; do not assume a repository uses any particular policy path. Implementation code and canonical truth docs are inspected evidence for current behavior; they do not silently override workflow write boundaries. -- inspect the configured root route index at docs/truthmark/areas.md and relevant child route files under docs/truthmark/areas/ when they exist +- inspect the configured root route index at docs/truthmark/routes/areas.md and relevant child route files under docs/truthmark/routes/areas/ when they exist - define areas by product or behavior ownership, not by mechanical directory mirroring -- create or repair docs/truthmark/areas.md +- create or repair docs/truthmark/routes/areas.md - create starter truth docs when useful and when they belong in the canonical current-truth surface - Starter truth docs must use closed YAML frontmatter bounded by opening and closing --- lines; include status, doc_type, last_reviewed, and source_of_truth inside that frontmatter. - Starter truth docs must include ## Product Decisions and ## Rationale sections. -When creating or updating a truth doc, inspect the routed truth kind and use the matching `docs/templates/-doc.md` template. +When creating or updating a truth doc, inspect the routed truth kind and use the matching template under the configured Truthmark templates root. Supported kinds: behavior, contract, architecture, workflow, operations, and test-behavior. Treat the HTML comments under each template section as normative authoring guidance for that section. Align existing docs to that template and write or repair section content so it satisfies the comment guidance while preserving accurate authored content. If the template is missing, use Scope, Product Decisions, Rationale, and the kind-specific current-truth section. -Teams may edit the template files under docs/templates/ to define their local truth-doc standards. -- use docs/truth/**, docs/architecture/**, or docs/standards/** for current truth destinations +Teams may edit template files under the configured Truthmark templates root to define their local truth-doc standards. +- use docs/truthmark/truth/** for current truth destinations - use only canonical current-truth destinations for starter truth docs - keep active Product Decisions and Rationale in the canonical doc that owns the behavior - preserve unrelated authored content @@ -47,7 +47,7 @@ Do not: - do not create generic catch-all docs - do not treat README files as Sync targets ## Topology Governance -Truth Structure owns documentation topology. Do not depend on humans to manually organize docs/truth. Treat the configured truth root as a managed semantic root. +Truth Structure owns documentation topology. Do not depend on humans to manually organize docs/truthmark/truth. Treat the configured truth root as a managed semantic root. Inspect controllers, routes, handlers, services, packages, tests, existing truth docs, and route files; infer product and domain ownership from behavior boundaries, not from mechanical directory mirroring. When topology pressure exists, repair structure before creating or extending truth docs. Truth-doc ownership gate: @@ -68,7 +68,7 @@ Topology pressure signals: - the configured truth root has many direct non-index docs - a changed controller, route, or service cannot map to a specific behavior doc - Truth Sync would need to create a new generic truth doc because routing is too broad -- endpoint or controller names reveal domains missing from docs/truthmark/areas/** +- endpoint or controller names reveal domains missing from docs/truthmark/routes/areas/** Use these review thresholds as guidance: - more than 10 direct truth docs in one folder - more than 15 leaf areas in one child route file @@ -77,7 +77,7 @@ Use these review thresholds as guidance: Repair rules: - split broad, overloaded, or catch-all areas into behavior-owned child route files - split mixed-owner truth docs into bounded owner docs before adding new behavior claims -- create route files under docs/truthmark/areas/ when a product/domain boundary is clear +- create route files under docs/truthmark/routes/areas/ when a product/domain boundary is clear - create behavior truth docs under the configured truth root only when behavior lacks a current doc - README.md files are indexes, not Truth Sync targets - prefer bounded leaf truth docs at //.md @@ -108,9 +108,9 @@ Portable fallback: - Use a subagent only when the host supports that pattern; otherwise perform the topology repair inline. Truthmark hierarchy hints: - Config, when present: .truthmark/config.yml -- Root route index, when present: docs/truthmark/areas.md -- Area route files, when present: docs/truthmark/areas/**/*.md -- Truth docs, when present: docs/truth/**/*.md +- Root route index, when present: docs/truthmark/routes/areas.md +- Area route files, when present: docs/truthmark/routes/areas/**/*.md +- Truth docs, when present: docs/truthmark/truth/**/*.md Decision truth lives in the canonical doc it governs; date active decisions inline when added or changed. Do not create separate active-decision ADR/planning logs; replace the active decision and let Git history carry the audit trail. Update Product Decisions and Rationale when a decision changes behavior. @@ -119,26 +119,26 @@ Report completion in this shape: Truth Structure: completed Topology reviewed: - controllers: src/auth/** -- docs root: docs/truth -- route files: docs/truthmark/areas.md +- docs root: docs/truthmark/truth +- route files: docs/truthmark/routes/areas.md Areas reviewed: - src/auth/** Routing updated: -- docs/truthmark/areas.md +- docs/truthmark/routes/areas.md Initial truth boundary: - Area: Authentication - Code: src/auth/** -- Truth owner: docs/truth/authentication/session.md +- Truth owner: docs/truthmark/truth/authentication/session.md - Scope: session behavior only Truth docs created: -- docs/truth/authentication/session.md +- docs/truthmark/truth/authentication/session.md Truth docs split: -- docs/truth/authentication/README.md -> docs/truth/authentication/session.md +- docs/truthmark/truth/authentication/README.md -> docs/truthmark/truth/authentication/session.md Truth docs restructured: -- docs/truth/authentication/README.md +- docs/truthmark/truth/authentication/README.md Evidence checked: - Claim: Session behavior belongs to a dedicated Authentication truth owner. - Evidence: src/auth/** / docs/truthmark/areas.md:7 + Evidence: src/auth/** / docs/truthmark/routes/areas.md:7 Result: supported Topology decisions: - Added an Authentication area because session behavior has a distinct code surface and truth owner. diff --git a/.gemini/commands/truthmark/sync.toml b/.gemini/commands/truthmark/sync.toml index 3aad154..59c1a34 100644 --- a/.gemini/commands/truthmark/sync.toml +++ b/.gemini/commands/truthmark/sync.toml @@ -5,7 +5,7 @@ name: truthmark-sync description: Use automatically at finish-time after functional code changes, or explicit /truthmark-sync, $truthmark-sync, or /truthmark:sync. Skip docs-only, formatting-only, behavior-preserving renames, missing config, and no-code changes. Not for doc-first realization or manual topology design. argument-hint: Optional changed-code area, truth-doc area, or sync focus user-invocable: true -truthmark-version: 1.6.1 +truthmark-version: 2.1.0 --- Use this skill automatically before finishing when functional code changed since the last successful Truth Sync. Also run it immediately when the user explicitly invokes Truth Sync. @@ -40,12 +40,12 @@ Product Decisions/Rationale preservation gate: - remove or narrow a decision or rationale only when checkout evidence shows it is stale or unsupported, and report the exact claim, evidence, and result - if ownership of a decision or rationale is unclear, block with manual-review files instead of deleting it or guessing - after the edit, verify every touched truth doc still has Product Decisions and Rationale sections and every pre-existing entry is preserved, moved, narrowed, removed with evidence, or blocked -When creating or updating a truth doc, inspect the routed truth kind and use the matching `docs/templates/-doc.md` template. +When creating or updating a truth doc, inspect the routed truth kind and use the matching template under the configured Truthmark templates root. Supported kinds: behavior, contract, architecture, workflow, operations, and test-behavior. Treat the HTML comments under each template section as normative authoring guidance for that section. Align existing docs to that template and write or repair section content so it satisfies the comment guidance while preserving accurate authored content. If the template is missing, use Scope, Product Decisions, Rationale, and the kind-specific current-truth section. -Teams may edit the template files under docs/templates/ to define their local truth-doc standards. +Teams may edit template files under the configured Truthmark templates root to define their local truth-doc standards. Truth-doc shape repair gate: - Truth Sync may restructure only truth docs impacted by the current functional-code change. - repair shape in place only after the ownership gate confirms the doc is the right bounded owner @@ -78,9 +78,9 @@ Helper status reporting: - Helper output is derived evidence and never replaces direct checkout inspection, evidence review, or parent acceptance. Truthmark hierarchy hints: - Config, when present: .truthmark/config.yml -- Root route index, when present: docs/truthmark/areas.md -- Area route files, when present: docs/truthmark/areas/**/*.md -- Truth docs, when present: docs/truth/**/*.md +- Root route index, when present: docs/truthmark/routes/areas.md +- Area route files, when present: docs/truthmark/routes/areas/**/*.md +- Truth docs, when present: docs/truthmark/truth/**/*.md Decision truth lives in the canonical doc it governs; date active decisions inline when added or changed. Do not create separate active-decision ADR/planning logs; replace the active decision and let Git history carry the audit trail. Update Product Decisions and Rationale when a decision changes behavior. @@ -101,14 +101,14 @@ Changed code reviewed: - src/auth/session.ts Ownership reviewed: -- docs/truthmark/areas.md +- docs/truthmark/routes/areas.md Truth docs updated: -- docs/truth/repository/overview.md +- docs/truthmark/truth/repository/overview.md Evidence checked: - Claim: Session timeout behavior is documented in the mapped repository truth doc. - Evidence: src/auth/session.ts:12 / docs/truthmark/areas.md:11 + Evidence: src/auth/session.ts:12 / docs/truthmark/routes/areas.md:11 Result: supported Helper scripts: @@ -125,7 +125,7 @@ Reason: - routing repair is not allowed Files requiring manual review: -- docs/truthmark/areas.md +- docs/truthmark/routes/areas.md Next action: - update routing metadata and rerun Truth Sync diff --git a/.gemini/skills/truthmark-check/SKILL.md b/.gemini/skills/truthmark-check/SKILL.md index 478cca2..b15383b 100644 --- a/.gemini/skills/truthmark-check/SKILL.md +++ b/.gemini/skills/truthmark-check/SKILL.md @@ -3,7 +3,7 @@ name: truthmark-check description: Use when the user asks to audit repository truth health, routing, ownership, or canonical docs. Not for normal lint/test/typecheck/code-review verification, finish-time Sync, or silently rewriting docs. argument-hint: Optional area, doc path, or audit focus user-invocable: true -truthmark-version: 1.6.1 +truthmark-version: 2.1.0 --- # Truthmark Check @@ -12,19 +12,17 @@ Use this skill to audit repository truth health. Use as a Gemini CLI Agent Skill; commands remain available under `/truthmark:*` for command-first invocation. - Invocations: OpenCode /skill truthmark-check; Codex /truthmark-check or $truthmark-check; Claude Code /truthmark-check; GitHub Copilot /truthmark-check; Gemini CLI /truthmark:check. Quick procedure: - Follow repository instruction files that exist in this checkout; do not assume any optional policy path exists. -- Inspect .truthmark/config.yml and configured route files (docs/truthmark/areas.md; docs/truthmark/areas/) only when they exist; then inspect canonical docs and relevant implementation directly. +- Inspect .truthmark/config.yml and configured route files (docs/truthmark/routes/areas.md; docs/truthmark/routes/areas/) only when they exist; then inspect canonical docs and relevant implementation directly. - Report issues and suggested fixes; do not silently rewrite unrelated files. -- Direct checkout inspection is valid even when local tooling is unavailable. - Read support/procedure.md before auditing details. -- Read support/subagents-and-leases.md before dispatching verifier subagents. +- Read support/subagents-and-leases.md only when dispatching verifier subagents. - Read support/report-template.md before the final report. Progressive disclosure: -- support/procedure.md -- support/report-template.md -- support/subagents-and-leases.md +- support/procedure.md — read before edits or detailed auditing; contains core quality gates +- support/report-template.md — read before the final report +- support/subagents-and-leases.md — read only when using subagents, leases, or accepting worker output diff --git a/.gemini/skills/truthmark-check/support/procedure.md b/.gemini/skills/truthmark-check/support/procedure.md index 72baa9b..6132ff9 100644 --- a/.gemini/skills/truthmark-check/support/procedure.md +++ b/.gemini/skills/truthmark-check/support/procedure.md @@ -1,6 +1,6 @@ # Truthmark Check Procedure -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. # Truthmark Check @@ -13,7 +13,7 @@ Truth Check is agent-led: - inspect .truthmark/config.yml and configured route files only when they exist; then inspect canonical docs and relevant implementation directly - Repository instruction files and explicitly configured policy docs remain instruction authority when present; do not assume a repository uses any particular policy path. Implementation code and canonical truth docs are inspected evidence for current behavior; they do not silently override workflow write boundaries. -- inspect the configured root route index at docs/truthmark/areas.md and relevant child route files under docs/truthmark/areas/ when they exist +- inspect the configured root route index at docs/truthmark/routes/areas.md and relevant child route files under docs/truthmark/routes/areas/ when they exist - check that current docs describe current code rather than historical plans - check that route files map code surfaces to canonical truth docs when route files exist - check for broad, catch-all, index-like, or mixed-owner truth docs and report them as topology issues requiring Truth Structure @@ -29,9 +29,9 @@ Evidence Gate: Truthmark hierarchy hints: - Config, when present: .truthmark/config.yml -- Root route index, when present: docs/truthmark/areas.md -- Area route files, when present: docs/truthmark/areas/**/*.md -- Truth docs, when present: docs/truth/**/*.md +- Root route index, when present: docs/truthmark/routes/areas.md +- Area route files, when present: docs/truthmark/routes/areas/**/*.md +- Truth docs, when present: docs/truthmark/truth/**/*.md Decision truth lives in the canonical doc it governs; date active decisions inline when added or changed. Do not create separate active-decision ADR/planning logs; replace the active decision and let Git history carry the audit trail. Update Product Decisions and Rationale when a decision changes behavior. diff --git a/.gemini/skills/truthmark-check/support/report-template.md b/.gemini/skills/truthmark-check/support/report-template.md index 2ce828e..00a3453 100644 --- a/.gemini/skills/truthmark-check/support/report-template.md +++ b/.gemini/skills/truthmark-check/support/report-template.md @@ -1,6 +1,6 @@ # Truthmark Check Report Template -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Report completion in this shape: @@ -8,7 +8,7 @@ Report completion in this shape: Truth Check: completed Files reviewed: -- docs/truthmark/areas.md +- docs/truthmark/routes/areas.md Issues found: - none @@ -18,7 +18,7 @@ Fixes suggested: Evidence checked: - Finding: The root route index is present and maps repository truth owners. - Evidence: docs/truthmark/areas.md:1 + Evidence: docs/truthmark/routes/areas.md:1 Suggested fix: none Confidence: high diff --git a/.gemini/skills/truthmark-check/support/subagents-and-leases.md b/.gemini/skills/truthmark-check/support/subagents-and-leases.md index 1935d53..e38dc16 100644 --- a/.gemini/skills/truthmark-check/support/subagents-and-leases.md +++ b/.gemini/skills/truthmark-check/support/subagents-and-leases.md @@ -1,6 +1,6 @@ # Truthmark Check Subagents And Leases -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Gemini CLI subagent mode: - use automatically when this workflow runs in Gemini CLI and the parent agent chooses bounded project subagent fan-out diff --git a/.gemini/skills/truthmark-document/SKILL.md b/.gemini/skills/truthmark-document/SKILL.md index 006d716..dfe6d2b 100644 --- a/.gemini/skills/truthmark-document/SKILL.md +++ b/.gemini/skills/truthmark-document/SKILL.md @@ -3,7 +3,7 @@ name: truthmark-document description: Use when the user asks to document existing implemented behavior, or Sync, Check, or Structure finds implemented behavior missing canonical truth. Not for functional-code changes, doc-first implementation, or topology repair that needs Structure. argument-hint: Optional implemented behavior, API endpoint, route, controller, package, or truth-doc area to document user-invocable: true -truthmark-version: 1.6.1 +truthmark-version: 2.1.0 --- # Truthmark Document @@ -12,21 +12,20 @@ Use this skill to document existing implemented behavior when no functional-code Use as a Gemini CLI Agent Skill; commands remain available under `/truthmark:*` for command-first invocation. - Invocations: OpenCode /skill truthmark-document; Codex /truthmark-document or $truthmark-document; Claude Code /truthmark-document; GitHub Copilot /truthmark-document; Gemini CLI /truthmark:document. Quick procedure: - Follow repository instruction files that exist in this checkout; do not assume any optional policy path exists. -- Inspect .truthmark/config.yml and configured route files (docs/truthmark/areas.md; docs/truthmark/areas/) only when they exist; then inspect existing canonical docs, implementation code, and tests directly. +- Inspect .truthmark/config.yml and configured route files (docs/truthmark/routes/areas.md; docs/truthmark/routes/areas/) only when they exist; then inspect existing canonical docs, implementation code, and tests directly. - Document current implemented behavior; do not invent future behavior. - May write canonical truth docs and truth routing files only; must not write functional code. - Read support/procedure.md before editing truth docs. -- Read support/subagents-and-leases.md before dispatching or accepting worker output. +- Read support/subagents-and-leases.md only when dispatching or accepting worker output. - Read support/report-template.md before the final report. Progressive disclosure: -- support/procedure.md -- support/report-template.md -- support/subagents-and-leases.md -- helper-manifest.yml -- support/helper-policy.md +- support/procedure.md — read before edits or detailed auditing; contains core quality gates +- support/report-template.md — read before the final report +- support/subagents-and-leases.md — read only when using subagents, leases, or accepting worker output +- helper-manifest.yml — read only when invoking helper validators or validating helper registration +- support/helper-policy.md — read only when invoking helper validators or reporting helper status diff --git a/.gemini/skills/truthmark-document/helper-manifest.yml b/.gemini/skills/truthmark-document/helper-manifest.yml index 2446476..175e1a0 100644 --- a/.gemini/skills/truthmark-document/helper-manifest.yml +++ b/.gemini/skills/truthmark-document/helper-manifest.yml @@ -1,8 +1,8 @@ -# Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +# Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. helpers: validate-document-report: optional: true - runner: truthmark>=1.6.1 + runner: truthmark>=2.1.0 command: argv: - truthmark @@ -17,7 +17,7 @@ helpers: fallback: manually validate support/report-template.md required sections and structured Evidence checked entries validate-write-lease: optional: true - runner: truthmark>=1.6.1 + runner: truthmark>=2.1.0 command: argv: - truthmark diff --git a/.gemini/skills/truthmark-document/support/helper-policy.md b/.gemini/skills/truthmark-document/support/helper-policy.md index e545d84..2cb7bd6 100644 --- a/.gemini/skills/truthmark-document/support/helper-policy.md +++ b/.gemini/skills/truthmark-document/support/helper-policy.md @@ -1,6 +1,6 @@ # Optional Helper CLI Policy -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Optional helper CLI commands may collect deterministic checkout facts or validate artifacts. If the Truthmark CLI is unavailable or too old for a declared helper, continue manually using this procedure and report which helper was skipped. Helper output is derived evidence; it does not override direct checkout inspection, workflow write boundaries, or parent acceptance. @@ -11,8 +11,8 @@ Runner detection: - Do not fail the workflow solely because a helper cannot run. Available helpers: -- validate-document-report: optional truthmark>=1.6.1; manual fallback: manually validate support/report-template.md required sections and structured Evidence checked entries -- validate-write-lease: optional truthmark>=1.6.1; manual fallback: manually compare declared allowedWrites and forbiddenWrites with the actual changed files +- validate-document-report: optional truthmark>=2.1.0; manual fallback: manually validate support/report-template.md required sections and structured Evidence checked entries +- validate-write-lease: optional truthmark>=2.1.0; manual fallback: manually compare declared allowedWrites and forbiddenWrites with the actual changed files Final reports should include helper status when helpers are declared for this workflow: diff --git a/.gemini/skills/truthmark-document/support/procedure.md b/.gemini/skills/truthmark-document/support/procedure.md index 3a38560..be8590f 100644 --- a/.gemini/skills/truthmark-document/support/procedure.md +++ b/.gemini/skills/truthmark-document/support/procedure.md @@ -1,6 +1,6 @@ # Truthmark Document Procedure -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. # Truthmark Document @@ -14,7 +14,7 @@ Truth Document is manual and implementation-first: - Repository instruction files and explicitly configured policy docs remain instruction authority when present; do not assume a repository uses any particular policy path. Implementation code and canonical truth docs are inspected evidence for current behavior; they do not silently override workflow write boundaries. - document current implemented behavior; do not invent future behavior or planned endpoints -- may write canonical truth docs and docs/truthmark/areas.md or relevant child route files only +- may write canonical truth docs and docs/truthmark/routes/areas.md or relevant child route files only - must not write functional code - when routing is missing, stale, broad, overloaded, catch-all, or cannot map the behavior to a bounded truth owner, run Truth Structure first when routing repair is safe and in scope - block and recommend Truth Structure when routing repair is unsafe, ambiguous, or outside the task boundary @@ -44,12 +44,12 @@ Evidence Gate: Repository intelligence artifacts are optional derived context: RepoIndex, RouteMap, ImpactSet, and ContextPack may guide routing, context selection, and verification planning when available. They do not override checkout evidence, canonical truth docs, route files, or workflow write boundaries. If unavailable, inspect any present Truthmark config, route files, source files, truth docs, and tests directly, then report that repository-intelligence artifacts were not generated. -When creating or updating a truth doc, inspect the routed truth kind and use the matching `docs/templates/-doc.md` template. +When creating or updating a truth doc, inspect the routed truth kind and use the matching template under the configured Truthmark templates root. Supported kinds: behavior, contract, architecture, workflow, operations, and test-behavior. Treat the HTML comments under each template section as normative authoring guidance for that section. Align existing docs to that template and write or repair section content so it satisfies the comment guidance while preserving accurate authored content. If the template is missing, use Scope, Product Decisions, Rationale, and the kind-specific current-truth section. -Teams may edit the template files under docs/templates/ to define their local truth-doc standards. +Teams may edit template files under the configured Truthmark templates root to define their local truth-doc standards. Truth-doc shape repair gate: - Truth Document may restructure only truth docs for the implemented behavior being documented. - repair shape in place only after the ownership gate confirms the doc is the right bounded owner @@ -61,9 +61,9 @@ Maintain architecture docs only for structure-level changes: system structure, m Keep ordinary behavior, endpoints, UI copy, validation rules, and bug fixes in behavior or contract docs unless they change those boundaries. Truthmark hierarchy hints: - Config, when present: .truthmark/config.yml -- Root route index, when present: docs/truthmark/areas.md -- Area route files, when present: docs/truthmark/areas/**/*.md -- Truth docs, when present: docs/truth/**/*.md +- Root route index, when present: docs/truthmark/routes/areas.md +- Area route files, when present: docs/truthmark/routes/areas/**/*.md +- Truth docs, when present: docs/truthmark/truth/**/*.md Decision truth lives in the canonical doc it governs; date active decisions inline when added or changed. Do not create separate active-decision ADR/planning logs; replace the active decision and let Git history carry the audit trail. Update Product Decisions and Rationale when a decision changes behavior. diff --git a/.gemini/skills/truthmark-document/support/report-template.md b/.gemini/skills/truthmark-document/support/report-template.md index 39c8efc..5e38b92 100644 --- a/.gemini/skills/truthmark-document/support/report-template.md +++ b/.gemini/skills/truthmark-document/support/report-template.md @@ -1,6 +1,6 @@ # Truthmark Document Report Template -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Report completion in this shape: ```md @@ -10,23 +10,23 @@ Implementation reviewed: - src/routing/area-resolver.ts Ownership reviewed: -- docs/truthmark/areas.md +- docs/truthmark/routes/areas.md Truth docs created: -- docs/truth/contracts.md +- docs/truthmark/truth/contracts.md Truth docs updated: -- docs/truth/check-diagnostics.md +- docs/truthmark/truth/check-diagnostics.md Truth docs restructured: -- docs/truth/check-diagnostics.md +- docs/truthmark/truth/check-diagnostics.md Routing updated: -- docs/truthmark/areas.md +- docs/truthmark/routes/areas.md Evidence checked: - Claim: Route resolution behavior is documented in the contracts truth doc. - Evidence: src/routing/area-resolver.ts:14 / docs/truthmark/areas.md:9 + Evidence: src/routing/area-resolver.ts:14 / docs/truthmark/routes/areas.md:9 Result: supported Helper scripts: diff --git a/.gemini/skills/truthmark-document/support/subagents-and-leases.md b/.gemini/skills/truthmark-document/support/subagents-and-leases.md index 5411d32..05cf06a 100644 --- a/.gemini/skills/truthmark-document/support/subagents-and-leases.md +++ b/.gemini/skills/truthmark-document/support/subagents-and-leases.md @@ -1,6 +1,6 @@ # Truthmark Document Subagents And Leases -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Gemini CLI subagent mode: - use automatically when this workflow runs in Gemini CLI and the parent agent chooses bounded project subagent fan-out diff --git a/.gemini/skills/truthmark-preview/SKILL.md b/.gemini/skills/truthmark-preview/SKILL.md index 3107500..78dff00 100644 --- a/.gemini/skills/truthmark-preview/SKILL.md +++ b/.gemini/skills/truthmark-preview/SKILL.md @@ -3,7 +3,7 @@ name: truthmark-preview description: Use when the user explicitly asks to preview likely workflow routing, target files, writes, or subagent use before edits. Not for validation, automatic gates, final correctness, or replacing Truth Check. argument-hint: Optional requested outcome, code area, doc path, or routing question user-invocable: true -truthmark-version: 1.6.1 +truthmark-version: 2.1.0 --- # Truthmark Preview @@ -12,18 +12,17 @@ Use this skill only when the user explicitly asks to preview Truthmark routing o Use as a Gemini CLI Agent Skill; commands remain available under `/truthmark:*` for command-first invocation. - Invocations: OpenCode /skill truthmark-preview; Codex /truthmark-preview or $truthmark-preview; Claude Code /truthmark-preview; GitHub Copilot /truthmark-preview; Gemini CLI /truthmark:preview. Quick procedure: - Follow repository instruction files that exist in this checkout; do not assume any optional policy path exists. -- Inspect .truthmark/config.yml and configured route files (docs/truthmark/areas.md; docs/truthmark/areas/) only when they exist; then inspect only the truth docs or implementation files needed to preview ownership. +- Inspect .truthmark/config.yml and configured route files (docs/truthmark/routes/areas.md; docs/truthmark/routes/areas/) only when they exist; then inspect only the truth docs or implementation files needed to preview ownership. - Truth Preview is read-only; this report is intended, not authorized. - must not edit files and must not issue write leases; do not run Truth Sync automatically, replace Truth Check, claim final correctness, or mutate code. - Use optional read-only route-auditor evidence only when it reduces context or clarifies ownership. - Hand off to the selected workflow after user approval. Progressive disclosure: -- support/procedure.md -- support/report-template.md -- support/subagents-and-leases.md +- support/procedure.md — read before edits or detailed auditing; contains core quality gates +- support/report-template.md — read before the final report +- support/subagents-and-leases.md — read only when using subagents, leases, or accepting worker output diff --git a/.gemini/skills/truthmark-preview/support/procedure.md b/.gemini/skills/truthmark-preview/support/procedure.md index 2a3f60a..276926b 100644 --- a/.gemini/skills/truthmark-preview/support/procedure.md +++ b/.gemini/skills/truthmark-preview/support/procedure.md @@ -1,6 +1,6 @@ # Truthmark Preview Procedure -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Use this skill only when the user explicitly asks to preview Truthmark routing or workflow choice before edits. @@ -15,8 +15,8 @@ Purpose: Read: - .truthmark/config.yml, only when present -- docs/truthmark/areas.md, only when present -- relevant child route files under docs/truthmark/areas/, only when present +- docs/truthmark/routes/areas.md, only when present +- relevant child route files under docs/truthmark/routes/areas/, only when present - relevant truth docs and implementation files needed to preview ownership - Repository instruction files and explicitly configured policy docs remain instruction authority when present; do not assume a repository uses any particular policy path. Implementation code and canonical truth docs are inspected evidence for current behavior; they do not silently override workflow write boundaries. @@ -38,6 +38,6 @@ Suggested subagent use: Truthmark hierarchy hints: - Config, when present: .truthmark/config.yml -- Root route index, when present: docs/truthmark/areas.md -- Area route files, when present: docs/truthmark/areas/**/*.md -- Truth docs, when present: docs/truth/**/*.md +- Root route index, when present: docs/truthmark/routes/areas.md +- Area route files, when present: docs/truthmark/routes/areas/**/*.md +- Truth docs, when present: docs/truthmark/truth/**/*.md diff --git a/.gemini/skills/truthmark-preview/support/report-template.md b/.gemini/skills/truthmark-preview/support/report-template.md index 2e63308..bff96a9 100644 --- a/.gemini/skills/truthmark-preview/support/report-template.md +++ b/.gemini/skills/truthmark-preview/support/report-template.md @@ -1,6 +1,6 @@ # Truthmark Preview Report Template -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Report completion in this shape: ```md @@ -18,15 +18,15 @@ Why this workflow: - forbidden adjacency considered: must not edit functional code Likely route owner: -- route file: docs/truthmark/areas.md -- truth doc: docs/truth/example.md +- route file: docs/truthmark/routes/areas.md +- truth doc: docs/truthmark/truth/example.md - confidence: medium Expected write classes: - truth docs Expected target files: -- docs/truth/example.md +- docs/truthmark/truth/example.md Suggested subagent use: - read-only verifiers: truth_route_auditor diff --git a/.gemini/skills/truthmark-preview/support/subagents-and-leases.md b/.gemini/skills/truthmark-preview/support/subagents-and-leases.md index 6f25b84..08ff8c8 100644 --- a/.gemini/skills/truthmark-preview/support/subagents-and-leases.md +++ b/.gemini/skills/truthmark-preview/support/subagents-and-leases.md @@ -1,6 +1,6 @@ # Truthmark Preview Subagents And Leases -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Gemini CLI subagent mode: - use automatically when this workflow runs in Gemini CLI and the parent agent chooses bounded project subagent fan-out diff --git a/.gemini/skills/truthmark-realize/SKILL.md b/.gemini/skills/truthmark-realize/SKILL.md index a438f06..116788d 100644 --- a/.gemini/skills/truthmark-realize/SKILL.md +++ b/.gemini/skills/truthmark-realize/SKILL.md @@ -3,7 +3,7 @@ name: truthmark-realize description: Use when the user explicitly asks to realize Truthmark truth docs into code, including /truthmark-realize, $truthmark-realize, or /truthmark:realize. Not for syncing docs after code changes, documenting existing code, topology repair, or truth audits. argument-hint: Optional truth doc path, area, or desired code behavior to realize user-invocable: true -truthmark-version: 1.6.1 +truthmark-version: 2.1.0 --- # Truthmark Realize @@ -12,17 +12,16 @@ Use this skill only when the user explicitly asks to realize truth docs into cod Use as a Gemini CLI Agent Skill; commands remain available under `/truthmark:*` for command-first invocation. - Invocations: OpenCode /skill truthmark-realize; Codex /truthmark-realize or $truthmark-realize; Claude Code /truthmark-realize; GitHub Copilot /truthmark-realize; Gemini CLI /truthmark:realize. Quick procedure: - Follow repository instruction files that exist in this checkout; do not assume any optional policy path exists. -- Read the source truth docs, inspect .truthmark/config.yml and configured route files (docs/truthmark/areas.md; docs/truthmark/areas/) only when they exist, then inspect tests and relevant functional code directly. +- Read the source truth docs, inspect .truthmark/config.yml and configured route files (docs/truthmark/routes/areas.md; docs/truthmark/routes/areas/) only when they exist, then inspect tests and relevant functional code directly. - Truth docs lead; code follows. - may write functional code only; must not edit truth docs or truth routing while realizing those docs. - Read support/procedure.md before changing code. - Read support/report-template.md before the final report. Progressive disclosure: -- support/procedure.md -- support/report-template.md +- support/procedure.md — read before edits or detailed auditing; contains core quality gates +- support/report-template.md — read before the final report diff --git a/.gemini/skills/truthmark-realize/support/procedure.md b/.gemini/skills/truthmark-realize/support/procedure.md index 2deeaff..c419a77 100644 --- a/.gemini/skills/truthmark-realize/support/procedure.md +++ b/.gemini/skills/truthmark-realize/support/procedure.md @@ -1,6 +1,6 @@ # Truthmark Realize Procedure -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. # Truthmark Realize @@ -17,7 +17,7 @@ Truth Realize is doc-first: Workflow: 1. Read the updated truth docs named by the user, or infer the relevant docs from configured route files when present. -2. Inspect .truthmark/config.yml and configured route files (docs/truthmark/areas.md; docs/truthmark/areas/) only when they exist; then read tests and the relevant functional code. +2. Inspect .truthmark/config.yml and configured route files (docs/truthmark/routes/areas.md; docs/truthmark/routes/areas/) only when they exist; then read tests and the relevant functional code. 3. Repository instruction files and explicitly configured policy docs remain instruction authority when present; do not assume a repository uses any particular policy path. Implementation code and canonical truth docs are inspected evidence for current behavior; they do not silently override workflow write boundaries. Truth-doc ownership gate: @@ -31,9 +31,9 @@ Truth-doc ownership gate: 7. Report changed code files and verification steps. Truthmark hierarchy hints: - Config, when present: .truthmark/config.yml -- Root route index, when present: docs/truthmark/areas.md -- Area route files, when present: docs/truthmark/areas/**/*.md -- Truth docs, when present: docs/truth/**/*.md +- Root route index, when present: docs/truthmark/routes/areas.md +- Area route files, when present: docs/truthmark/routes/areas/**/*.md +- Truth docs, when present: docs/truthmark/truth/**/*.md Read and write boundaries: diff --git a/.gemini/skills/truthmark-realize/support/report-template.md b/.gemini/skills/truthmark-realize/support/report-template.md index 6e887cc..b540f61 100644 --- a/.gemini/skills/truthmark-realize/support/report-template.md +++ b/.gemini/skills/truthmark-realize/support/report-template.md @@ -1,6 +1,6 @@ # Truthmark Realize Report Template -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Report completion in this shape: @@ -8,7 +8,7 @@ Report completion in this shape: Truth Realize: completed Truth docs used: -- docs/truth/authentication/session-timeout.md +- docs/truthmark/truth/authentication/session-timeout.md Code updated: - src/auth/session.ts diff --git a/.gemini/skills/truthmark-structure/SKILL.md b/.gemini/skills/truthmark-structure/SKILL.md index 1a942d5..ad9ca04 100644 --- a/.gemini/skills/truthmark-structure/SKILL.md +++ b/.gemini/skills/truthmark-structure/SKILL.md @@ -3,7 +3,7 @@ name: truthmark-structure description: Use when routing or truth ownership is missing, stale, broad, overloaded, catch-all, unrouteable, mixed-owner, needs split/repair, or needs new area setup. Not for documenting implemented behavior, syncing a code diff, or realizing docs into code. argument-hint: Optional area, directory, or routing concern user-invocable: true -truthmark-version: 1.6.1 +truthmark-version: 2.1.0 --- # Truthmark Structure @@ -12,18 +12,17 @@ Use this skill to design or repair Truthmark area structure. Use as a Gemini CLI Agent Skill; commands remain available under `/truthmark:*` for command-first invocation. - Invocations: OpenCode /skill truthmark-structure; Codex /truthmark-structure or $truthmark-structure; Claude Code /truthmark-structure; GitHub Copilot /truthmark-structure; Gemini CLI /truthmark:structure. Quick procedure: - Follow repository instruction files that exist in this checkout; do not assume any optional policy path exists. -- Inspect .truthmark/config.yml and configured route files (docs/truthmark/areas.md; docs/truthmark/areas/) only when they exist; then inspect current docs and relevant code directly. +- Inspect .truthmark/config.yml and configured route files (docs/truthmark/routes/areas.md; docs/truthmark/routes/areas/) only when they exist; then inspect current docs and relevant code directly. - Define areas by product or behavior ownership, not by mechanical directory mirroring. - Do not edit functional code. - Read support/procedure.md before writing route or starter truth-doc changes. - Read support/report-template.md before the final report. Progressive disclosure: -- support/procedure.md -- support/report-template.md -- support/subagents-and-leases.md +- support/procedure.md — read before edits or detailed auditing; contains core quality gates +- support/report-template.md — read before the final report +- support/subagents-and-leases.md — read only when using subagents, leases, or accepting worker output diff --git a/.gemini/skills/truthmark-structure/support/procedure.md b/.gemini/skills/truthmark-structure/support/procedure.md index bf91e44..5112d6e 100644 --- a/.gemini/skills/truthmark-structure/support/procedure.md +++ b/.gemini/skills/truthmark-structure/support/procedure.md @@ -1,6 +1,6 @@ # Truthmark Structure Procedure -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Use this skill to design or repair Truthmark area structure. Invocations: OpenCode /skill truthmark-structure; Codex /truthmark-structure or $truthmark-structure; Claude Code /truthmark-structure; GitHub Copilot /truthmark-structure; Gemini CLI /truthmark:structure. @@ -8,20 +8,20 @@ Truth Structure is agent-native: - inspect repository layout, current docs, Truthmark config and route files when present, and relevant code directly - Repository instruction files and explicitly configured policy docs remain instruction authority when present; do not assume a repository uses any particular policy path. Implementation code and canonical truth docs are inspected evidence for current behavior; they do not silently override workflow write boundaries. -- inspect the configured root route index at docs/truthmark/areas.md and relevant child route files under docs/truthmark/areas/ when they exist +- inspect the configured root route index at docs/truthmark/routes/areas.md and relevant child route files under docs/truthmark/routes/areas/ when they exist - define areas by product or behavior ownership, not by mechanical directory mirroring -- create or repair docs/truthmark/areas.md +- create or repair docs/truthmark/routes/areas.md - create starter truth docs when useful and when they belong in the canonical current-truth surface - Starter truth docs must use closed YAML frontmatter bounded by opening and closing --- lines; include status, doc_type, last_reviewed, and source_of_truth inside that frontmatter. - Starter truth docs must include ## Product Decisions and ## Rationale sections. -When creating or updating a truth doc, inspect the routed truth kind and use the matching `docs/templates/-doc.md` template. +When creating or updating a truth doc, inspect the routed truth kind and use the matching template under the configured Truthmark templates root. Supported kinds: behavior, contract, architecture, workflow, operations, and test-behavior. Treat the HTML comments under each template section as normative authoring guidance for that section. Align existing docs to that template and write or repair section content so it satisfies the comment guidance while preserving accurate authored content. If the template is missing, use Scope, Product Decisions, Rationale, and the kind-specific current-truth section. -Teams may edit the template files under docs/templates/ to define their local truth-doc standards. -- use docs/truth/**, docs/architecture/**, or docs/standards/** for current truth destinations +Teams may edit template files under the configured Truthmark templates root to define their local truth-doc standards. +- use docs/truthmark/truth/** for current truth destinations - use only canonical current-truth destinations for starter truth docs - keep active Product Decisions and Rationale in the canonical doc that owns the behavior - preserve unrelated authored content @@ -41,7 +41,7 @@ Do not: - do not create generic catch-all docs - do not treat README files as Sync targets ## Topology Governance -Truth Structure owns documentation topology. Do not depend on humans to manually organize docs/truth. Treat the configured truth root as a managed semantic root. +Truth Structure owns documentation topology. Do not depend on humans to manually organize docs/truthmark/truth. Treat the configured truth root as a managed semantic root. Inspect controllers, routes, handlers, services, packages, tests, existing truth docs, and route files; infer product and domain ownership from behavior boundaries, not from mechanical directory mirroring. When topology pressure exists, repair structure before creating or extending truth docs. Truth-doc ownership gate: @@ -62,7 +62,7 @@ Topology pressure signals: - the configured truth root has many direct non-index docs - a changed controller, route, or service cannot map to a specific behavior doc - Truth Sync would need to create a new generic truth doc because routing is too broad -- endpoint or controller names reveal domains missing from docs/truthmark/areas/** +- endpoint or controller names reveal domains missing from docs/truthmark/routes/areas/** Use these review thresholds as guidance: - more than 10 direct truth docs in one folder - more than 15 leaf areas in one child route file @@ -71,7 +71,7 @@ Use these review thresholds as guidance: Repair rules: - split broad, overloaded, or catch-all areas into behavior-owned child route files - split mixed-owner truth docs into bounded owner docs before adding new behavior claims -- create route files under docs/truthmark/areas/ when a product/domain boundary is clear +- create route files under docs/truthmark/routes/areas/ when a product/domain boundary is clear - create behavior truth docs under the configured truth root only when behavior lacks a current doc - README.md files are indexes, not Truth Sync targets - prefer bounded leaf truth docs at //.md @@ -102,9 +102,9 @@ Portable fallback: - Use a subagent only when the host supports that pattern; otherwise perform the topology repair inline. Truthmark hierarchy hints: - Config, when present: .truthmark/config.yml -- Root route index, when present: docs/truthmark/areas.md -- Area route files, when present: docs/truthmark/areas/**/*.md -- Truth docs, when present: docs/truth/**/*.md +- Root route index, when present: docs/truthmark/routes/areas.md +- Area route files, when present: docs/truthmark/routes/areas/**/*.md +- Truth docs, when present: docs/truthmark/truth/**/*.md Decision truth lives in the canonical doc it governs; date active decisions inline when added or changed. Do not create separate active-decision ADR/planning logs; replace the active decision and let Git history carry the audit trail. Update Product Decisions and Rationale when a decision changes behavior. diff --git a/.gemini/skills/truthmark-structure/support/report-template.md b/.gemini/skills/truthmark-structure/support/report-template.md index 11efef7..1be260b 100644 --- a/.gemini/skills/truthmark-structure/support/report-template.md +++ b/.gemini/skills/truthmark-structure/support/report-template.md @@ -1,32 +1,32 @@ # Truthmark Structure Report Template -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Report completion in this shape: ```md Truth Structure: completed Topology reviewed: - controllers: src/auth/** -- docs root: docs/truth -- route files: docs/truthmark/areas.md +- docs root: docs/truthmark/truth +- route files: docs/truthmark/routes/areas.md Areas reviewed: - src/auth/** Routing updated: -- docs/truthmark/areas.md +- docs/truthmark/routes/areas.md Initial truth boundary: - Area: Authentication - Code: src/auth/** -- Truth owner: docs/truth/authentication/session.md +- Truth owner: docs/truthmark/truth/authentication/session.md - Scope: session behavior only Truth docs created: -- docs/truth/authentication/session.md +- docs/truthmark/truth/authentication/session.md Truth docs split: -- docs/truth/authentication/README.md -> docs/truth/authentication/session.md +- docs/truthmark/truth/authentication/README.md -> docs/truthmark/truth/authentication/session.md Truth docs restructured: -- docs/truth/authentication/README.md +- docs/truthmark/truth/authentication/README.md Evidence checked: - Claim: Session behavior belongs to a dedicated Authentication truth owner. - Evidence: src/auth/** / docs/truthmark/areas.md:7 + Evidence: src/auth/** / docs/truthmark/routes/areas.md:7 Result: supported Topology decisions: - Added an Authentication area because session behavior has a distinct code surface and truth owner. diff --git a/.gemini/skills/truthmark-structure/support/subagents-and-leases.md b/.gemini/skills/truthmark-structure/support/subagents-and-leases.md index ce2df28..bd8594e 100644 --- a/.gemini/skills/truthmark-structure/support/subagents-and-leases.md +++ b/.gemini/skills/truthmark-structure/support/subagents-and-leases.md @@ -1,6 +1,6 @@ # Truthmark Structure Subagents And Leases -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Gemini CLI subagent mode: - use automatically when this workflow runs in Gemini CLI and the parent agent chooses bounded project subagent fan-out diff --git a/.gemini/skills/truthmark-sync/SKILL.md b/.gemini/skills/truthmark-sync/SKILL.md index 8dd8c9f..6a6fbd4 100644 --- a/.gemini/skills/truthmark-sync/SKILL.md +++ b/.gemini/skills/truthmark-sync/SKILL.md @@ -3,7 +3,7 @@ name: truthmark-sync description: Use automatically at finish-time after functional code changes, or explicit /truthmark-sync, $truthmark-sync, or /truthmark:sync. Skip docs-only, formatting-only, behavior-preserving renames, missing config, and no-code changes. Not for doc-first realization or manual topology design. argument-hint: Optional changed-code area, truth-doc area, or sync focus user-invocable: true -truthmark-version: 1.6.1 +truthmark-version: 2.1.0 --- # Truthmark Sync @@ -12,22 +12,21 @@ Use this skill automatically before finishing when functional code changed since Use as a Gemini CLI Agent Skill; commands remain available under `/truthmark:*` for command-first invocation. - Invocations: OpenCode /skill truthmark-sync; Codex /truthmark-sync or $truthmark-sync; Claude Code /truthmark-sync; GitHub Copilot /truthmark-sync; Gemini CLI /truthmark:sync. Quick procedure: - Follow repository instruction files that exist in this checkout; do not assume any optional policy path exists. - Skip docs-only, formatting-only, behavior-preserving renames with no truth impact, missing config, and no-code changes. -- Inspect .truthmark/config.yml and configured route files (docs/truthmark/areas.md; docs/truthmark/areas/) only when they exist; then inspect relevant canonical docs directly. +- Inspect .truthmark/config.yml and configured route files (docs/truthmark/routes/areas.md; docs/truthmark/routes/areas/) only when they exist; then inspect relevant canonical docs directly. - direct checkout inspection is the canonical path; do not require the truthmark binary. - May write canonical truth docs and truth routing files only; must not rewrite functional code. - Read support/procedure.md before editing truth docs. -- Read support/subagents-and-leases.md before dispatching or accepting worker output. +- Read support/subagents-and-leases.md only when dispatching or accepting worker output. - Read support/report-template.md before the final report. Progressive disclosure: -- support/procedure.md -- support/report-template.md -- support/subagents-and-leases.md -- helper-manifest.yml -- support/helper-policy.md +- support/procedure.md — read before edits or detailed auditing; contains core quality gates +- support/report-template.md — read before the final report +- support/subagents-and-leases.md — read only when using subagents, leases, or accepting worker output +- helper-manifest.yml — read only when invoking helper validators or validating helper registration +- support/helper-policy.md — read only when invoking helper validators or reporting helper status diff --git a/.gemini/skills/truthmark-sync/helper-manifest.yml b/.gemini/skills/truthmark-sync/helper-manifest.yml index 669b903..dd0153a 100644 --- a/.gemini/skills/truthmark-sync/helper-manifest.yml +++ b/.gemini/skills/truthmark-sync/helper-manifest.yml @@ -1,8 +1,8 @@ -# Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +# Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. helpers: validate-sync-report: optional: true - runner: truthmark>=1.6.1 + runner: truthmark>=2.1.0 command: argv: - truthmark @@ -17,7 +17,7 @@ helpers: fallback: "manually validate support/report-template.md and check Evidence checked entries match Claim, indented Evidence, and Result: supported | narrowed | removed | blocked" validate-write-lease: optional: true - runner: truthmark>=1.6.1 + runner: truthmark>=2.1.0 command: argv: - truthmark diff --git a/.gemini/skills/truthmark-sync/support/helper-policy.md b/.gemini/skills/truthmark-sync/support/helper-policy.md index 78e8645..6c44128 100644 --- a/.gemini/skills/truthmark-sync/support/helper-policy.md +++ b/.gemini/skills/truthmark-sync/support/helper-policy.md @@ -1,6 +1,6 @@ # Optional Helper CLI Policy -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Optional helper CLI commands may collect deterministic checkout facts or validate artifacts. If the Truthmark CLI is unavailable or too old for a declared helper, continue manually using this procedure and report which helper was skipped. Helper output is derived evidence; it does not override direct checkout inspection, workflow write boundaries, or parent acceptance. @@ -11,8 +11,8 @@ Runner detection: - Do not fail the workflow solely because a helper cannot run. Available helpers: -- validate-sync-report: optional truthmark>=1.6.1; manual fallback: manually validate support/report-template.md and check Evidence checked entries match Claim, indented Evidence, and Result: supported | narrowed | removed | blocked -- validate-write-lease: optional truthmark>=1.6.1; manual fallback: manually compare declared allowedWrites and forbiddenWrites with the actual changed files +- validate-sync-report: optional truthmark>=2.1.0; manual fallback: manually validate support/report-template.md and check Evidence checked entries match Claim, indented Evidence, and Result: supported | narrowed | removed | blocked +- validate-write-lease: optional truthmark>=2.1.0; manual fallback: manually compare declared allowedWrites and forbiddenWrites with the actual changed files Final reports should include helper status when helpers are declared for this workflow: diff --git a/.gemini/skills/truthmark-sync/support/procedure.md b/.gemini/skills/truthmark-sync/support/procedure.md index e839f8f..ff0f6f7 100644 --- a/.gemini/skills/truthmark-sync/support/procedure.md +++ b/.gemini/skills/truthmark-sync/support/procedure.md @@ -1,6 +1,6 @@ # Truthmark Sync Procedure -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Use this skill automatically before finishing when functional code changed since the last successful Truth Sync. Also run it immediately when the user explicitly invokes Truth Sync. Invocations: OpenCode /skill truthmark-sync; Codex /truthmark-sync or $truthmark-sync; Claude Code /truthmark-sync; GitHub Copilot /truthmark-sync; Gemini CLI /truthmark:sync. @@ -34,12 +34,12 @@ Product Decisions/Rationale preservation gate: - remove or narrow a decision or rationale only when checkout evidence shows it is stale or unsupported, and report the exact claim, evidence, and result - if ownership of a decision or rationale is unclear, block with manual-review files instead of deleting it or guessing - after the edit, verify every touched truth doc still has Product Decisions and Rationale sections and every pre-existing entry is preserved, moved, narrowed, removed with evidence, or blocked -When creating or updating a truth doc, inspect the routed truth kind and use the matching `docs/templates/-doc.md` template. +When creating or updating a truth doc, inspect the routed truth kind and use the matching template under the configured Truthmark templates root. Supported kinds: behavior, contract, architecture, workflow, operations, and test-behavior. Treat the HTML comments under each template section as normative authoring guidance for that section. Align existing docs to that template and write or repair section content so it satisfies the comment guidance while preserving accurate authored content. If the template is missing, use Scope, Product Decisions, Rationale, and the kind-specific current-truth section. -Teams may edit the template files under docs/templates/ to define their local truth-doc standards. +Teams may edit template files under the configured Truthmark templates root to define their local truth-doc standards. Truth-doc shape repair gate: - Truth Sync may restructure only truth docs impacted by the current functional-code change. - repair shape in place only after the ownership gate confirms the doc is the right bounded owner @@ -72,9 +72,9 @@ Helper status reporting: - Helper output is derived evidence and never replaces direct checkout inspection, evidence review, or parent acceptance. Truthmark hierarchy hints: - Config, when present: .truthmark/config.yml -- Root route index, when present: docs/truthmark/areas.md -- Area route files, when present: docs/truthmark/areas/**/*.md -- Truth docs, when present: docs/truth/**/*.md +- Root route index, when present: docs/truthmark/routes/areas.md +- Area route files, when present: docs/truthmark/routes/areas/**/*.md +- Truth docs, when present: docs/truthmark/truth/**/*.md Decision truth lives in the canonical doc it governs; date active decisions inline when added or changed. Do not create separate active-decision ADR/planning logs; replace the active decision and let Git history carry the audit trail. Update Product Decisions and Rationale when a decision changes behavior. diff --git a/.gemini/skills/truthmark-sync/support/report-template.md b/.gemini/skills/truthmark-sync/support/report-template.md index 4cca036..4dfa42d 100644 --- a/.gemini/skills/truthmark-sync/support/report-template.md +++ b/.gemini/skills/truthmark-sync/support/report-template.md @@ -1,6 +1,6 @@ # Truthmark Sync Report Template -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Report completion in this shape: ```md @@ -10,14 +10,14 @@ Changed code reviewed: - src/auth/session.ts Ownership reviewed: -- docs/truthmark/areas.md +- docs/truthmark/routes/areas.md Truth docs updated: -- docs/truth/repository/overview.md +- docs/truthmark/truth/repository/overview.md Evidence checked: - Claim: Session timeout behavior is documented in the mapped repository truth doc. - Evidence: src/auth/session.ts:12 / docs/truthmark/areas.md:11 + Evidence: src/auth/session.ts:12 / docs/truthmark/routes/areas.md:11 Result: supported Helper scripts: @@ -34,7 +34,7 @@ Reason: - routing repair is not allowed Files requiring manual review: -- docs/truthmark/areas.md +- docs/truthmark/routes/areas.md Next action: - update routing metadata and rerun Truth Sync diff --git a/.gemini/skills/truthmark-sync/support/subagents-and-leases.md b/.gemini/skills/truthmark-sync/support/subagents-and-leases.md index 7865dd0..6c5c65f 100644 --- a/.gemini/skills/truthmark-sync/support/subagents-and-leases.md +++ b/.gemini/skills/truthmark-sync/support/subagents-and-leases.md @@ -1,6 +1,6 @@ # Truthmark Sync Subagents And Leases -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Gemini CLI subagent mode: - use automatically when this workflow runs in Gemini CLI and the parent agent chooses bounded project subagent fan-out diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..3538a69 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +*.ts text diff diff --git a/.github/agents/truth-claim-verifier.agent.md b/.github/agents/truth-claim-verifier.md similarity index 94% rename from .github/agents/truth-claim-verifier.agent.md rename to .github/agents/truth-claim-verifier.md index f835d02..0502791 100644 --- a/.github/agents/truth-claim-verifier.agent.md +++ b/.github/agents/truth-claim-verifier.md @@ -4,7 +4,7 @@ description: Read-only Truthmark claim verifier for checking canonical truth aga tools: [read, search] --- -# Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +# Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Stay read-only. Verify the behavior-bearing truth claims assigned by the parent against primary checkout evidence. diff --git a/.github/agents/truth-doc-reviewer.agent.md b/.github/agents/truth-doc-reviewer.md similarity index 94% rename from .github/agents/truth-doc-reviewer.agent.md rename to .github/agents/truth-doc-reviewer.md index 599d246..62db034 100644 --- a/.github/agents/truth-doc-reviewer.agent.md +++ b/.github/agents/truth-doc-reviewer.md @@ -4,7 +4,7 @@ description: Read-only Truthmark doc reviewer for shape, decision, rationale, an tools: [read, search] --- -# Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +# Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Stay read-only. Review assigned canonical truth docs for frontmatter, source_of_truth, required template sections, Evidence checked entries, Product Decisions, and Rationale. diff --git a/.github/agents/truth-doc-writer.agent.md b/.github/agents/truth-doc-writer.md similarity index 95% rename from .github/agents/truth-doc-writer.agent.md rename to .github/agents/truth-doc-writer.md index 13780d9..118ecdf 100644 --- a/.github/agents/truth-doc-writer.agent.md +++ b/.github/agents/truth-doc-writer.md @@ -4,7 +4,7 @@ description: Write-capable Truthmark doc worker for one parent-leased truth-docu tools: [read, search, edit] --- -# Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +# Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Write one leased Truthmark truth-document shard assigned by the parent. Require an explicit write lease before editing. The lease must name workflow, worker, shard, objective, requiredReads, allowedWrites, forbiddenWrites, evidenceRequired, verification, and reportFields. diff --git a/.github/agents/truth-route-auditor.agent.md b/.github/agents/truth-route-auditor.md similarity index 94% rename from .github/agents/truth-route-auditor.agent.md rename to .github/agents/truth-route-auditor.md index 3e8bbc0c..ffdd0f4 100644 --- a/.github/agents/truth-route-auditor.agent.md +++ b/.github/agents/truth-route-auditor.md @@ -4,7 +4,7 @@ description: Read-only Truthmark route auditor for bounded routing and ownership tools: [read, search] --- -# Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +# Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Stay read-only. Audit one bounded Truthmark route, area, or doc shard assigned by the parent. diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index b245a84..5202bc3 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -9,8 +9,8 @@ Agent-specific: ## Truthmark Workflow -Generated by Truthmark 1.6.1. Rerun `truthmark init` after upgrades. -Hierarchy hints: config .truthmark/config.yml when present; routes docs/truthmark/areas.md and docs/truthmark/areas/**/*.md when present; Truth docs: docs/truth/**/*.md when present. +Generated by Truthmark 2.1.0. Rerun `truthmark init` after upgrades. +Hierarchy hints: config .truthmark/config.yml when present; routes docs/truthmark/routes/areas.md and docs/truthmark/routes/areas/**/*.md when present; Truth docs: docs/truthmark/truth/**/*.md when present. Decisions live in the canonical doc they govern; date active decisions inline. Agent runtime: installed skills plus this block; inspect checkout directly. Delegation is host-owned. ### Truth Sync diff --git a/.github/prompts/truthmark-check.prompt.md b/.github/prompts/truthmark-check.prompt.md index ae9d13c..e1f326b 100644 --- a/.github/prompts/truthmark-check.prompt.md +++ b/.github/prompts/truthmark-check.prompt.md @@ -8,7 +8,7 @@ name: truthmark-check description: Use when the user asks to audit repository truth health, routing, ownership, or canonical docs. Not for normal lint/test/typecheck/code-review verification, finish-time Sync, or silently rewriting docs. argument-hint: Optional area, doc path, or audit focus user-invocable: true -truthmark-version: 1.6.1 +truthmark-version: 2.1.0 --- # Truthmark Check @@ -22,7 +22,7 @@ Truth Check is agent-led: - inspect .truthmark/config.yml and configured route files only when they exist; then inspect canonical docs and relevant implementation directly - Repository instruction files and explicitly configured policy docs remain instruction authority when present; do not assume a repository uses any particular policy path. Implementation code and canonical truth docs are inspected evidence for current behavior; they do not silently override workflow write boundaries. -- inspect the configured root route index at docs/truthmark/areas.md and relevant child route files under docs/truthmark/areas/ when they exist +- inspect the configured root route index at docs/truthmark/routes/areas.md and relevant child route files under docs/truthmark/routes/areas/ when they exist - check that current docs describe current code rather than historical plans - check that route files map code surfaces to canonical truth docs when route files exist - check for broad, catch-all, index-like, or mixed-owner truth docs and report them as topology issues requiring Truth Structure @@ -45,9 +45,9 @@ Copilot custom-agent mode: Truthmark hierarchy hints: - Config, when present: .truthmark/config.yml -- Root route index, when present: docs/truthmark/areas.md -- Area route files, when present: docs/truthmark/areas/**/*.md -- Truth docs, when present: docs/truth/**/*.md +- Root route index, when present: docs/truthmark/routes/areas.md +- Area route files, when present: docs/truthmark/routes/areas/**/*.md +- Truth docs, when present: docs/truthmark/truth/**/*.md Decision truth lives in the canonical doc it governs; date active decisions inline when added or changed. Do not create separate active-decision ADR/planning logs; replace the active decision and let Git history carry the audit trail. Update Product Decisions and Rationale when a decision changes behavior. @@ -58,7 +58,7 @@ Report completion in this shape: Truth Check: completed Files reviewed: -- docs/truthmark/areas.md +- docs/truthmark/routes/areas.md Issues found: - none @@ -68,7 +68,7 @@ Fixes suggested: Evidence checked: - Finding: The root route index is present and maps repository truth owners. - Evidence: docs/truthmark/areas.md:1 + Evidence: docs/truthmark/routes/areas.md:1 Suggested fix: none Confidence: high diff --git a/.github/prompts/truthmark-document.prompt.md b/.github/prompts/truthmark-document.prompt.md index 967ec3a..c88472a 100644 --- a/.github/prompts/truthmark-document.prompt.md +++ b/.github/prompts/truthmark-document.prompt.md @@ -8,7 +8,7 @@ name: truthmark-document description: Use when the user asks to document existing implemented behavior, or Sync, Check, or Structure finds implemented behavior missing canonical truth. Not for functional-code changes, doc-first implementation, or topology repair that needs Structure. argument-hint: Optional implemented behavior, API endpoint, route, controller, package, or truth-doc area to document user-invocable: true -truthmark-version: 1.6.1 +truthmark-version: 2.1.0 --- # Truthmark Document @@ -23,7 +23,7 @@ Truth Document is manual and implementation-first: - Repository instruction files and explicitly configured policy docs remain instruction authority when present; do not assume a repository uses any particular policy path. Implementation code and canonical truth docs are inspected evidence for current behavior; they do not silently override workflow write boundaries. - document current implemented behavior; do not invent future behavior or planned endpoints -- may write canonical truth docs and docs/truthmark/areas.md or relevant child route files only +- may write canonical truth docs and docs/truthmark/routes/areas.md or relevant child route files only - must not write functional code - when routing is missing, stale, broad, overloaded, catch-all, or cannot map the behavior to a bounded truth owner, run Truth Structure first when routing repair is safe and in scope - block and recommend Truth Structure when routing repair is unsafe, ambiguous, or outside the task boundary @@ -63,12 +63,12 @@ Copilot custom-agent mode: Repository intelligence artifacts are optional derived context: RepoIndex, RouteMap, ImpactSet, and ContextPack may guide routing, context selection, and verification planning when available. They do not override checkout evidence, canonical truth docs, route files, or workflow write boundaries. If unavailable, inspect any present Truthmark config, route files, source files, truth docs, and tests directly, then report that repository-intelligence artifacts were not generated. -When creating or updating a truth doc, inspect the routed truth kind and use the matching `docs/templates/-doc.md` template. +When creating or updating a truth doc, inspect the routed truth kind and use the matching template under the configured Truthmark templates root. Supported kinds: behavior, contract, architecture, workflow, operations, and test-behavior. Treat the HTML comments under each template section as normative authoring guidance for that section. Align existing docs to that template and write or repair section content so it satisfies the comment guidance while preserving accurate authored content. If the template is missing, use Scope, Product Decisions, Rationale, and the kind-specific current-truth section. -Teams may edit the template files under docs/templates/ to define their local truth-doc standards. +Teams may edit template files under the configured Truthmark templates root to define their local truth-doc standards. Truth-doc shape repair gate: - Truth Document may restructure only truth docs for the implemented behavior being documented. - repair shape in place only after the ownership gate confirms the doc is the right bounded owner @@ -80,9 +80,9 @@ Maintain architecture docs only for structure-level changes: system structure, m Keep ordinary behavior, endpoints, UI copy, validation rules, and bug fixes in behavior or contract docs unless they change those boundaries. Truthmark hierarchy hints: - Config, when present: .truthmark/config.yml -- Root route index, when present: docs/truthmark/areas.md -- Area route files, when present: docs/truthmark/areas/**/*.md -- Truth docs, when present: docs/truth/**/*.md +- Root route index, when present: docs/truthmark/routes/areas.md +- Area route files, when present: docs/truthmark/routes/areas/**/*.md +- Truth docs, when present: docs/truthmark/truth/**/*.md Decision truth lives in the canonical doc it governs; date active decisions inline when added or changed. Do not create separate active-decision ADR/planning logs; replace the active decision and let Git history carry the audit trail. Update Product Decisions and Rationale when a decision changes behavior. @@ -106,23 +106,23 @@ Implementation reviewed: - src/routing/area-resolver.ts Ownership reviewed: -- docs/truthmark/areas.md +- docs/truthmark/routes/areas.md Truth docs created: -- docs/truth/contracts.md +- docs/truthmark/truth/contracts.md Truth docs updated: -- docs/truth/check-diagnostics.md +- docs/truthmark/truth/check-diagnostics.md Truth docs restructured: -- docs/truth/check-diagnostics.md +- docs/truthmark/truth/check-diagnostics.md Routing updated: -- docs/truthmark/areas.md +- docs/truthmark/routes/areas.md Evidence checked: - Claim: Route resolution behavior is documented in the contracts truth doc. - Evidence: src/routing/area-resolver.ts:14 / docs/truthmark/areas.md:9 + Evidence: src/routing/area-resolver.ts:14 / docs/truthmark/routes/areas.md:9 Result: supported Helper scripts: diff --git a/.github/prompts/truthmark-preview.prompt.md b/.github/prompts/truthmark-preview.prompt.md index 767ded1..a3bdc50 100644 --- a/.github/prompts/truthmark-preview.prompt.md +++ b/.github/prompts/truthmark-preview.prompt.md @@ -8,7 +8,7 @@ name: truthmark-preview description: Use when the user explicitly asks to preview likely workflow routing, target files, writes, or subagent use before edits. Not for validation, automatic gates, final correctness, or replacing Truth Check. argument-hint: Optional requested outcome, code area, doc path, or routing question user-invocable: true -truthmark-version: 1.6.1 +truthmark-version: 2.1.0 --- Use this skill only when the user explicitly asks to preview Truthmark routing or workflow choice before edits. @@ -24,8 +24,8 @@ Purpose: Read: - .truthmark/config.yml, only when present -- docs/truthmark/areas.md, only when present -- relevant child route files under docs/truthmark/areas/, only when present +- docs/truthmark/routes/areas.md, only when present +- relevant child route files under docs/truthmark/routes/areas/, only when present - relevant truth docs and implementation files needed to preview ownership - Repository instruction files and explicitly configured policy docs remain instruction authority when present; do not assume a repository uses any particular policy path. Implementation code and canonical truth docs are inspected evidence for current behavior; they do not silently override workflow write boundaries. @@ -47,9 +47,9 @@ Suggested subagent use: Truthmark hierarchy hints: - Config, when present: .truthmark/config.yml -- Root route index, when present: docs/truthmark/areas.md -- Area route files, when present: docs/truthmark/areas/**/*.md -- Truth docs, when present: docs/truth/**/*.md +- Root route index, when present: docs/truthmark/routes/areas.md +- Area route files, when present: docs/truthmark/routes/areas/**/*.md +- Truth docs, when present: docs/truthmark/truth/**/*.md Report completion in this shape: ```md @@ -67,15 +67,15 @@ Why this workflow: - forbidden adjacency considered: must not edit functional code Likely route owner: -- route file: docs/truthmark/areas.md -- truth doc: docs/truth/example.md +- route file: docs/truthmark/routes/areas.md +- truth doc: docs/truthmark/truth/example.md - confidence: medium Expected write classes: - truth docs Expected target files: -- docs/truth/example.md +- docs/truthmark/truth/example.md Suggested subagent use: - read-only verifiers: truth_route_auditor diff --git a/.github/prompts/truthmark-realize.prompt.md b/.github/prompts/truthmark-realize.prompt.md index a8bb909..cc20366 100644 --- a/.github/prompts/truthmark-realize.prompt.md +++ b/.github/prompts/truthmark-realize.prompt.md @@ -8,7 +8,7 @@ name: truthmark-realize description: Use when the user explicitly asks to realize Truthmark truth docs into code, including /truthmark-realize, $truthmark-realize, or /truthmark:realize. Not for syncing docs after code changes, documenting existing code, topology repair, or truth audits. argument-hint: Optional truth doc path, area, or desired code behavior to realize user-invocable: true -truthmark-version: 1.6.1 +truthmark-version: 2.1.0 --- # Truthmark Realize @@ -26,7 +26,7 @@ Truth Realize is doc-first: Workflow: 1. Read the updated truth docs named by the user, or infer the relevant docs from configured route files when present. -2. Inspect .truthmark/config.yml and configured route files (docs/truthmark/areas.md; docs/truthmark/areas/) only when they exist; then read tests and the relevant functional code. +2. Inspect .truthmark/config.yml and configured route files (docs/truthmark/routes/areas.md; docs/truthmark/routes/areas/) only when they exist; then read tests and the relevant functional code. 3. Repository instruction files and explicitly configured policy docs remain instruction authority when present; do not assume a repository uses any particular policy path. Implementation code and canonical truth docs are inspected evidence for current behavior; they do not silently override workflow write boundaries. Truth-doc ownership gate: @@ -40,9 +40,9 @@ Truth-doc ownership gate: 7. Report changed code files and verification steps. Truthmark hierarchy hints: - Config, when present: .truthmark/config.yml -- Root route index, when present: docs/truthmark/areas.md -- Area route files, when present: docs/truthmark/areas/**/*.md -- Truth docs, when present: docs/truth/**/*.md +- Root route index, when present: docs/truthmark/routes/areas.md +- Area route files, when present: docs/truthmark/routes/areas/**/*.md +- Truth docs, when present: docs/truthmark/truth/**/*.md Read and write boundaries: @@ -56,7 +56,7 @@ Report completion in this shape: Truth Realize: completed Truth docs used: -- docs/truth/authentication/session-timeout.md +- docs/truthmark/truth/authentication/session-timeout.md Code updated: - src/auth/session.ts diff --git a/.github/prompts/truthmark-structure.prompt.md b/.github/prompts/truthmark-structure.prompt.md index 5302553..2d5e5de 100644 --- a/.github/prompts/truthmark-structure.prompt.md +++ b/.github/prompts/truthmark-structure.prompt.md @@ -8,7 +8,7 @@ name: truthmark-structure description: Use when routing or truth ownership is missing, stale, broad, overloaded, catch-all, unrouteable, mixed-owner, needs split/repair, or needs new area setup. Not for documenting implemented behavior, syncing a code diff, or realizing docs into code. argument-hint: Optional area, directory, or routing concern user-invocable: true -truthmark-version: 1.6.1 +truthmark-version: 2.1.0 --- Use this skill to design or repair Truthmark area structure. @@ -17,9 +17,9 @@ Truth Structure is agent-native: - inspect repository layout, current docs, Truthmark config and route files when present, and relevant code directly - Repository instruction files and explicitly configured policy docs remain instruction authority when present; do not assume a repository uses any particular policy path. Implementation code and canonical truth docs are inspected evidence for current behavior; they do not silently override workflow write boundaries. -- inspect the configured root route index at docs/truthmark/areas.md and relevant child route files under docs/truthmark/areas/ when they exist +- inspect the configured root route index at docs/truthmark/routes/areas.md and relevant child route files under docs/truthmark/routes/areas/ when they exist - define areas by product or behavior ownership, not by mechanical directory mirroring -- create or repair docs/truthmark/areas.md +- create or repair docs/truthmark/routes/areas.md - create starter truth docs when useful and when they belong in the canonical current-truth surface - Starter truth docs must use closed YAML frontmatter bounded by opening and closing --- lines; include status, doc_type, last_reviewed, and source_of_truth inside that frontmatter. - Starter truth docs must include ## Product Decisions and ## Rationale sections. @@ -30,13 +30,13 @@ Copilot custom-agent mode: - parent supplies bounded evidence shards; custom agents must not preload host instruction files or repo-wide policy docs unless assigned as evidence - Parent agent owns all Truth Structure writes and final topology decisions -When creating or updating a truth doc, inspect the routed truth kind and use the matching `docs/templates/-doc.md` template. +When creating or updating a truth doc, inspect the routed truth kind and use the matching template under the configured Truthmark templates root. Supported kinds: behavior, contract, architecture, workflow, operations, and test-behavior. Treat the HTML comments under each template section as normative authoring guidance for that section. Align existing docs to that template and write or repair section content so it satisfies the comment guidance while preserving accurate authored content. If the template is missing, use Scope, Product Decisions, Rationale, and the kind-specific current-truth section. -Teams may edit the template files under docs/templates/ to define their local truth-doc standards. -- use docs/truth/**, docs/architecture/**, or docs/standards/** for current truth destinations +Teams may edit template files under the configured Truthmark templates root to define their local truth-doc standards. +- use docs/truthmark/truth/** for current truth destinations - use only canonical current-truth destinations for starter truth docs - keep active Product Decisions and Rationale in the canonical doc that owns the behavior - preserve unrelated authored content @@ -56,7 +56,7 @@ Do not: - do not create generic catch-all docs - do not treat README files as Sync targets ## Topology Governance -Truth Structure owns documentation topology. Do not depend on humans to manually organize docs/truth. Treat the configured truth root as a managed semantic root. +Truth Structure owns documentation topology. Do not depend on humans to manually organize docs/truthmark/truth. Treat the configured truth root as a managed semantic root. Inspect controllers, routes, handlers, services, packages, tests, existing truth docs, and route files; infer product and domain ownership from behavior boundaries, not from mechanical directory mirroring. When topology pressure exists, repair structure before creating or extending truth docs. Truth-doc ownership gate: @@ -77,7 +77,7 @@ Topology pressure signals: - the configured truth root has many direct non-index docs - a changed controller, route, or service cannot map to a specific behavior doc - Truth Sync would need to create a new generic truth doc because routing is too broad -- endpoint or controller names reveal domains missing from docs/truthmark/areas/** +- endpoint or controller names reveal domains missing from docs/truthmark/routes/areas/** Use these review thresholds as guidance: - more than 10 direct truth docs in one folder - more than 15 leaf areas in one child route file @@ -86,7 +86,7 @@ Use these review thresholds as guidance: Repair rules: - split broad, overloaded, or catch-all areas into behavior-owned child route files - split mixed-owner truth docs into bounded owner docs before adding new behavior claims -- create route files under docs/truthmark/areas/ when a product/domain boundary is clear +- create route files under docs/truthmark/routes/areas/ when a product/domain boundary is clear - create behavior truth docs under the configured truth root only when behavior lacks a current doc - README.md files are indexes, not Truth Sync targets - prefer bounded leaf truth docs at //.md @@ -117,9 +117,9 @@ Portable fallback: - Use a subagent only when the host supports that pattern; otherwise perform the topology repair inline. Truthmark hierarchy hints: - Config, when present: .truthmark/config.yml -- Root route index, when present: docs/truthmark/areas.md -- Area route files, when present: docs/truthmark/areas/**/*.md -- Truth docs, when present: docs/truth/**/*.md +- Root route index, when present: docs/truthmark/routes/areas.md +- Area route files, when present: docs/truthmark/routes/areas/**/*.md +- Truth docs, when present: docs/truthmark/truth/**/*.md Decision truth lives in the canonical doc it governs; date active decisions inline when added or changed. Do not create separate active-decision ADR/planning logs; replace the active decision and let Git history carry the audit trail. Update Product Decisions and Rationale when a decision changes behavior. @@ -128,26 +128,26 @@ Report completion in this shape: Truth Structure: completed Topology reviewed: - controllers: src/auth/** -- docs root: docs/truth -- route files: docs/truthmark/areas.md +- docs root: docs/truthmark/truth +- route files: docs/truthmark/routes/areas.md Areas reviewed: - src/auth/** Routing updated: -- docs/truthmark/areas.md +- docs/truthmark/routes/areas.md Initial truth boundary: - Area: Authentication - Code: src/auth/** -- Truth owner: docs/truth/authentication/session.md +- Truth owner: docs/truthmark/truth/authentication/session.md - Scope: session behavior only Truth docs created: -- docs/truth/authentication/session.md +- docs/truthmark/truth/authentication/session.md Truth docs split: -- docs/truth/authentication/README.md -> docs/truth/authentication/session.md +- docs/truthmark/truth/authentication/README.md -> docs/truthmark/truth/authentication/session.md Truth docs restructured: -- docs/truth/authentication/README.md +- docs/truthmark/truth/authentication/README.md Evidence checked: - Claim: Session behavior belongs to a dedicated Authentication truth owner. - Evidence: src/auth/** / docs/truthmark/areas.md:7 + Evidence: src/auth/** / docs/truthmark/routes/areas.md:7 Result: supported Topology decisions: - Added an Authentication area because session behavior has a distinct code surface and truth owner. diff --git a/.github/prompts/truthmark-sync.prompt.md b/.github/prompts/truthmark-sync.prompt.md index 5943843..26b5352 100644 --- a/.github/prompts/truthmark-sync.prompt.md +++ b/.github/prompts/truthmark-sync.prompt.md @@ -8,7 +8,7 @@ name: truthmark-sync description: Use automatically at finish-time after functional code changes, or explicit /truthmark-sync, $truthmark-sync, or /truthmark:sync. Skip docs-only, formatting-only, behavior-preserving renames, missing config, and no-code changes. Not for doc-first realization or manual topology design. argument-hint: Optional changed-code area, truth-doc area, or sync focus user-invocable: true -truthmark-version: 1.6.1 +truthmark-version: 2.1.0 --- Use this skill automatically before finishing when functional code changed since the last successful Truth Sync. Also run it immediately when the user explicitly invokes Truth Sync. @@ -53,12 +53,12 @@ Product Decisions/Rationale preservation gate: - remove or narrow a decision or rationale only when checkout evidence shows it is stale or unsupported, and report the exact claim, evidence, and result - if ownership of a decision or rationale is unclear, block with manual-review files instead of deleting it or guessing - after the edit, verify every touched truth doc still has Product Decisions and Rationale sections and every pre-existing entry is preserved, moved, narrowed, removed with evidence, or blocked -When creating or updating a truth doc, inspect the routed truth kind and use the matching `docs/templates/-doc.md` template. +When creating or updating a truth doc, inspect the routed truth kind and use the matching template under the configured Truthmark templates root. Supported kinds: behavior, contract, architecture, workflow, operations, and test-behavior. Treat the HTML comments under each template section as normative authoring guidance for that section. Align existing docs to that template and write or repair section content so it satisfies the comment guidance while preserving accurate authored content. If the template is missing, use Scope, Product Decisions, Rationale, and the kind-specific current-truth section. -Teams may edit the template files under docs/templates/ to define their local truth-doc standards. +Teams may edit template files under the configured Truthmark templates root to define their local truth-doc standards. Truth-doc shape repair gate: - Truth Sync may restructure only truth docs impacted by the current functional-code change. - repair shape in place only after the ownership gate confirms the doc is the right bounded owner @@ -91,9 +91,9 @@ Helper status reporting: - Helper output is derived evidence and never replaces direct checkout inspection, evidence review, or parent acceptance. Truthmark hierarchy hints: - Config, when present: .truthmark/config.yml -- Root route index, when present: docs/truthmark/areas.md -- Area route files, when present: docs/truthmark/areas/**/*.md -- Truth docs, when present: docs/truth/**/*.md +- Root route index, when present: docs/truthmark/routes/areas.md +- Area route files, when present: docs/truthmark/routes/areas/**/*.md +- Truth docs, when present: docs/truthmark/truth/**/*.md Decision truth lives in the canonical doc it governs; date active decisions inline when added or changed. Do not create separate active-decision ADR/planning logs; replace the active decision and let Git history carry the audit trail. Update Product Decisions and Rationale when a decision changes behavior. @@ -114,14 +114,14 @@ Changed code reviewed: - src/auth/session.ts Ownership reviewed: -- docs/truthmark/areas.md +- docs/truthmark/routes/areas.md Truth docs updated: -- docs/truth/repository/overview.md +- docs/truthmark/truth/repository/overview.md Evidence checked: - Claim: Session timeout behavior is documented in the mapped repository truth doc. - Evidence: src/auth/session.ts:12 / docs/truthmark/areas.md:11 + Evidence: src/auth/session.ts:12 / docs/truthmark/routes/areas.md:11 Result: supported Helper scripts: @@ -138,7 +138,7 @@ Reason: - routing repair is not allowed Files requiring manual review: -- docs/truthmark/areas.md +- docs/truthmark/routes/areas.md Next action: - update routing metadata and rerun Truth Sync diff --git a/.github/skills/truthmark-check/SKILL.md b/.github/skills/truthmark-check/SKILL.md index d56004c..1ffbf63 100644 --- a/.github/skills/truthmark-check/SKILL.md +++ b/.github/skills/truthmark-check/SKILL.md @@ -3,7 +3,7 @@ name: truthmark-check description: Use when the user asks to audit repository truth health, routing, ownership, or canonical docs. Not for normal lint/test/typecheck/code-review verification, finish-time Sync, or silently rewriting docs. argument-hint: Optional area, doc path, or audit focus user-invocable: true -truthmark-version: 1.6.1 +truthmark-version: 2.1.0 --- # Truthmark Check @@ -12,19 +12,17 @@ Use this skill to audit repository truth health. Use as a Copilot agent skill. Prompt files remain available under `.github/prompts/` for command-style invocation in supported Copilot IDEs. - Invocations: OpenCode /skill truthmark-check; Codex /truthmark-check or $truthmark-check; Claude Code /truthmark-check; GitHub Copilot /truthmark-check; Gemini CLI /truthmark:check. Quick procedure: - Follow repository instruction files that exist in this checkout; do not assume any optional policy path exists. -- Inspect .truthmark/config.yml and configured route files (docs/truthmark/areas.md; docs/truthmark/areas/) only when they exist; then inspect canonical docs and relevant implementation directly. +- Inspect .truthmark/config.yml and configured route files (docs/truthmark/routes/areas.md; docs/truthmark/routes/areas/) only when they exist; then inspect canonical docs and relevant implementation directly. - Report issues and suggested fixes; do not silently rewrite unrelated files. -- Direct checkout inspection is valid even when local tooling is unavailable. - Read support/procedure.md before auditing details. -- Read support/subagents-and-leases.md before dispatching verifier subagents. +- Read support/subagents-and-leases.md only when dispatching verifier subagents. - Read support/report-template.md before the final report. Progressive disclosure: -- support/procedure.md -- support/report-template.md -- support/subagents-and-leases.md +- support/procedure.md — read before edits or detailed auditing; contains core quality gates +- support/report-template.md — read before the final report +- support/subagents-and-leases.md — read only when using subagents, leases, or accepting worker output diff --git a/.github/skills/truthmark-check/support/procedure.md b/.github/skills/truthmark-check/support/procedure.md index 72baa9b..6132ff9 100644 --- a/.github/skills/truthmark-check/support/procedure.md +++ b/.github/skills/truthmark-check/support/procedure.md @@ -1,6 +1,6 @@ # Truthmark Check Procedure -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. # Truthmark Check @@ -13,7 +13,7 @@ Truth Check is agent-led: - inspect .truthmark/config.yml and configured route files only when they exist; then inspect canonical docs and relevant implementation directly - Repository instruction files and explicitly configured policy docs remain instruction authority when present; do not assume a repository uses any particular policy path. Implementation code and canonical truth docs are inspected evidence for current behavior; they do not silently override workflow write boundaries. -- inspect the configured root route index at docs/truthmark/areas.md and relevant child route files under docs/truthmark/areas/ when they exist +- inspect the configured root route index at docs/truthmark/routes/areas.md and relevant child route files under docs/truthmark/routes/areas/ when they exist - check that current docs describe current code rather than historical plans - check that route files map code surfaces to canonical truth docs when route files exist - check for broad, catch-all, index-like, or mixed-owner truth docs and report them as topology issues requiring Truth Structure @@ -29,9 +29,9 @@ Evidence Gate: Truthmark hierarchy hints: - Config, when present: .truthmark/config.yml -- Root route index, when present: docs/truthmark/areas.md -- Area route files, when present: docs/truthmark/areas/**/*.md -- Truth docs, when present: docs/truth/**/*.md +- Root route index, when present: docs/truthmark/routes/areas.md +- Area route files, when present: docs/truthmark/routes/areas/**/*.md +- Truth docs, when present: docs/truthmark/truth/**/*.md Decision truth lives in the canonical doc it governs; date active decisions inline when added or changed. Do not create separate active-decision ADR/planning logs; replace the active decision and let Git history carry the audit trail. Update Product Decisions and Rationale when a decision changes behavior. diff --git a/.github/skills/truthmark-check/support/report-template.md b/.github/skills/truthmark-check/support/report-template.md index 2ce828e..00a3453 100644 --- a/.github/skills/truthmark-check/support/report-template.md +++ b/.github/skills/truthmark-check/support/report-template.md @@ -1,6 +1,6 @@ # Truthmark Check Report Template -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Report completion in this shape: @@ -8,7 +8,7 @@ Report completion in this shape: Truth Check: completed Files reviewed: -- docs/truthmark/areas.md +- docs/truthmark/routes/areas.md Issues found: - none @@ -18,7 +18,7 @@ Fixes suggested: Evidence checked: - Finding: The root route index is present and maps repository truth owners. - Evidence: docs/truthmark/areas.md:1 + Evidence: docs/truthmark/routes/areas.md:1 Suggested fix: none Confidence: high diff --git a/.github/skills/truthmark-check/support/subagents-and-leases.md b/.github/skills/truthmark-check/support/subagents-and-leases.md index 5fbce04..f588254 100644 --- a/.github/skills/truthmark-check/support/subagents-and-leases.md +++ b/.github/skills/truthmark-check/support/subagents-and-leases.md @@ -1,6 +1,6 @@ # Truthmark Check Subagents And Leases -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Copilot custom-agent mode: - use automatically when this workflow runs in Copilot and the parent agent chooses bounded custom-agent fan-out diff --git a/.github/skills/truthmark-document/SKILL.md b/.github/skills/truthmark-document/SKILL.md index 3cad910..7309fe0 100644 --- a/.github/skills/truthmark-document/SKILL.md +++ b/.github/skills/truthmark-document/SKILL.md @@ -3,7 +3,7 @@ name: truthmark-document description: Use when the user asks to document existing implemented behavior, or Sync, Check, or Structure finds implemented behavior missing canonical truth. Not for functional-code changes, doc-first implementation, or topology repair that needs Structure. argument-hint: Optional implemented behavior, API endpoint, route, controller, package, or truth-doc area to document user-invocable: true -truthmark-version: 1.6.1 +truthmark-version: 2.1.0 --- # Truthmark Document @@ -12,21 +12,20 @@ Use this skill to document existing implemented behavior when no functional-code Use as a Copilot agent skill. Prompt files remain available under `.github/prompts/` for command-style invocation in supported Copilot IDEs. - Invocations: OpenCode /skill truthmark-document; Codex /truthmark-document or $truthmark-document; Claude Code /truthmark-document; GitHub Copilot /truthmark-document; Gemini CLI /truthmark:document. Quick procedure: - Follow repository instruction files that exist in this checkout; do not assume any optional policy path exists. -- Inspect .truthmark/config.yml and configured route files (docs/truthmark/areas.md; docs/truthmark/areas/) only when they exist; then inspect existing canonical docs, implementation code, and tests directly. +- Inspect .truthmark/config.yml and configured route files (docs/truthmark/routes/areas.md; docs/truthmark/routes/areas/) only when they exist; then inspect existing canonical docs, implementation code, and tests directly. - Document current implemented behavior; do not invent future behavior. - May write canonical truth docs and truth routing files only; must not write functional code. - Read support/procedure.md before editing truth docs. -- Read support/subagents-and-leases.md before dispatching or accepting worker output. +- Read support/subagents-and-leases.md only when dispatching or accepting worker output. - Read support/report-template.md before the final report. Progressive disclosure: -- support/procedure.md -- support/report-template.md -- support/subagents-and-leases.md -- helper-manifest.yml -- support/helper-policy.md +- support/procedure.md — read before edits or detailed auditing; contains core quality gates +- support/report-template.md — read before the final report +- support/subagents-and-leases.md — read only when using subagents, leases, or accepting worker output +- helper-manifest.yml — read only when invoking helper validators or validating helper registration +- support/helper-policy.md — read only when invoking helper validators or reporting helper status diff --git a/.github/skills/truthmark-document/helper-manifest.yml b/.github/skills/truthmark-document/helper-manifest.yml index 2446476..175e1a0 100644 --- a/.github/skills/truthmark-document/helper-manifest.yml +++ b/.github/skills/truthmark-document/helper-manifest.yml @@ -1,8 +1,8 @@ -# Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +# Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. helpers: validate-document-report: optional: true - runner: truthmark>=1.6.1 + runner: truthmark>=2.1.0 command: argv: - truthmark @@ -17,7 +17,7 @@ helpers: fallback: manually validate support/report-template.md required sections and structured Evidence checked entries validate-write-lease: optional: true - runner: truthmark>=1.6.1 + runner: truthmark>=2.1.0 command: argv: - truthmark diff --git a/.github/skills/truthmark-document/support/helper-policy.md b/.github/skills/truthmark-document/support/helper-policy.md index e545d84..2cb7bd6 100644 --- a/.github/skills/truthmark-document/support/helper-policy.md +++ b/.github/skills/truthmark-document/support/helper-policy.md @@ -1,6 +1,6 @@ # Optional Helper CLI Policy -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Optional helper CLI commands may collect deterministic checkout facts or validate artifacts. If the Truthmark CLI is unavailable or too old for a declared helper, continue manually using this procedure and report which helper was skipped. Helper output is derived evidence; it does not override direct checkout inspection, workflow write boundaries, or parent acceptance. @@ -11,8 +11,8 @@ Runner detection: - Do not fail the workflow solely because a helper cannot run. Available helpers: -- validate-document-report: optional truthmark>=1.6.1; manual fallback: manually validate support/report-template.md required sections and structured Evidence checked entries -- validate-write-lease: optional truthmark>=1.6.1; manual fallback: manually compare declared allowedWrites and forbiddenWrites with the actual changed files +- validate-document-report: optional truthmark>=2.1.0; manual fallback: manually validate support/report-template.md required sections and structured Evidence checked entries +- validate-write-lease: optional truthmark>=2.1.0; manual fallback: manually compare declared allowedWrites and forbiddenWrites with the actual changed files Final reports should include helper status when helpers are declared for this workflow: diff --git a/.github/skills/truthmark-document/support/procedure.md b/.github/skills/truthmark-document/support/procedure.md index 3a38560..be8590f 100644 --- a/.github/skills/truthmark-document/support/procedure.md +++ b/.github/skills/truthmark-document/support/procedure.md @@ -1,6 +1,6 @@ # Truthmark Document Procedure -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. # Truthmark Document @@ -14,7 +14,7 @@ Truth Document is manual and implementation-first: - Repository instruction files and explicitly configured policy docs remain instruction authority when present; do not assume a repository uses any particular policy path. Implementation code and canonical truth docs are inspected evidence for current behavior; they do not silently override workflow write boundaries. - document current implemented behavior; do not invent future behavior or planned endpoints -- may write canonical truth docs and docs/truthmark/areas.md or relevant child route files only +- may write canonical truth docs and docs/truthmark/routes/areas.md or relevant child route files only - must not write functional code - when routing is missing, stale, broad, overloaded, catch-all, or cannot map the behavior to a bounded truth owner, run Truth Structure first when routing repair is safe and in scope - block and recommend Truth Structure when routing repair is unsafe, ambiguous, or outside the task boundary @@ -44,12 +44,12 @@ Evidence Gate: Repository intelligence artifacts are optional derived context: RepoIndex, RouteMap, ImpactSet, and ContextPack may guide routing, context selection, and verification planning when available. They do not override checkout evidence, canonical truth docs, route files, or workflow write boundaries. If unavailable, inspect any present Truthmark config, route files, source files, truth docs, and tests directly, then report that repository-intelligence artifacts were not generated. -When creating or updating a truth doc, inspect the routed truth kind and use the matching `docs/templates/-doc.md` template. +When creating or updating a truth doc, inspect the routed truth kind and use the matching template under the configured Truthmark templates root. Supported kinds: behavior, contract, architecture, workflow, operations, and test-behavior. Treat the HTML comments under each template section as normative authoring guidance for that section. Align existing docs to that template and write or repair section content so it satisfies the comment guidance while preserving accurate authored content. If the template is missing, use Scope, Product Decisions, Rationale, and the kind-specific current-truth section. -Teams may edit the template files under docs/templates/ to define their local truth-doc standards. +Teams may edit template files under the configured Truthmark templates root to define their local truth-doc standards. Truth-doc shape repair gate: - Truth Document may restructure only truth docs for the implemented behavior being documented. - repair shape in place only after the ownership gate confirms the doc is the right bounded owner @@ -61,9 +61,9 @@ Maintain architecture docs only for structure-level changes: system structure, m Keep ordinary behavior, endpoints, UI copy, validation rules, and bug fixes in behavior or contract docs unless they change those boundaries. Truthmark hierarchy hints: - Config, when present: .truthmark/config.yml -- Root route index, when present: docs/truthmark/areas.md -- Area route files, when present: docs/truthmark/areas/**/*.md -- Truth docs, when present: docs/truth/**/*.md +- Root route index, when present: docs/truthmark/routes/areas.md +- Area route files, when present: docs/truthmark/routes/areas/**/*.md +- Truth docs, when present: docs/truthmark/truth/**/*.md Decision truth lives in the canonical doc it governs; date active decisions inline when added or changed. Do not create separate active-decision ADR/planning logs; replace the active decision and let Git history carry the audit trail. Update Product Decisions and Rationale when a decision changes behavior. diff --git a/.github/skills/truthmark-document/support/report-template.md b/.github/skills/truthmark-document/support/report-template.md index 39c8efc..5e38b92 100644 --- a/.github/skills/truthmark-document/support/report-template.md +++ b/.github/skills/truthmark-document/support/report-template.md @@ -1,6 +1,6 @@ # Truthmark Document Report Template -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Report completion in this shape: ```md @@ -10,23 +10,23 @@ Implementation reviewed: - src/routing/area-resolver.ts Ownership reviewed: -- docs/truthmark/areas.md +- docs/truthmark/routes/areas.md Truth docs created: -- docs/truth/contracts.md +- docs/truthmark/truth/contracts.md Truth docs updated: -- docs/truth/check-diagnostics.md +- docs/truthmark/truth/check-diagnostics.md Truth docs restructured: -- docs/truth/check-diagnostics.md +- docs/truthmark/truth/check-diagnostics.md Routing updated: -- docs/truthmark/areas.md +- docs/truthmark/routes/areas.md Evidence checked: - Claim: Route resolution behavior is documented in the contracts truth doc. - Evidence: src/routing/area-resolver.ts:14 / docs/truthmark/areas.md:9 + Evidence: src/routing/area-resolver.ts:14 / docs/truthmark/routes/areas.md:9 Result: supported Helper scripts: diff --git a/.github/skills/truthmark-document/support/subagents-and-leases.md b/.github/skills/truthmark-document/support/subagents-and-leases.md index 6328897..19f3dc3 100644 --- a/.github/skills/truthmark-document/support/subagents-and-leases.md +++ b/.github/skills/truthmark-document/support/subagents-and-leases.md @@ -1,6 +1,6 @@ # Truthmark Document Subagents And Leases -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Copilot custom-agent mode: - use automatically when this workflow runs in Copilot and the parent agent chooses bounded custom-agent fan-out diff --git a/.github/skills/truthmark-preview/SKILL.md b/.github/skills/truthmark-preview/SKILL.md index 3a3b401..48820f0 100644 --- a/.github/skills/truthmark-preview/SKILL.md +++ b/.github/skills/truthmark-preview/SKILL.md @@ -3,7 +3,7 @@ name: truthmark-preview description: Use when the user explicitly asks to preview likely workflow routing, target files, writes, or subagent use before edits. Not for validation, automatic gates, final correctness, or replacing Truth Check. argument-hint: Optional requested outcome, code area, doc path, or routing question user-invocable: true -truthmark-version: 1.6.1 +truthmark-version: 2.1.0 --- # Truthmark Preview @@ -12,18 +12,17 @@ Use this skill only when the user explicitly asks to preview Truthmark routing o Use as a Copilot agent skill. Prompt files remain available under `.github/prompts/` for command-style invocation in supported Copilot IDEs. - Invocations: OpenCode /skill truthmark-preview; Codex /truthmark-preview or $truthmark-preview; Claude Code /truthmark-preview; GitHub Copilot /truthmark-preview; Gemini CLI /truthmark:preview. Quick procedure: - Follow repository instruction files that exist in this checkout; do not assume any optional policy path exists. -- Inspect .truthmark/config.yml and configured route files (docs/truthmark/areas.md; docs/truthmark/areas/) only when they exist; then inspect only the truth docs or implementation files needed to preview ownership. +- Inspect .truthmark/config.yml and configured route files (docs/truthmark/routes/areas.md; docs/truthmark/routes/areas/) only when they exist; then inspect only the truth docs or implementation files needed to preview ownership. - Truth Preview is read-only; this report is intended, not authorized. - must not edit files and must not issue write leases; do not run Truth Sync automatically, replace Truth Check, claim final correctness, or mutate code. - Use optional read-only route-auditor evidence only when it reduces context or clarifies ownership. - Hand off to the selected workflow after user approval. Progressive disclosure: -- support/procedure.md -- support/report-template.md -- support/subagents-and-leases.md +- support/procedure.md — read before edits or detailed auditing; contains core quality gates +- support/report-template.md — read before the final report +- support/subagents-and-leases.md — read only when using subagents, leases, or accepting worker output diff --git a/.github/skills/truthmark-preview/support/procedure.md b/.github/skills/truthmark-preview/support/procedure.md index 2a3f60a..276926b 100644 --- a/.github/skills/truthmark-preview/support/procedure.md +++ b/.github/skills/truthmark-preview/support/procedure.md @@ -1,6 +1,6 @@ # Truthmark Preview Procedure -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Use this skill only when the user explicitly asks to preview Truthmark routing or workflow choice before edits. @@ -15,8 +15,8 @@ Purpose: Read: - .truthmark/config.yml, only when present -- docs/truthmark/areas.md, only when present -- relevant child route files under docs/truthmark/areas/, only when present +- docs/truthmark/routes/areas.md, only when present +- relevant child route files under docs/truthmark/routes/areas/, only when present - relevant truth docs and implementation files needed to preview ownership - Repository instruction files and explicitly configured policy docs remain instruction authority when present; do not assume a repository uses any particular policy path. Implementation code and canonical truth docs are inspected evidence for current behavior; they do not silently override workflow write boundaries. @@ -38,6 +38,6 @@ Suggested subagent use: Truthmark hierarchy hints: - Config, when present: .truthmark/config.yml -- Root route index, when present: docs/truthmark/areas.md -- Area route files, when present: docs/truthmark/areas/**/*.md -- Truth docs, when present: docs/truth/**/*.md +- Root route index, when present: docs/truthmark/routes/areas.md +- Area route files, when present: docs/truthmark/routes/areas/**/*.md +- Truth docs, when present: docs/truthmark/truth/**/*.md diff --git a/.github/skills/truthmark-preview/support/report-template.md b/.github/skills/truthmark-preview/support/report-template.md index 2e63308..bff96a9 100644 --- a/.github/skills/truthmark-preview/support/report-template.md +++ b/.github/skills/truthmark-preview/support/report-template.md @@ -1,6 +1,6 @@ # Truthmark Preview Report Template -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Report completion in this shape: ```md @@ -18,15 +18,15 @@ Why this workflow: - forbidden adjacency considered: must not edit functional code Likely route owner: -- route file: docs/truthmark/areas.md -- truth doc: docs/truth/example.md +- route file: docs/truthmark/routes/areas.md +- truth doc: docs/truthmark/truth/example.md - confidence: medium Expected write classes: - truth docs Expected target files: -- docs/truth/example.md +- docs/truthmark/truth/example.md Suggested subagent use: - read-only verifiers: truth_route_auditor diff --git a/.github/skills/truthmark-preview/support/subagents-and-leases.md b/.github/skills/truthmark-preview/support/subagents-and-leases.md index 43fd52e..9f41bbc 100644 --- a/.github/skills/truthmark-preview/support/subagents-and-leases.md +++ b/.github/skills/truthmark-preview/support/subagents-and-leases.md @@ -1,6 +1,6 @@ # Truthmark Preview Subagents And Leases -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Copilot custom-agent mode: - use automatically when this workflow runs in Copilot and the parent agent chooses bounded custom-agent fan-out diff --git a/.github/skills/truthmark-realize/SKILL.md b/.github/skills/truthmark-realize/SKILL.md index 4330516..138b9e3 100644 --- a/.github/skills/truthmark-realize/SKILL.md +++ b/.github/skills/truthmark-realize/SKILL.md @@ -3,7 +3,7 @@ name: truthmark-realize description: Use when the user explicitly asks to realize Truthmark truth docs into code, including /truthmark-realize, $truthmark-realize, or /truthmark:realize. Not for syncing docs after code changes, documenting existing code, topology repair, or truth audits. argument-hint: Optional truth doc path, area, or desired code behavior to realize user-invocable: true -truthmark-version: 1.6.1 +truthmark-version: 2.1.0 --- # Truthmark Realize @@ -12,17 +12,16 @@ Use this skill only when the user explicitly asks to realize truth docs into cod Use as a Copilot agent skill. Prompt files remain available under `.github/prompts/` for command-style invocation in supported Copilot IDEs. - Invocations: OpenCode /skill truthmark-realize; Codex /truthmark-realize or $truthmark-realize; Claude Code /truthmark-realize; GitHub Copilot /truthmark-realize; Gemini CLI /truthmark:realize. Quick procedure: - Follow repository instruction files that exist in this checkout; do not assume any optional policy path exists. -- Read the source truth docs, inspect .truthmark/config.yml and configured route files (docs/truthmark/areas.md; docs/truthmark/areas/) only when they exist, then inspect tests and relevant functional code directly. +- Read the source truth docs, inspect .truthmark/config.yml and configured route files (docs/truthmark/routes/areas.md; docs/truthmark/routes/areas/) only when they exist, then inspect tests and relevant functional code directly. - Truth docs lead; code follows. - may write functional code only; must not edit truth docs or truth routing while realizing those docs. - Read support/procedure.md before changing code. - Read support/report-template.md before the final report. Progressive disclosure: -- support/procedure.md -- support/report-template.md +- support/procedure.md — read before edits or detailed auditing; contains core quality gates +- support/report-template.md — read before the final report diff --git a/.github/skills/truthmark-realize/support/procedure.md b/.github/skills/truthmark-realize/support/procedure.md index 2deeaff..c419a77 100644 --- a/.github/skills/truthmark-realize/support/procedure.md +++ b/.github/skills/truthmark-realize/support/procedure.md @@ -1,6 +1,6 @@ # Truthmark Realize Procedure -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. # Truthmark Realize @@ -17,7 +17,7 @@ Truth Realize is doc-first: Workflow: 1. Read the updated truth docs named by the user, or infer the relevant docs from configured route files when present. -2. Inspect .truthmark/config.yml and configured route files (docs/truthmark/areas.md; docs/truthmark/areas/) only when they exist; then read tests and the relevant functional code. +2. Inspect .truthmark/config.yml and configured route files (docs/truthmark/routes/areas.md; docs/truthmark/routes/areas/) only when they exist; then read tests and the relevant functional code. 3. Repository instruction files and explicitly configured policy docs remain instruction authority when present; do not assume a repository uses any particular policy path. Implementation code and canonical truth docs are inspected evidence for current behavior; they do not silently override workflow write boundaries. Truth-doc ownership gate: @@ -31,9 +31,9 @@ Truth-doc ownership gate: 7. Report changed code files and verification steps. Truthmark hierarchy hints: - Config, when present: .truthmark/config.yml -- Root route index, when present: docs/truthmark/areas.md -- Area route files, when present: docs/truthmark/areas/**/*.md -- Truth docs, when present: docs/truth/**/*.md +- Root route index, when present: docs/truthmark/routes/areas.md +- Area route files, when present: docs/truthmark/routes/areas/**/*.md +- Truth docs, when present: docs/truthmark/truth/**/*.md Read and write boundaries: diff --git a/.github/skills/truthmark-realize/support/report-template.md b/.github/skills/truthmark-realize/support/report-template.md index 6e887cc..b540f61 100644 --- a/.github/skills/truthmark-realize/support/report-template.md +++ b/.github/skills/truthmark-realize/support/report-template.md @@ -1,6 +1,6 @@ # Truthmark Realize Report Template -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Report completion in this shape: @@ -8,7 +8,7 @@ Report completion in this shape: Truth Realize: completed Truth docs used: -- docs/truth/authentication/session-timeout.md +- docs/truthmark/truth/authentication/session-timeout.md Code updated: - src/auth/session.ts diff --git a/.github/skills/truthmark-structure/SKILL.md b/.github/skills/truthmark-structure/SKILL.md index 8a468d8..8bbe8b6 100644 --- a/.github/skills/truthmark-structure/SKILL.md +++ b/.github/skills/truthmark-structure/SKILL.md @@ -3,7 +3,7 @@ name: truthmark-structure description: Use when routing or truth ownership is missing, stale, broad, overloaded, catch-all, unrouteable, mixed-owner, needs split/repair, or needs new area setup. Not for documenting implemented behavior, syncing a code diff, or realizing docs into code. argument-hint: Optional area, directory, or routing concern user-invocable: true -truthmark-version: 1.6.1 +truthmark-version: 2.1.0 --- # Truthmark Structure @@ -12,18 +12,17 @@ Use this skill to design or repair Truthmark area structure. Use as a Copilot agent skill. Prompt files remain available under `.github/prompts/` for command-style invocation in supported Copilot IDEs. - Invocations: OpenCode /skill truthmark-structure; Codex /truthmark-structure or $truthmark-structure; Claude Code /truthmark-structure; GitHub Copilot /truthmark-structure; Gemini CLI /truthmark:structure. Quick procedure: - Follow repository instruction files that exist in this checkout; do not assume any optional policy path exists. -- Inspect .truthmark/config.yml and configured route files (docs/truthmark/areas.md; docs/truthmark/areas/) only when they exist; then inspect current docs and relevant code directly. +- Inspect .truthmark/config.yml and configured route files (docs/truthmark/routes/areas.md; docs/truthmark/routes/areas/) only when they exist; then inspect current docs and relevant code directly. - Define areas by product or behavior ownership, not by mechanical directory mirroring. - Do not edit functional code. - Read support/procedure.md before writing route or starter truth-doc changes. - Read support/report-template.md before the final report. Progressive disclosure: -- support/procedure.md -- support/report-template.md -- support/subagents-and-leases.md +- support/procedure.md — read before edits or detailed auditing; contains core quality gates +- support/report-template.md — read before the final report +- support/subagents-and-leases.md — read only when using subagents, leases, or accepting worker output diff --git a/.github/skills/truthmark-structure/support/procedure.md b/.github/skills/truthmark-structure/support/procedure.md index bf91e44..5112d6e 100644 --- a/.github/skills/truthmark-structure/support/procedure.md +++ b/.github/skills/truthmark-structure/support/procedure.md @@ -1,6 +1,6 @@ # Truthmark Structure Procedure -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Use this skill to design or repair Truthmark area structure. Invocations: OpenCode /skill truthmark-structure; Codex /truthmark-structure or $truthmark-structure; Claude Code /truthmark-structure; GitHub Copilot /truthmark-structure; Gemini CLI /truthmark:structure. @@ -8,20 +8,20 @@ Truth Structure is agent-native: - inspect repository layout, current docs, Truthmark config and route files when present, and relevant code directly - Repository instruction files and explicitly configured policy docs remain instruction authority when present; do not assume a repository uses any particular policy path. Implementation code and canonical truth docs are inspected evidence for current behavior; they do not silently override workflow write boundaries. -- inspect the configured root route index at docs/truthmark/areas.md and relevant child route files under docs/truthmark/areas/ when they exist +- inspect the configured root route index at docs/truthmark/routes/areas.md and relevant child route files under docs/truthmark/routes/areas/ when they exist - define areas by product or behavior ownership, not by mechanical directory mirroring -- create or repair docs/truthmark/areas.md +- create or repair docs/truthmark/routes/areas.md - create starter truth docs when useful and when they belong in the canonical current-truth surface - Starter truth docs must use closed YAML frontmatter bounded by opening and closing --- lines; include status, doc_type, last_reviewed, and source_of_truth inside that frontmatter. - Starter truth docs must include ## Product Decisions and ## Rationale sections. -When creating or updating a truth doc, inspect the routed truth kind and use the matching `docs/templates/-doc.md` template. +When creating or updating a truth doc, inspect the routed truth kind and use the matching template under the configured Truthmark templates root. Supported kinds: behavior, contract, architecture, workflow, operations, and test-behavior. Treat the HTML comments under each template section as normative authoring guidance for that section. Align existing docs to that template and write or repair section content so it satisfies the comment guidance while preserving accurate authored content. If the template is missing, use Scope, Product Decisions, Rationale, and the kind-specific current-truth section. -Teams may edit the template files under docs/templates/ to define their local truth-doc standards. -- use docs/truth/**, docs/architecture/**, or docs/standards/** for current truth destinations +Teams may edit template files under the configured Truthmark templates root to define their local truth-doc standards. +- use docs/truthmark/truth/** for current truth destinations - use only canonical current-truth destinations for starter truth docs - keep active Product Decisions and Rationale in the canonical doc that owns the behavior - preserve unrelated authored content @@ -41,7 +41,7 @@ Do not: - do not create generic catch-all docs - do not treat README files as Sync targets ## Topology Governance -Truth Structure owns documentation topology. Do not depend on humans to manually organize docs/truth. Treat the configured truth root as a managed semantic root. +Truth Structure owns documentation topology. Do not depend on humans to manually organize docs/truthmark/truth. Treat the configured truth root as a managed semantic root. Inspect controllers, routes, handlers, services, packages, tests, existing truth docs, and route files; infer product and domain ownership from behavior boundaries, not from mechanical directory mirroring. When topology pressure exists, repair structure before creating or extending truth docs. Truth-doc ownership gate: @@ -62,7 +62,7 @@ Topology pressure signals: - the configured truth root has many direct non-index docs - a changed controller, route, or service cannot map to a specific behavior doc - Truth Sync would need to create a new generic truth doc because routing is too broad -- endpoint or controller names reveal domains missing from docs/truthmark/areas/** +- endpoint or controller names reveal domains missing from docs/truthmark/routes/areas/** Use these review thresholds as guidance: - more than 10 direct truth docs in one folder - more than 15 leaf areas in one child route file @@ -71,7 +71,7 @@ Use these review thresholds as guidance: Repair rules: - split broad, overloaded, or catch-all areas into behavior-owned child route files - split mixed-owner truth docs into bounded owner docs before adding new behavior claims -- create route files under docs/truthmark/areas/ when a product/domain boundary is clear +- create route files under docs/truthmark/routes/areas/ when a product/domain boundary is clear - create behavior truth docs under the configured truth root only when behavior lacks a current doc - README.md files are indexes, not Truth Sync targets - prefer bounded leaf truth docs at //.md @@ -102,9 +102,9 @@ Portable fallback: - Use a subagent only when the host supports that pattern; otherwise perform the topology repair inline. Truthmark hierarchy hints: - Config, when present: .truthmark/config.yml -- Root route index, when present: docs/truthmark/areas.md -- Area route files, when present: docs/truthmark/areas/**/*.md -- Truth docs, when present: docs/truth/**/*.md +- Root route index, when present: docs/truthmark/routes/areas.md +- Area route files, when present: docs/truthmark/routes/areas/**/*.md +- Truth docs, when present: docs/truthmark/truth/**/*.md Decision truth lives in the canonical doc it governs; date active decisions inline when added or changed. Do not create separate active-decision ADR/planning logs; replace the active decision and let Git history carry the audit trail. Update Product Decisions and Rationale when a decision changes behavior. diff --git a/.github/skills/truthmark-structure/support/report-template.md b/.github/skills/truthmark-structure/support/report-template.md index 11efef7..1be260b 100644 --- a/.github/skills/truthmark-structure/support/report-template.md +++ b/.github/skills/truthmark-structure/support/report-template.md @@ -1,32 +1,32 @@ # Truthmark Structure Report Template -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Report completion in this shape: ```md Truth Structure: completed Topology reviewed: - controllers: src/auth/** -- docs root: docs/truth -- route files: docs/truthmark/areas.md +- docs root: docs/truthmark/truth +- route files: docs/truthmark/routes/areas.md Areas reviewed: - src/auth/** Routing updated: -- docs/truthmark/areas.md +- docs/truthmark/routes/areas.md Initial truth boundary: - Area: Authentication - Code: src/auth/** -- Truth owner: docs/truth/authentication/session.md +- Truth owner: docs/truthmark/truth/authentication/session.md - Scope: session behavior only Truth docs created: -- docs/truth/authentication/session.md +- docs/truthmark/truth/authentication/session.md Truth docs split: -- docs/truth/authentication/README.md -> docs/truth/authentication/session.md +- docs/truthmark/truth/authentication/README.md -> docs/truthmark/truth/authentication/session.md Truth docs restructured: -- docs/truth/authentication/README.md +- docs/truthmark/truth/authentication/README.md Evidence checked: - Claim: Session behavior belongs to a dedicated Authentication truth owner. - Evidence: src/auth/** / docs/truthmark/areas.md:7 + Evidence: src/auth/** / docs/truthmark/routes/areas.md:7 Result: supported Topology decisions: - Added an Authentication area because session behavior has a distinct code surface and truth owner. diff --git a/.github/skills/truthmark-structure/support/subagents-and-leases.md b/.github/skills/truthmark-structure/support/subagents-and-leases.md index 1092cf2..23d8abc 100644 --- a/.github/skills/truthmark-structure/support/subagents-and-leases.md +++ b/.github/skills/truthmark-structure/support/subagents-and-leases.md @@ -1,6 +1,6 @@ # Truthmark Structure Subagents And Leases -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Copilot custom-agent mode: - use automatically when this workflow runs in Copilot and the parent agent chooses bounded custom-agent fan-out diff --git a/.github/skills/truthmark-sync/SKILL.md b/.github/skills/truthmark-sync/SKILL.md index f5df8a4..0e7e53e 100644 --- a/.github/skills/truthmark-sync/SKILL.md +++ b/.github/skills/truthmark-sync/SKILL.md @@ -3,7 +3,7 @@ name: truthmark-sync description: Use automatically at finish-time after functional code changes, or explicit /truthmark-sync, $truthmark-sync, or /truthmark:sync. Skip docs-only, formatting-only, behavior-preserving renames, missing config, and no-code changes. Not for doc-first realization or manual topology design. argument-hint: Optional changed-code area, truth-doc area, or sync focus user-invocable: true -truthmark-version: 1.6.1 +truthmark-version: 2.1.0 --- # Truthmark Sync @@ -12,22 +12,21 @@ Use this skill automatically before finishing when functional code changed since Use as a Copilot agent skill. Prompt files remain available under `.github/prompts/` for command-style invocation in supported Copilot IDEs. - Invocations: OpenCode /skill truthmark-sync; Codex /truthmark-sync or $truthmark-sync; Claude Code /truthmark-sync; GitHub Copilot /truthmark-sync; Gemini CLI /truthmark:sync. Quick procedure: - Follow repository instruction files that exist in this checkout; do not assume any optional policy path exists. - Skip docs-only, formatting-only, behavior-preserving renames with no truth impact, missing config, and no-code changes. -- Inspect .truthmark/config.yml and configured route files (docs/truthmark/areas.md; docs/truthmark/areas/) only when they exist; then inspect relevant canonical docs directly. +- Inspect .truthmark/config.yml and configured route files (docs/truthmark/routes/areas.md; docs/truthmark/routes/areas/) only when they exist; then inspect relevant canonical docs directly. - direct checkout inspection is the canonical path; do not require the truthmark binary. - May write canonical truth docs and truth routing files only; must not rewrite functional code. - Read support/procedure.md before editing truth docs. -- Read support/subagents-and-leases.md before dispatching or accepting worker output. +- Read support/subagents-and-leases.md only when dispatching or accepting worker output. - Read support/report-template.md before the final report. Progressive disclosure: -- support/procedure.md -- support/report-template.md -- support/subagents-and-leases.md -- helper-manifest.yml -- support/helper-policy.md +- support/procedure.md — read before edits or detailed auditing; contains core quality gates +- support/report-template.md — read before the final report +- support/subagents-and-leases.md — read only when using subagents, leases, or accepting worker output +- helper-manifest.yml — read only when invoking helper validators or validating helper registration +- support/helper-policy.md — read only when invoking helper validators or reporting helper status diff --git a/.github/skills/truthmark-sync/helper-manifest.yml b/.github/skills/truthmark-sync/helper-manifest.yml index 669b903..dd0153a 100644 --- a/.github/skills/truthmark-sync/helper-manifest.yml +++ b/.github/skills/truthmark-sync/helper-manifest.yml @@ -1,8 +1,8 @@ -# Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +# Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. helpers: validate-sync-report: optional: true - runner: truthmark>=1.6.1 + runner: truthmark>=2.1.0 command: argv: - truthmark @@ -17,7 +17,7 @@ helpers: fallback: "manually validate support/report-template.md and check Evidence checked entries match Claim, indented Evidence, and Result: supported | narrowed | removed | blocked" validate-write-lease: optional: true - runner: truthmark>=1.6.1 + runner: truthmark>=2.1.0 command: argv: - truthmark diff --git a/.github/skills/truthmark-sync/support/helper-policy.md b/.github/skills/truthmark-sync/support/helper-policy.md index 78e8645..6c44128 100644 --- a/.github/skills/truthmark-sync/support/helper-policy.md +++ b/.github/skills/truthmark-sync/support/helper-policy.md @@ -1,6 +1,6 @@ # Optional Helper CLI Policy -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Optional helper CLI commands may collect deterministic checkout facts or validate artifacts. If the Truthmark CLI is unavailable or too old for a declared helper, continue manually using this procedure and report which helper was skipped. Helper output is derived evidence; it does not override direct checkout inspection, workflow write boundaries, or parent acceptance. @@ -11,8 +11,8 @@ Runner detection: - Do not fail the workflow solely because a helper cannot run. Available helpers: -- validate-sync-report: optional truthmark>=1.6.1; manual fallback: manually validate support/report-template.md and check Evidence checked entries match Claim, indented Evidence, and Result: supported | narrowed | removed | blocked -- validate-write-lease: optional truthmark>=1.6.1; manual fallback: manually compare declared allowedWrites and forbiddenWrites with the actual changed files +- validate-sync-report: optional truthmark>=2.1.0; manual fallback: manually validate support/report-template.md and check Evidence checked entries match Claim, indented Evidence, and Result: supported | narrowed | removed | blocked +- validate-write-lease: optional truthmark>=2.1.0; manual fallback: manually compare declared allowedWrites and forbiddenWrites with the actual changed files Final reports should include helper status when helpers are declared for this workflow: diff --git a/.github/skills/truthmark-sync/support/procedure.md b/.github/skills/truthmark-sync/support/procedure.md index e839f8f..ff0f6f7 100644 --- a/.github/skills/truthmark-sync/support/procedure.md +++ b/.github/skills/truthmark-sync/support/procedure.md @@ -1,6 +1,6 @@ # Truthmark Sync Procedure -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Use this skill automatically before finishing when functional code changed since the last successful Truth Sync. Also run it immediately when the user explicitly invokes Truth Sync. Invocations: OpenCode /skill truthmark-sync; Codex /truthmark-sync or $truthmark-sync; Claude Code /truthmark-sync; GitHub Copilot /truthmark-sync; Gemini CLI /truthmark:sync. @@ -34,12 +34,12 @@ Product Decisions/Rationale preservation gate: - remove or narrow a decision or rationale only when checkout evidence shows it is stale or unsupported, and report the exact claim, evidence, and result - if ownership of a decision or rationale is unclear, block with manual-review files instead of deleting it or guessing - after the edit, verify every touched truth doc still has Product Decisions and Rationale sections and every pre-existing entry is preserved, moved, narrowed, removed with evidence, or blocked -When creating or updating a truth doc, inspect the routed truth kind and use the matching `docs/templates/-doc.md` template. +When creating or updating a truth doc, inspect the routed truth kind and use the matching template under the configured Truthmark templates root. Supported kinds: behavior, contract, architecture, workflow, operations, and test-behavior. Treat the HTML comments under each template section as normative authoring guidance for that section. Align existing docs to that template and write or repair section content so it satisfies the comment guidance while preserving accurate authored content. If the template is missing, use Scope, Product Decisions, Rationale, and the kind-specific current-truth section. -Teams may edit the template files under docs/templates/ to define their local truth-doc standards. +Teams may edit template files under the configured Truthmark templates root to define their local truth-doc standards. Truth-doc shape repair gate: - Truth Sync may restructure only truth docs impacted by the current functional-code change. - repair shape in place only after the ownership gate confirms the doc is the right bounded owner @@ -72,9 +72,9 @@ Helper status reporting: - Helper output is derived evidence and never replaces direct checkout inspection, evidence review, or parent acceptance. Truthmark hierarchy hints: - Config, when present: .truthmark/config.yml -- Root route index, when present: docs/truthmark/areas.md -- Area route files, when present: docs/truthmark/areas/**/*.md -- Truth docs, when present: docs/truth/**/*.md +- Root route index, when present: docs/truthmark/routes/areas.md +- Area route files, when present: docs/truthmark/routes/areas/**/*.md +- Truth docs, when present: docs/truthmark/truth/**/*.md Decision truth lives in the canonical doc it governs; date active decisions inline when added or changed. Do not create separate active-decision ADR/planning logs; replace the active decision and let Git history carry the audit trail. Update Product Decisions and Rationale when a decision changes behavior. diff --git a/.github/skills/truthmark-sync/support/report-template.md b/.github/skills/truthmark-sync/support/report-template.md index 4cca036..4dfa42d 100644 --- a/.github/skills/truthmark-sync/support/report-template.md +++ b/.github/skills/truthmark-sync/support/report-template.md @@ -1,6 +1,6 @@ # Truthmark Sync Report Template -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Report completion in this shape: ```md @@ -10,14 +10,14 @@ Changed code reviewed: - src/auth/session.ts Ownership reviewed: -- docs/truthmark/areas.md +- docs/truthmark/routes/areas.md Truth docs updated: -- docs/truth/repository/overview.md +- docs/truthmark/truth/repository/overview.md Evidence checked: - Claim: Session timeout behavior is documented in the mapped repository truth doc. - Evidence: src/auth/session.ts:12 / docs/truthmark/areas.md:11 + Evidence: src/auth/session.ts:12 / docs/truthmark/routes/areas.md:11 Result: supported Helper scripts: @@ -34,7 +34,7 @@ Reason: - routing repair is not allowed Files requiring manual review: -- docs/truthmark/areas.md +- docs/truthmark/routes/areas.md Next action: - update routing metadata and rerun Truth Sync diff --git a/.github/skills/truthmark-sync/support/subagents-and-leases.md b/.github/skills/truthmark-sync/support/subagents-and-leases.md index 1f5da8c..3ee4ee9 100644 --- a/.github/skills/truthmark-sync/support/subagents-and-leases.md +++ b/.github/skills/truthmark-sync/support/subagents-and-leases.md @@ -1,6 +1,6 @@ # Truthmark Sync Subagents And Leases -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Copilot custom-agent mode: - use automatically when this workflow runs in Copilot and the parent agent chooses bounded custom-agent fan-out diff --git a/.gitignore b/.gitignore index 036e6cb..7bb3207 100644 --- a/.gitignore +++ b/.gitignore @@ -32,5 +32,6 @@ Thumbs.db *.swp *.swo *.swn +.hermes/ .lean-ctx/graph.db .lean-ctx/graph.meta.json diff --git a/.opencode/agents/truth-claim-verifier.md b/.opencode/agents/truth-claim-verifier.md index 5cfb60b..604da61 100644 --- a/.opencode/agents/truth-claim-verifier.md +++ b/.opencode/agents/truth-claim-verifier.md @@ -16,7 +16,7 @@ permission: "grep *": allow --- -# Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +# Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Manual invocation: @truth-claim-verifier diff --git a/.opencode/agents/truth-doc-reviewer.md b/.opencode/agents/truth-doc-reviewer.md index 9351126..6f1fbea 100644 --- a/.opencode/agents/truth-doc-reviewer.md +++ b/.opencode/agents/truth-doc-reviewer.md @@ -16,7 +16,7 @@ permission: "grep *": allow --- -# Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +# Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Manual invocation: @truth-doc-reviewer diff --git a/.opencode/agents/truth-doc-writer.md b/.opencode/agents/truth-doc-writer.md index fff01b3..a0539af 100644 --- a/.opencode/agents/truth-doc-writer.md +++ b/.opencode/agents/truth-doc-writer.md @@ -8,9 +8,9 @@ permission: glob: allow edit: "*": deny - "docs/truth/**": allow - "docs/truthmark/areas.md": allow - "docs/truthmark/areas/**/*.md": allow + "docs/truthmark/truth/**": allow + "docs/truthmark/routes/areas.md": allow + "docs/truthmark/routes/areas/**/*.md": allow task: deny webfetch: deny websearch: deny @@ -21,7 +21,7 @@ permission: "git diff*": allow --- -# Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +# Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Manual invocation: @truth-doc-writer diff --git a/.opencode/agents/truth-route-auditor.md b/.opencode/agents/truth-route-auditor.md index 0475015..938ca1a 100644 --- a/.opencode/agents/truth-route-auditor.md +++ b/.opencode/agents/truth-route-auditor.md @@ -16,7 +16,7 @@ permission: "grep *": allow --- -# Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +# Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Manual invocation: @truth-route-auditor diff --git a/.opencode/skills/truthmark-check/SKILL.md b/.opencode/skills/truthmark-check/SKILL.md index e330fd0..b8b5902 100644 --- a/.opencode/skills/truthmark-check/SKILL.md +++ b/.opencode/skills/truthmark-check/SKILL.md @@ -3,26 +3,24 @@ name: truthmark-check description: Use when the user asks to audit repository truth health, routing, ownership, or canonical docs. Not for normal lint/test/typecheck/code-review verification, finish-time Sync, or silently rewriting docs. argument-hint: Optional area, doc path, or audit focus user-invocable: true -truthmark-version: 1.6.1 +truthmark-version: 2.1.0 --- # Truthmark Check Use this skill to audit repository truth health. - Invocations: OpenCode /skill truthmark-check; Codex /truthmark-check or $truthmark-check; Claude Code /truthmark-check; GitHub Copilot /truthmark-check; Gemini CLI /truthmark:check. Quick procedure: - Follow repository instruction files that exist in this checkout; do not assume any optional policy path exists. -- Inspect .truthmark/config.yml and configured route files (docs/truthmark/areas.md; docs/truthmark/areas/) only when they exist; then inspect canonical docs and relevant implementation directly. +- Inspect .truthmark/config.yml and configured route files (docs/truthmark/routes/areas.md; docs/truthmark/routes/areas/) only when they exist; then inspect canonical docs and relevant implementation directly. - Report issues and suggested fixes; do not silently rewrite unrelated files. -- Direct checkout inspection is valid even when local tooling is unavailable. - Read support/procedure.md before auditing details. -- Read support/subagents-and-leases.md before dispatching verifier subagents. +- Read support/subagents-and-leases.md only when dispatching verifier subagents. - Read support/report-template.md before the final report. Progressive disclosure: -- support/procedure.md -- support/report-template.md -- support/subagents-and-leases.md +- support/procedure.md — read before edits or detailed auditing; contains core quality gates +- support/report-template.md — read before the final report +- support/subagents-and-leases.md — read only when using subagents, leases, or accepting worker output diff --git a/.opencode/skills/truthmark-check/support/procedure.md b/.opencode/skills/truthmark-check/support/procedure.md index 72baa9b..6132ff9 100644 --- a/.opencode/skills/truthmark-check/support/procedure.md +++ b/.opencode/skills/truthmark-check/support/procedure.md @@ -1,6 +1,6 @@ # Truthmark Check Procedure -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. # Truthmark Check @@ -13,7 +13,7 @@ Truth Check is agent-led: - inspect .truthmark/config.yml and configured route files only when they exist; then inspect canonical docs and relevant implementation directly - Repository instruction files and explicitly configured policy docs remain instruction authority when present; do not assume a repository uses any particular policy path. Implementation code and canonical truth docs are inspected evidence for current behavior; they do not silently override workflow write boundaries. -- inspect the configured root route index at docs/truthmark/areas.md and relevant child route files under docs/truthmark/areas/ when they exist +- inspect the configured root route index at docs/truthmark/routes/areas.md and relevant child route files under docs/truthmark/routes/areas/ when they exist - check that current docs describe current code rather than historical plans - check that route files map code surfaces to canonical truth docs when route files exist - check for broad, catch-all, index-like, or mixed-owner truth docs and report them as topology issues requiring Truth Structure @@ -29,9 +29,9 @@ Evidence Gate: Truthmark hierarchy hints: - Config, when present: .truthmark/config.yml -- Root route index, when present: docs/truthmark/areas.md -- Area route files, when present: docs/truthmark/areas/**/*.md -- Truth docs, when present: docs/truth/**/*.md +- Root route index, when present: docs/truthmark/routes/areas.md +- Area route files, when present: docs/truthmark/routes/areas/**/*.md +- Truth docs, when present: docs/truthmark/truth/**/*.md Decision truth lives in the canonical doc it governs; date active decisions inline when added or changed. Do not create separate active-decision ADR/planning logs; replace the active decision and let Git history carry the audit trail. Update Product Decisions and Rationale when a decision changes behavior. diff --git a/.opencode/skills/truthmark-check/support/report-template.md b/.opencode/skills/truthmark-check/support/report-template.md index 2ce828e..00a3453 100644 --- a/.opencode/skills/truthmark-check/support/report-template.md +++ b/.opencode/skills/truthmark-check/support/report-template.md @@ -1,6 +1,6 @@ # Truthmark Check Report Template -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Report completion in this shape: @@ -8,7 +8,7 @@ Report completion in this shape: Truth Check: completed Files reviewed: -- docs/truthmark/areas.md +- docs/truthmark/routes/areas.md Issues found: - none @@ -18,7 +18,7 @@ Fixes suggested: Evidence checked: - Finding: The root route index is present and maps repository truth owners. - Evidence: docs/truthmark/areas.md:1 + Evidence: docs/truthmark/routes/areas.md:1 Suggested fix: none Confidence: high diff --git a/.opencode/skills/truthmark-check/support/subagents-and-leases.md b/.opencode/skills/truthmark-check/support/subagents-and-leases.md index 254cfb4..74eb60a 100644 --- a/.opencode/skills/truthmark-check/support/subagents-and-leases.md +++ b/.opencode/skills/truthmark-check/support/subagents-and-leases.md @@ -1,6 +1,6 @@ # Truthmark Check Subagents And Leases -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. OpenCode subagent mode: - use automatically when this workflow runs in OpenCode and the parent agent chooses bounded subagent fan-out diff --git a/.opencode/skills/truthmark-document/SKILL.md b/.opencode/skills/truthmark-document/SKILL.md index 6e2469f..241a841 100644 --- a/.opencode/skills/truthmark-document/SKILL.md +++ b/.opencode/skills/truthmark-document/SKILL.md @@ -3,28 +3,27 @@ name: truthmark-document description: Use when the user asks to document existing implemented behavior, or Sync, Check, or Structure finds implemented behavior missing canonical truth. Not for functional-code changes, doc-first implementation, or topology repair that needs Structure. argument-hint: Optional implemented behavior, API endpoint, route, controller, package, or truth-doc area to document user-invocable: true -truthmark-version: 1.6.1 +truthmark-version: 2.1.0 --- # Truthmark Document Use this skill to document existing implemented behavior when no functional-code changes are required for the task. - Invocations: OpenCode /skill truthmark-document; Codex /truthmark-document or $truthmark-document; Claude Code /truthmark-document; GitHub Copilot /truthmark-document; Gemini CLI /truthmark:document. Quick procedure: - Follow repository instruction files that exist in this checkout; do not assume any optional policy path exists. -- Inspect .truthmark/config.yml and configured route files (docs/truthmark/areas.md; docs/truthmark/areas/) only when they exist; then inspect existing canonical docs, implementation code, and tests directly. +- Inspect .truthmark/config.yml and configured route files (docs/truthmark/routes/areas.md; docs/truthmark/routes/areas/) only when they exist; then inspect existing canonical docs, implementation code, and tests directly. - Document current implemented behavior; do not invent future behavior. - May write canonical truth docs and truth routing files only; must not write functional code. - Read support/procedure.md before editing truth docs. -- Read support/subagents-and-leases.md before dispatching or accepting worker output. +- Read support/subagents-and-leases.md only when dispatching or accepting worker output. - Read support/report-template.md before the final report. Progressive disclosure: -- support/procedure.md -- support/report-template.md -- support/subagents-and-leases.md -- helper-manifest.yml -- support/helper-policy.md +- support/procedure.md — read before edits or detailed auditing; contains core quality gates +- support/report-template.md — read before the final report +- support/subagents-and-leases.md — read only when using subagents, leases, or accepting worker output +- helper-manifest.yml — read only when invoking helper validators or validating helper registration +- support/helper-policy.md — read only when invoking helper validators or reporting helper status diff --git a/.opencode/skills/truthmark-document/helper-manifest.yml b/.opencode/skills/truthmark-document/helper-manifest.yml index 2446476..175e1a0 100644 --- a/.opencode/skills/truthmark-document/helper-manifest.yml +++ b/.opencode/skills/truthmark-document/helper-manifest.yml @@ -1,8 +1,8 @@ -# Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +# Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. helpers: validate-document-report: optional: true - runner: truthmark>=1.6.1 + runner: truthmark>=2.1.0 command: argv: - truthmark @@ -17,7 +17,7 @@ helpers: fallback: manually validate support/report-template.md required sections and structured Evidence checked entries validate-write-lease: optional: true - runner: truthmark>=1.6.1 + runner: truthmark>=2.1.0 command: argv: - truthmark diff --git a/.opencode/skills/truthmark-document/support/helper-policy.md b/.opencode/skills/truthmark-document/support/helper-policy.md index e545d84..2cb7bd6 100644 --- a/.opencode/skills/truthmark-document/support/helper-policy.md +++ b/.opencode/skills/truthmark-document/support/helper-policy.md @@ -1,6 +1,6 @@ # Optional Helper CLI Policy -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Optional helper CLI commands may collect deterministic checkout facts or validate artifacts. If the Truthmark CLI is unavailable or too old for a declared helper, continue manually using this procedure and report which helper was skipped. Helper output is derived evidence; it does not override direct checkout inspection, workflow write boundaries, or parent acceptance. @@ -11,8 +11,8 @@ Runner detection: - Do not fail the workflow solely because a helper cannot run. Available helpers: -- validate-document-report: optional truthmark>=1.6.1; manual fallback: manually validate support/report-template.md required sections and structured Evidence checked entries -- validate-write-lease: optional truthmark>=1.6.1; manual fallback: manually compare declared allowedWrites and forbiddenWrites with the actual changed files +- validate-document-report: optional truthmark>=2.1.0; manual fallback: manually validate support/report-template.md required sections and structured Evidence checked entries +- validate-write-lease: optional truthmark>=2.1.0; manual fallback: manually compare declared allowedWrites and forbiddenWrites with the actual changed files Final reports should include helper status when helpers are declared for this workflow: diff --git a/.opencode/skills/truthmark-document/support/procedure.md b/.opencode/skills/truthmark-document/support/procedure.md index 3a38560..be8590f 100644 --- a/.opencode/skills/truthmark-document/support/procedure.md +++ b/.opencode/skills/truthmark-document/support/procedure.md @@ -1,6 +1,6 @@ # Truthmark Document Procedure -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. # Truthmark Document @@ -14,7 +14,7 @@ Truth Document is manual and implementation-first: - Repository instruction files and explicitly configured policy docs remain instruction authority when present; do not assume a repository uses any particular policy path. Implementation code and canonical truth docs are inspected evidence for current behavior; they do not silently override workflow write boundaries. - document current implemented behavior; do not invent future behavior or planned endpoints -- may write canonical truth docs and docs/truthmark/areas.md or relevant child route files only +- may write canonical truth docs and docs/truthmark/routes/areas.md or relevant child route files only - must not write functional code - when routing is missing, stale, broad, overloaded, catch-all, or cannot map the behavior to a bounded truth owner, run Truth Structure first when routing repair is safe and in scope - block and recommend Truth Structure when routing repair is unsafe, ambiguous, or outside the task boundary @@ -44,12 +44,12 @@ Evidence Gate: Repository intelligence artifacts are optional derived context: RepoIndex, RouteMap, ImpactSet, and ContextPack may guide routing, context selection, and verification planning when available. They do not override checkout evidence, canonical truth docs, route files, or workflow write boundaries. If unavailable, inspect any present Truthmark config, route files, source files, truth docs, and tests directly, then report that repository-intelligence artifacts were not generated. -When creating or updating a truth doc, inspect the routed truth kind and use the matching `docs/templates/-doc.md` template. +When creating or updating a truth doc, inspect the routed truth kind and use the matching template under the configured Truthmark templates root. Supported kinds: behavior, contract, architecture, workflow, operations, and test-behavior. Treat the HTML comments under each template section as normative authoring guidance for that section. Align existing docs to that template and write or repair section content so it satisfies the comment guidance while preserving accurate authored content. If the template is missing, use Scope, Product Decisions, Rationale, and the kind-specific current-truth section. -Teams may edit the template files under docs/templates/ to define their local truth-doc standards. +Teams may edit template files under the configured Truthmark templates root to define their local truth-doc standards. Truth-doc shape repair gate: - Truth Document may restructure only truth docs for the implemented behavior being documented. - repair shape in place only after the ownership gate confirms the doc is the right bounded owner @@ -61,9 +61,9 @@ Maintain architecture docs only for structure-level changes: system structure, m Keep ordinary behavior, endpoints, UI copy, validation rules, and bug fixes in behavior or contract docs unless they change those boundaries. Truthmark hierarchy hints: - Config, when present: .truthmark/config.yml -- Root route index, when present: docs/truthmark/areas.md -- Area route files, when present: docs/truthmark/areas/**/*.md -- Truth docs, when present: docs/truth/**/*.md +- Root route index, when present: docs/truthmark/routes/areas.md +- Area route files, when present: docs/truthmark/routes/areas/**/*.md +- Truth docs, when present: docs/truthmark/truth/**/*.md Decision truth lives in the canonical doc it governs; date active decisions inline when added or changed. Do not create separate active-decision ADR/planning logs; replace the active decision and let Git history carry the audit trail. Update Product Decisions and Rationale when a decision changes behavior. diff --git a/.opencode/skills/truthmark-document/support/report-template.md b/.opencode/skills/truthmark-document/support/report-template.md index 39c8efc..5e38b92 100644 --- a/.opencode/skills/truthmark-document/support/report-template.md +++ b/.opencode/skills/truthmark-document/support/report-template.md @@ -1,6 +1,6 @@ # Truthmark Document Report Template -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Report completion in this shape: ```md @@ -10,23 +10,23 @@ Implementation reviewed: - src/routing/area-resolver.ts Ownership reviewed: -- docs/truthmark/areas.md +- docs/truthmark/routes/areas.md Truth docs created: -- docs/truth/contracts.md +- docs/truthmark/truth/contracts.md Truth docs updated: -- docs/truth/check-diagnostics.md +- docs/truthmark/truth/check-diagnostics.md Truth docs restructured: -- docs/truth/check-diagnostics.md +- docs/truthmark/truth/check-diagnostics.md Routing updated: -- docs/truthmark/areas.md +- docs/truthmark/routes/areas.md Evidence checked: - Claim: Route resolution behavior is documented in the contracts truth doc. - Evidence: src/routing/area-resolver.ts:14 / docs/truthmark/areas.md:9 + Evidence: src/routing/area-resolver.ts:14 / docs/truthmark/routes/areas.md:9 Result: supported Helper scripts: diff --git a/.opencode/skills/truthmark-document/support/subagents-and-leases.md b/.opencode/skills/truthmark-document/support/subagents-and-leases.md index a8c3f15..b4f7b6a 100644 --- a/.opencode/skills/truthmark-document/support/subagents-and-leases.md +++ b/.opencode/skills/truthmark-document/support/subagents-and-leases.md @@ -1,6 +1,6 @@ # Truthmark Document Subagents And Leases -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. OpenCode subagent mode: - use automatically when this workflow runs in OpenCode and the parent agent chooses bounded subagent fan-out diff --git a/.opencode/skills/truthmark-preview/SKILL.md b/.opencode/skills/truthmark-preview/SKILL.md index c9acc27..7db8d92 100644 --- a/.opencode/skills/truthmark-preview/SKILL.md +++ b/.opencode/skills/truthmark-preview/SKILL.md @@ -3,25 +3,24 @@ name: truthmark-preview description: Use when the user explicitly asks to preview likely workflow routing, target files, writes, or subagent use before edits. Not for validation, automatic gates, final correctness, or replacing Truth Check. argument-hint: Optional requested outcome, code area, doc path, or routing question user-invocable: true -truthmark-version: 1.6.1 +truthmark-version: 2.1.0 --- # Truthmark Preview Use this skill only when the user explicitly asks to preview Truthmark routing or workflow choice before edits. - Invocations: OpenCode /skill truthmark-preview; Codex /truthmark-preview or $truthmark-preview; Claude Code /truthmark-preview; GitHub Copilot /truthmark-preview; Gemini CLI /truthmark:preview. Quick procedure: - Follow repository instruction files that exist in this checkout; do not assume any optional policy path exists. -- Inspect .truthmark/config.yml and configured route files (docs/truthmark/areas.md; docs/truthmark/areas/) only when they exist; then inspect only the truth docs or implementation files needed to preview ownership. +- Inspect .truthmark/config.yml and configured route files (docs/truthmark/routes/areas.md; docs/truthmark/routes/areas/) only when they exist; then inspect only the truth docs or implementation files needed to preview ownership. - Truth Preview is read-only; this report is intended, not authorized. - must not edit files and must not issue write leases; do not run Truth Sync automatically, replace Truth Check, claim final correctness, or mutate code. - Use optional read-only route-auditor evidence only when it reduces context or clarifies ownership. - Hand off to the selected workflow after user approval. Progressive disclosure: -- support/procedure.md -- support/report-template.md -- support/subagents-and-leases.md +- support/procedure.md — read before edits or detailed auditing; contains core quality gates +- support/report-template.md — read before the final report +- support/subagents-and-leases.md — read only when using subagents, leases, or accepting worker output diff --git a/.opencode/skills/truthmark-preview/support/procedure.md b/.opencode/skills/truthmark-preview/support/procedure.md index 2a3f60a..276926b 100644 --- a/.opencode/skills/truthmark-preview/support/procedure.md +++ b/.opencode/skills/truthmark-preview/support/procedure.md @@ -1,6 +1,6 @@ # Truthmark Preview Procedure -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Use this skill only when the user explicitly asks to preview Truthmark routing or workflow choice before edits. @@ -15,8 +15,8 @@ Purpose: Read: - .truthmark/config.yml, only when present -- docs/truthmark/areas.md, only when present -- relevant child route files under docs/truthmark/areas/, only when present +- docs/truthmark/routes/areas.md, only when present +- relevant child route files under docs/truthmark/routes/areas/, only when present - relevant truth docs and implementation files needed to preview ownership - Repository instruction files and explicitly configured policy docs remain instruction authority when present; do not assume a repository uses any particular policy path. Implementation code and canonical truth docs are inspected evidence for current behavior; they do not silently override workflow write boundaries. @@ -38,6 +38,6 @@ Suggested subagent use: Truthmark hierarchy hints: - Config, when present: .truthmark/config.yml -- Root route index, when present: docs/truthmark/areas.md -- Area route files, when present: docs/truthmark/areas/**/*.md -- Truth docs, when present: docs/truth/**/*.md +- Root route index, when present: docs/truthmark/routes/areas.md +- Area route files, when present: docs/truthmark/routes/areas/**/*.md +- Truth docs, when present: docs/truthmark/truth/**/*.md diff --git a/.opencode/skills/truthmark-preview/support/report-template.md b/.opencode/skills/truthmark-preview/support/report-template.md index 2e63308..bff96a9 100644 --- a/.opencode/skills/truthmark-preview/support/report-template.md +++ b/.opencode/skills/truthmark-preview/support/report-template.md @@ -1,6 +1,6 @@ # Truthmark Preview Report Template -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Report completion in this shape: ```md @@ -18,15 +18,15 @@ Why this workflow: - forbidden adjacency considered: must not edit functional code Likely route owner: -- route file: docs/truthmark/areas.md -- truth doc: docs/truth/example.md +- route file: docs/truthmark/routes/areas.md +- truth doc: docs/truthmark/truth/example.md - confidence: medium Expected write classes: - truth docs Expected target files: -- docs/truth/example.md +- docs/truthmark/truth/example.md Suggested subagent use: - read-only verifiers: truth_route_auditor diff --git a/.opencode/skills/truthmark-preview/support/subagents-and-leases.md b/.opencode/skills/truthmark-preview/support/subagents-and-leases.md index 8f043a0..896c506 100644 --- a/.opencode/skills/truthmark-preview/support/subagents-and-leases.md +++ b/.opencode/skills/truthmark-preview/support/subagents-and-leases.md @@ -1,6 +1,6 @@ # Truthmark Preview Subagents And Leases -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. OpenCode subagent mode: - use automatically when this workflow runs in OpenCode and the parent agent chooses bounded subagent fan-out diff --git a/.opencode/skills/truthmark-realize/SKILL.md b/.opencode/skills/truthmark-realize/SKILL.md index afbe84c..8256b8e 100644 --- a/.opencode/skills/truthmark-realize/SKILL.md +++ b/.opencode/skills/truthmark-realize/SKILL.md @@ -3,24 +3,23 @@ name: truthmark-realize description: Use when the user explicitly asks to realize Truthmark truth docs into code, including /truthmark-realize, $truthmark-realize, or /truthmark:realize. Not for syncing docs after code changes, documenting existing code, topology repair, or truth audits. argument-hint: Optional truth doc path, area, or desired code behavior to realize user-invocable: true -truthmark-version: 1.6.1 +truthmark-version: 2.1.0 --- # Truthmark Realize Use this skill only when the user explicitly asks to realize truth docs into code. - Invocations: OpenCode /skill truthmark-realize; Codex /truthmark-realize or $truthmark-realize; Claude Code /truthmark-realize; GitHub Copilot /truthmark-realize; Gemini CLI /truthmark:realize. Quick procedure: - Follow repository instruction files that exist in this checkout; do not assume any optional policy path exists. -- Read the source truth docs, inspect .truthmark/config.yml and configured route files (docs/truthmark/areas.md; docs/truthmark/areas/) only when they exist, then inspect tests and relevant functional code directly. +- Read the source truth docs, inspect .truthmark/config.yml and configured route files (docs/truthmark/routes/areas.md; docs/truthmark/routes/areas/) only when they exist, then inspect tests and relevant functional code directly. - Truth docs lead; code follows. - may write functional code only; must not edit truth docs or truth routing while realizing those docs. - Read support/procedure.md before changing code. - Read support/report-template.md before the final report. Progressive disclosure: -- support/procedure.md -- support/report-template.md +- support/procedure.md — read before edits or detailed auditing; contains core quality gates +- support/report-template.md — read before the final report diff --git a/.opencode/skills/truthmark-realize/support/procedure.md b/.opencode/skills/truthmark-realize/support/procedure.md index 2deeaff..c419a77 100644 --- a/.opencode/skills/truthmark-realize/support/procedure.md +++ b/.opencode/skills/truthmark-realize/support/procedure.md @@ -1,6 +1,6 @@ # Truthmark Realize Procedure -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. # Truthmark Realize @@ -17,7 +17,7 @@ Truth Realize is doc-first: Workflow: 1. Read the updated truth docs named by the user, or infer the relevant docs from configured route files when present. -2. Inspect .truthmark/config.yml and configured route files (docs/truthmark/areas.md; docs/truthmark/areas/) only when they exist; then read tests and the relevant functional code. +2. Inspect .truthmark/config.yml and configured route files (docs/truthmark/routes/areas.md; docs/truthmark/routes/areas/) only when they exist; then read tests and the relevant functional code. 3. Repository instruction files and explicitly configured policy docs remain instruction authority when present; do not assume a repository uses any particular policy path. Implementation code and canonical truth docs are inspected evidence for current behavior; they do not silently override workflow write boundaries. Truth-doc ownership gate: @@ -31,9 +31,9 @@ Truth-doc ownership gate: 7. Report changed code files and verification steps. Truthmark hierarchy hints: - Config, when present: .truthmark/config.yml -- Root route index, when present: docs/truthmark/areas.md -- Area route files, when present: docs/truthmark/areas/**/*.md -- Truth docs, when present: docs/truth/**/*.md +- Root route index, when present: docs/truthmark/routes/areas.md +- Area route files, when present: docs/truthmark/routes/areas/**/*.md +- Truth docs, when present: docs/truthmark/truth/**/*.md Read and write boundaries: diff --git a/.opencode/skills/truthmark-realize/support/report-template.md b/.opencode/skills/truthmark-realize/support/report-template.md index 6e887cc..b540f61 100644 --- a/.opencode/skills/truthmark-realize/support/report-template.md +++ b/.opencode/skills/truthmark-realize/support/report-template.md @@ -1,6 +1,6 @@ # Truthmark Realize Report Template -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Report completion in this shape: @@ -8,7 +8,7 @@ Report completion in this shape: Truth Realize: completed Truth docs used: -- docs/truth/authentication/session-timeout.md +- docs/truthmark/truth/authentication/session-timeout.md Code updated: - src/auth/session.ts diff --git a/.opencode/skills/truthmark-structure/SKILL.md b/.opencode/skills/truthmark-structure/SKILL.md index c250fc2..4e0d2ab 100644 --- a/.opencode/skills/truthmark-structure/SKILL.md +++ b/.opencode/skills/truthmark-structure/SKILL.md @@ -3,25 +3,24 @@ name: truthmark-structure description: Use when routing or truth ownership is missing, stale, broad, overloaded, catch-all, unrouteable, mixed-owner, needs split/repair, or needs new area setup. Not for documenting implemented behavior, syncing a code diff, or realizing docs into code. argument-hint: Optional area, directory, or routing concern user-invocable: true -truthmark-version: 1.6.1 +truthmark-version: 2.1.0 --- # Truthmark Structure Use this skill to design or repair Truthmark area structure. - Invocations: OpenCode /skill truthmark-structure; Codex /truthmark-structure or $truthmark-structure; Claude Code /truthmark-structure; GitHub Copilot /truthmark-structure; Gemini CLI /truthmark:structure. Quick procedure: - Follow repository instruction files that exist in this checkout; do not assume any optional policy path exists. -- Inspect .truthmark/config.yml and configured route files (docs/truthmark/areas.md; docs/truthmark/areas/) only when they exist; then inspect current docs and relevant code directly. +- Inspect .truthmark/config.yml and configured route files (docs/truthmark/routes/areas.md; docs/truthmark/routes/areas/) only when they exist; then inspect current docs and relevant code directly. - Define areas by product or behavior ownership, not by mechanical directory mirroring. - Do not edit functional code. - Read support/procedure.md before writing route or starter truth-doc changes. - Read support/report-template.md before the final report. Progressive disclosure: -- support/procedure.md -- support/report-template.md -- support/subagents-and-leases.md +- support/procedure.md — read before edits or detailed auditing; contains core quality gates +- support/report-template.md — read before the final report +- support/subagents-and-leases.md — read only when using subagents, leases, or accepting worker output diff --git a/.opencode/skills/truthmark-structure/support/procedure.md b/.opencode/skills/truthmark-structure/support/procedure.md index bf91e44..5112d6e 100644 --- a/.opencode/skills/truthmark-structure/support/procedure.md +++ b/.opencode/skills/truthmark-structure/support/procedure.md @@ -1,6 +1,6 @@ # Truthmark Structure Procedure -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Use this skill to design or repair Truthmark area structure. Invocations: OpenCode /skill truthmark-structure; Codex /truthmark-structure or $truthmark-structure; Claude Code /truthmark-structure; GitHub Copilot /truthmark-structure; Gemini CLI /truthmark:structure. @@ -8,20 +8,20 @@ Truth Structure is agent-native: - inspect repository layout, current docs, Truthmark config and route files when present, and relevant code directly - Repository instruction files and explicitly configured policy docs remain instruction authority when present; do not assume a repository uses any particular policy path. Implementation code and canonical truth docs are inspected evidence for current behavior; they do not silently override workflow write boundaries. -- inspect the configured root route index at docs/truthmark/areas.md and relevant child route files under docs/truthmark/areas/ when they exist +- inspect the configured root route index at docs/truthmark/routes/areas.md and relevant child route files under docs/truthmark/routes/areas/ when they exist - define areas by product or behavior ownership, not by mechanical directory mirroring -- create or repair docs/truthmark/areas.md +- create or repair docs/truthmark/routes/areas.md - create starter truth docs when useful and when they belong in the canonical current-truth surface - Starter truth docs must use closed YAML frontmatter bounded by opening and closing --- lines; include status, doc_type, last_reviewed, and source_of_truth inside that frontmatter. - Starter truth docs must include ## Product Decisions and ## Rationale sections. -When creating or updating a truth doc, inspect the routed truth kind and use the matching `docs/templates/-doc.md` template. +When creating or updating a truth doc, inspect the routed truth kind and use the matching template under the configured Truthmark templates root. Supported kinds: behavior, contract, architecture, workflow, operations, and test-behavior. Treat the HTML comments under each template section as normative authoring guidance for that section. Align existing docs to that template and write or repair section content so it satisfies the comment guidance while preserving accurate authored content. If the template is missing, use Scope, Product Decisions, Rationale, and the kind-specific current-truth section. -Teams may edit the template files under docs/templates/ to define their local truth-doc standards. -- use docs/truth/**, docs/architecture/**, or docs/standards/** for current truth destinations +Teams may edit template files under the configured Truthmark templates root to define their local truth-doc standards. +- use docs/truthmark/truth/** for current truth destinations - use only canonical current-truth destinations for starter truth docs - keep active Product Decisions and Rationale in the canonical doc that owns the behavior - preserve unrelated authored content @@ -41,7 +41,7 @@ Do not: - do not create generic catch-all docs - do not treat README files as Sync targets ## Topology Governance -Truth Structure owns documentation topology. Do not depend on humans to manually organize docs/truth. Treat the configured truth root as a managed semantic root. +Truth Structure owns documentation topology. Do not depend on humans to manually organize docs/truthmark/truth. Treat the configured truth root as a managed semantic root. Inspect controllers, routes, handlers, services, packages, tests, existing truth docs, and route files; infer product and domain ownership from behavior boundaries, not from mechanical directory mirroring. When topology pressure exists, repair structure before creating or extending truth docs. Truth-doc ownership gate: @@ -62,7 +62,7 @@ Topology pressure signals: - the configured truth root has many direct non-index docs - a changed controller, route, or service cannot map to a specific behavior doc - Truth Sync would need to create a new generic truth doc because routing is too broad -- endpoint or controller names reveal domains missing from docs/truthmark/areas/** +- endpoint or controller names reveal domains missing from docs/truthmark/routes/areas/** Use these review thresholds as guidance: - more than 10 direct truth docs in one folder - more than 15 leaf areas in one child route file @@ -71,7 +71,7 @@ Use these review thresholds as guidance: Repair rules: - split broad, overloaded, or catch-all areas into behavior-owned child route files - split mixed-owner truth docs into bounded owner docs before adding new behavior claims -- create route files under docs/truthmark/areas/ when a product/domain boundary is clear +- create route files under docs/truthmark/routes/areas/ when a product/domain boundary is clear - create behavior truth docs under the configured truth root only when behavior lacks a current doc - README.md files are indexes, not Truth Sync targets - prefer bounded leaf truth docs at //.md @@ -102,9 +102,9 @@ Portable fallback: - Use a subagent only when the host supports that pattern; otherwise perform the topology repair inline. Truthmark hierarchy hints: - Config, when present: .truthmark/config.yml -- Root route index, when present: docs/truthmark/areas.md -- Area route files, when present: docs/truthmark/areas/**/*.md -- Truth docs, when present: docs/truth/**/*.md +- Root route index, when present: docs/truthmark/routes/areas.md +- Area route files, when present: docs/truthmark/routes/areas/**/*.md +- Truth docs, when present: docs/truthmark/truth/**/*.md Decision truth lives in the canonical doc it governs; date active decisions inline when added or changed. Do not create separate active-decision ADR/planning logs; replace the active decision and let Git history carry the audit trail. Update Product Decisions and Rationale when a decision changes behavior. diff --git a/.opencode/skills/truthmark-structure/support/report-template.md b/.opencode/skills/truthmark-structure/support/report-template.md index 11efef7..1be260b 100644 --- a/.opencode/skills/truthmark-structure/support/report-template.md +++ b/.opencode/skills/truthmark-structure/support/report-template.md @@ -1,32 +1,32 @@ # Truthmark Structure Report Template -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Report completion in this shape: ```md Truth Structure: completed Topology reviewed: - controllers: src/auth/** -- docs root: docs/truth -- route files: docs/truthmark/areas.md +- docs root: docs/truthmark/truth +- route files: docs/truthmark/routes/areas.md Areas reviewed: - src/auth/** Routing updated: -- docs/truthmark/areas.md +- docs/truthmark/routes/areas.md Initial truth boundary: - Area: Authentication - Code: src/auth/** -- Truth owner: docs/truth/authentication/session.md +- Truth owner: docs/truthmark/truth/authentication/session.md - Scope: session behavior only Truth docs created: -- docs/truth/authentication/session.md +- docs/truthmark/truth/authentication/session.md Truth docs split: -- docs/truth/authentication/README.md -> docs/truth/authentication/session.md +- docs/truthmark/truth/authentication/README.md -> docs/truthmark/truth/authentication/session.md Truth docs restructured: -- docs/truth/authentication/README.md +- docs/truthmark/truth/authentication/README.md Evidence checked: - Claim: Session behavior belongs to a dedicated Authentication truth owner. - Evidence: src/auth/** / docs/truthmark/areas.md:7 + Evidence: src/auth/** / docs/truthmark/routes/areas.md:7 Result: supported Topology decisions: - Added an Authentication area because session behavior has a distinct code surface and truth owner. diff --git a/.opencode/skills/truthmark-structure/support/subagents-and-leases.md b/.opencode/skills/truthmark-structure/support/subagents-and-leases.md index c92be1b..ac1129b 100644 --- a/.opencode/skills/truthmark-structure/support/subagents-and-leases.md +++ b/.opencode/skills/truthmark-structure/support/subagents-and-leases.md @@ -1,6 +1,6 @@ # Truthmark Structure Subagents And Leases -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. OpenCode subagent mode: - use automatically when this workflow runs in OpenCode and the parent agent chooses bounded subagent fan-out diff --git a/.opencode/skills/truthmark-sync/SKILL.md b/.opencode/skills/truthmark-sync/SKILL.md index 94278d7..ff1d4eb 100644 --- a/.opencode/skills/truthmark-sync/SKILL.md +++ b/.opencode/skills/truthmark-sync/SKILL.md @@ -3,29 +3,28 @@ name: truthmark-sync description: Use automatically at finish-time after functional code changes, or explicit /truthmark-sync, $truthmark-sync, or /truthmark:sync. Skip docs-only, formatting-only, behavior-preserving renames, missing config, and no-code changes. Not for doc-first realization or manual topology design. argument-hint: Optional changed-code area, truth-doc area, or sync focus user-invocable: true -truthmark-version: 1.6.1 +truthmark-version: 2.1.0 --- # Truthmark Sync Use this skill automatically before finishing when functional code changed since the last successful Truth Sync. Also run it immediately when the user explicitly invokes Truth Sync. - Invocations: OpenCode /skill truthmark-sync; Codex /truthmark-sync or $truthmark-sync; Claude Code /truthmark-sync; GitHub Copilot /truthmark-sync; Gemini CLI /truthmark:sync. Quick procedure: - Follow repository instruction files that exist in this checkout; do not assume any optional policy path exists. - Skip docs-only, formatting-only, behavior-preserving renames with no truth impact, missing config, and no-code changes. -- Inspect .truthmark/config.yml and configured route files (docs/truthmark/areas.md; docs/truthmark/areas/) only when they exist; then inspect relevant canonical docs directly. +- Inspect .truthmark/config.yml and configured route files (docs/truthmark/routes/areas.md; docs/truthmark/routes/areas/) only when they exist; then inspect relevant canonical docs directly. - direct checkout inspection is the canonical path; do not require the truthmark binary. - May write canonical truth docs and truth routing files only; must not rewrite functional code. - Read support/procedure.md before editing truth docs. -- Read support/subagents-and-leases.md before dispatching or accepting worker output. +- Read support/subagents-and-leases.md only when dispatching or accepting worker output. - Read support/report-template.md before the final report. Progressive disclosure: -- support/procedure.md -- support/report-template.md -- support/subagents-and-leases.md -- helper-manifest.yml -- support/helper-policy.md +- support/procedure.md — read before edits or detailed auditing; contains core quality gates +- support/report-template.md — read before the final report +- support/subagents-and-leases.md — read only when using subagents, leases, or accepting worker output +- helper-manifest.yml — read only when invoking helper validators or validating helper registration +- support/helper-policy.md — read only when invoking helper validators or reporting helper status diff --git a/.opencode/skills/truthmark-sync/helper-manifest.yml b/.opencode/skills/truthmark-sync/helper-manifest.yml index 669b903..dd0153a 100644 --- a/.opencode/skills/truthmark-sync/helper-manifest.yml +++ b/.opencode/skills/truthmark-sync/helper-manifest.yml @@ -1,8 +1,8 @@ -# Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +# Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. helpers: validate-sync-report: optional: true - runner: truthmark>=1.6.1 + runner: truthmark>=2.1.0 command: argv: - truthmark @@ -17,7 +17,7 @@ helpers: fallback: "manually validate support/report-template.md and check Evidence checked entries match Claim, indented Evidence, and Result: supported | narrowed | removed | blocked" validate-write-lease: optional: true - runner: truthmark>=1.6.1 + runner: truthmark>=2.1.0 command: argv: - truthmark diff --git a/.opencode/skills/truthmark-sync/support/helper-policy.md b/.opencode/skills/truthmark-sync/support/helper-policy.md index 78e8645..6c44128 100644 --- a/.opencode/skills/truthmark-sync/support/helper-policy.md +++ b/.opencode/skills/truthmark-sync/support/helper-policy.md @@ -1,6 +1,6 @@ # Optional Helper CLI Policy -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Optional helper CLI commands may collect deterministic checkout facts or validate artifacts. If the Truthmark CLI is unavailable or too old for a declared helper, continue manually using this procedure and report which helper was skipped. Helper output is derived evidence; it does not override direct checkout inspection, workflow write boundaries, or parent acceptance. @@ -11,8 +11,8 @@ Runner detection: - Do not fail the workflow solely because a helper cannot run. Available helpers: -- validate-sync-report: optional truthmark>=1.6.1; manual fallback: manually validate support/report-template.md and check Evidence checked entries match Claim, indented Evidence, and Result: supported | narrowed | removed | blocked -- validate-write-lease: optional truthmark>=1.6.1; manual fallback: manually compare declared allowedWrites and forbiddenWrites with the actual changed files +- validate-sync-report: optional truthmark>=2.1.0; manual fallback: manually validate support/report-template.md and check Evidence checked entries match Claim, indented Evidence, and Result: supported | narrowed | removed | blocked +- validate-write-lease: optional truthmark>=2.1.0; manual fallback: manually compare declared allowedWrites and forbiddenWrites with the actual changed files Final reports should include helper status when helpers are declared for this workflow: diff --git a/.opencode/skills/truthmark-sync/support/procedure.md b/.opencode/skills/truthmark-sync/support/procedure.md index e839f8f..ff0f6f7 100644 --- a/.opencode/skills/truthmark-sync/support/procedure.md +++ b/.opencode/skills/truthmark-sync/support/procedure.md @@ -1,6 +1,6 @@ # Truthmark Sync Procedure -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Use this skill automatically before finishing when functional code changed since the last successful Truth Sync. Also run it immediately when the user explicitly invokes Truth Sync. Invocations: OpenCode /skill truthmark-sync; Codex /truthmark-sync or $truthmark-sync; Claude Code /truthmark-sync; GitHub Copilot /truthmark-sync; Gemini CLI /truthmark:sync. @@ -34,12 +34,12 @@ Product Decisions/Rationale preservation gate: - remove or narrow a decision or rationale only when checkout evidence shows it is stale or unsupported, and report the exact claim, evidence, and result - if ownership of a decision or rationale is unclear, block with manual-review files instead of deleting it or guessing - after the edit, verify every touched truth doc still has Product Decisions and Rationale sections and every pre-existing entry is preserved, moved, narrowed, removed with evidence, or blocked -When creating or updating a truth doc, inspect the routed truth kind and use the matching `docs/templates/-doc.md` template. +When creating or updating a truth doc, inspect the routed truth kind and use the matching template under the configured Truthmark templates root. Supported kinds: behavior, contract, architecture, workflow, operations, and test-behavior. Treat the HTML comments under each template section as normative authoring guidance for that section. Align existing docs to that template and write or repair section content so it satisfies the comment guidance while preserving accurate authored content. If the template is missing, use Scope, Product Decisions, Rationale, and the kind-specific current-truth section. -Teams may edit the template files under docs/templates/ to define their local truth-doc standards. +Teams may edit template files under the configured Truthmark templates root to define their local truth-doc standards. Truth-doc shape repair gate: - Truth Sync may restructure only truth docs impacted by the current functional-code change. - repair shape in place only after the ownership gate confirms the doc is the right bounded owner @@ -72,9 +72,9 @@ Helper status reporting: - Helper output is derived evidence and never replaces direct checkout inspection, evidence review, or parent acceptance. Truthmark hierarchy hints: - Config, when present: .truthmark/config.yml -- Root route index, when present: docs/truthmark/areas.md -- Area route files, when present: docs/truthmark/areas/**/*.md -- Truth docs, when present: docs/truth/**/*.md +- Root route index, when present: docs/truthmark/routes/areas.md +- Area route files, when present: docs/truthmark/routes/areas/**/*.md +- Truth docs, when present: docs/truthmark/truth/**/*.md Decision truth lives in the canonical doc it governs; date active decisions inline when added or changed. Do not create separate active-decision ADR/planning logs; replace the active decision and let Git history carry the audit trail. Update Product Decisions and Rationale when a decision changes behavior. diff --git a/.opencode/skills/truthmark-sync/support/report-template.md b/.opencode/skills/truthmark-sync/support/report-template.md index 4cca036..4dfa42d 100644 --- a/.opencode/skills/truthmark-sync/support/report-template.md +++ b/.opencode/skills/truthmark-sync/support/report-template.md @@ -1,6 +1,6 @@ # Truthmark Sync Report Template -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. Report completion in this shape: ```md @@ -10,14 +10,14 @@ Changed code reviewed: - src/auth/session.ts Ownership reviewed: -- docs/truthmark/areas.md +- docs/truthmark/routes/areas.md Truth docs updated: -- docs/truth/repository/overview.md +- docs/truthmark/truth/repository/overview.md Evidence checked: - Claim: Session timeout behavior is documented in the mapped repository truth doc. - Evidence: src/auth/session.ts:12 / docs/truthmark/areas.md:11 + Evidence: src/auth/session.ts:12 / docs/truthmark/routes/areas.md:11 Result: supported Helper scripts: @@ -34,7 +34,7 @@ Reason: - routing repair is not allowed Files requiring manual review: -- docs/truthmark/areas.md +- docs/truthmark/routes/areas.md Next action: - update routing metadata and rerun Truth Sync diff --git a/.opencode/skills/truthmark-sync/support/subagents-and-leases.md b/.opencode/skills/truthmark-sync/support/subagents-and-leases.md index d1b0913..57c829b 100644 --- a/.opencode/skills/truthmark-sync/support/subagents-and-leases.md +++ b/.opencode/skills/truthmark-sync/support/subagents-and-leases.md @@ -1,6 +1,6 @@ # Truthmark Sync Subagents And Leases -Generated by Truthmark 1.6.1. Rerun truthmark init after upgrades. +Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. OpenCode subagent mode: - use automatically when this workflow runs in OpenCode and the parent agent chooses bounded subagent fan-out diff --git a/.truthmark/config.yml b/.truthmark/config.yml index 117cee7..e6ac65e 100644 --- a/.truthmark/config.yml +++ b/.truthmark/config.yml @@ -1,33 +1,26 @@ -version: 1 +version: 2 platforms: - codex - opencode - claude-code - github-copilot - gemini-cli -docs: - layout: hierarchical - roots: - ai: docs/ai - standards: docs/standards - architecture: docs/architecture - truth: docs/truth - routing: - root_index: docs/truthmark/areas.md - area_files_root: docs/truthmark/areas +truthmark: + workspace: docs/truthmark + routes: + index: routes/areas.md + areas: routes/areas default_area: repository max_delegation_depth: 1 -authority: - - docs/truthmark/areas.md - - docs/truthmark/areas/**/*.md - - docs/ai/**/*.md - - docs/standards/**/*.md - - docs/architecture/**/*.md - - docs/truth/**/*.md + truth: + root: truth + templates: + root: templates + generated: + portal: + enabled: false instruction_targets: - AGENTS.md - - CLAUDE.md - - GEMINI.md frontmatter: required: [] recommended: diff --git a/AGENTS.md b/AGENTS.md index b245a84..5202bc3 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -9,8 +9,8 @@ Agent-specific: ## Truthmark Workflow -Generated by Truthmark 1.6.1. Rerun `truthmark init` after upgrades. -Hierarchy hints: config .truthmark/config.yml when present; routes docs/truthmark/areas.md and docs/truthmark/areas/**/*.md when present; Truth docs: docs/truth/**/*.md when present. +Generated by Truthmark 2.1.0. Rerun `truthmark init` after upgrades. +Hierarchy hints: config .truthmark/config.yml when present; routes docs/truthmark/routes/areas.md and docs/truthmark/routes/areas/**/*.md when present; Truth docs: docs/truthmark/truth/**/*.md when present. Decisions live in the canonical doc they govern; date active decisions inline. Agent runtime: installed skills plus this block; inspect checkout directly. Delegation is host-owned. ### Truth Sync diff --git a/CLAUDE.md b/CLAUDE.md index b245a84..5202bc3 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -9,8 +9,8 @@ Agent-specific: ## Truthmark Workflow -Generated by Truthmark 1.6.1. Rerun `truthmark init` after upgrades. -Hierarchy hints: config .truthmark/config.yml when present; routes docs/truthmark/areas.md and docs/truthmark/areas/**/*.md when present; Truth docs: docs/truth/**/*.md when present. +Generated by Truthmark 2.1.0. Rerun `truthmark init` after upgrades. +Hierarchy hints: config .truthmark/config.yml when present; routes docs/truthmark/routes/areas.md and docs/truthmark/routes/areas/**/*.md when present; Truth docs: docs/truthmark/truth/**/*.md when present. Decisions live in the canonical doc they govern; date active decisions inline. Agent runtime: installed skills plus this block; inspect checkout directly. Delegation is host-owned. ### Truth Sync diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 10daa75..b55290b 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -14,6 +14,6 @@ Use this source-checkout flow when changing Truthmark's own code, templates, or ## What To Verify -- If you edit `src/templates/**`, `src/agents/**`, or generated workflow renderers, rerun `npm run dev -- init` and review the diffs in `AGENTS.md`, `.codex/skills/`, and `.opencode/skills/`. +- If you edit `src/templates/**`, `src/agents/**`, or generated workflow renderers, rerun `npm run dev -- init` and review the diffs in `AGENTS.md`, `.agents/skills/`, and `.opencode/skills/`. - If you change behavior in `src/checks/**`, `src/init/**`, `src/sync/**`, or `src/realize/**`, run the relevant tests and `npm run dev -- check`. - Keep the public [README.md](README.md) user-facing; put contributor setup here. diff --git a/GEMINI.md b/GEMINI.md index b245a84..5202bc3 100644 --- a/GEMINI.md +++ b/GEMINI.md @@ -9,8 +9,8 @@ Agent-specific: ## Truthmark Workflow -Generated by Truthmark 1.6.1. Rerun `truthmark init` after upgrades. -Hierarchy hints: config .truthmark/config.yml when present; routes docs/truthmark/areas.md and docs/truthmark/areas/**/*.md when present; Truth docs: docs/truth/**/*.md when present. +Generated by Truthmark 2.1.0. Rerun `truthmark init` after upgrades. +Hierarchy hints: config .truthmark/config.yml when present; routes docs/truthmark/routes/areas.md and docs/truthmark/routes/areas/**/*.md when present; Truth docs: docs/truthmark/truth/**/*.md when present. Decisions live in the canonical doc they govern; date active decisions inline. Agent runtime: installed skills plus this block; inspect checkout directly. Delegation is host-owned. ### Truth Sync diff --git a/README.de.md b/README.de.md index f45a5f9..d64cd2a 100644 --- a/README.de.md +++ b/README.de.md @@ -1,12 +1,12 @@ # Truthmark -**Deine Agenten schreiben Code. Truthmark macht ihren Kontext in Git prüfbar.** +**Deine Agenten schreiben Code. Truthmark hält menschenorientierte Dokumentation in Git prüfbar.** [English](README.md) | Deutsch | [中文](README.zh.md) | [Español](README.es.md) | [Русский](README.ru.md) ![Truthmark-Banner](docs/assets/truthmark-banner.png) -KI-Coding-Agenten können ein Repository schneller verändern, als Menschen den Kontext ausrichten können. +KI-Coding-Agenten können ein Repository schneller verändern, als Menschen die Dokumentation ausrichten können. Truthmark repariert den Teil, der normalerweise nach dem Code-Schreiben bricht: die Repository-Wahrheit. @@ -33,9 +33,9 @@ Die Implementierung ändert sich, aber die Repository-Erzählung driftet ab: - Produktentscheidungen verschwinden nach der Übergabe - Reviewer sehen Code-Diffs ohne die zugehörigen Truth-Diffs - Branches entwickeln unbemerkt unterschiedliche Versionen davon, „was wahr ist“ -- jede Agentensitzung muss Kontext neu entdecken +- jede Agentensitzung muss Repository-Wahrheit neu entdecken -Truthmark verwandelt diesen fragilen Kontext in festgeschriebene Repository-Infrastruktur. +Truthmark verwandelt diese fragile Repository-Wahrheit in festgeschriebene Repository-Infrastruktur. Statt darauf zu vertrauen, dass jeder Mensch und jeder Agent die richtige Dokumentationsgewohnheit beibehält, installiert Truthmark diese Gewohnheit im Repository. @@ -66,7 +66,7 @@ Es hat zwei unterschiedliche Oberflächen, und diese Unterscheidung ist wichtig. Die CLI ist für Maintainer, Reviewer und Automatisierung. -Nutze sie, um ein Repository zu konfigurieren, Workflow-Dateien zu installieren oder zu aktualisieren, Truth-Artefakte zu validieren und optionalen Review-Kontext zu erzeugen. +Nutze sie, um ein Repository zu konfigurieren, Workflow-Dateien zu installieren oder zu aktualisieren, Truth-Artefakte zu validieren und optionales Review-Material zu erzeugen. ```bash truthmark config @@ -179,6 +179,14 @@ Bitte deinen Agenten, die breite Route in tatsächliche Produkt-, Service-, Dom /truthmark-structure die breite repository-area in auth, billing und notifications aufteilen ``` +Wenn das Projekt bereits implementierte Features hat, aber Truth-Dokumente fehlen oder schwach sind, bitte den installierten Truth-Document-Workflow, einen fokussierten Scope zu dokumentieren: + +```text +/truthmark-document dokumentiere das implementierte payment-retry-verhalten in src/billing/retry.ts und den zugehörigen tests +``` + +Truth Document ist der häufigste erste Workflow für bestehende Projekte. Er inspiziert Implementierung, Tests, Routen und vorhandene Dokumentation und erstellt oder repariert danach Truth-Dokumente und Routing, ohne funktionalen Code zu ändern. + Danach nutzt du deinen KI-Coding-Agenten normal. Wenn der Agent funktionalen Code ändert, wirkt Truth Sync als Abschlusskontrolle und prüft vor der Übergabe, ob zugeordnete Truth-Dokumente geändert werden müssen. @@ -188,7 +196,7 @@ Wenn der Agent funktionalen Code ändert, wirkt Truth Sync als Abschlusskontroll | Fähigkeit | Was sie tut | | --- | --- | | Git-native Wahrheit | Hält Repository-Wahrheit in festgeschriebenem Markdown und Config. | -| Branch-gebundener Kontext | Wahrheit wandert mit dem Branch statt in einer privaten Sitzung zu leben. | +| Branch-gebundene Dokumentation | Wahrheit wandert mit dem Branch statt in einer privaten Sitzung zu leben. | | Menschen-CLI | Gibt Maintainern Befehle für Setup, Aktualisierung, Validierung und Inspektion. | | KI-orientierte Workflows | Gibt Agenten host-native Workflows für Sync, Dokumentation, Struktur, Preview, Realisierung und Audit. | | Explizites Routing | Ordnet Codebereiche kanonischen Truth-Dokumenten zu. | @@ -229,10 +237,10 @@ Es ist nützlich, wenn du Folgendes brauchst: - weniger Dokumentationsdrift - bessere Übergaben - branch-spezifische Produktwahrheit -- dauerhaften Architektur- und API-Kontext +- dauerhafte Architektur- und API-Dokumentation - explizite Ownership zwischen Dokumentation und Code - sicherere Schreibgrenzen für Agenten -- prüffähigen Kontext statt verborgener Memory +- prüffähige Dokumentation statt verborgener Memory - KI-Workflows, die weiterhin aus festgeschriebenen Repo-Dateien funktionieren ## Wo Truthmark hineinpasst @@ -248,7 +256,7 @@ Es gibt diesen Workflows einen dauerhaften Ort in Git. | Plan-first Feature-Arbeit | Spec-Workflow | | Branch-gebundene Wahrheit, die mit dem Code mitwandert | Truthmark | | Korrektheit von Verhalten validieren | Tests und Review | -| KI-gestützte Kontextänderungen prüfen | Truthmark plus Git-Review | +| KI-gestützte Dokumentationsänderungen prüfen | Truthmark plus Git-Review | Truthmarks Spur ist absichtlich eng: @@ -305,7 +313,7 @@ truthmark init | Plattform-Configname | Generierte Oberfläche | Aufrufform | | --- | --- | --- | -| `codex` | `.codex/skills/truthmark-*/`, `.codex/agents/` | `/truthmark-*` oder `$truthmark-*` | +| `codex` | `.agents/skills/truthmark-*/`, `.codex/agents/` | `/truthmark-*` oder `$truthmark-*` | | `claude-code` | `.claude/skills/truthmark-*/`, `.claude/agents/`, `CLAUDE.md` | `/truthmark-*` | | `github-copilot` | `.github/skills/truthmark-*/`, `.github/prompts/`, `.github/agents/`, `.github/copilot-instructions.md` | `/truthmark-*` in unterstützten Copilot-IDEs; `@truth-*` Custom Agents in Copilot CLI | | `opencode` | `.opencode/skills/truthmark-*/`, `.opencode/agents/` | `/skill truthmark-*` | @@ -365,12 +373,16 @@ Der direkte Aufruf ist trotzdem nützlich für Fehlersuche, frühes Synchronisie ## Bestehendes Verhalten ohne Doku -Nutze Truth Document, wenn die Implementierung bereits existiert, aber die Repository-Wahrheit unvollständig ist. +Nutze Truth Document, wenn die Implementierung bereits existiert, aber die Repository-Wahrheit unvollständig ist. Das ist der normale Weg für etablierte Repositories, die Truthmark übernehmen, nachdem die Codebasis bereits existiert. ```text -/truthmark-document das implementierte Session-Timeout-Verhalten unter docs/truth/authentication dokumentieren +/truthmark-document dokumentiere das implementierte session-timeout-verhalten über src/auth/session.ts, src/auth/middleware.ts und tests/auth/session.test.ts ``` +Gib den Feature-Namen, Codepfade, Testpfade oder den gewünschten Truth-Doc-Bereich an. In OpenCode-ähnlichen Hosts rufst du denselben Workflow als `/skill truthmark-document ...` auf; in Gemini CLI nutzt du `/truthmark:document ...`. + +Bei einem großen Repo, das noch eine breite Platzhalterroute hat, führe zuerst Truth Structure aus und rufe danach Truth Document für jeweils ein abgegrenztes Feature oder einen Bereich auf. + Truth Document prüft Implementierung, Tests, Routendateien und vorhandene Dokumente als Evidenz. Es schreibt nur Truth-Dokumente und Routing. @@ -382,7 +394,7 @@ Es darf keinen funktionalen Code ändern. Nutze Truth Realize, wenn eine Produkt- oder Architekturentscheidung in Dokumenten beginnt und Code daran angepasst werden soll. ```text -/truthmark-realize docs/truth/authentication/session-timeout.md in Code realisieren +/truthmark-realize docs/truthmark/truth/authentication/session-timeout.md in Code realisieren ``` Truth Realize ist doc-first. @@ -429,7 +441,7 @@ Die meisten Maintainer beginnen mit drei Befehlen. | `truthmark init` | Installiert oder aktualisiert konfigurierte Workflow-Oberflächen aus der geprüften Config. | | `truthmark check` | Validiert Config, Autorität, Routing, entscheidungstragende Dokumente, Frontmatter, interne Links, Branch-Scope, generierte Oberflächen, Freshness und Coverage-Diagnostik. | -Optionale Repository-Intelligence-Helfer erzeugen abgeleiteten Review-Kontext für den aktiven Checkout. Generierte Workflow-Skill-Pakete können außerdem Helper-Manifeste und Helper-Policies bereitstellen, die installierte `truthmark validate ... --json` CLI-Validatoren aufrufen; diese Helpers sind Beschleuniger, keine im Repository gebündelten lokalen Skripte und keine Quellen der Wahrheit. Eigenständige Copilot-Prompts und Gemini-Commands verwenden denselben CLI-Validator-Vertrag, wenn der installierte Runner verfügbar ist; andernfalls melden sie einen sichtbaren übersprungenen Helper-Status und führen eine manuelle Validierung durch. +Optionale Repository-Intelligence-Helfer erzeugen abgeleitetes Review-Material für den aktiven Checkout, etwa RepoIndex-, RouteMap-, ImpactSet- und begrenzte ContextPack-Artefakte. Generierte Workflow-Skill-Pakete können außerdem Helper-Manifeste und Helper-Policies bereitstellen, die installierte `truthmark validate ... --json` CLI-Validatoren aufrufen; diese Helpers sind Beschleuniger, keine im Repository gebündelten lokalen Skripte und keine Quellen der Wahrheit. Eigenständige Copilot-Prompts und Gemini-Commands verwenden denselben CLI-Validator-Vertrag, wenn der installierte Runner verfügbar ist; andernfalls melden sie einen sichtbaren übersprungenen Helper-Status und führen eine manuelle Validierung durch. Sie sind keine Quellen der Wahrheit. @@ -456,10 +468,10 @@ Er ist bewusst vom Kern-Truth-Workflow getrennt: Aktiviere es mit dem namespaced Config-Block: ```yaml -truthmark-portal: - enabled: true - output: docs/truthmark-portal - template: default +truthmark: + generated: + portal: + enabled: true ``` Dann erneut ausführen: @@ -498,14 +510,14 @@ Wichtige Config-Bereiche sind: | --- | --- | | `version` | Version des Config-Vertrags. | | `platforms` | Agenten-Hosts, die plattformspezifische generierte Oberflächen erhalten sollen. | -| `docs.layout` | Aktueller Docs-Layoutmodus. | -| `docs.roots` | Benannte kanonische Dokumentationswurzeln. | -| `docs.routing.root_index` | Pfad zum Root-Routenindex. | -| `docs.routing.area_files_root` | Verzeichnis für delegierte untergeordnete Routendateien. | -| `docs.routing.default_area` | Dateiname des initial erzeugten untergeordneten Routings ohne Erweiterung. | -| `docs.routing.max_delegation_depth` | Aktuelle maximale Routing-Delegationstiefe. | -| `truthmark-portal` | Optionale manuelle Präsentations-Workflow-Einstellungen: `enabled`, `output` und `template`. | -| `authority` | Geordnete kanonische Dokumente und Globs, die als Repository-Truth-Autorität dienen. | +| `truthmark.workspace` | Truthmark-eigener Workspace für Routen, Truth-Dokumente, Vorlagen und generierte Präsentationsausgabe. | +| `truthmark.routes.index` | Root-Routenindex relativ zu `truthmark.workspace`. | +| `truthmark.routes.areas` | Verzeichnis für delegierte untergeordnete Routendateien relativ zu `truthmark.workspace`. | +| `truthmark.routes.default_area` | Dateiname des initial erzeugten untergeordneten Routings ohne Erweiterung. | +| `truthmark.routes.max_delegation_depth` | Aktuelle maximale Routing-Delegationstiefe. | +| `truthmark.truth.root` | Truth-Dokumentwurzel relativ zu `truthmark.workspace`. | +| `truthmark.templates.root` | Truth-Dokumentvorlagenwurzel relativ zu `truthmark.workspace`. | +| `truthmark.generated.portal` | Optionale manuelle Präsentations-Workflow-Aktivierung: `enabled`. | | `instruction_targets` | Dateien, die gemeinsam verwaltete Instruktionsblöcke erhalten, etwa `AGENTS.md`. | | `frontmatter.required` | Metadatenfelder, die bei Fehlen Error-Diagnostik erzeugen. | | `frontmatter.recommended` | Metadatenfelder, die bei Fehlen Review-Diagnostik erzeugen. | @@ -518,8 +530,8 @@ Truthmark ordnet Codeoberflächen Truth-Dokumenten zu. Die wichtigsten Routendateien sind: ```text -docs/truthmark/areas.md -docs/truthmark/areas/**/*.md +docs/truthmark/routes/areas.md +docs/truthmark/routes/areas/**/*.md ``` Eine Route sagt dem Agenten: @@ -549,7 +561,7 @@ Das geschieht in vier Schichten: - Config und Routing für Ownership-Grenzen - kanonische Truth-Dokumente und Starter-Templates -- kompakte verwaltete Instruction-Blöcke für repositoryweiten Agent-Kontext +- kompakte verwaltete Instruction-Blöcke für repositoryweite Agent-Instruktionen - host-native Workflow-Pakete, Commands, Prompts und Verifier-Agents für die in der Config aktivierten Plattformen Truthmark bewahrt manuellen Inhalt außerhalb verwalteter Instruktionsblöcke. @@ -633,7 +645,7 @@ truthmark check ### Implementiertes Verhalten dokumentieren ```text -/truthmark-document den implementierten Password-Reset-Flow unter docs/truth/authentication dokumentieren +/truthmark-document den implementierten Password-Reset-Flow unter docs/truthmark/truth/authentication dokumentieren ``` ### Nach Codeänderungen synchronisieren @@ -645,7 +657,7 @@ truthmark check ### Eine doc-first Entscheidung realisieren ```text -/truthmark-realize docs/truth/billing/invoice-retry-policy.md in Code realisieren +/truthmark-realize docs/truthmark/truth/billing/invoice-retry-policy.md in Code realisieren ``` ### Truth-Gesundheit im Terminal auditieren @@ -654,13 +666,13 @@ truthmark check truthmark check ``` -### Branch-Impact-Kontext erzeugen +### Branch-Impact-Zusammenfassung erzeugen ```bash truthmark impact --base main ``` -### Workflow-Kontext erzeugen +### Workflow-ContextPack erzeugen ```bash truthmark context --workflow truth-sync --base main --format markdown @@ -669,10 +681,10 @@ truthmark context --workflow truth-sync --base main --format markdown ### Optionalen Portal-Workflow aktivieren ```yaml -truthmark-portal: - enabled: true - output: docs/truthmark-portal - template: default +truthmark: + generated: + portal: + enabled: true ``` ```bash @@ -746,11 +758,11 @@ Die README ist der schnelle Pfad für Evaluation und Setup. Aktuelles Verhalten im Detail lebt unter `docs/`: - [Dokumentationsindex](docs/README.md) -- [Architekturüberblick](docs/architecture/overview.md) -- [API- und CLI-Verträge](docs/truth/contracts.md) -- [Init- und Scaffold-Verhalten](docs/truth/init-and-scaffold.md) -- [Check-Diagnostik](docs/truth/check-diagnostics.md) -- [Installierte Workflows](docs/truth/workflows/overview.md) +- [Architekturüberblick](docs/truthmark/truth/architecture/overview.md) +- [API- und CLI-Verträge](docs/truthmark/truth/contracts.md) +- [Init- und Scaffold-Verhalten](docs/truthmark/truth/init-and-scaffold.md) +- [Check-Diagnostik](docs/truthmark/truth/check-diagnostics.md) +- [Installierte Workflows](docs/truthmark/truth/workflows/overview.md) - [Leitfaden zur Pflege von Repository-Wahrheit](docs/standards/maintaining-repository-truth.md) ## Designgrenzen @@ -787,7 +799,7 @@ Teams sollten weiterhin: - Diffs generierter Workflow-Oberflächen nach Upgrades prüfen - menschliche Ownership über Produkt- und Architekturentscheidungen behalten -Truthmark macht Agentenkontext sichtbar. Es ersetzt menschliches Urteil nicht. +Truthmark macht agentenseitige Repository-Wahrheit sichtbar. Es ersetzt menschliches Urteil nicht. ## Roadmap-Richtung @@ -807,7 +819,7 @@ Der Schwerpunkt bleibt gleich: Repository-Wahrheit agent-native Workflows Git-Review -branch-gebundener Kontext +branch-gebundene Dokumentation ``` ## Lizenz diff --git a/README.es.md b/README.es.md index 86b3e3f..d05061b 100644 --- a/README.es.md +++ b/README.es.md @@ -1,12 +1,12 @@ # Truthmark -**Tus agentes escriben código. Truthmark hace que su contexto sea revisable en Git.** +**Tus agentes escriben código. Truthmark mantiene documentación orientada a humanos y revisable en Git.** [English](README.md) | [Deutsch](README.de.md) | [中文](README.zh.md) | Español | [Русский](README.ru.md) ![Banner de Truthmark](docs/assets/truthmark-banner.png) -Los agentes de programación con IA pueden cambiar un repositorio más rápido de lo que las personas pueden mantener alineado su contexto. +Los agentes de programación con IA pueden cambiar un repositorio más rápido de lo que las personas pueden mantener alineada su documentación. Truthmark arregla la parte que normalmente se rompe después de escribir el código: la verdad del repositorio. @@ -33,9 +33,9 @@ La implementación cambia, pero la historia del repositorio se desvía: - las decisiones de producto desaparecen después del traspaso - quienes revisan ven diffs de código sin los diffs de verdad relacionados - las ramas desarrollan silenciosamente distintas versiones de “lo que es verdad” -- cada sesión de agente tiene que redescubrir el contexto desde cero +- cada sesión de agente tiene que redescubrir la verdad del repositorio desde cero -Truthmark convierte ese contexto frágil en infraestructura del repositorio confirmada en Git. +Truthmark convierte esa verdad frágil del repositorio en infraestructura confirmada en Git. En lugar de depender de que cada persona y cada agente recuerden el hábito correcto de documentación, Truthmark instala ese hábito en el repositorio. @@ -66,7 +66,7 @@ Tiene dos superficies distintas, y la distinción importa. La CLI es para mantenedores, revisores y automatización. -Úsala para configurar un repositorio, instalar o refrescar archivos de flujo de trabajo, validar artefactos de verdad y generar contexto opcional para revisión. +Úsala para configurar un repositorio, instalar o refrescar archivos de flujo de trabajo, validar artefactos de verdad y generar material opcional para revisión. ```bash truthmark config @@ -179,6 +179,14 @@ Pide a tu agente que divida la ruta amplia en áreas reales de producto, servici /truthmark-structure divide el área amplia repository en auth, billing y notifications ``` +Si el proyecto ya tiene features implementadas pero faltan documentos de verdad o son débiles, pide al flujo Truth Document instalado que documente un alcance enfocado: + +```text +/truthmark-document documenta el comportamiento implementado de payment retry en src/billing/retry.ts y sus tests relacionados +``` + +Truth Document es el primer flujo más común para proyectos existentes. Inspecciona implementación, pruebas, rutas y documentación existente, y luego crea o repara documentos de verdad y rutas sin cambiar código funcional. + Después usa tu agente de programación con IA normalmente. Cuando el agente cambia código funcional, Truth Sync actúa como guarda de cierre que revisa si los documentos de verdad asignados deben cambiar antes del traspaso. @@ -188,7 +196,7 @@ Cuando el agente cambia código funcional, Truth Sync actúa como guarda de cier | Capacidad | Qué hace | | --- | --- | | Verdad nativa de Git | Mantiene la verdad del repositorio en Markdown y config confirmados. | -| Contexto acotado a la rama | La verdad se mueve con la rama en lugar de vivir en una sesión privada. | +| Documentación acotada a la rama | La verdad se mueve con la rama en lugar de vivir en una sesión privada. | | CLI humana | Da a mantenedores comandos de configuración, refresco, validación e inspección. | | Flujos orientados a IA | Da a los agentes flujos nativos del host para sincronización, documentación, estructura, preview, realización y auditoría. | | Rutas explícitas | Mapea áreas de código a documentos de verdad canónicos. | @@ -229,10 +237,10 @@ Es útil cuando necesitas: - menos deriva de documentación - mejores traspasos - verdad de producto específica de cada rama -- contexto duradero de arquitectura y API +- documentación duradera de arquitectura y API - propiedad explícita entre documentos y código - límites de escritura más seguros para agentes -- contexto revisable en lugar de memoria oculta +- documentación revisable en lugar de memoria oculta - flujos de IA que sigan funcionando desde archivos confirmados del repo ## Dónde encaja Truthmark @@ -248,7 +256,7 @@ Les da a esos flujos un lugar duradero donde aterrizar en Git. | Trabajo de funciones plan-first | Flujo de especificación | | Verdad acotada a la rama que viaja con el código | Truthmark | | Validar la corrección del comportamiento | Pruebas y revisión | -| Revisar cambios de contexto asistidos por IA | Truthmark más revisión Git | +| Revisar cambios de documentación asistidos por IA | Truthmark más revisión Git | El carril de Truthmark es estrecho por diseño: @@ -305,7 +313,7 @@ truthmark init | Nombre de plataforma en config | Superficie generada | Forma de invocación | | --- | --- | --- | -| `codex` | `.codex/skills/truthmark-*/`, `.codex/agents/` | `/truthmark-*` o `$truthmark-*` | +| `codex` | `.agents/skills/truthmark-*/`, `.codex/agents/` | `/truthmark-*` o `$truthmark-*` | | `claude-code` | `.claude/skills/truthmark-*/`, `.claude/agents/`, `CLAUDE.md` | `/truthmark-*` | | `github-copilot` | `.github/skills/truthmark-*/`, `.github/prompts/`, `.github/agents/`, `.github/copilot-instructions.md` | `/truthmark-*` en IDEs de Copilot compatibles; agentes personalizados `@truth-*` en Copilot CLI | | `opencode` | `.opencode/skills/truthmark-*/`, `.opencode/agents/` | `/skill truthmark-*` | @@ -365,12 +373,16 @@ La invocación directa sigue siendo útil para depurar, forzar una sincronizaci ## Comportamiento existente sin docs -Usa Truth Document cuando la implementación ya existe pero la verdad del repositorio está incompleta. +Usa Truth Document cuando la implementación ya existe pero la verdad del repositorio está incompleta. Esta es la ruta normal para repositorios establecidos que adoptan Truthmark después de que la base de código ya existe. ```text -/truthmark-document documenta el comportamiento implementado de timeout de sesión bajo docs/truth/authentication +/truthmark-document documenta el comportamiento implementado de timeout de sesión en src/auth/session.ts, src/auth/middleware.ts y tests/auth/session.test.ts ``` +Indica el nombre del feature, rutas de código, rutas de pruebas o el área deseada de documentos de verdad. En hosts estilo OpenCode, llama al mismo flujo como `/skill truthmark-document ...`; en Gemini CLI, usa `/truthmark:document ...`. + +Para un repo grande que aún tiene una ruta placeholder amplia, ejecuta primero Truth Structure y luego invoca Truth Document para un feature o área acotada cada vez. + Truth Document inspecciona implementación, pruebas, archivos de rutas y documentación existente como evidencia. Escribe solo documentos de verdad y rutas. @@ -382,7 +394,7 @@ No debe cambiar código funcional. Usa Truth Realize cuando una decisión de producto o arquitectura empieza en documentos y el código debe actualizarse para coincidir. ```text -/truthmark-realize realiza docs/truth/authentication/session-timeout.md como código +/truthmark-realize realiza docs/truthmark/truth/authentication/session-timeout.md como código ``` Truth Realize es doc-first. @@ -429,7 +441,7 @@ La mayoría de los mantenedores empieza con tres comandos. | `truthmark init` | Instala o refresca superficies de flujo configuradas desde la config revisada. | | `truthmark check` | Valida configuración, autoridad, rutas, documentos con decisiones, frontmatter, enlaces internos, alcance de rama, superficies generadas, frescura y diagnósticos de cobertura. | -Los ayudantes opcionales de inteligencia del repositorio generan contexto derivado para revisión sobre el checkout activo. Los paquetes de skill de flujo generados también pueden exponer manifests y policies de helpers que llaman a validadores CLI `truthmark validate ... --json` instalados; esos helpers son aceleradores, no scripts locales empaquetados en el repo ni fuentes de verdad. Los prompts independientes de Copilot y los comandos de Gemini usan el mismo contrato de validador CLI cuando el runner instalado está disponible; de lo contrario informan un estado de helper omitido visible y hacen validación manual. +Los ayudantes opcionales de inteligencia del repositorio generan material derivado para revisión sobre el checkout activo, como artefactos RepoIndex, RouteMap, ImpactSet y ContextPack acotados. Los paquetes de skill de flujo generados también pueden exponer manifests y policies de helpers que llaman a validadores CLI `truthmark validate ... --json` instalados; esos helpers son aceleradores, no scripts locales empaquetados en el repo ni fuentes de verdad. Los prompts independientes de Copilot y los comandos de Gemini usan el mismo contrato de validador CLI cuando el runner instalado está disponible; de lo contrario informan un estado de helper omitido visible y hacen validación manual. No son fuentes de verdad. @@ -456,10 +468,10 @@ Está separado deliberadamente del flujo central de verdad: Habilítalo con el bloque de configuración con espacio de nombres: ```yaml -truthmark-portal: - enabled: true - output: docs/truthmark-portal - template: default +truthmark: + generated: + portal: + enabled: true ``` Luego vuelve a ejecutar: @@ -498,14 +510,14 @@ Las áreas importantes de configuración incluyen: | --- | --- | | `version` | Versión del contrato de configuración. | | `platforms` | Hosts de agentes que deben recibir superficies generadas específicas de plataforma. | -| `docs.layout` | Modo actual de layout de documentación. | -| `docs.roots` | Raíces nombradas de documentación canónica. | -| `docs.routing.root_index` | Ruta del índice raíz de rutas. | -| `docs.routing.area_files_root` | Directorio para archivos de rutas secundarias delegadas. | -| `docs.routing.default_area` | Nombre base de la ruta secundaria inicial generada. | -| `docs.routing.max_delegation_depth` | Profundidad máxima actual de delegación de rutas. | -| `truthmark-portal` | Ajustes opcionales del flujo manual de presentación: `enabled`, `output` y `template`. | -| `authority` | Documentos canónicos y globs ordenados usados como autoridad de verdad del repositorio. | +| `truthmark.workspace` | Workspace propiedad de Truthmark para rutas, documentos de verdad, plantillas y salida de presentación generada. | +| `truthmark.routes.index` | Ruta del índice raíz relativa a `truthmark.workspace`. | +| `truthmark.routes.areas` | Directorio de rutas secundarias delegadas relativo a `truthmark.workspace`. | +| `truthmark.routes.default_area` | Nombre base de la ruta secundaria inicial generada. | +| `truthmark.routes.max_delegation_depth` | Profundidad máxima actual de delegación de rutas. | +| `truthmark.truth.root` | Raíz de documentos de verdad relativa a `truthmark.workspace`. | +| `truthmark.templates.root` | Raíz de plantillas de documentos de verdad relativa a `truthmark.workspace`. | +| `truthmark.generated.portal` | Activación opcional del flujo manual de presentación: `enabled`. | | `instruction_targets` | Archivos que reciben bloques de instrucciones administrados compartidos, como `AGENTS.md`. | | `frontmatter.required` | Campos de metadatos que producen diagnósticos de error cuando faltan. | | `frontmatter.recommended` | Campos de metadatos que producen diagnósticos de revisión cuando faltan. | @@ -518,8 +530,8 @@ Truthmark mapea superficies de código a documentos de verdad. Los archivos principales de rutas son: ```text -docs/truthmark/areas.md -docs/truthmark/areas/**/*.md +docs/truthmark/routes/areas.md +docs/truthmark/routes/areas/**/*.md ``` Una ruta le dice al agente: @@ -549,7 +561,7 @@ Lo instala en cuatro capas: - config y routing para límites de ownership - documentos truth canónicos y plantillas iniciales -- bloques de instrucciones administrados y compactos para contexto de agente en todo el repo +- bloques de instrucciones administrados y compactos para instrucciones de agente en todo el repo - paquetes de workflow, comandos, prompts y agentes verificadores host-native para las plataformas habilitadas en la config Truthmark conserva el contenido manual fuera de los bloques de instrucciones administrados. @@ -633,7 +645,7 @@ truthmark check ### Documentar comportamiento implementado ```text -/truthmark-document documenta el flujo implementado de restablecimiento de contraseña bajo docs/truth/authentication +/truthmark-document documenta el flujo implementado de restablecimiento de contraseña bajo docs/truthmark/truth/authentication ``` ### Sincronizar después de cambios de código @@ -645,7 +657,7 @@ truthmark check ### Realizar una decisión doc-first ```text -/truthmark-realize realiza docs/truth/billing/invoice-retry-policy.md como código +/truthmark-realize realiza docs/truthmark/truth/billing/invoice-retry-policy.md como código ``` ### Auditar la salud de verdad desde la terminal @@ -654,13 +666,13 @@ truthmark check truthmark check ``` -### Generar contexto de impacto de rama +### Generar resumen de impacto de rama ```bash truthmark impact --base main ``` -### Generar contexto de workflow +### Generar un ContextPack de workflow ```bash truthmark context --workflow truth-sync --base main --format markdown @@ -669,10 +681,10 @@ truthmark context --workflow truth-sync --base main --format markdown ### Habilitar el flujo Portal opcional ```yaml -truthmark-portal: - enabled: true - output: docs/truthmark-portal - template: default +truthmark: + generated: + portal: + enabled: true ``` ```bash @@ -746,11 +758,11 @@ El README es el camino rápido para evaluación y configuración. El comportamiento actual detallado vive bajo `docs/`: - [Índice de documentación](docs/README.md) -- [Resumen de arquitectura](docs/architecture/overview.md) -- [Contratos de API y CLI](docs/truth/contracts.md) -- [Comportamiento de init y scaffold](docs/truth/init-and-scaffold.md) -- [Diagnósticos de check](docs/truth/check-diagnostics.md) -- [Flujos instalados](docs/truth/workflows/overview.md) +- [Resumen de arquitectura](docs/truthmark/truth/architecture/overview.md) +- [Contratos de API y CLI](docs/truthmark/truth/contracts.md) +- [Comportamiento de init y scaffold](docs/truthmark/truth/init-and-scaffold.md) +- [Diagnósticos de check](docs/truthmark/truth/check-diagnostics.md) +- [Flujos instalados](docs/truthmark/truth/workflows/overview.md) - [Guía para mantener la verdad del repositorio](docs/standards/maintaining-repository-truth.md) ## Límites de diseño @@ -787,7 +799,7 @@ Los equipos deberían seguir: - revisando diffs de superficies de flujo generadas después de upgrades - conservando propiedad humana sobre decisiones de producto y arquitectura -Truthmark hace visible el contexto del agente. No reemplaza el juicio humano. +Truthmark hace visible la verdad del repositorio orientada al agente. No reemplaza el juicio humano. ## Dirección de la hoja de ruta @@ -807,7 +819,7 @@ El centro de gravedad se mantiene igual: verdad del repositorio flujos nativos para agentes revisión en Git -contexto acotado a la rama +documentación acotada a la rama ``` ## Licencia diff --git a/README.md b/README.md index 6f6a1d5..fdefc6d 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,12 @@ # Truthmark -**Your agents write code. Truthmark makes their context reviewable in Git.** +**Your agents write code. Truthmark maintains human-facing, Git-reviewable documentation.** English | [Deutsch](README.de.md) | [中文](README.zh.md) | [Español](README.es.md) | [Русский](README.ru.md) ![Truthmark banner](docs/assets/truthmark-banner.png) -AI coding agents can change a repository faster than humans can keep its context aligned. +AI coding agents can change a repository faster than humans can keep its documentation aligned. Truthmark fixes the part that usually breaks after the code is written: the repository truth. @@ -33,9 +33,9 @@ The implementation changes, but the repository story drifts: - product decisions disappear after handoff - reviewers see code diffs without the related truth diffs - branches quietly develop different versions of “what is true” -- each agent session has to rediscover context from scratch +- each agent session has to rediscover repository truth from scratch -Truthmark turns that fragile context into committed repository infrastructure. +Truthmark turns that fragile repository truth into committed repository infrastructure. Instead of relying on every human and every agent to remember the right documentation habit, Truthmark installs the habit into the repository. @@ -66,7 +66,7 @@ It has two distinct surfaces, and the distinction matters. The CLI is for maintainers, reviewers, and automation. -Use it to configure a repository, install or refresh workflow files, validate truth artifacts, and generate optional review context. +Use it to configure a repository, install or refresh workflow files, validate truth artifacts, and generate optional review material. ```bash truthmark config @@ -179,6 +179,14 @@ Ask your agent to split the broad route into actual product, service, domain, or /truthmark-structure split the broad repository area into auth, billing, and notifications ``` +If the project already has implemented features but missing or weak truth docs, ask the installed Truth Document workflow to document a focused scope: + +```text +/truthmark-document document the implemented payment retry behavior in src/billing/retry.ts and related tests +``` + +Truth Document is the common first workflow for existing projects. It inspects implementation, tests, routes, and existing docs, then creates or repairs truth docs and routing without changing functional code. + After that, use your AI coding agent normally. When the agent changes functional code, Truth Sync acts as the finish-time guard that checks whether mapped truth docs need to change before handoff. @@ -188,7 +196,7 @@ When the agent changes functional code, Truth Sync acts as the finish-time guard | Capability | What it does | | --- | --- | | Git-native truth | Keeps repository truth in committed Markdown and config. | -| Branch-scoped context | Truth moves with the branch instead of living in a private session. | +| Branch-scoped documentation | Truth moves with the branch instead of living in a private session. | | Human CLI | Gives maintainers setup, refresh, validation, and inspection commands. | | AI-facing workflows | Gives agents host-native workflows for sync, documentation, structure, preview, realization, and audit. | | Explicit routing | Maps code areas to canonical truth docs. | @@ -229,10 +237,10 @@ It is useful when you need: - less documentation drift - better handoffs - branch-specific product truth -- durable architecture and API context +- durable architecture and API documentation - explicit ownership between docs and code - safer agent write boundaries -- reviewable context instead of hidden memory +- reviewable documentation instead of hidden memory - AI workflows that still work from committed repo files ## Where Truthmark fits @@ -248,7 +256,7 @@ It gives those workflows a durable place to land in Git. | Plan-first feature work | Spec workflow | | Branch-scoped truth that travels with code | Truthmark | | Validating behavior correctness | Tests and review | -| Reviewing AI-assisted context changes | Truthmark plus Git review | +| Reviewing AI-assisted documentation changes | Truthmark plus Git review | Truthmark’s lane is narrow by design: @@ -329,7 +337,7 @@ They are used by agents or agent hosts during repository work. They are not top- | Truth Preview | read-only | The agent needs to preview likely routing before edits. | Reads only. Does not authorize writes. | | Truth Realize | doc-first | Product or architecture truth docs lead and code should be updated to match. | Updates code only. The agent must not edit the truth docs it is realizing. | | Truth Check | audit-first | A reviewer or agent needs to audit repository truth health. | Audits and reports. | -| Truthmark Portal | presentation-only | A human explicitly asks for a browsable static HTML Portal over repository truth docs. | Writes generated non-canonical static files only under the configured Portal output directory. | +| Truthmark Portal | presentation-only | A human explicitly asks for a browsable static HTML Portal over repository truth docs. | Writes generated non-canonical static files only under the fixed Portal output directory. | ### Important distinction @@ -365,12 +373,16 @@ Direct invocation is still useful for troubleshooting, forcing an early sync, or ## Existing behavior without docs -Use Truth Document when the implementation already exists but the repository truth is incomplete. +Use Truth Document when the implementation already exists but the repository truth is incomplete. This is the normal path for established repositories adopting Truthmark after the codebase already exists. ```text -/truthmark-document document the implemented session timeout behavior under docs/truth/authentication +/truthmark-document document the implemented session timeout behavior across src/auth/session.ts, src/auth/middleware.ts, and tests/auth/session.test.ts ``` +Give it the feature name, code paths, test paths, or desired truth-doc area. On OpenCode-style hosts, call the same workflow as `/skill truthmark-document ...`; on Gemini CLI, use `/truthmark:document ...`. + +For a large repo that still has one broad placeholder route, run Truth Structure first, then invoke Truth Document for one bounded feature or area at a time. + Truth Document inspects implementation, tests, route files, and existing docs as evidence. It writes truth docs and routing only. @@ -382,7 +394,7 @@ It must not change functional code. Use Truth Realize when a product or architecture decision starts in docs and code should be updated to match. ```text -/truthmark-realize realize docs/truth/authentication/session-timeout.md into code +/truthmark-realize realize docs/truthmark/truth/authentication/session-timeout.md into code ``` Truth Realize is doc-first. @@ -429,7 +441,7 @@ Most maintainers start with three commands. | `truthmark init` | Install or refresh configured workflow surfaces from the reviewed config. | | `truthmark check` | Validate configuration, authority, routing, decision-bearing docs, frontmatter, internal links, branch scope, generated surfaces, freshness, and coverage diagnostics. | -Optional repository-intelligence helpers generate derived review context for the active checkout. Generated workflow skill packages may also expose helper manifests and helper policies that call installed `truthmark validate ... --json` CLI validators; those helpers are accelerators, not bundled repo-local scripts or sources of truth. Standalone Copilot prompts and Gemini commands use the same CLI validator contract when the installed runner is available, and otherwise report a visible skipped helper status with manual validation. +Optional repository-intelligence helpers generate derived review material for the active checkout, such as RepoIndex, RouteMap, ImpactSet, and bounded ContextPack artifacts. Generated workflow skill packages may also expose helper manifests and helper policies that call installed `truthmark validate ... --json` CLI validators; those helpers are accelerators, not bundled repo-local scripts or sources of truth. Standalone Copilot prompts and Gemini commands use the same CLI validator contract when the installed runner is available, and otherwise report a visible skipped helper status with manual validation. They are not sources of truth. @@ -450,16 +462,16 @@ It is deliberately separate from the core truth workflow: - Markdown truth docs remain canonical. - Generated Portal HTML is presentation only. - Portal is manual-only; it does not run as a completion gate, Truth Sync step, `truthmark check` step, or automatic post-change hook. -- Portal writes stay inside the configured output directory unless the user explicitly changes scope. +- Portal writes stay inside the fixed Truthmark-derived output directory. - Generated pages should use local assets, source provenance, and a visible Markdown-canonical disclaimer. Enable it with the namespaced config block: ```yaml -truthmark-portal: - enabled: true - output: docs/truthmark-portal - template: default +truthmark: + generated: + portal: + enabled: true ``` Then rerun: @@ -498,14 +510,14 @@ Important config areas include: | --- | --- | | `version` | Config contract version. | | `platforms` | Agent hosts that should receive platform-specific generated surfaces. | -| `docs.layout` | Current docs layout mode. | -| `docs.roots` | Named canonical documentation roots. | -| `docs.routing.root_index` | Root route index path. | -| `docs.routing.area_files_root` | Directory for delegated child route files. | -| `docs.routing.default_area` | Initial scaffolded child route basename. | -| `docs.routing.max_delegation_depth` | Current maximum route delegation depth. | -| `truthmark-portal` | Optional manual presentation workflow settings: `enabled`, `output`, and `template`. | -| `authority` | Ordered canonical docs and globs used as repository truth authority. | +| `truthmark.workspace` | Truthmark-owned workspace for routes, truth docs, templates, and generated presentation output. | +| `truthmark.routes.index` | Root route index path relative to `truthmark.workspace`. | +| `truthmark.routes.areas` | Directory for delegated child route files relative to `truthmark.workspace`. | +| `truthmark.routes.default_area` | Initial scaffolded child route basename. | +| `truthmark.routes.max_delegation_depth` | Current maximum route delegation depth. | +| `truthmark.truth.root` | Truth doc root relative to `truthmark.workspace`. | +| `truthmark.templates.root` | Truth-doc template root relative to `truthmark.workspace`. | +| `truthmark.generated.portal` | Optional manual presentation workflow enablement: `enabled`. | | `instruction_targets` | Files that receive shared managed instruction blocks, such as `AGENTS.md`. | | `frontmatter.required` | Metadata fields that produce error diagnostics when missing. | | `frontmatter.recommended` | Metadata fields that produce review diagnostics when missing. | @@ -518,8 +530,8 @@ Truthmark maps code surfaces to truth docs. The main routing files are: ```text -docs/truthmark/areas.md -docs/truthmark/areas/**/*.md +docs/truthmark/routes/areas.md +docs/truthmark/routes/areas/**/*.md ``` A route tells the agent: @@ -549,7 +561,7 @@ It does this in four layers: - configuration and routing for ownership boundaries - canonical truth docs and starter templates -- compact managed instruction blocks for repository-wide agent context +- compact managed instruction blocks for repository-wide agent instructions - host-native workflow packages, commands, prompts, and verifier agents for the platforms enabled in config Truthmark preserves manual content outside managed instruction blocks. @@ -633,7 +645,7 @@ truthmark check ### Document implemented behavior ```text -/truthmark-document document the implemented password reset flow under docs/truth/authentication +/truthmark-document document the implemented password reset flow under docs/truthmark/truth/authentication ``` ### Sync after code changes @@ -645,7 +657,7 @@ truthmark check ### Realize a doc-first decision ```text -/truthmark-realize realize docs/truth/billing/invoice-retry-policy.md into code +/truthmark-realize realize docs/truthmark/truth/billing/invoice-retry-policy.md into code ``` ### Audit truth health from the terminal @@ -654,13 +666,13 @@ truthmark check truthmark check ``` -### Generate branch-impact context +### Generate branch-impact summary ```bash truthmark impact --base main ``` -### Generate workflow context +### Generate a workflow ContextPack ```bash truthmark context --workflow truth-sync --base main --format markdown @@ -669,10 +681,10 @@ truthmark context --workflow truth-sync --base main --format markdown ### Enable the optional Portal workflow ```yaml -truthmark-portal: - enabled: true - output: docs/truthmark-portal - template: default +truthmark: + generated: + portal: + enabled: true ``` ```bash @@ -746,11 +758,11 @@ The README is the fast path for evaluation and setup. Detailed current behavior lives under `docs/`: - [Docs index](docs/README.md) -- [Architecture overview](docs/architecture/overview.md) -- [API and CLI contracts](docs/truth/contracts.md) -- [Init and scaffold behavior](docs/truth/init-and-scaffold.md) -- [Check diagnostics](docs/truth/check-diagnostics.md) -- [Installed workflows](docs/truth/workflows/overview.md) +- [Architecture overview](docs/truthmark/truth/architecture/overview.md) +- [API and CLI contracts](docs/truthmark/truth/contracts.md) +- [Init and scaffold behavior](docs/truthmark/truth/init-and-scaffold.md) +- [Check diagnostics](docs/truthmark/truth/check-diagnostics.md) +- [Installed workflows](docs/truthmark/truth/workflows/overview.md) - [Repository truth maintenance guide](docs/standards/maintaining-repository-truth.md) ## Design boundaries @@ -787,7 +799,7 @@ Teams should still: - review generated workflow-surface diffs after upgrades - keep human ownership over product and architecture decisions -Truthmark makes agent context visible. It does not replace human judgment. +Truthmark makes agent-facing repository truth visible. It does not replace human judgment. ## Roadmap direction @@ -807,7 +819,7 @@ The center of gravity stays the same: repository truth agent-native workflows Git review -branch-scoped context +branch-scoped documentation ``` ## License diff --git a/README.ru.md b/README.ru.md index 200df5b..2cf0203 100644 --- a/README.ru.md +++ b/README.ru.md @@ -1,12 +1,12 @@ # Truthmark -**Ваши агенты пишут код. Truthmark делает их контекст проверяемым в Git.** +**Ваши агенты пишут код. Truthmark поддерживает ориентированную на людей документацию, проверяемую в Git.** [English](README.md) | [Deutsch](README.de.md) | [中文](README.zh.md) | [Español](README.es.md) | Русский ![Баннер Truthmark](docs/assets/truthmark-banner.png) -ИИ-агенты для разработки могут менять репозиторий быстрее, чем люди успевают выравнивать его контекст. +ИИ-агенты для разработки могут менять репозиторий быстрее, чем люди успевают выравнивать его документацию. Truthmark чинит ту часть, которая обычно ломается после написания кода: истину репозитория. @@ -33,9 +33,9 @@ Truthmark чинит ту часть, которая обычно ломаетс - продуктовые решения исчезают после передачи работы - ревьюеры видят diff кода без связанных diff истины - ветки незаметно развивают разные версии того, «что является правдой» -- каждой сессии агента приходится заново открывать контекст +- каждой сессии агента приходится заново открывать истину репозитория -Truthmark превращает этот хрупкий контекст в зафиксированную инфраструктуру репозитория. +Truthmark превращает эту хрупкую истину репозитория в зафиксированную инфраструктуру репозитория. Вместо надежды на то, что каждый человек и каждый агент вспомнят правильную привычку документирования, Truthmark устанавливает эту привычку в репозиторий. @@ -66,7 +66,7 @@ Truthmark — это не только CLI. CLI предназначен для мейнтейнеров, ревьюеров и автоматизации. -Используйте его, чтобы настроить репозиторий, установить или обновить файлы рабочих процессов, проверить артефакты истины и создать дополнительный контекст для ревью. +Используйте его, чтобы настроить репозиторий, установить или обновить файлы рабочих процессов, проверить артефакты истины и создать дополнительные материалы для ревью. ```bash truthmark config @@ -179,6 +179,14 @@ truthmark check /truthmark-structure раздели широкий repository area на auth, billing и notifications ``` +Если в проекте уже есть реализованные функции, но документы истины отсутствуют или слабы, попросите установленный workflow Truth Document задокументировать сфокусированный scope: + +```text +/truthmark-document задокументируй реализованное поведение payment retry в src/billing/retry.ts и связанных тестах +``` + +Truth Document — самый частый первый workflow для существующих проектов. Он инспектирует реализацию, тесты, маршруты и существующие документы, затем создает или исправляет документы истины и маршрутизацию, не меняя функциональный код. + После этого используйте своего ИИ-агента для разработки как обычно. Когда агент меняет функциональный код, Truth Sync действует как финальная защита, которая перед передачей работы проверяет, должны ли измениться сопоставленные документы истины. @@ -188,7 +196,7 @@ truthmark check | Возможность | Что она делает | | --- | --- | | Git-native истина | Хранит истину репозитория в зафиксированных Markdown и config. | -| Контекст в пределах ветки | Истина движется с веткой вместо жизни в приватной сессии. | +| Документация в пределах ветки | Истина движется с веткой вместо жизни в приватной сессии. | | CLI для людей | Дает мейнтейнерам команды настройки, обновления, валидации и инспекции. | | Workflows для ИИ | Дает агентам host-native workflows для sync, documentation, structure, preview, realization и audit. | | Явная маршрутизация | Сопоставляет области кода с каноническими документами истины. | @@ -229,10 +237,10 @@ Truthmark помогает командам отвечать на это с по - меньший дрейф документации - лучшие передачи работы - продуктовая истина, специфичная для ветки -- долговечный архитектурный и API-контекст +- долговечная архитектурная и API-документация - явное владение между документацией и кодом - более безопасные границы записи для агентов -- проверяемый контекст вместо скрытой памяти +- проверяемая документация вместо скрытой памяти - ИИ-workflows, которые продолжают работать из зафиксированных файлов repo ## Где уместен Truthmark @@ -248,7 +256,7 @@ Truthmark не заменяет prompts, memory, specs, tests или code review | Работа над функцией plan-first | Spec workflow | | Истина в пределах ветки, которая путешествует с кодом | Truthmark | | Проверка корректности поведения | Tests and review | -| Ревью контекстных изменений, выполненных с ИИ | Truthmark plus Git review | +| Ревью изменений документации, выполненных с ИИ | Truthmark plus Git review | Область Truthmark намеренно узкая: @@ -305,7 +313,7 @@ truthmark init | Имя платформы в config | Сгенерированная поверхность | Форма вызова | | --- | --- | --- | -| `codex` | `.codex/skills/truthmark-*/`, `.codex/agents/` | `/truthmark-*` или `$truthmark-*` | +| `codex` | `.agents/skills/truthmark-*/`, `.codex/agents/` | `/truthmark-*` или `$truthmark-*` | | `claude-code` | `.claude/skills/truthmark-*/`, `.claude/agents/`, `CLAUDE.md` | `/truthmark-*` | | `github-copilot` | `.github/skills/truthmark-*/`, `.github/prompts/`, `.github/agents/`, `.github/copilot-instructions.md` | `/truthmark-*` в поддерживаемых Copilot IDE; custom agents `@truth-*` в Copilot CLI | | `opencode` | `.opencode/skills/truthmark-*/`, `.opencode/agents/` | `/skill truthmark-*` | @@ -365,12 +373,16 @@ Truth Sync проверяет сопоставленные документы и ## Существующее поведение без docs -Используйте Truth Document, когда реализация уже существует, но истина репозитория неполна. +Используйте Truth Document, когда реализация уже существует, но истина репозитория неполна. Это обычный путь для зрелых репозиториев, которые внедряют Truthmark после того, как кодовая база уже существует. ```text -/truthmark-document задокументируй реализованное поведение session timeout в docs/truth/authentication +/truthmark-document задокументируй реализованное поведение session timeout в src/auth/session.ts, src/auth/middleware.ts и tests/auth/session.test.ts ``` +Укажите имя функции, пути к коду, пути к тестам или желаемую область truth-документов. В OpenCode-подобных хостах тот же workflow вызывается как `/skill truthmark-document ...`; в Gemini CLI используйте `/truthmark:document ...`. + +Для большого repo, где все еще есть один широкий placeholder-маршрут, сначала запустите Truth Structure, а затем вызывайте Truth Document по одному ограниченному feature или area за раз. + Truth Document проверяет реализацию, тесты, файлы маршрутов и существующие docs как evidence. Он пишет только документы истины и routing. @@ -382,7 +394,7 @@ Truth Document проверяет реализацию, тесты, файлы Используйте Truth Realize, когда продуктовое или архитектурное решение начинается в docs и код нужно обновить под него. ```text -/truthmark-realize реализуй docs/truth/authentication/session-timeout.md в коде +/truthmark-realize реализуй docs/truthmark/truth/authentication/session-timeout.md в коде ``` Truth Realize работает doc-first. @@ -429,7 +441,7 @@ truthmark check | `truthmark init` | Устанавливает или обновляет настроенные поверхности workflow из проверенной config. | | `truthmark check` | Валидирует config, authority, routing, документы с decisions, frontmatter, внутренние ссылки, branch scope, generated surfaces, freshness и coverage diagnostics. | -Необязательные helpers repository-intelligence создают производный review context для активного checkout. Сгенерированные workflow skill packages также могут предоставлять helper manifests и helper policies, которые вызывают установленные CLI validators `truthmark validate ... --json`; эти helpers являются ускорителями, а не локальными скриптами, упакованными в репозиторий, и не источниками истины. Отдельные Copilot prompts и Gemini commands используют тот же CLI validator contract, когда установленный runner доступен; иначе они должны сообщать видимый skipped helper status и выполнять manual validation. +Необязательные helpers repository-intelligence создают производные материалы для ревью активного checkout, например артефакты RepoIndex, RouteMap, ImpactSet и ограниченные ContextPack. Сгенерированные workflow skill packages также могут предоставлять helper manifests и helper policies, которые вызывают установленные CLI validators `truthmark validate ... --json`; эти helpers являются ускорителями, а не локальными скриптами, упакованными в репозиторий, и не источниками истины. Отдельные Copilot prompts и Gemini commands используют тот же CLI validator contract, когда установленный runner доступен; иначе они должны сообщать видимый skipped helper status и выполнять manual validation. Они не являются источниками истины. @@ -456,10 +468,10 @@ Truthmark Portal — опциональный презентационный wor Включите его namespaced config-блоком: ```yaml -truthmark-portal: - enabled: true - output: docs/truthmark-portal - template: default +truthmark: + generated: + portal: + enabled: true ``` Затем запустите снова: @@ -498,14 +510,14 @@ truthmark init | --- | --- | | `version` | Версия контракта config. | | `platforms` | Agent hosts, которые должны получить сгенерированные поверхности для платформы. | -| `docs.layout` | Текущий режим layout документации. | -| `docs.roots` | Именованные корни канонической документации. | -| `docs.routing.root_index` | Путь к корневому индексу маршрутов. | -| `docs.routing.area_files_root` | Директория для делегированных дочерних файлов маршрутов. | -| `docs.routing.default_area` | Базовое имя начального scaffolded дочернего маршрута. | -| `docs.routing.max_delegation_depth` | Текущая максимальная глубина делегирования routing. | -| `truthmark-portal` | Опциональные настройки ручного презентационного workflow: `enabled`, `output` и `template`. | -| `authority` | Упорядоченные канонические docs и globs, используемые как authority истины репозитория. | +| `truthmark.workspace` | Workspace, принадлежащий Truthmark, для маршрутов, документов истины, шаблонов и сгенерированного презентационного вывода. | +| `truthmark.routes.index` | Путь к корневому индексу маршрутов относительно `truthmark.workspace`. | +| `truthmark.routes.areas` | Директория делегированных дочерних маршрутов относительно `truthmark.workspace`. | +| `truthmark.routes.default_area` | Базовое имя начального scaffolded дочернего маршрута. | +| `truthmark.routes.max_delegation_depth` | Текущая максимальная глубина делегирования routing. | +| `truthmark.truth.root` | Корень документов истины относительно `truthmark.workspace`. | +| `truthmark.templates.root` | Корень шаблонов документов истины относительно `truthmark.workspace`. | +| `truthmark.generated.portal` | Опциональное включение ручного презентационного workflow: `enabled`. | | `instruction_targets` | Файлы, которые получают общие управляемые блоки инструкций, например `AGENTS.md`. | | `frontmatter.required` | Поля metadata, которые создают error diagnostics при отсутствии. | | `frontmatter.recommended` | Поля metadata, которые создают review diagnostics при отсутствии. | @@ -518,8 +530,8 @@ Truthmark сопоставляет code surfaces с документами ис Основные файлы маршрутизации: ```text -docs/truthmark/areas.md -docs/truthmark/areas/**/*.md +docs/truthmark/routes/areas.md +docs/truthmark/routes/areas/**/*.md ``` Маршрут сообщает агенту: @@ -549,7 +561,7 @@ Truthmark устанавливает компактный, встроенный - config и routing для границ владения - канонические truth docs и стартовые шаблоны -- компактные управляемые instruction blocks для repo-wide agent context +- компактные управляемые instruction blocks для repo-wide agent instructions - host-native workflow packages, commands, prompts и verifier agents для платформ, включённых в config Truthmark сохраняет ручной контент вне управляемых блоков инструкций. @@ -633,7 +645,7 @@ truthmark check ### Документировать реализованное поведение ```text -/truthmark-document задокументируй реализованный password reset flow в docs/truth/authentication +/truthmark-document задокументируй реализованный password reset flow в docs/truthmark/truth/authentication ``` ### Синхронизировать после изменений кода @@ -645,7 +657,7 @@ truthmark check ### Реализовать doc-first решение ```text -/truthmark-realize реализуй docs/truth/billing/invoice-retry-policy.md в коде +/truthmark-realize реализуй docs/truthmark/truth/billing/invoice-retry-policy.md в коде ``` ### Проверить здоровье истины из терминала @@ -654,13 +666,13 @@ truthmark check truthmark check ``` -### Создать branch-impact context +### Создать summary branch-impact ```bash truthmark impact --base main ``` -### Создать workflow context +### Создать workflow ContextPack ```bash truthmark context --workflow truth-sync --base main --format markdown @@ -669,10 +681,10 @@ truthmark context --workflow truth-sync --base main --format markdown ### Включить опциональный Portal workflow ```yaml -truthmark-portal: - enabled: true - output: docs/truthmark-portal - template: default +truthmark: + generated: + portal: + enabled: true ``` ```bash @@ -746,11 +758,11 @@ README — быстрый путь для оценки и настройки. Подробное текущее поведение живет в `docs/`: - [Индекс документации](docs/README.md) -- [Обзор архитектуры](docs/architecture/overview.md) -- [Контракты API и CLI](docs/truth/contracts.md) -- [Поведение init и scaffold](docs/truth/init-and-scaffold.md) -- [Диагностика check](docs/truth/check-diagnostics.md) -- [Установленные workflows](docs/truth/workflows/overview.md) +- [Обзор архитектуры](docs/truthmark/truth/architecture/overview.md) +- [Контракты API и CLI](docs/truthmark/truth/contracts.md) +- [Поведение init и scaffold](docs/truthmark/truth/init-and-scaffold.md) +- [Диагностика check](docs/truthmark/truth/check-diagnostics.md) +- [Установленные workflows](docs/truthmark/truth/workflows/overview.md) - [Руководство по поддержанию истины репозитория](docs/standards/maintaining-repository-truth.md) ## Границы дизайна @@ -787,7 +799,7 @@ Truthmark помогает репозиторию оставаться чест - проверять diff сгенерированных workflow surfaces после upgrades - сохранять человеческое владение продуктовыми и архитектурными решениями -Truthmark делает контекст агента видимым. Он не заменяет человеческое суждение. +Truthmark делает видимой ориентированную на агента истину репозитория. Он не заменяет человеческое суждение. ## Направление roadmap @@ -807,7 +819,7 @@ Truthmark делает контекст агента видимым. Он не истина репозитория agent-native workflows Git review -контекст в пределах ветки +документация в пределах ветки ``` ## Лицензия diff --git a/README.zh.md b/README.zh.md index ff60e99..21c6c31 100644 --- a/README.zh.md +++ b/README.zh.md @@ -1,12 +1,12 @@ # Truthmark -**你的代理会写代码。Truthmark 让它们的上下文在 Git 中可审查。** +**你的代理会写代码。Truthmark 维护面向人类、可在 Git 中审查的文档。** [English](README.md) | [Deutsch](README.de.md) | 中文 | [Español](README.es.md) | [Русский](README.ru.md) ![Truthmark 横幅](docs/assets/truthmark-banner.png) -AI 编码代理改变仓库的速度,可能比人类对齐上下文的速度更快。 +AI 编码代理改变仓库的速度,可能比人类对齐文档的速度更快。 Truthmark 修复代码写完后通常会坏掉的那一部分:仓库事实。 @@ -33,9 +33,9 @@ AI 编码代理很擅长产出代码。这会制造一种新的失效模式。 - 产品决策在交接后消失 - 审查者看到代码 diff,却看不到相关的事实 diff - 分支悄悄发展出不同版本的“什么是真的” -- 每个代理会话都必须从头重新发现上下文 +- 每个代理会话都必须从头重新发现仓库事实 -Truthmark 把这种脆弱上下文变成已提交的仓库基础设施。 +Truthmark 把这种脆弱的仓库事实变成已提交的仓库基础设施。 它不是依赖每个人和每个代理都记住正确的文档习惯,而是把这个习惯安装进仓库。 @@ -66,7 +66,7 @@ Truthmark 不只是一个 CLI。 CLI 面向维护者、审查者和自动化。 -用它来配置仓库、安装或刷新工作流文件、验证事实产物,并生成可选的审查上下文。 +用它来配置仓库、安装或刷新工作流文件、验证事实产物,并生成可选的审查材料。 ```bash truthmark config @@ -181,6 +181,14 @@ truthmark check /truthmark-structure 将宽泛的 repository 区域拆成 auth、billing 和 notifications ``` +如果项目已经有实现好的功能,但事实文档缺失或很弱,请让已安装的 Truth Document 工作流记录一个聚焦范围: + +```text +/truthmark-document 记录 src/billing/retry.ts 及相关测试中已实现的 payment retry 行为 +``` + +Truth Document 是既有项目最常用的第一个工作流。它会检查实现、测试、路由和现有文档,然后创建或修复事实文档与路由,不会修改功能代码。 + 之后就正常使用你的 AI 编码代理。 当代理修改功能代码时,Truth Sync 会作为收尾保护,在交接前检查已映射的事实文档是否需要改变。 @@ -190,7 +198,7 @@ truthmark check | 能力 | 作用 | | --- | --- | | Git 原生事实 | 将仓库事实保存在已提交的 Markdown 和配置中。 | -| 按分支生效的上下文 | 事实随分支移动,而不是存在于私有会话中。 | +| 按分支生效的文档 | 事实随分支移动,而不是存在于私有会话中。 | | 面向人的 CLI | 为维护者提供设置、刷新、验证和检查命令。 | | 面向 AI 的工作流 | 为代理提供宿主原生的同步、文档、结构、预览、实现和审计工作流。 | | 显式路由 | 将代码区域映射到规范事实文档。 | @@ -231,10 +239,10 @@ Truthmark 通过已提交文件、显式路由和可审查 diff 帮助团队回 - 更少的文档漂移 - 更好的交接 - 按分支生效的产品事实 -- 持久的架构和 API 上下文 +- 持久的架构和 API 文档 - 文档与代码之间的明确所有权 - 更安全的代理写入边界 -- 可审查上下文,而不是隐藏记忆 +- 可审查文档,而不是隐藏记忆 - 仍然能从已提交 repo 文件运行的 AI 工作流 ## Truthmark 适合放在哪里 @@ -250,7 +258,7 @@ Truthmark 不替代提示词、记忆、规格、测试或代码审查。 | plan-first 的功能工作 | 规格工作流 | | 随代码移动、按分支生效的事实 | Truthmark | | 验证行为正确性 | 测试和审查 | -| 审查 AI 辅助的上下文变更 | Truthmark 加 Git 审查 | +| 审查 AI 辅助的文档变更 | Truthmark 加 Git 审查 | Truthmark 的范围故意很窄: @@ -367,12 +375,16 @@ Truth Sync 检查已映射事实文档 ## 已有行为但没有文档 -当实现已经存在,但仓库事实不完整时,使用 Truth Document。 +当实现已经存在但仓库事实不完整时,使用 Truth Document。对于代码库已经存在后才接入 Truthmark 的成熟仓库,这是常规路径。 ```text -/truthmark-document 在 docs/truth/authentication 下记录已实现的会话超时行为 +/truthmark-document 记录 src/auth/session.ts、src/auth/middleware.ts 和 tests/auth/session.test.ts 中已实现的 session timeout 行为 ``` +提供功能名、代码路径、测试路径或目标事实文档区域。在 OpenCode 风格的宿主中,同一个工作流用 `/skill truthmark-document ...` 调用;在 Gemini CLI 中,使用 `/truthmark:document ...`。 + +如果大型仓库仍然只有一个宽泛的占位路由,请先运行 Truth Structure,然后每次针对一个有边界的功能或区域调用 Truth Document。 + Truth Document 会把实现、测试、路由文件和现有文档作为证据来检查。 它只写事实文档和路由。 @@ -384,7 +396,7 @@ Truth Document 会把实现、测试、路由文件和现有文档作为证据 当产品或架构决策从文档开始,并且代码应更新以匹配时,使用 Truth Realize。 ```text -/truthmark-realize 将 docs/truth/authentication/session-timeout.md 实现到代码中 +/truthmark-realize 将 docs/truthmark/truth/authentication/session-timeout.md 实现到代码中 ``` Truth Realize 是 doc-first。 @@ -431,7 +443,7 @@ truthmark check | `truthmark init` | 从已审查配置安装或刷新已配置的工作流表面。 | | `truthmark check` | 验证配置、权限边界、路由、承载决策的文档、frontmatter、内部链接、分支范围、生成表面、freshness 和覆盖率诊断。 | -可选的仓库情报辅助工具会为当前 checkout 生成派生审查上下文。生成的工作流 skill packages 也可以暴露 helper manifests 和 helper policies,用来调用已安装的 `truthmark validate ... --json` CLI validators;这些 helpers 是加速器,不是打包进仓库的本地脚本,也不是事实来源。独立的 Copilot prompts 和 Gemini commands 在已安装 runner 可用时使用同一 CLI validator contract;不可用时应报告可见的 skipped helper status,并进行 manual validation。 +可选的仓库情报辅助工具会为当前 checkout 生成派生审查材料,例如 RepoIndex、RouteMap、ImpactSet 和有边界的 ContextPack 产物。生成的工作流 skill packages 也可以暴露 helper manifests 和 helper policies,用来调用已安装的 `truthmark validate ... --json` CLI validators;这些 helpers 是加速器,不是打包进仓库的本地脚本,也不是事实来源。独立的 Copilot prompts 和 Gemini commands 在已安装 runner 可用时使用同一 CLI validator contract;不可用时应报告可见的 skipped helper status,并进行 manual validation。 它们不是事实来源。 @@ -458,10 +470,10 @@ Truthmark Portal 是一个可选的展示工作流,适合想要基于已提交 用这个命名空间配置块启用它: ```yaml -truthmark-portal: - enabled: true - output: docs/truthmark-portal - template: default +truthmark: + generated: + portal: + enabled: true ``` 然后重新运行: @@ -500,14 +512,14 @@ truthmark init | --- | --- | | `version` | 配置契约版本。 | | `platforms` | 应接收平台专属生成表面的代理宿主。 | -| `docs.layout` | 当前文档布局模式。 | -| `docs.roots` | 命名的规范文档根。 | -| `docs.routing.root_index` | 根路由索引路径。 | -| `docs.routing.area_files_root` | 委托子路由文件目录。 | -| `docs.routing.default_area` | 初始脚手架子路由 basename。 | -| `docs.routing.max_delegation_depth` | 当前最大路由委托深度。 | -| `truthmark-portal` | 可选手动展示工作流设置:`enabled`、`output` 和 `template`。 | -| `authority` | 用作仓库事实权威的有序规范文档和 glob。 | +| `truthmark.workspace` | Truthmark 拥有的工作区,用于路由、事实文档、模板和生成的展示输出。 | +| `truthmark.routes.index` | 相对于 `truthmark.workspace` 的根路由索引路径。 | +| `truthmark.routes.areas` | 相对于 `truthmark.workspace` 的委托子路由目录。 | +| `truthmark.routes.default_area` | 初始脚手架子路由 basename。 | +| `truthmark.routes.max_delegation_depth` | 当前最大路由委托深度。 | +| `truthmark.truth.root` | 相对于 `truthmark.workspace` 的事实文档根。 | +| `truthmark.templates.root` | 相对于 `truthmark.workspace` 的事实文档模板根。 | +| `truthmark.generated.portal` | 可选手动展示工作流启用设置:`enabled`。 | | `instruction_targets` | 接收共享受管说明块的文件,例如 `AGENTS.md`。 | | `frontmatter.required` | 缺失时产生错误诊断的元数据字段。 | | `frontmatter.recommended` | 缺失时产生审查诊断的元数据字段。 | @@ -520,8 +532,8 @@ Truthmark 将代码表面映射到事实文档。 主要路由文件是: ```text -docs/truthmark/areas.md -docs/truthmark/areas/**/*.md +docs/truthmark/routes/areas.md +docs/truthmark/routes/areas/**/*.md ``` 路由告诉代理: @@ -551,7 +563,7 @@ Truthmark 安装一个紧凑、仓库原生的事实层。 - 用于所有权边界的配置和路由 - 规范 truth 文档和起始模板 -- 用于仓库级 agent 上下文的紧凑受管说明块 +- 用于仓库级 agent 指令的紧凑受管说明块 - 为配置中启用的平台生成 host-native 工作流包、命令、prompts 和 verifier agents Truthmark 会保留受管说明块之外的手写内容。 @@ -635,7 +647,7 @@ truthmark check ### 记录已实现行为 ```text -/truthmark-document 在 docs/truth/authentication 下记录已实现的密码重置流程 +/truthmark-document 在 docs/truthmark/truth/authentication 下记录已实现的密码重置流程 ``` ### 代码变更后同步 @@ -647,7 +659,7 @@ truthmark check ### 实现 doc-first 决策 ```text -/truthmark-realize 将 docs/truth/billing/invoice-retry-policy.md 实现到代码中 +/truthmark-realize 将 docs/truthmark/truth/billing/invoice-retry-policy.md 实现到代码中 ``` ### 从终端审计事实健康 @@ -656,13 +668,13 @@ truthmark check truthmark check ``` -### 生成分支影响上下文 +### 生成分支影响摘要 ```bash truthmark impact --base main ``` -### 生成工作流上下文 +### 生成工作流 ContextPack ```bash truthmark context --workflow truth-sync --base main --format markdown @@ -671,10 +683,10 @@ truthmark context --workflow truth-sync --base main --format markdown ### 启用可选 Portal 工作流 ```yaml -truthmark-portal: - enabled: true - output: docs/truthmark-portal - template: default +truthmark: + generated: + portal: + enabled: true ``` ```bash @@ -748,11 +760,11 @@ README 是评估和设置的快速路径。 详细的当前行为位于 `docs/` 下: - [文档索引](docs/README.md) -- [架构概览](docs/architecture/overview.md) -- [API 和 CLI 契约](docs/truth/contracts.md) -- [Init 和脚手架行为](docs/truth/init-and-scaffold.md) -- [Check 诊断](docs/truth/check-diagnostics.md) -- [已安装工作流](docs/truth/workflows/overview.md) +- [架构概览](docs/truthmark/truth/architecture/overview.md) +- [API 和 CLI 契约](docs/truthmark/truth/contracts.md) +- [Init 和脚手架行为](docs/truthmark/truth/init-and-scaffold.md) +- [Check 诊断](docs/truthmark/truth/check-diagnostics.md) +- [已安装工作流](docs/truthmark/truth/workflows/overview.md) - [仓库事实维护指南](docs/standards/maintaining-repository-truth.md) ## 设计边界 @@ -789,7 +801,7 @@ Truthmark 帮助仓库保持诚实。它不能证明代码正确。 - 升级后审查生成工作流表面的 diff - 保留人类对产品和架构决策的所有权 -Truthmark 让代理上下文可见。它不替代人类判断。 +Truthmark 让面向代理的仓库事实可见。它不替代人类判断。 ## 路线图方向 @@ -809,7 +821,7 @@ Truthmark 让代理上下文可见。它不替代人类判断。 仓库事实 代理原生工作流 Git 审查 -按分支生效的上下文 +按分支生效的文档 ``` ## 许可证 diff --git a/changes/2026-06-01-version-2-0-0.md b/changes/2026-06-01-version-2-0-0.md new file mode 100644 index 0000000..94b8993 --- /dev/null +++ b/changes/2026-06-01-version-2-0-0.md @@ -0,0 +1,23 @@ +# Truthmark v2 workspace refactor + +Previous version: 1.6.1 +New version: 2.0.0 +Diff basis: release/1.6.1..HEAD plus working tree +Version action: major +SemVer rationale: The pending payload intentionally rejects legacy `docs.roots` and top-level `authority` config shapes and changes shipped default workspace, routing, scaffold, and generated workflow behavior. + +Release payload: +- Replace the old repo-doc hierarchy defaults with a `version: 2` `truthmark.workspace` config model. +- Move Truthmark-owned routes, truth docs, templates, and generated Portal output under `docs/truthmark/` while leaving project-owned `docs/ai`, `docs/architecture`, and `docs/standards` outside the Truthmark workspace. +- Refresh generated host-native workflow surfaces, managed instruction blocks, routing tests, and README examples for the clean v2 workspace. + +User-facing release text: +- Truthmark 2.0.0 introduces the clean workspace-scoped config model and removes compatibility loading for legacy `docs.roots` / top-level `authority` configs. Re-run `truthmark config` / `truthmark init` and update existing repositories to the `truthmark.workspace` layout before relying on generated workflows. + +Verification: +- `npx tsx src/cli/main.ts init --json` +- `npx vitest run tests/git/repository.test.ts tests/evidence/validate.test.ts tests/fs/paths.test.ts tests/evals/workflow-routing.test.ts` +- `npm run release:check` +- `npx tsx src/cli/main.ts check --json` +- `npx tsx src/cli/main.ts index --json` +- README stale-path sweep and heading-depth parity check across localized READMEs. diff --git a/changes/2026-06-11-version-2-1-0.md b/changes/2026-06-11-version-2-1-0.md new file mode 100644 index 0000000..3917b67 --- /dev/null +++ b/changes/2026-06-11-version-2-1-0.md @@ -0,0 +1,24 @@ +# Truth Health Scorecard + +Previous version: 2.0.0 +New version: 2.1.0 +Diff basis: release/1.6.1..HEAD plus working tree +Version action: minor +SemVer rationale: Pass 4 adds the backward-compatible `data.scorecard` JSON contract to `truthmark check --json` while preserving raw diagnostics and existing check payload fields. + +Release payload: +- Add `truthmark-scorecard/v0` as a compact Truth Health Scorecard in `truthmark check --json` under `data.scorecard`. +- Summarize raw check diagnostics into routing coverage, ownership clarity, source traceability, branch freshness, generated-surface freshness, truth doc structure, and decision/rationale preservation dimensions. +- Preserve raw diagnostics, branch scope, truth visibility, and optional impact set output while marking branch freshness as `not-run` when no `--base` is supplied. + +User-facing release text: +- `truthmark check --json` now includes `data.scorecard`, a compact `truthmark-scorecard/v0` health summary that points back to the raw diagnostics array for detail. Existing diagnostics and JSON fields remain available. + +Verification: +- `npx vitest run tests/checks/scorecard.test.ts tests/checks/check.test.ts tests/cli/help.test.ts` +- `npm run release:check` +- `npx tsx src/cli/main.ts check --json` +- `npx tsx src/cli/main.ts index --json` +- `node dist/main.js check --json` +- `node dist/main.js index --json` +- `git diff --check -- src/checks tests docs/truthmark package.json package-lock.json changes` diff --git a/docs/README.md b/docs/README.md index 5db6a29..fc4410b 100644 --- a/docs/README.md +++ b/docs/README.md @@ -32,10 +32,11 @@ Repository-wide conflict order and completion policy live in [docs/ai/repo-rules - `docs/ai/` for repository rules and agent onboarding - `docs/truthmark/` for routing metadata - `docs/standards/` for reusable constraints and completion rules -- `docs/architecture/` for current system structure -- `docs/truth/` for current behavior and invariants -- `docs/templates/` for editable scaffold templates used to create new docs -- `docs/truth/contracts.md` for stable contracts the CLI exposes +- `docs/truthmark/truth/architecture/` for current system structure +- `docs/architecture/` for repository-specific architecture guardrails +- `docs/truthmark/truth/` for current behavior and invariants +- `docs/truthmark/templates/` for editable scaffold templates used to create new docs +- `docs/truthmark/truth/contracts.md` for stable contracts the CLI exposes ### Human-centric docs @@ -48,9 +49,10 @@ Repository-wide conflict order and completion policy live in [docs/ai/repo-rules | `docs/ai/` | agent rules | agent | Repository-wide rules and fast onboarding | | `docs/truthmark/` | routing | both | Truth-routing metadata such as `areas.md` and `areas/**/*.md` | | `docs/standards/` | standard | agent | Reusable constraints, verification rules, completion gates | -| `docs/architecture/` | architecture | agent | Current structure and module boundaries | -| `docs/truth/` | truth | agent | Current behavior for init, check, contracts, and installed workflows | -| `docs/templates/` | template | both | Editable templates for scaffolded docs; templates are not Truth Sync targets | +| `docs/truthmark/truth/architecture/` | architecture | agent | Current structure and module boundaries | +| `docs/architecture/` | architecture | agent | Repository-specific architecture guardrails | +| `docs/truthmark/truth/` | truth | agent | Current behavior for init, check, contracts, and installed workflows | +| `docs/truthmark/templates/` | template | both | Editable templates for scaffolded docs; templates are not Truth Sync targets | ## Frontmatter Policy @@ -64,7 +66,7 @@ Canonical docs should include frontmatter and keep these fields current: ## Update Rules - When repository-wide agent policy changes, update [docs/ai/repo-rules.md](ai/repo-rules.md). -- When code-to-doc routing changes, update [docs/truthmark/areas.md](truthmark/areas.md) in the same change. +- When code-to-doc routing changes, update [docs/truthmark/routes/areas.md](truthmark/routes/areas.md) in the same change. - When package versions or release/version policy change, apply [docs/standards/versioning.md](standards/versioning.md) before accepting the version. - When PR or release source text is needed, write a `changes/` note using [docs/standards/change-notes.md](standards/change-notes.md). - When `truthmark init` or scaffolded files change, update the relevant truth or architecture doc, not only [README.md](../README.md). @@ -85,18 +87,18 @@ New repositories should run `truthmark config` before `truthmark init` so teams 1. [README.md](../README.md) 2. [.truthmark/config.yml](../.truthmark/config.yml) 3. [docs/ai/repo-rules.md](ai/repo-rules.md) -4. [docs/architecture/overview.md](architecture/overview.md) +4. [docs/truthmark/truth/architecture/overview.md](truthmark/truth/architecture/overview.md) 5. the relevant truth or standard doc for the area being changed ### For agents 1. [docs/ai/repo-rules.md](ai/repo-rules.md) 2. [docs/ai/agent-onboarding.md](ai/agent-onboarding.md), when routing is unclear or cross-area -3. [docs/truthmark/areas.md](truthmark/areas.md), when mapping code to canonical truth -4. [docs/architecture/module-map.md](architecture/module-map.md), when changing module boundaries +3. [docs/truthmark/routes/areas.md](truthmark/routes/areas.md), when mapping code to canonical truth +4. [docs/truthmark/truth/architecture/module-map.md](truthmark/truth/architecture/module-map.md), when changing module boundaries 5. the relevant standard and truth docs for the task -Use [docs/truth/routing-examples.md](truth/routing-examples.md) when designing areas for larger API, frontend, infrastructure, or monorepo repositories. +Use [docs/truthmark/truth/routing-examples.md](truth/routing-examples.md) when designing areas for larger API, frontend, infrastructure, or monorepo repositories. ## Maintenance Principle diff --git a/docs/ai/agent-onboarding.md b/docs/ai/agent-onboarding.md index e891718..53567f7 100644 --- a/docs/ai/agent-onboarding.md +++ b/docs/ai/agent-onboarding.md @@ -26,26 +26,26 @@ Fast routing for agents. Repository-wide rules live in [docs/ai/repo-rules.md](r Read: -1. [docs/architecture/overview.md](../architecture/overview.md) -2. [docs/architecture/module-map.md](../architecture/module-map.md) -3. [docs/truth/init-and-scaffold.md](../truth/init-and-scaffold.md) -4. [docs/truth/contracts.md](../truth/contracts.md) +1. [docs/truthmark/truth/architecture/overview.md](../truthmark/truth/architecture/overview.md) +2. [docs/truthmark/truth/architecture/module-map.md](../truthmark/truth/architecture/module-map.md) +3. [docs/truthmark/truth/init-and-scaffold.md](../truthmark/truth/init-and-scaffold.md) +4. [docs/truthmark/truth/contracts.md](../truthmark/truth/contracts.md) ### Diagnostics, routing, or containment checks Read: -1. [docs/architecture/module-map.md](../architecture/module-map.md) -2. [docs/truth/check-diagnostics.md](../truth/check-diagnostics.md) +1. [docs/truthmark/truth/architecture/module-map.md](../truthmark/truth/architecture/module-map.md) +2. [docs/truthmark/truth/check-diagnostics.md](../truthmark/truth/check-diagnostics.md) 3. [docs/standards/documentation-governance.md](../standards/documentation-governance.md) -4. [docs/truth/contracts.md](../truth/contracts.md) +4. [docs/truthmark/truth/contracts.md](../truthmark/truth/contracts.md) ### Installed workflow, prompt, or reporting changes Read: 1. [.truthmark/config.yml](../../.truthmark/config.yml) -2. [docs/truth/workflows/overview.md](../truth/workflows/overview.md) and the relevant workflow leaf doc under `docs/truth/workflows/` +2. [docs/truthmark/truth/workflows/overview.md](../truthmark/truth/workflows/overview.md) and the relevant workflow leaf doc under `docs/truthmark/truth/workflows/` 3. [docs/standards/maintaining-repository-truth.md](../standards/maintaining-repository-truth.md) 4. The manifest, renderer, generated surfaces, and focused tests named by the workflow truth docs @@ -78,7 +78,7 @@ Do: - treat [docs/ai/repo-rules.md](repo-rules.md) as the primary authority for repository-wide rules - route code changes to the nearest maintained architecture, contract, and truth docs -- update [docs/truthmark/areas.md](../truthmark/areas.md) when canonical routing changes +- update [docs/truthmark/routes/areas.md](../truthmark/routes/areas.md) when canonical routing changes - apply [docs/standards/versioning.md](../standards/versioning.md) before changing or accepting a package version - write `changes/` notes from [docs/standards/change-notes.md](../standards/change-notes.md) when PR or release text is needed - preserve the generated Truthmark block in [AGENTS.md](../../AGENTS.md) unless the template behavior itself is changing diff --git a/docs/ai/repo-rules.md b/docs/ai/repo-rules.md index e186693..6dc7f66 100644 --- a/docs/ai/repo-rules.md +++ b/docs/ai/repo-rules.md @@ -1,10 +1,11 @@ --- status: active doc_type: agent-rules -last_reviewed: 2026-05-19 +last_reviewed: 2026-06-12 source_of_truth: - ../../AGENTS.md - ../README.md + - ../architecture/product-boundary.md --- # Repository Rules @@ -17,10 +18,10 @@ Conflict order: 1. this file 2. [.truthmark/config.yml](../../.truthmark/config.yml) -3. [docs/truthmark/areas.md](../truthmark/areas.md) and `docs/truthmark/areas/**/*.md` +3. [docs/truthmark/routes/areas.md](../truthmark/routes/areas.md) and `docs/truthmark/routes/areas/**/*.md` 4. `docs/standards/**/*.md` 5. `docs/architecture/**/*.md` -6. `docs/truth/**/*.md` +6. `docs/truthmark/truth/**/*.md` Authoritative context is the current checkout plus user-provided session context; chat, external notes, and off-repo memory are non-authoritative unless committed or supplied now. @@ -28,26 +29,29 @@ Code is the implementation. On code/doc conflict, inspect code, decide whether c ## Product Boundary -Truthmark public CLI commands are `config`, `init`, `check`, `index`, `impact`, `context`, and `validate`. The `validate` subcommands are optional CLI-owned workflow helper validators; they validate reports or write leases but do not run Truth Structure, Truth Document, Truth Sync, Truth Preview, Truth Realize, or Truth Check. Those named workflows are installed workflow surfaces, not top-level CLI commands. +The canonical product boundary is [docs/architecture/product-boundary.md](../architecture/product-boundary.md). This is repo-local policy for developing Truthmark itself; do not treat it as a downstream scaffold, generated surface, or required artifact for repositories that install Truthmark. Read it before generating any new design, implementation plan, generated-workflow redesign, architecture proposal, runtime/dependency change, or command-surface change. New designs and plans must include a product-boundary check that explains how the proposal preserves Truthmark's North Star, in-scope surfaces, explicit non-goals, optional-helper rule, and fail-closed write boundaries. -Agents inspect the active checkout directly. There is no daemon, database, remote service, or V1 MCP server. +Truthmark public CLI commands are `config`, `init`, `check`, `index`, `impact`, `context`, `workflow`, and `validate`. The `workflow` subcommands expose read-only agent-facing status/instructions contracts; they do not run installed workflows. The `validate` subcommands are optional CLI-owned workflow helper validators; they validate reports or write leases but do not run Truth Structure, Truth Document, Truth Sync, Truth Preview, Truth Realize, or Truth Check. Those named workflows are installed workflow surfaces, not top-level CLI commands. + +Agents inspect the active checkout directly. There is no daemon, database, remote service, hidden memory layer, or product-centered MCP server. ## Rules 1. Workflow and skill quality, performance, dispatch clarity, and agent effectiveness are the highest-priority repo concerns. Treat workflows and skills as the core product surface of this agent-native project; when tradeoffs conflict, optimize them before secondary structure, convenience, or polish. -2. Rules in this file are a compact behavior contract for observed repository failure modes. Prefer replacing weak or stale rules over accumulating generic prompts, identity statements, examples, or tool-dependent ceremony. -3. Branch-local Markdown is canonical; the current checkout is the truth boundary. -4. Current truth belongs in canonical docs, not historical plans or separate timestamped decision logs. -5. Active decisions and rationale live in the canonical doc for the governed behavior. -6. Read owning surfaces before writing: for workflows, skills, prompts, commands, generated instructions, or managed blocks, inspect the nearest canonical doc plus the source renderer, template, schema, or parser before editing. -7. Generated surfaces are products, not source authority. Edit templates and renderers by default; patch generated output only when explicitly maintaining that generated surface. -8. Claims about commands, platforms, runtime topology, services, generated surfaces, or workflow capabilities require primary checkout evidence. Surface desired-vs-implemented conflicts instead of averaging patterns or inventing future behavior. -9. Deterministic policy belongs in code, schemas, parsers, templates, or checks when the repository can enforce it. Use model-facing workflow prose to guide agents, not as the only guard for repeatable routing, ownership, parsing, or generation decisions. -10. Keep routing explicit: when a code area changes canonical docs, update truth routing in the same change. -11. Behavior, contract, workflow, and completion-rule changes update the nearest canonical doc. Major product/onboarding/install/command/positioning/workflow changes also update the root README. A material root README change blocks completion until the localized root READMEs change in the same working change. -12. Follow established module boundaries and existing generated-surface patterns; avoid duplicate surfaces, single-use abstractions, speculative configurability, and impossible-scenario error handling. -13. Verify the text and file contracts that changed with the narrowest evidence that can falsify them: generated diffs, structured parsers, snapshots, fixture round-trips, build/package/check commands, or focused tests. Do not run broad tests as ceremony when they add no evidence; state skipped checks. -14. Work surgically and fail visibly: surface assumptions, conflicts, skipped files, blocked ownership, and unverified claims; touch only request-traceable lines, match existing style, checkpoint long workflow or skill edits, and report unrelated issues instead of editing them. +2. Product boundaries are mandatory design inputs. Before generating a new design or plan, read [docs/architecture/product-boundary.md](../architecture/product-boundary.md) and include its product-boundary check in the design/plan artifact. +3. Rules in this file are a compact behavior contract for observed repository failure modes. Prefer replacing weak or stale rules over accumulating generic prompts, identity statements, examples, or tool-dependent ceremony. +4. Branch-local Markdown is canonical; the current checkout is the truth boundary. +5. Current truth belongs in canonical docs, not historical plans or separate timestamped decision logs. +6. Active decisions and rationale live in the canonical doc for the governed behavior. +7. Read owning surfaces before writing: for workflows, skills, prompts, commands, generated instructions, or managed blocks, inspect the nearest canonical doc plus the source renderer, template, schema, or parser before editing. +8. Generated surfaces are products, not source authority. Edit templates and renderers by default; patch generated output only when explicitly maintaining that generated surface. +9. Claims about commands, platforms, runtime topology, services, generated surfaces, or workflow capabilities require primary checkout evidence. Surface desired-vs-implemented conflicts instead of averaging patterns or inventing future behavior. +10. Deterministic policy belongs in code, schemas, parsers, templates, or checks when the repository can enforce it. Use model-facing workflow prose to guide agents, not as the only guard for repeatable routing, ownership, parsing, or generation decisions. +11. Keep routing explicit: when a code area changes canonical docs, update truth routing in the same change. +12. Behavior, contract, workflow, and completion-rule changes update the nearest canonical doc. Major product/onboarding/install/command/positioning/workflow changes also update the root README. A material root README change blocks completion until the localized root READMEs change in the same working change. +13. Follow established module boundaries and existing generated-surface patterns; avoid duplicate surfaces, single-use abstractions, speculative configurability, and impossible-scenario error handling. +14. Verify the text and file contracts that changed with the narrowest evidence that can falsify them: generated diffs, structured parsers, snapshots, fixture round-trips, build/package/check commands, or focused tests. Do not run broad tests as ceremony when they add no evidence; state skipped checks. +15. Work surgically and fail visibly: surface assumptions, conflicts, skipped files, blocked ownership, and unverified claims; touch only request-traceable lines, match existing style, checkpoint long workflow or skill edits, and report unrelated issues instead of editing them. ## Instruction Surface Boundary @@ -65,4 +69,4 @@ If blocked, re-read the relevant canonical docs and owning implementation, then ## Maintenance -Update this file only for repository-wide agent rules. Keep it compact and policy-focused. Put procedures in standards or guides, feature behavior in `docs/truth`, and update `last_reviewed`. +Update this file only for repository-wide agent rules. Keep it compact and policy-focused. Put procedures in standards or guides, feature behavior in `docs/truthmark/truth`, and update `last_reviewed`. diff --git a/docs/architecture/product-boundary.md b/docs/architecture/product-boundary.md new file mode 100644 index 0000000..09ef61a --- /dev/null +++ b/docs/architecture/product-boundary.md @@ -0,0 +1,112 @@ +--- +status: active +doc_type: architecture +last_reviewed: 2026-06-12 +source_of_truth: + - ../../README.md + - ../truthmark/truth/architecture/overview.md + - ../truthmark/truth/workflows/overview.md + - ../truthmark/truth/repository/workflow-state.md +--- + +# Truthmark Product Boundary + +**Audience:** Truthmark maintainers and agents changing this repository. +**Portability:** repo-local only; not installed into downstream projects. + +## Purpose + +This is the product-boundary guardrail for Truthmark designs and plans. + +This document governs the Truthmark repository itself. It is not a scaffolded Truthmark artifact and must not be installed into downstream repositories as their product boundary. + +Downstream repositories may define their own product-boundary docs if useful, but Truthmark's installed workflows must not impose this repository's product strategy, non-goals, or governance doctrine on user projects. + +Read it before proposing changes to product shape, runtime model, persistence, dependencies, workflow authority, generated surfaces, command surface, or agent write boundaries. + +## North Star + +**Your agents write code. Truthmark maintains the human-facing, Git-reviewable documentation.** + +Truthmark keeps repository documentation aligned with agent-made code changes so humans can review the resulting documentation changes in Git. + +Canonical truth documents are human-facing Git-review artifacts. Human maintainers are the primary reviewers; agents write and maintain truth docs, but agents are not the only consumers. + +Truth-doc structure, wording, and style must be friendly for humans to read and understand. + +Human-friendly truth docs: + +- Make the audience and purpose clear near the top. +- Separate current behavior from rationale, decisions, operations, contracts, and future or non-goals. +- Use scannable headings and bounded sections. +- Use plain, concrete, present-tense wording. +- Expand or link terms and acronyms that are not obvious to a maintainer. +- Trace claims to source evidence without forcing readers to inspect giant machine payloads. +- Keep examples, commands, and paths accurate, minimal, and reviewable. +- Keep prose concise enough for Git diff review while complete enough to preserve decisions and rationale. + +## In Scope + +Truthmark is an agent-native, host-native, local-first documentation workflow layer for software repositories. + +Truthmark owns: + +- Git-tracked repository documentation and routing metadata +- host-native agent workflow surfaces such as skills, prompts, commands, managed instruction blocks, and subagents +- branch-local documentation checks, indexes, impact summaries, context packs, and workflow state derived from the active checkout +- write boundaries for read-only, documentation-write, route-write, code-write, and presentation-write workflows +- optional CLI/package helpers that improve validation or setup without becoming required for normal agent workflow execution + +Truthmark workflows must remain operational from repository files alone. A design that blocks the agent workflow because a package, CLI, daemon, server, IDE plugin, or external service is missing is outside the product boundary. + +## Out Of Scope + +Truthmark must not become: + +- a hosted service +- a daemon or workflow orchestrator +- a database-backed runtime +- a hidden memory or session-persistence layer +- an IDE plugin, MCP server, or CLI package as the product center of gravity +- a requirements-management, PRD, proposal, or spec lifecycle platform +- a documentation hosting platform +- a default CI, PR approval, or merge-enforcement product +- an arbitrary workflow DAG engine + +Optional integrations are acceptable only when they preserve host-native agent workflows, Git-tracked documentation, and a no-blockade fallback path. + +## Design Guardrails + +1. **Repository files are the authority.** The active checkout and Git-tracked docs outrank chat history, caches, generated summaries, and off-repo memory. +2. **Agent workflows are host-native.** Truthmark should meet agents inside their existing hosts through generated skills, prompts, commands, instruction blocks, and subagents. +3. **CLI/package helpers are optional.** They may configure, validate, index, or refresh files, but missing helpers must not block the documented agent workflow. +4. **Generated surfaces are product output, not source authority.** Update templates, schemas, manifests, and renderers first; review generated diffs. +5. **Write boundaries fail closed.** Missing config, ambiguous ownership, missing comparison base, or stale routing must block or narrow writes, never widen them. +6. **Human review stays central.** Truthmark produces reviewable documentation changes, not silent approval or merge authority. +7. **Local-first simplicity wins.** Add dependencies, services, or runtime layers only when they preserve the no-blockade repository-file workflow. +8. **Truth docs stay human-friendly.** Truth docs must be structured and written for maintainers to review, scan, and understand before they are optimized for agent or machine consumption. + +## Required Product Boundary Check + +Every new design or implementation plan must answer: + +- Which part of the North Star improves? +- Which in-scope surface changes? +- What adjacent out-of-scope product shape could this drift toward? +- Does it introduce a package, CLI, daemon, database, hosted service, IDE plugin, MCP server, memory layer, lifecycle artifact, or workflow engine as a requirement? +- If a helper or integration is unavailable, how does the agent workflow continue from repository files alone? +- What are the allowed writes, forbidden writes, and fail-closed states? +- Which docs or tests prevent future boundary drift? + +A plan that cannot answer these questions is not ready for implementation. + +## Product Decisions + +- Decision (2026-06-12): Product-boundary checks live in architecture because they govern runtime topology, persistence, dependencies, workflow authority, generated surfaces, and write boundaries. +- Decision (2026-06-12): Repository rules cite this document so agents must check product boundaries before generating new designs or plans. +- Decision (2026-06-12): Truthmark workflows must stay 100% operational from repository files and host-native agent surfaces; missing packages, CLIs, daemons, services, or plugins must not block normal workflow execution. +- Decision (2026-06-12): Human-facing readability is part of the Truthmark product boundary for canonical truth documents. + +## Maintenance Notes + +Update this document when Truthmark's North Star, runtime model, persistence model, generated-surface model, workflow model, command boundary, or non-goals change. diff --git a/docs/standards/default-principles.md b/docs/standards/default-principles.md index 76e26f0..d21a828 100644 --- a/docs/standards/default-principles.md +++ b/docs/standards/default-principles.md @@ -94,7 +94,7 @@ Truthmark can provide places for those rules to live, but the content should bel When a repository has no explicit standards yet, a small default baseline is reasonable: - a documentation governance standard -- authority and routing entrypoints such as `.truthmark/config.yml` and `docs/truthmark/areas.md` +- authority and routing entrypoints such as `.truthmark/config.yml` and `docs/truthmark/routes/areas.md` - a verification standard with canonical commands and skip rules - a completion checklist or equivalent completion gate diff --git a/docs/standards/documentation-governance.md b/docs/standards/documentation-governance.md index 0061599..5c85c8b 100644 --- a/docs/standards/documentation-governance.md +++ b/docs/standards/documentation-governance.md @@ -45,8 +45,8 @@ Truthmark's minimal canonical surface is: - `docs/ai/repo-rules.md` as the repository-wide agent policy source - `.truthmark/config.yml` as the committed hierarchy contract -- `docs/truthmark/areas.md` as the primary routing surface -- the project's canonical truth docs under directories such as `docs/standards/`, `docs/architecture/`, and `docs/truth/` +- `docs/truthmark/routes/areas.md` as the primary routing surface +- the project's canonical truth docs under directories such as `docs/standards/`, `docs/architecture/`, and `docs/truthmark/truth/` By default, instruction files such as `AGENTS.md` install workflow behavior. They do not outrank the canonical truth surface unless a project opts into that explicitly. @@ -83,7 +83,7 @@ Do not create separate timestamped ADR folders, planning tickets, or historical - Behavior changes and truth-doc updates should land in the same working change when possible. - Major product, onboarding, install, command, positioning, or workflow changes should include a root README review in the same working change. Update the README when its human-facing claims, examples, or command sequences are stale. - When the root README has localized variants, keep them aligned with the English README for materially changed install, command, positioning, and workflow guidance in the same working change, or explicitly document why a variant intentionally differs. -- When routing changes, update `docs/truthmark/areas.md` and any affected canonical docs together. +- When routing changes, update `docs/truthmark/routes/areas.md` and any affected canonical docs together. - When routing is missing, stale, broad, overloaded, catch-all, or cannot map changed code to a bounded truth owner, run Truth Structure before adding more generic truth docs. - When a code change alters system structure, module boundaries, runtime topology, persistence boundaries, cross-cutting contracts, or generated-surface ownership, update the owning architecture doc in the same change. - Do not update architecture docs for ordinary product behavior unless that behavior changes an architecture boundary. @@ -111,7 +111,7 @@ Do not create separate timestamped ADR folders, planning tickets, or historical - Does this document have one primary responsibility? - Does each class of fact have one canonical source? - Is this fact stored in the correct document class? -- Does `docs/truthmark/areas.md` route the changed area to the right truth docs? +- Does `docs/truthmark/routes/areas.md` route the changed area to the right truth docs? - If routing is broad or overloaded, has Truth Structure repaired topology before new truth docs were created? - Are duplicated or shadow documentation paths being avoided? - Is generated helper output still treated as non-authoritative rather than truth? diff --git a/docs/standards/maintaining-repository-truth.md b/docs/standards/maintaining-repository-truth.md index 1d9bcaa..35aaa9d 100644 --- a/docs/standards/maintaining-repository-truth.md +++ b/docs/standards/maintaining-repository-truth.md @@ -16,9 +16,9 @@ This guide is for humans maintaining Truthmark's own docs tree. ## When To Update Which Docs -- Change to scaffolded files or AGENTS management: update [docs/truth/init-and-scaffold.md](../truth/init-and-scaffold.md) -- Change to diagnostics, routing, containment, or branch scope: update [docs/truth/check-diagnostics.md](../truth/check-diagnostics.md) -- Change to installed workflow text, skip reasons, report shape, or ownership gates: update [docs/truth/workflows/overview.md](../truth/workflows/overview.md) and the relevant bounded doc under `docs/truth/workflows/` +- Change to scaffolded files or AGENTS management: update [docs/truthmark/truth/init-and-scaffold.md](../truthmark/truth/init-and-scaffold.md) +- Change to diagnostics, routing, containment, or branch scope: update [docs/truthmark/truth/check-diagnostics.md](../truthmark/truth/check-diagnostics.md) +- Change to installed workflow text, skip reasons, report shape, or ownership gates: update [docs/truthmark/truth/workflows/overview.md](../truthmark/truth/workflows/overview.md) and the relevant bounded doc under `docs/truthmark/truth/workflows/` - Change to repository-wide rules or completion policy: update [docs/ai/repo-rules.md](../ai/repo-rules.md) or the relevant standard ## Maintaining AGENTS.md @@ -30,9 +30,9 @@ Treat [AGENTS.md](../../AGENTS.md) as two surfaces: Do not hand-edit the managed block for one-off wording changes. Change the template source instead, then refresh the block through the normal workflow. -Generated Truthmark skill files under `.codex/skills/` and `.opencode/skills/` follow the same rule. Edit the renderers in `src/agents/` and `src/templates/`, then refresh through `truthmark init`. +Generated Truthmark skill files under `.agents/skills/` and `.opencode/skills/` follow the same rule. Edit the renderers in `src/agents/` and `src/templates/`, then refresh through `truthmark init`. -## Maintaining docs/truthmark/areas.md +## Maintaining docs/truthmark/routes/areas.md When code boundaries or canonical docs change: @@ -40,7 +40,7 @@ When code boundaries or canonical docs change: 2. narrow overly broad truth-doc lists instead of adding more shadow docs 3. make sure every relevant `src/**` file still matches at least one area mapping -With hierarchical routing, treat [docs/truthmark/areas.md](../truthmark/areas.md) as the root route index and `docs/truthmark/areas/**/*.md` as the delegated child route files. Keep delegation to one level. +With hierarchical routing, treat [docs/truthmark/routes/areas.md](../truthmark/routes/areas.md) as the root route index and `docs/truthmark/routes/areas/**/*.md` as the delegated child route files. Keep delegation to one level. ## Changing Hierarchy diff --git a/docs/standards/pre-completion-checklist.md b/docs/standards/pre-completion-checklist.md index 10c83fc..6e31dfa 100644 --- a/docs/standards/pre-completion-checklist.md +++ b/docs/standards/pre-completion-checklist.md @@ -21,7 +21,7 @@ Use this checklist before declaring Truthmark work complete. - If behavior, contracts, or workflow text changed, did the nearest canonical docs change in the same working change? - If this was a major product, onboarding, install, command, positioning, or workflow change, did you review the root [README.md](../../README.md) and update stale user-facing claims, examples, or command sequences? - If the root README changed materially, did the localized README variants change in the same working change? If not, stop unless you have an explicit repo-authorized reason they intentionally remain different, and state that reason. A passing verification command does not waive this gate. -- If canonical routing changed, did [docs/truthmark/areas.md](../truthmark/areas.md) change too? +- If canonical routing changed, did [docs/truthmark/routes/areas.md](../truthmark/routes/areas.md) change too? - If the change is PR-worthy, release-worthy, or changes the package version, did you add or update a `changes/` note using [docs/standards/change-notes.md](change-notes.md)? - If any package version or release/version policy changed, did you apply [docs/standards/versioning.md](versioning.md) before accepting the version? - If [AGENTS.md](../../AGENTS.md) changed, did manual edits stay outside the managed Truthmark block? diff --git a/docs/standards/template-standards.md b/docs/standards/template-standards.md index 7d8308a..9a59201 100644 --- a/docs/standards/template-standards.md +++ b/docs/standards/template-standards.md @@ -98,4 +98,4 @@ Truthmark defaults are justified because they optimize for the reviewable artifa Update this standard when Truthmark adds, removes, renames, or materially changes default truth-document templates, or when the references behind the default template rationale change. -When changing default template content, keep `docs/templates/*.md`, `src/templates/init-files.ts`, `docs/standards/default-principles.md`, and this standard aligned. +When changing default template content, keep `docs/truthmark/templates/*.md`, `src/templates/init-files.ts`, `docs/standards/default-principles.md`, and this standard aligned. diff --git a/docs/truth/repository/context-pack.md b/docs/truth/repository/context-pack.md deleted file mode 100644 index 4460b9c..0000000 --- a/docs/truth/repository/context-pack.md +++ /dev/null @@ -1,71 +0,0 @@ ---- -status: active -doc_type: behavior -truth_kind: behavior -last_reviewed: 2026-05-16 -source_of_truth: - - ../../../src/context-pack/build.ts - - ../../../src/context-pack/render.ts - - ../../../src/impact/build.ts ---- - -# ContextPack - -## Purpose - -This document protects ContextPack v0 as a bounded, derived workflow-context artifact for Truth Sync, Truth Document, and Truth Realize. - -## Scope - -This document owns ContextPack v0 behavior for Truth Sync, Truth Document, and Truth Realize workflows. - -## Current Behavior - -`truthmark context --workflow [--base ] --json` generates a bounded context artifact for a workflow. `--format markdown` renders a deterministic human-readable pack, and `--json --format markdown` includes the rendered Markdown in `data.markdown`. ContextPack rejects unsupported `--format` values with a `context-pack` error diagnostic. ContextPack includes route ownership, affected truth docs, selected source files, related tests, warnings, and allowed write paths. - -ContextPack output includes `schemaVersion: context-pack/v0`. It is generated from the active checkout and, when a base ref is supplied, ImpactSet. - -## Core Rules - -- ContextPack is optional generated context and does not replace direct checkout inspection. -- ContextPack write paths restate workflow boundaries; they do not create new permissions. -- Truth Sync and Truth Document write paths include the route index and selected truth docs. Truth Realize write paths include the matched route code surfaces because Realize may write functional code but not truth docs or routing. -- Truth Realize without `--base` cannot infer matched code surfaces, so selected truth docs, source files, and `allowedWritePaths` are empty and ContextPack emits a review warning instead of widening to every route. -- Source files include changed files from ImpactSet when a base ref is supplied and `source_of_truth` references from selected truth docs. Glob references are expanded against the checkout. -- ContextPack-only text is not evidence. Generated docs must cite checkout files, route files, truth docs, tests, schemas, or explicit evidence blocks. -- If ContextPack conflicts with the current checkout, the checkout wins. - -## Flows And States - -`truthmark context` resolves route ownership, affected truth docs, selected source files, related tests, and write-boundary guidance from the active checkout, then renders JSON or deterministic Markdown for the selected workflow. Agents use the artifact as reviewable context and still inspect the checkout directly before acting. - -## Contracts - -`truthmark context --workflow [--base ] --json` returns the shared command envelope with ContextPack data. `--format markdown` renders deterministic Markdown, and `--json --format markdown` includes rendered Markdown in `data.markdown`. Unsupported formats produce a `context-pack` error diagnostic. - -## Product Decisions - -- Decision (2026-05-16): ContextPack v0 is a bounded review artifact, not memory and not a source of authority. -- Decision (2026-05-16): No-CLI workflow execution remains supported, but with weaker automation and explicit reporting. - -## Rationale - -ContextPack makes agent context auditable without making hidden retrieval or stale generated artifacts authoritative. Keeping it derived prevents a fast path from changing ownership or write behavior. - -## Non-Goals - -- ContextPack is not repository authority. -- ContextPack does not grant permissions beyond installed workflow boundaries. -- ContextPack does not replace direct checkout inspection. - -## Maintenance Notes - -ContextPack requires the Truthmark CLI or an equivalent local runner. If unavailable, agents must follow the installed workflow manually by reading route files, truth docs, source files, and tests directly. Completion reports must say ContextPack was not generated. - -Primary implementation files: - -- `src/context-pack/build.ts` -- `src/context-pack/render.ts` -- `src/impact/build.ts` - -Update this doc when the command output, schema version, derived inputs, fallback behavior, or workflow relationship changes. diff --git a/docs/truthmark/areas.md b/docs/truthmark/routes/areas.md similarity index 77% rename from docs/truthmark/areas.md rename to docs/truthmark/routes/areas.md index 9d030e7..374e442 100644 --- a/docs/truthmark/areas.md +++ b/docs/truthmark/routes/areas.md @@ -3,9 +3,9 @@ status: active doc_type: routing last_reviewed: 2026-05-16 source_of_truth: - - ../README.md - - ../ai/repo-rules.md - - ../../.truthmark/config.yml + - ../../README.md + - ../../ai/repo-rules.md + - ../../../.truthmark/config.yml --- # Truthmark Areas @@ -15,7 +15,7 @@ The root route index delegates Truthmark's main behavior surfaces to smaller are ## Contracts And Commands Area files: -- docs/truthmark/areas/contracts-and-commands.md +- docs/truthmark/routes/areas/contracts-and-commands.md Code surface: - src/cli/** @@ -33,24 +33,23 @@ Update truth when: ## Initialization And Scaffold Area files: -- docs/truthmark/areas/init-and-scaffold.md +- docs/truthmark/routes/areas/init-and-scaffold.md Code surface: - src/fs/paths.ts - src/init/** -- src/templates/default-standards.ts -- src/templates/generated-surfaces.ts -- src/templates/init-files.ts +- src/templates/** +- tests/init/** Update truth when: - `truthmark init` scaffolds or refreshes files differently - default canonical docs or generated surface lists change -- hierarchy migration review behavior changes +- configured hierarchy scaffold behavior changes ## Check And Routing Area files: -- docs/truthmark/areas/check-and-routing.md +- docs/truthmark/routes/areas/check-and-routing.md Code surface: - src/checks/** @@ -68,7 +67,7 @@ Update truth when: ## Installed Workflows Area files: -- docs/truthmark/areas/installed-workflows.md +- docs/truthmark/routes/areas/installed-workflows.md Code surface: - src/agents/** @@ -80,6 +79,8 @@ Code surface: - src/templates/generated-surfaces.ts - src/truth/** - src/version.ts +- tests/evals/** +- tests/templates/** Update truth when: - installed workflow boundaries or report shapes change @@ -89,7 +90,7 @@ Update truth when: ## Release Automation Area files: -- docs/truthmark/areas/release-automation.md +- docs/truthmark/routes/areas/release-automation.md Code surface: - .github/workflows/** @@ -102,7 +103,7 @@ Update truth when: ## Repository Intelligence Area files: -- docs/truthmark/areas/repository-intelligence.md +- docs/truthmark/routes/areas/repository-intelligence.md Code surface: - src/repo-index/** @@ -110,7 +111,8 @@ Code surface: - src/evidence/** - src/freshness/** - src/context-pack/** +- src/workflow-state/** Update truth when: -- repository indexing, route-map, impact analysis, evidence validation, freshness checks, or context-pack behavior changes +- repository indexing, route-map, impact analysis, evidence validation, freshness checks, context-pack behavior, or workflow-state behavior changes - `truthmark index`, `truthmark impact`, or `truthmark context` result shapes change diff --git a/docs/truthmark/areas/check-and-routing.md b/docs/truthmark/routes/areas/check-and-routing.md similarity index 70% rename from docs/truthmark/areas/check-and-routing.md rename to docs/truthmark/routes/areas/check-and-routing.md index 4e68a35..3679990 100644 --- a/docs/truthmark/areas/check-and-routing.md +++ b/docs/truthmark/routes/areas/check-and-routing.md @@ -15,15 +15,15 @@ source_of_truth: Truth documents: ```yaml truth_documents: - - path: docs/truth/contracts.md + - path: docs/truthmark/truth/contracts.md kind: contract - - path: docs/architecture/overview.md + - path: docs/truthmark/truth/architecture/overview.md kind: architecture - - path: docs/architecture/module-map.md + - path: docs/truthmark/truth/architecture/module-map.md kind: architecture - - path: docs/truth/check-diagnostics.md + - path: docs/truthmark/truth/check-diagnostics.md kind: behavior - - path: docs/truth/routing-examples.md + - path: docs/truthmark/truth/routing-examples.md kind: behavior ``` diff --git a/docs/truthmark/areas/contracts-and-commands.md b/docs/truthmark/routes/areas/contracts-and-commands.md similarity index 93% rename from docs/truthmark/areas/contracts-and-commands.md rename to docs/truthmark/routes/areas/contracts-and-commands.md index 5512abb..8e2389c 100644 --- a/docs/truthmark/areas/contracts-and-commands.md +++ b/docs/truthmark/routes/areas/contracts-and-commands.md @@ -15,7 +15,7 @@ source_of_truth: Truth documents: ```yaml truth_documents: - - path: docs/truth/contracts.md + - path: docs/truthmark/truth/contracts.md kind: contract ``` diff --git a/docs/truthmark/areas/init-and-scaffold.md b/docs/truthmark/routes/areas/init-and-scaffold.md similarity index 62% rename from docs/truthmark/areas/init-and-scaffold.md rename to docs/truthmark/routes/areas/init-and-scaffold.md index 7be4612..846c268 100644 --- a/docs/truthmark/areas/init-and-scaffold.md +++ b/docs/truthmark/routes/areas/init-and-scaffold.md @@ -15,24 +15,23 @@ source_of_truth: Truth documents: ```yaml truth_documents: - - path: docs/architecture/overview.md + - path: docs/truthmark/truth/architecture/overview.md kind: architecture - - path: docs/architecture/module-map.md + - path: docs/truthmark/truth/architecture/module-map.md kind: architecture - - path: docs/truth/init-and-scaffold.md + - path: docs/truthmark/truth/init-and-scaffold.md kind: behavior - - path: docs/truth/repository/overview.md + - path: docs/truthmark/truth/repository/overview.md kind: behavior ``` Code surface: - src/fs/paths.ts - src/init/** -- src/templates/default-standards.ts -- src/templates/generated-surfaces.ts -- src/templates/init-files.ts +- src/templates/** +- tests/init/** Update truth when: - `truthmark init` scaffolds or refreshes files differently - default canonical docs or generated surface lists change -- hierarchy migration review behavior changes +- configured hierarchy scaffold behavior changes diff --git a/docs/truthmark/areas/installed-workflows.md b/docs/truthmark/routes/areas/installed-workflows.md similarity index 60% rename from docs/truthmark/areas/installed-workflows.md rename to docs/truthmark/routes/areas/installed-workflows.md index ce0a846..ffc5b83 100644 --- a/docs/truthmark/areas/installed-workflows.md +++ b/docs/truthmark/routes/areas/installed-workflows.md @@ -16,27 +16,27 @@ Truth documents: ```yaml truth_documents: - - path: docs/truth/contracts.md + - path: docs/truthmark/truth/contracts.md kind: contract - - path: docs/truth/workflows/overview.md + - path: docs/truthmark/truth/workflows/overview.md kind: workflow - - path: docs/truth/workflows/shared-gates.md + - path: docs/truthmark/truth/workflows/shared-gates.md kind: workflow - - path: docs/truth/workflows/truth-structure.md + - path: docs/truthmark/truth/workflows/truth-structure.md kind: workflow - - path: docs/truth/workflows/truth-document.md + - path: docs/truthmark/truth/workflows/truth-document.md kind: workflow - - path: docs/truth/workflows/truth-sync.md + - path: docs/truthmark/truth/workflows/truth-sync.md kind: workflow - - path: docs/truth/workflows/truth-preview.md + - path: docs/truthmark/truth/workflows/truth-preview.md kind: workflow - - path: docs/truth/workflows/truth-realize.md + - path: docs/truthmark/truth/workflows/truth-realize.md kind: workflow - - path: docs/truth/workflows/truth-check.md + - path: docs/truthmark/truth/workflows/truth-check.md kind: workflow - - path: docs/truth/workflows/truthmark-portal.md + - path: docs/truthmark/truth/workflows/truthmark-portal.md kind: workflow - - path: docs/truth/workflows/content-generation.md + - path: docs/truthmark/truth/workflows/content-generation.md kind: workflow ``` @@ -51,6 +51,8 @@ Code surface: - src/templates/generated-surfaces.ts - src/truth/\*\* - src/version.ts +- tests/evals/** +- tests/templates/** Update truth when: diff --git a/docs/truthmark/areas/release-automation.md b/docs/truthmark/routes/areas/release-automation.md similarity index 90% rename from docs/truthmark/areas/release-automation.md rename to docs/truthmark/routes/areas/release-automation.md index afd43a9..3c77991 100644 --- a/docs/truthmark/areas/release-automation.md +++ b/docs/truthmark/routes/areas/release-automation.md @@ -15,7 +15,7 @@ source_of_truth: Truth documents: ```yaml truth_documents: - - path: docs/truth/release/automation.md + - path: docs/truthmark/truth/release/automation.md kind: workflow ``` diff --git a/docs/truthmark/areas/repository-intelligence.md b/docs/truthmark/routes/areas/repository-intelligence.md similarity index 61% rename from docs/truthmark/areas/repository-intelligence.md rename to docs/truthmark/routes/areas/repository-intelligence.md index 4113742..2344a53 100644 --- a/docs/truthmark/areas/repository-intelligence.md +++ b/docs/truthmark/routes/areas/repository-intelligence.md @@ -15,11 +15,13 @@ source_of_truth: Truth documents: ```yaml truth_documents: - - path: docs/truth/repository/repo-index.md + - path: docs/truthmark/truth/repository/repo-index.md kind: behavior - - path: docs/truth/repository/impact-set.md + - path: docs/truthmark/truth/repository/impact-set.md kind: behavior - - path: docs/truth/repository/context-pack.md + - path: docs/truthmark/truth/repository/context-pack.md + kind: behavior + - path: docs/truthmark/truth/repository/workflow-state.md kind: behavior ``` @@ -29,7 +31,8 @@ Code surface: - src/evidence/** - src/freshness/** - src/context-pack/** +- src/workflow-state/** Update truth when: -- RepoIndex, RouteMap, ImpactSet, evidence validation, freshness diagnostics, or ContextPack behavior changes +- RepoIndex, RouteMap, ImpactSet, evidence validation, freshness diagnostics, ContextPack behavior, or WorkflowState behavior changes - repository-intelligence command output changes diff --git a/docs/templates/architecture-doc.md b/docs/truthmark/templates/architecture-doc.md similarity index 100% rename from docs/templates/architecture-doc.md rename to docs/truthmark/templates/architecture-doc.md diff --git a/docs/templates/behavior-doc.md b/docs/truthmark/templates/behavior-doc.md similarity index 100% rename from docs/templates/behavior-doc.md rename to docs/truthmark/templates/behavior-doc.md diff --git a/docs/templates/contract-doc.md b/docs/truthmark/templates/contract-doc.md similarity index 100% rename from docs/templates/contract-doc.md rename to docs/truthmark/templates/contract-doc.md diff --git a/docs/templates/operations-doc.md b/docs/truthmark/templates/operations-doc.md similarity index 100% rename from docs/templates/operations-doc.md rename to docs/truthmark/templates/operations-doc.md diff --git a/docs/templates/test-behavior-doc.md b/docs/truthmark/templates/test-behavior-doc.md similarity index 100% rename from docs/templates/test-behavior-doc.md rename to docs/truthmark/templates/test-behavior-doc.md diff --git a/docs/templates/workflow-doc.md b/docs/truthmark/templates/workflow-doc.md similarity index 100% rename from docs/templates/workflow-doc.md rename to docs/truthmark/templates/workflow-doc.md diff --git a/docs/truth/README.md b/docs/truthmark/truth/README.md similarity index 92% rename from docs/truth/README.md rename to docs/truthmark/truth/README.md index 24994a9..29b7bca 100644 --- a/docs/truth/README.md +++ b/docs/truthmark/truth/README.md @@ -3,7 +3,7 @@ status: active doc_type: index last_reviewed: 2026-05-09 source_of_truth: - - ../truthmark/areas.md + - ../routes/areas.md --- # Truth Docs diff --git a/docs/truthmark/truth/architecture/README.md b/docs/truthmark/truth/architecture/README.md new file mode 100644 index 0000000..659fe18 --- /dev/null +++ b/docs/truthmark/truth/architecture/README.md @@ -0,0 +1,19 @@ +--- +status: active +doc_type: index +last_reviewed: 2026-06-12 +source_of_truth: + - ../../routes/areas/check-and-routing.md + - ../../routes/areas/init-and-scaffold.md +--- + +# Architecture Truth Docs + +This directory indexes routed architecture truth docs in the configured Truthmark truth root. + +README.md files are indexes, not Truth Sync targets. Keep architecture truth in bounded leaf docs in this directory. + +Current leaf docs: + +- [Overview](overview.md) +- [Module Map](module-map.md) diff --git a/docs/architecture/module-map.md b/docs/truthmark/truth/architecture/module-map.md similarity index 93% rename from docs/architecture/module-map.md rename to docs/truthmark/truth/architecture/module-map.md index e10596e..1d9ab8d 100644 --- a/docs/architecture/module-map.md +++ b/docs/truthmark/truth/architecture/module-map.md @@ -54,9 +54,9 @@ This doc covers the current module grouping of the Truthmark codebase and the pr ## Documentation Pairings -- `src/init/`, `src/templates/`, and the write-path parts of `src/fs/` pair with [docs/truth/init-and-scaffold.md](../truth/init-and-scaffold.md) -- `src/checks/`, `src/routing/`, `src/config/`, `src/output/`, and the containment-path parts of `src/fs/` pair with [docs/truth/check-diagnostics.md](../truth/check-diagnostics.md) -- `src/agents/`, `src/generation/`, `src/sync/`, `src/realize/`, `src/truth/`, and installed workflow skill templates under `src/templates/` pair with [docs/truth/workflows/overview.md](../truth/workflows/overview.md) and bounded workflow docs under `docs/truth/workflows/` +- `src/init/`, `src/templates/`, and the write-path parts of `src/fs/` pair with [docs/truthmark/truth/init-and-scaffold.md](../init-and-scaffold.md) +- `src/checks/`, `src/routing/`, `src/config/`, `src/output/`, and the containment-path parts of `src/fs/` pair with [docs/truthmark/truth/check-diagnostics.md](../check-diagnostics.md) +- `src/agents/`, `src/generation/`, `src/sync/`, `src/realize/`, `src/truth/`, and installed workflow skill templates under `src/templates/` pair with [docs/truthmark/truth/workflows/overview.md](../workflows/overview.md) and bounded workflow docs under `docs/truthmark/truth/workflows/` ## Product Decisions diff --git a/docs/architecture/overview.md b/docs/truthmark/truth/architecture/overview.md similarity index 80% rename from docs/architecture/overview.md rename to docs/truthmark/truth/architecture/overview.md index ab45979..f894453 100644 --- a/docs/architecture/overview.md +++ b/docs/truthmark/truth/architecture/overview.md @@ -3,19 +3,19 @@ status: active doc_type: architecture last_reviewed: 2026-05-16 source_of_truth: - - ../../.truthmark/config.yml - - ../truth/contracts.md - - ../truth/init-and-scaffold.md - - ../truth/check-diagnostics.md - - ../truth/workflows/overview.md - - ../truth/workflows/shared-gates.md + - ../../../../.truthmark/config.yml + - ../contracts.md + - ../init-and-scaffold.md + - ../check-diagnostics.md + - ../workflows/overview.md + - ../workflows/shared-gates.md --- # Architecture Overview ## Scope -This document describes Truthmark's current V1 architecture as implemented today. +This document describes Truthmark's current architecture as implemented today. ## Runtime Model @@ -33,20 +33,21 @@ Truthmark does not currently include: The durable surfaces are ordinary repository files: - `.truthmark/config.yml` -- [docs/truthmark/areas.md](../truthmark/areas.md) +- [docs/truthmark/routes/areas.md](../../routes/areas.md) - canonical docs under `docs/` -- the managed Truthmark block inside [AGENTS.md](../../AGENTS.md) -- generated Truth Structure, Truth Document, Truth Sync, Truth Preview, Truth Realize, and Truth Check surfaces under `.codex/skills/`, `.opencode/skills/`, `.claude/skills/`, `.github/prompts/`, and `.gemini/commands/truthmark/` -- Codex workflow metadata under `.codex/skills/truthmark-*/agents/openai.yaml` -- configured platform instruction files such as [AGENTS.md](../../AGENTS.md), `CLAUDE.md`, `.github/copilot-instructions.md`, and `GEMINI.md` +- the managed Truthmark block inside [AGENTS.md](../../../../AGENTS.md) +- generated Truth Structure, Truth Document, Truth Sync, Truth Preview, Truth Realize, and Truth Check surfaces under `.agents/skills/`, `.opencode/skills/`, `.claude/skills/`, `.github/prompts/`, and `.gemini/commands/truthmark/` +- Codex workflow metadata under `.agents/skills/truthmark-*/agents/openai.yaml` +- configured platform instruction files such as [AGENTS.md](../../../../AGENTS.md), `CLAUDE.md`, `.github/copilot-instructions.md`, and `GEMINI.md` -Generated workflow surfaces are committed repository files with Truthmark version markers. The V1 upgrade path is to upgrade the package, rerun `truthmark init`, and review the generated diffs. +Generated workflow surfaces are committed repository files with Truthmark version markers. The upgrade path is to upgrade the package, rerun `truthmark init`, and review the generated diffs. ## Boundaries - The CLI owns committed config, routing, diagnostics, scaffolded files, and generated workflow surfaces inside the active repository. - Repository truth stays in Git-tracked Markdown and managed instruction surfaces rather than off-repo caches, daemons, or hosted services. - Architecture docs own structure and ownership boundaries; behavior and contract docs own ordinary product behavior and machine-facing contracts. +- [Product Boundary](../../../architecture/product-boundary.md) is the mandatory architecture guardrail for new designs and plans; proposals must check the North Star, in-scope surfaces, explicit non-goals, optional-helper rule, and fail-closed write boundaries before implementation. ## Core Pipelines @@ -71,7 +72,7 @@ Key implementation surfaces: - `src/checks/*` for individual validation passes - `src/config/*` for config loading and schema validation -- `src/routing/*` for `docs/truthmark/areas.md` parsing and area resolution +- `src/routing/*` for `docs/truthmark/routes/areas.md` parsing and area resolution - `src/markdown/*` for document parsing and hashing - `src/output/*` for result rendering @@ -86,7 +87,7 @@ Truthmark also contains support primitives for the installed Truth Structure, Tr - `src/sync/*` classifies functional-code paths and renders Truth Sync reports - `src/realize/report.ts` renders the Truth Realize completion report shape -These modules support the installed workflow contract even though V1 does not expose dedicated CLI entrypoints for the installed Truth Structure, Truth Document, Truth Sync, Truth Preview, Truth Realize, or Truth Check workflows. +These modules support the installed workflow contract even though the current CLI does not expose dedicated entrypoints for the installed Truth Structure, Truth Document, Truth Sync, Truth Preview, Truth Realize, or Truth Check workflows. ## Architecture Doc Boundary @@ -107,7 +108,7 @@ Normal branch checkouts are identified by branch name plus HEAD SHA. Detached ch ## Polyglot Code Surface -Truth Sync path classification is multi-language and path-based. `truthmark check` coverage diagnostics reuse the same functional-code classifier across common code roots so V1 can support Go, Python, C#, and Java repositories at a minimum, in addition to JavaScript and TypeScript projects. +Truth Sync path classification is multi-language and path-based. `truthmark check` coverage diagnostics reuse the same functional-code classifier across common code roots to support Go, Python, C#, and Java repositories at a minimum, in addition to JavaScript and TypeScript projects. Current automatic coverage discovery scans common roots such as `src/`, `api/`, `app/`, `apps/`, `cmd/`, `frontend/`, `infra/`, `internal/`, `k8s/`, `lib/`, `packages/`, `proto/`, `schema/`, `scripts/`, `server/`, `services/`, `terraform/`, `web/`, and `.github/workflows/`. Area mappings remain the authority for which truth docs own each code surface. @@ -127,7 +128,7 @@ Current automatic coverage discovery scans common roots such as `src/`, `api/`, ## Product Decisions - Truthmark is config-first: repositories review committed hierarchy before installed workflow surfaces are generated. -- Hierarchical routing is the only scaffold model in V1, with one child delegation level from the root route index. +- Hierarchical routing is the only scaffold model, with one child delegation level from the root route index. - Default truth scaffolding uses index `README.md` files plus bounded leaf truth docs so Truth Sync has a small current-behavior target from the first init. - Current architecture and truth docs carry their own active decisions and rationale instead of delegating that truth to historical ADR-style logs. - Architecture docs are maintained for structure and ownership changes, not for ordinary product behavior. diff --git a/docs/truth/check-diagnostics.md b/docs/truthmark/truth/check-diagnostics.md similarity index 73% rename from docs/truth/check-diagnostics.md rename to docs/truthmark/truth/check-diagnostics.md index e428d8e..119bcb2 100644 --- a/docs/truth/check-diagnostics.md +++ b/docs/truthmark/truth/check-diagnostics.md @@ -2,18 +2,22 @@ status: active doc_type: behavior truth_kind: behavior -last_reviewed: 2026-05-31 +last_reviewed: 2026-06-12 source_of_truth: - - ../../src/checks/check.ts - - ../../src/checks/authority.ts - - ../../src/checks/areas.ts - - ../../src/checks/branch-scope.ts - - ../../src/freshness/check.ts - - ../../src/impact/build.ts - - ../../src/evidence/validate.ts - - ../../src/checks/frontmatter.ts - - ../../src/checks/links.ts - - ../../src/markdown/discovery.ts + - ../../../src/config/load.ts + - ../../../src/checks/check.ts + - ../../../src/checks/scorecard.ts + - ../../../src/checks/authority.ts + - ../../../src/checks/areas.ts + - ../../../src/checks/branch-scope.ts + - ../../../src/freshness/check.ts + - ../../../src/impact/build.ts + - ../../../src/evidence/validate.ts + - ../../../src/evidence/parse.ts + - ../../../src/checks/frontmatter.ts + - ../../../src/checks/links.ts + - ../../../src/markdown/discovery.ts + - ../../../src/routing/areas.ts --- # Check Diagnostics @@ -36,8 +40,9 @@ The command: 2. computes branch-scope metadata 3. loads `.truthmark/config.yml` 4. runs authority, area, decision-structure, frontmatter, internal-link, generated-surface, and coverage diagnostics when config is valid -5. when `--base ` is supplied, builds an ImpactSet and adds freshness diagnostics for changed code without route ownership, stale evidence, invalid base comparisons, and changed public API without docs sync -6. returns a human summary or the shared JSON envelope +5. runs source-traceability diagnostics for configured truth docs independently of `--base `; when `--base ` is supplied, builds an ImpactSet and adds branch-freshness diagnostics for changed code without route ownership, invalid base comparisons, and changed public API without docs sync +6. builds the compact `data.scorecard` summary from the final raw diagnostics array and explicit run context +7. returns a human summary or the shared JSON envelope There is no supported `--workflow` helper mode. Agent workflows inspect the checkout directly and may run `truthmark check` only as optional validation. @@ -71,7 +76,7 @@ Each resolved leaf area must define: - `Code surface` - `Update truth when` -`Truth documents` may be expressed either as a legacy Markdown list of document paths or as a fenced YAML block with a `truth_documents` array of `{ path, kind }` entries. Explicit route metadata is authoritative and owns the section, so legacy list lines in the same section are ignored. Legacy lists fall back to path-based kind inference such as the configured truth root, `docs/truth/** -> behavior`, `docs/contracts/**` or `docs/api/** -> contract`, `docs/architecture/** -> architecture`, `docs/workflows/** -> workflow`, `docs/operations/** -> operations`, and `docs/testing/** -> test-behavior`. When an explicit route entry is a glob, Truthmark expands it to concrete truth document entries before frontmatter and doc-structure checks so the routed kind applies to every matched file. +`Truth documents` may be expressed either as a Markdown list of document paths or as a fenced YAML block with a `truth_documents` array of `{ path, kind }` entries. Explicit route metadata is authoritative and owns the section, so list lines in the same section are ignored. List entries under the configured truth root default to behavior; clean workspace truth docs under `docs/truthmark/truth/**` are valid behavior truth docs even when explicit kind metadata is absent. List entries outside the configured truth root default to behavior with a review diagnostic instead of using removed project-doc path conventions such as `docs/api/**` or `docs/architecture/**`. When an explicit route entry is a glob, Truthmark expands it to concrete truth document entries before frontmatter and doc-structure checks so the routed kind applies to every matched file. Current severity behavior: @@ -180,6 +185,13 @@ Current severity behavior: - changed public API with no affected truth document: `review` - changed public API with affected truth docs that were not changed in the impact set: `review` - invalid base ref or failed base comparison: `error` + +### Source Traceability + +Source traceability checks run whenever configured truth docs can be loaded; they are not gated on `--base `. They verify that truth-doc `source_of_truth` entries and optional evidence blocks still point at live checkout material. Fenced YAML is treated as an evidence block only when it contains a top-level `evidence:` marker, so illustrative non-evidence YAML examples are ignored even when malformed. They do not prove claim semantics. + +Current severity behavior: + - deleted `source_of_truth` or evidence reference: `error` - `source_of_truth` glob reference with no matching files: `error` - evidence reference outside the repository root: `error` @@ -193,7 +205,7 @@ Current severity behavior: 1. Resolve the active repository and worktree. 2. Load `.truthmark/config.yml` and configured authority roots. 3. Build branch-scope metadata and relevant-file hashes for the current checkout. -4. Run configured authority, area, frontmatter, link, generated-surface, coverage, decision-structure, and topology diagnostics. +4. Run configured authority, area, frontmatter, link, generated-surface, source-traceability, coverage, decision-structure, and topology diagnostics. 5. Render either human-readable output or the shared JSON command envelope. The command does not run Truth Sync, Truth Preview, Truth Realize, Truth Structure, or Truth Check workflows. It only reports the current repository-truth health it can derive from local checkout state. @@ -204,9 +216,16 @@ The command does not run Truth Sync, Truth Preview, Truth Realize, Truth Structu - JSON output returns the shared command envelope - JSON output includes `data.branchScope` - JSON output includes `data.truthVisibility` +- JSON output includes `data.scorecard` with `schemaVersion: truthmark-scorecard/v0` - JSON output includes `data.impactSet` only when `--base ` is supplied - JSON output does not include workflow payloads +`data.scorecard` is a compact Truth Health Scorecard over the same raw diagnostics returned at top level. It includes seven dimensions: `routing-coverage`, `ownership-clarity`, `source-traceability`, `branch-freshness`, `generated-surface-freshness`, `truth-doc-structure`, and `decision-rationale-preservation`. Each dimension contains `id`, categorical `status`, and `diagnosticIndexes`; non-pass dimensions may include capped short `evidence`. `diagnosticIndexes` always point into the final returned `diagnostics` array, so raw diagnostics remain the source of full messages, files, severities, and machine data. + +Status derivation is deterministic: any mapped `error` diagnostic makes the dimension `fail`, mapped non-error diagnostics make it `warn`, no mapped diagnostics after the relevant checker ran makes it `pass`, and unavailable or skipped context makes it `not-run`. `branch-freshness` is `not-run` when `--base` is omitted. Missing or invalid config still returns a parseable check envelope with `data.scorecard`; dimensions affected by config errors fail or report not-run instead of being omitted. + +Pass 4 keeps workflow-state scorecard exposure deferred: `truthmark check --json` has the scorecard, but `workflow status` and generated playbooks do not receive `data.workflowState.scorecard` in this change. + Branch scope identifies the active checkout: - normal branches use branch name plus HEAD SHA @@ -246,6 +265,7 @@ Keeping topology repair in generated agent workflows preserves portability: a re Primary implementation files: - `src/checks/check.ts` +- `src/checks/scorecard.ts` - `src/checks/authority.ts` - `src/checks/areas.ts` - `src/checks/frontmatter.ts` diff --git a/docs/truth/contracts.md b/docs/truthmark/truth/contracts.md similarity index 62% rename from docs/truth/contracts.md rename to docs/truthmark/truth/contracts.md index 5d8d4bd..6239bc7 100644 --- a/docs/truth/contracts.md +++ b/docs/truthmark/truth/contracts.md @@ -2,18 +2,19 @@ status: active doc_type: contract truth_kind: contract -last_reviewed: 2026-05-19 +last_reviewed: 2026-06-01 source_of_truth: - - ../../src/config/schema.ts - - ../../src/checks/check.ts - - ../../src/templates/init-files.ts - - ../../src/templates/generated-surfaces.ts - - ../../src/init/init.ts - - ../../src/output/diagnostic.ts - - ../../src/output/render.ts - - ../../src/cli/handlers.ts - - ../../src/cli/program.ts - - ../../src/agents/workflow-helper-validation.ts + - ../../../src/config/schema.ts + - ../../../src/checks/check.ts + - ../../../src/checks/scorecard.ts + - ../../../src/templates/init-files.ts + - ../../../src/templates/generated-surfaces.ts + - ../../../src/init/init.ts + - ../../../src/output/diagnostic.ts + - ../../../src/output/render.ts + - ../../../src/cli/handlers.ts + - ../../../src/cli/program.ts + - ../../../src/agents/workflow-helper-validation.ts --- # Contracts @@ -29,41 +30,40 @@ This document defines the current machine-facing contracts exposed by Truthmark: ## Contract Surface - The committed `.truthmark/config.yml` schema and defaults. -- Route metadata under `docs/truthmark/areas.md` and delegated child route files. -- The JSON result envelope emitted by `truthmark config`, `truthmark init`, `truthmark check`, `truthmark index`, `truthmark impact`, `truthmark context`, and workflow helper validator commands under `truthmark validate`. +- Route metadata under `docs/truthmark/routes/areas.md` and delegated child route files. +- The JSON result envelope emitted by human/setup commands such as `truthmark config` and `truthmark init`, agent/context commands such as `truthmark check`, `truthmark index`, `truthmark impact`, `truthmark context`, and `truthmark workflow status`, and workflow helper validator commands under `truthmark validate`. ## Inputs - Committed config fields under `.truthmark/config.yml`. -- Routed truth-document metadata from `docs/truthmark/areas.md` and `docs/truthmark/areas/**/*.md`. +- Routed truth-document metadata from `docs/truthmark/routes/areas.md` and `docs/truthmark/routes/areas/**/*.md`. - CLI options such as `--json`, `--stdout`, and command-specific flags. Truthmark loads `.truthmark/config.yml` and validates it against the current schema. Current fields: -- `version`: must be `1` +- `version`: must be `2` - `platforms`: optional list of agent harnesses to initialize; defaults to all supported platforms -- `docs.layout`: currently `hierarchical` -- `docs.roots`: named canonical doc roots; omitted root names are filled from current defaults -- `docs.routing.root_index`: root area index path -- `docs.routing.area_files_root`: child area route directory -- `docs.routing.default_area`: default child route file basename used by scaffold -- `docs.routing.max_delegation_depth`: currently must be `1` -- `authority`: ordered list of canonical doc paths or globs +- `truthmark.workspace`: workspace root for Truthmark-owned routing, truth, templates, and generated output +- `truthmark.routes.index`: root area index path relative to `truthmark.workspace` +- `truthmark.routes.areas`: child route directory relative to `truthmark.workspace` +- `truthmark.routes.default_area`: default child route file basename used by scaffold +- `truthmark.routes.max_delegation_depth`: currently must be `1` +- `truthmark.truth.root`: canonical truth-doc root relative to `truthmark.workspace` +- `truthmark.templates.root`: template root relative to `truthmark.workspace` +- `truthmark.generated.portal.enabled`: whether `truthmark init` renders optional Portal workflow surfaces - `instruction_targets`: files that receive installed instructions; defaults to `AGENTS.md` - `frontmatter.required`: frontmatter fields that produce `error` diagnostics when missing - `frontmatter.recommended`: frontmatter fields that produce `review` diagnostics when missing - `ignore`: glob patterns excluded from relevant checks and routing logic -The default scaffolded authority list includes: +The default derived controlled paths include: -- `docs/truthmark/areas.md` -- `docs/truthmark/areas/**/*.md` -- `docs/ai/**/*.md` -- `docs/standards/**/*.md` -- `docs/architecture/**/*.md` -- `docs/truth/**/*.md` +- `docs/truthmark/routes/areas.md` +- `docs/truthmark/routes/areas/**/*.md` +- `docs/truthmark/truth/**/*.md` +- `docs/truthmark/templates/*.md` Route files may express `Truth documents` in either of these forms: @@ -83,7 +83,7 @@ Supported routed truth kinds are: - `operations` - `test-behavior` -When explicit `kind` metadata is present, it is the authoritative routed kind and the fenced metadata block owns the `Truth documents` section. Legacy list lines in the same section are ignored. When route files use the legacy list form, Truthmark falls back to path-based kind inference such as `/**` or `docs/truth/** -> behavior`, `docs/contracts/**` or `docs/api/** -> contract`, `docs/architecture/** -> architecture`, `docs/workflows/** -> workflow`, `docs/operations/** -> operations`, and `docs/testing/** -> test-behavior`. +When explicit `kind` metadata is present, it is the authoritative routed kind and the fenced metadata block owns the `Truth documents` section. Legacy list lines in the same section are ignored. When route files use the legacy list form, Truthmark falls back to path-based kind inference such as `/**` or `docs/truthmark/truth/** -> behavior`, `docs/contracts/**` or `docs/api/** -> contract`, `docs/architecture/** -> architecture`, `docs/workflows/** -> workflow`, `docs/operations/** -> operations`, and `docs/testing/** -> test-behavior`. Canonical truth docs may include optional `truth_kind` frontmatter. When present, it must match the routed kind. @@ -110,20 +110,37 @@ Current shape: Diagnostic fields: -- `category`: one of `config`, `authority`, `frontmatter`, `links`, `area-index`, `coverage`, `truth-sync`, `realization`, `doc-structure`, `generated-surface`, `repo-index`, `impact`, `freshness`, or `context-pack` +- `category`: one of `config`, `authority`, `frontmatter`, `links`, `area-index`, `coverage`, `truth-sync`, `realization`, `doc-structure`, `generated-surface`, `repo-index`, `impact`, `freshness`, `context-pack`, or `workflow-state` - `severity`: one of `info`, `action`, `review`, or `error` - `message`: human-readable detail - `file`: optional repository-relative file path -- `area`: optional area name from `docs/truthmark/areas.md` +- `area`: optional area name from `docs/truthmark/routes/areas.md` - `data`: optional machine-readable extras Human-rendered output is intended for people. JSON output is the machine-facing contract. CLI invocations that render a `CommandResult` set a non-zero process exit code when any diagnostic has `severity: "error"`; `info`, `action`, and `review` diagnostics do not make the process fail. `truthmark index --json` returns `data.repoIndex` with `schemaVersion: repo-index/v0` and `data.routeMap` with `schemaVersion: route-map/v0`. +`truthmark check --json` returns `data.branchScope`, the compatibility `data.truthVisibility` summary, and `data.scorecard` with `schemaVersion: truthmark-scorecard/v0`. The scorecard is additive triage over the same top-level `diagnostics` array; raw diagnostics remain authoritative and keep their existing shape. `data.impactSet` is included only when `--base ` is supplied. + +The Truth Health Scorecard dimensions are compact runtime objects: + +- `id`: one of `routing-coverage`, `ownership-clarity`, `source-traceability`, `branch-freshness`, `generated-surface-freshness`, `truth-doc-structure`, or `decision-rationale-preservation` +- `status`: `pass`, `warn`, `fail`, or `not-run` +- `diagnosticIndexes`: indexes into the same raw `diagnostics` array returned by the command +- `evidence`: optional, capped short snippets for non-pass states only + +Scorecard statuses are categorical: mapped `error` diagnostics produce `fail`; mapped non-error diagnostics produce `warn`; a dimension whose relevant checker ran with no mapped diagnostics produces `pass`; and unavailable or intentionally skipped context produces `not-run`. `branch-freshness` is `not-run` when `truthmark check` runs without `--base`, rather than `pass` just because freshness diagnostics did not run. Pass 4 does not add a scorecard command, numeric health grade, generated-playbook payload, or `data.workflowState.scorecard`. + `truthmark impact --base --json` returns `data.impactSet` with `schemaVersion: impact-set/v0`. -`truthmark context --workflow [--base ] --json` returns `data.contextPack` with `schemaVersion: context-pack/v0`. `--workflow` accepts `truth-sync`, `truth-document`, and `truth-realize`. `--format` accepts `json` or `markdown`; unsupported formats return a `context-pack` error diagnostic. `--format markdown` renders a deterministic Markdown ContextPack for human review, and `--json --format markdown` includes that Markdown under `data.markdown`. +`truthmark context --workflow [--base ] --json` returns a shared command envelope with `data.markdown` and `data.summary`; it never returns `data.contextPack`, `truthDocs[*].content`, or `sourceFiles[*].content`. `--workflow` accepts `truth-sync`, `truth-document`, and `truth-realize`. The default format is `markdown`, and `--format markdown` renders a deterministic Markdown ContextPack for human review when `--json` is not used. `--format json` returns a `context-pack` error diagnostic because JSON ContextPack output was removed in v2. + +`truthmark workflow status --workflow [--base ] --json` returns `command: "workflow status"`, `data.request`, and manifest-only `data.workflowState` with nested `schemaVersion: truthmark-workflow/v0`. It is retained for status-only/debug inspection. `data.request.workflow` records the caller-supplied canonical workflow ID, and `data.request.base` records the caller-supplied comparison ref when present. The WorkflowState schema is not extended for request metadata unless a later explicit schema change does so. + +Workflow status accepts full manifest workflow IDs such as `truthmark-sync` and `truthmark-check`. Short ContextPack aliases such as `truth-sync` are rejected and are not mapped to full manifest IDs. Missing `--workflow` or unknown workflow IDs return a parseable `CommandResult` JSON envelope with a `workflow-state` error diagnostic, a non-zero exit code, and no workflow state or permissive write-boundary payload. + +`workflow status` is an agent-facing repository-intelligence command for status-only/debug inspection. Default JSON preserves schema version, workflow ID, applicability, action context and write boundaries, changed files, affected routes, target truth docs, diagnostics, checks, next steps, report sections, and helper validation command metadata. WorkflowState does not include `workflowState.contextPack`, truth document content, source file content, or a full route map. Workflow helper validators are optional CLI-owned accelerators used by generated skill `helper-manifest.yml` files. They validate report text or lease/path inputs that agents provide after doing checkout inspection; they do not grant workflow write authority and do not replace route files, source files, truth docs, or parent workflow validation. @@ -176,25 +193,25 @@ Generated Truth Structure, Truth Document, Truth Sync, Truth Preview, Truth Chec Current agent-native scaffold targets include: -- `.codex/skills/truthmark-structure/SKILL.md` -- `.codex/skills/truthmark-structure/agents/openai.yaml` -- `.codex/skills/truthmark-document/SKILL.md` -- `.codex/skills/truthmark-document/agents/openai.yaml` -- `.codex/skills/truthmark-sync/SKILL.md` -- `.codex/skills/truthmark-sync/agents/openai.yaml` -- `.codex/skills/truthmark-realize/SKILL.md` -- `.codex/skills/truthmark-realize/agents/openai.yaml` -- `.codex/skills/truthmark-check/SKILL.md` -- `.codex/skills/truthmark-check/agents/openai.yaml` -- `.codex/skills/truthmark-preview/SKILL.md` -- `.codex/skills/truthmark-preview/agents/openai.yaml` -- `.codex/skills/truthmark-portal/SKILL.md` when Truthmark Portal is enabled -- `.codex/skills/truthmark-portal/agents/openai.yaml` when Truthmark Portal is enabled -- `.codex/skills/truthmark-*/support/procedure.md` -- `.codex/skills/truthmark-*/support/report-template.md` -- `.codex/skills/truthmark-*/support/subagents-and-leases.md` when the workflow has generated subagent guidance -- `.codex/skills/truthmark-*/helper-manifest.yml` when the workflow declares helpers -- `.codex/skills/truthmark-*/support/helper-policy.md` when the workflow declares helpers +- `.agents/skills/truthmark-structure/SKILL.md` +- `.agents/skills/truthmark-structure/agents/openai.yaml` +- `.agents/skills/truthmark-document/SKILL.md` +- `.agents/skills/truthmark-document/agents/openai.yaml` +- `.agents/skills/truthmark-sync/SKILL.md` +- `.agents/skills/truthmark-sync/agents/openai.yaml` +- `.agents/skills/truthmark-realize/SKILL.md` +- `.agents/skills/truthmark-realize/agents/openai.yaml` +- `.agents/skills/truthmark-check/SKILL.md` +- `.agents/skills/truthmark-check/agents/openai.yaml` +- `.agents/skills/truthmark-preview/SKILL.md` +- `.agents/skills/truthmark-preview/agents/openai.yaml` +- `.agents/skills/truthmark-portal/SKILL.md` when Truthmark Portal is enabled +- `.agents/skills/truthmark-portal/agents/openai.yaml` when Truthmark Portal is enabled +- `.agents/skills/truthmark-*/support/procedure.md` +- `.agents/skills/truthmark-*/support/report-template.md` +- `.agents/skills/truthmark-*/support/subagents-and-leases.md` when the workflow has generated subagent guidance +- `.agents/skills/truthmark-*/helper-manifest.yml` when the workflow declares helpers +- `.agents/skills/truthmark-*/support/helper-policy.md` when the workflow declares helpers - `.codex/agents/truth-route-auditor.toml` - `.codex/agents/truth-claim-verifier.toml` - `.codex/agents/truth-doc-reviewer.toml` @@ -253,10 +270,10 @@ Current agent-native scaffold targets include: - `.github/prompts/truthmark-check.prompt.md` - `.github/prompts/truthmark-preview.prompt.md` - `.github/prompts/truthmark-portal.prompt.md` when Truthmark Portal is enabled -- `.github/agents/truth-route-auditor.agent.md` -- `.github/agents/truth-claim-verifier.agent.md` -- `.github/agents/truth-doc-reviewer.agent.md` -- `.github/agents/truth-doc-writer.agent.md` +- `.github/agents/truth-route-auditor.md` +- `.github/agents/truth-claim-verifier.md` +- `.github/agents/truth-doc-reviewer.md` +- `.github/agents/truth-doc-writer.md` - `GEMINI.md` - `.gemini/skills/truthmark-structure/SKILL.md` - `.gemini/skills/truthmark-document/SKILL.md` @@ -282,9 +299,9 @@ Current agent-native scaffold targets include: - `.gemini/agents/truth-doc-reviewer.md` - `.gemini/agents/truth-doc-writer.md` -Generated `SKILL.md` files use closed YAML frontmatter with `name`, `description`, `argument-hint`, `user-invocable`, and `truthmark-version` fields so Codex-style, Claude Code, GitHub Copilot, Gemini CLI, and OpenCode-style skill indexers can parse every generated workflow surface. For those skill-package hosts, `SKILL.md` is the compact routing and quick-procedure entrypoint; detailed procedure text, report templates, and subagent or lease reference material live in generated sibling `support/*.md` files. Helper-capable workflows also emit `helper-manifest.yml` and `support/helper-policy.md` files that call installed `truthmark validate ... --json` CLI validators; generated packages do not bundle repo-local helper scripts. Generated Copilot prompt files use `.github/prompts/*.prompt.md` files with `agent` and `description` frontmatter so supported Copilot IDEs can expose `/truthmark-*` prompts. Generated verifier agents are read-only and context-bounded to parent-assigned shards, while generated `truth-doc-writer` agents are write-capable only through parent-provided leases and parent diff validation. Generated Codex metadata includes a `truthmark.version` marker plus `truthmark.refresh_command: "truthmark init"`. Managed instruction blocks also render the Truthmark package version, and `package.json` is the single maintained version source for those markers. Generated Gemini command files use project-scoped TOML custom commands so `truthmark init` can install `/truthmark:structure`, `/truthmark:document`, `/truthmark:sync`, `/truthmark:preview`, `/truthmark:realize`, and `/truthmark:check` alongside `GEMINI.md`; each command prompt ends with an explicit `User focus or arguments: {{args}}` handoff. Re-running `truthmark init` after a package upgrade refreshes configured committed surfaces and exposes staleness through ordinary Git diffs. Removing a platform from config stops future refreshes for that platform; it does not delete previously generated files. +Generated `SKILL.md` files use closed YAML frontmatter with `name`, `description`, `argument-hint`, `user-invocable`, and `truthmark-version` fields so Codex-style, Claude Code, GitHub Copilot, Gemini CLI, and OpenCode-style skill indexers can parse every generated workflow surface. For those skill-package hosts, `SKILL.md` is the compact routing and quick-procedure entrypoint; detailed procedure text, report templates, and subagent or lease reference material live in generated sibling `support/*.md` files. Public workflow entrypoints, generated GitHub Copilot prompt files, and generated Gemini command files use checked-in workflow text as the execution contract: agents inspect the checkout directly, open progressive-disclosure support files only when needed, and use local CLI checks only as focused validation after relevant work has been performed. Helper-capable workflows also emit `helper-manifest.yml` and `support/helper-policy.md` files that call installed `truthmark validate ... --json` CLI validators; generated packages do not bundle repo-local helper scripts. Generated Copilot prompt files use `.github/prompts/*.prompt.md` files with `agent` and `description` frontmatter so supported Copilot IDEs can expose `/truthmark-*` prompts. Generated verifier agents are read-only and context-bounded to parent-assigned shards, while generated `truth-doc-writer` agents are write-capable only through parent-provided leases and parent diff validation. Generated Codex metadata includes a `truthmark.version` marker plus `truthmark.refresh_command: "truthmark init"`. Managed instruction blocks also render the Truthmark package version, and `package.json` is the single maintained version source for those markers. Generated Gemini command files use project-scoped TOML custom commands so `truthmark init` can install `/truthmark:structure`, `/truthmark:document`, `/truthmark:sync`, `/truthmark:preview`, `/truthmark:realize`, and `/truthmark:check` alongside `GEMINI.md`; each command prompt ends with an explicit `User focus or arguments: {{args}}` handoff. Re-running `truthmark init` after a package upgrade refreshes configured committed surfaces and exposes staleness through ordinary Git diffs. Removing a platform from config stops future refreshes for that platform; it does not delete previously generated files. -The OpenCode `truth-doc-writer` edit allow-list is rendered from the active `docs.roots.truth`, `docs.routing.root_index`, and `docs.routing.area_files_root` config paths so valid leases remain writable in non-default documentation layouts. +The OpenCode `truth-doc-writer` edit allow-list is rendered from the active `truthmark.workspace`, `truthmark.truth.root`, `truthmark.routes.index`, and `truthmark.routes.areas` config paths so valid leases remain writable in non-default documentation layouts. `truthmark check --json` returns: @@ -330,17 +347,17 @@ For normal branches, `identity` is branch name plus HEAD SHA. For detached check ## Compatibility Rules -- `version` remains `1` in the committed config contract. -- `docs.roots.truth` is the configured root for behavior truth docs. +- `version` remains `2` in the committed config contract. +- `truthmark.truth.root`, resolved under `truthmark.workspace`, is the configured root for behavior truth docs. - Repositories refresh generated workflow surfaces through `truthmark init`; removing a platform from config stops future refreshes but does not delete previously generated files. - Truth Realize has no config switch; selected platforms receive its explicit manual workflow surface. -- `truthmark-portal` is an optional namespaced config block. When omitted, normalized `truthmarkPortal` is `{ enabled: false, output: "docs/truthmark-portal", template: "default" }`; an existing block with omitted `enabled` also remains disabled. -- `truthmark-portal.output` and `truthmark-portal.template` must be strings when present. Output must be a non-empty repository-relative directory without absolute or parent traversal segments and must not overlap source roots, instruction targets, `.truthmark/config.yml`, route files, or canonical Markdown roots. Template must be `default` or a non-empty repository-relative path without absolute or parent traversal segments. +- Portal config lives at `truthmark.generated.portal`. Generated defaults include only `enabled: false`; Portal output is derived as `${truthmark.workspace}/generated/portal`, and the Portal template path is derived as `${truthmark.workspace}/templates/portal.html`. +- Custom Portal output and template properties are unsupported. Portal output and template paths are fixed by Truthmark and are not configurable. - There is no `.truthmark/local.yml` compatibility surface in the current implementation. ## Versioning And Migration -- The committed config contract remains `version: 1` until an intentional schema-version migration is implemented. +- The committed config contract is `version: 2` with a required `truthmark.workspace` hierarchy. - Route metadata accepts both legacy Markdown truth-document lists and fenced YAML `truth_documents` arrays for compatibility with existing repositories. - Repositories refresh generated workflow surfaces and templates through `truthmark init`; removing a platform from config stops future refreshes but does not delete previously generated files. - New command data fields should be additive where possible and remain nested under the shared command envelope. @@ -351,15 +368,16 @@ For normal branches, `identity` is branch name plus HEAD SHA. For detached check - The committed config file owns the documentation hierarchy contract, while route files own domain-to-doc mappings. - `truthmark config` and `truthmark init` are separate contracts so repositories can review hierarchy before workflow installation. - Active decisions stay in the canonical doc they govern instead of in separate timestamped decision logs. Date active decisions inline when added or changed. -- The V1 user-facing CLI surface is `config`, `init`, `check`, `index`, `impact`, `context`, and optional helper `validate` subcommands; workflow verbs such as `sync`, `realize`, `structure`, `audit`, `packet`, `review`, `scan`, `doctor`, and `build` are not top-level commands. +- The V1 user-facing CLI surface is `config`, `init`, `check`, `index`, `impact`, `context`, agent-facing `workflow status`, and optional helper `validate` subcommands; workflow execution verbs such as `sync`, `realize`, `structure`, `audit`, `packet`, `review`, `scan`, `doctor`, and `build` are not top-level commands. - `gemini-cli` installs hierarchical `GEMINI.md` context, Agent Skills under `.gemini/skills/`, project-scoped `.gemini/commands/truthmark/*.toml` custom commands, and project subagents under `.gemini/agents/` so Gemini users get explicit workflow entrypoints and bounded delegation without adding top-level CLI verbs. +- Generated public workflow entrypoints, GitHub Copilot prompts, and Gemini commands do not consume a live workflow-instructions contract before acting; `workflow status` is retained for status-only/debug inspection, and support files remain progressive-disclosure fallback references. - Decision (2026-05-14): Truth Realize is manually invoked through installed workflow surfaces and is not controlled by `realization.enabled` or any other config key. ## Rationale Separating config from init keeps repository layout reviewable and predictable. Keeping decisions with the owning behavior, contract, or architecture doc prevents agents from having to infer which historical note is still active. -Keeping workflow verbs out of the CLI preserves the agent-native model: installed skills and instruction blocks run the workflows, while the CLI installs and validates repository artifacts. +Keeping workflow execution verbs out of the CLI preserves the agent-native model: installed skills and instruction blocks run the workflows, while the CLI installs, validates, and exposes bounded machine-readable state/instruction contracts for agents. ## Non-Goals diff --git a/docs/truth/init-and-scaffold.md b/docs/truthmark/truth/init-and-scaffold.md similarity index 73% rename from docs/truth/init-and-scaffold.md rename to docs/truthmark/truth/init-and-scaffold.md index 0bc875a..75a07e5 100644 --- a/docs/truth/init-and-scaffold.md +++ b/docs/truthmark/truth/init-and-scaffold.md @@ -2,20 +2,20 @@ status: active doc_type: behavior truth_kind: behavior -last_reviewed: 2026-05-31 +last_reviewed: 2026-06-01 source_of_truth: - - ../../src/config/defaults.ts - - ../../src/fs/paths.ts - - ../../src/init/init.ts - - ../../src/init/hierarchy.ts - - ../../src/templates/init-files.ts - - ../../src/templates/agents-block.ts - - ../../src/agents/workflow-manifest.ts - - ../../src/agents/workflow-helper-validation.ts - - ../../src/cli/program.ts - - ../../src/cli/handlers.ts - - ../../src/templates/workflow-surfaces.ts - - ../../src/templates/generated-surfaces.ts + - ../../../src/config/defaults.ts + - ../../../src/fs/paths.ts + - ../../../src/init/init.ts + - ../../../src/init/hierarchy.ts + - ../../../src/templates/init-files.ts + - ../../../src/templates/agents-block.ts + - ../../../src/agents/workflow-manifest.ts + - ../../../src/agents/workflow-helper-validation.ts + - ../../../src/cli/program.ts + - ../../../src/cli/handlers.ts + - ../../../src/templates/workflow-surfaces.ts + - ../../../src/templates/generated-surfaces.ts --- # Init And Scaffold @@ -42,46 +42,43 @@ This document owns the current setup and scaffold behavior for `truthmark config 6. writes or refreshes configured instruction targets and configured platform surfaces 7. rewrites managed Truthmark instruction blocks while preserving manual content outside those blocks 8. writes generated skill surfaces for configured skill-based platforms -9. reports migration risks instead of moving existing truth docs when hierarchy changes imply manual migration -10. reports each touched file as `created`, `updated`, or `unchanged` +9. reports each touched file as `created`, `updated`, or `unchanged` ## Core Rules Current scaffold targets: - `.truthmark/config.yml` via `truthmark config` -- [docs/truthmark/areas.md](../truthmark/areas.md) -- configured child route files referenced by the root route index under `docs/truthmark/areas/**/*.md` -- configured truth-root README files such as `docs/truth/README.md` -- configured default-area index README files such as `docs/truth/repository/README.md` -- [docs/templates/behavior-doc.md](../templates/behavior-doc.md) -- [docs/templates/contract-doc.md](../templates/contract-doc.md) -- [docs/templates/architecture-doc.md](../templates/architecture-doc.md) -- [docs/templates/workflow-doc.md](../templates/workflow-doc.md) -- [docs/templates/operations-doc.md](../templates/operations-doc.md) -- [docs/templates/test-behavior-doc.md](../templates/test-behavior-doc.md) -- configured default-area bounded leaf truth docs such as `docs/truth/repository/overview.md` -- [docs/standards/default-principles.md](../standards/default-principles.md) -- [docs/standards/documentation-governance.md](../standards/documentation-governance.md) -- the managed block inside [AGENTS.md](../../AGENTS.md) -- [CLAUDE.md](../../CLAUDE.md) -- `.codex/skills/truthmark-structure/SKILL.md` -- `.codex/skills/truthmark-structure/agents/openai.yaml` -- `.codex/skills/truthmark-document/SKILL.md` -- `.codex/skills/truthmark-document/agents/openai.yaml` -- `.codex/skills/truthmark-sync/SKILL.md` -- `.codex/skills/truthmark-sync/agents/openai.yaml` -- `.codex/skills/truthmark-realize/SKILL.md` -- `.codex/skills/truthmark-realize/agents/openai.yaml` -- `.codex/skills/truthmark-check/SKILL.md` -- `.codex/skills/truthmark-check/agents/openai.yaml` -- `.codex/skills/truthmark-preview/SKILL.md` -- `.codex/skills/truthmark-preview/agents/openai.yaml` -- `.codex/skills/truthmark-*/support/procedure.md` -- `.codex/skills/truthmark-*/support/report-template.md` -- `.codex/skills/truthmark-*/support/subagents-and-leases.md` when the workflow has generated subagent guidance -- `.codex/skills/truthmark-*/helper-manifest.yml` when the workflow declares helpers -- `.codex/skills/truthmark-*/support/helper-policy.md` when the workflow declares helpers +- [docs/truthmark/routes/areas.md](../routes/areas.md) +- configured child route files referenced by the root route index under `docs/truthmark/routes/areas/**/*.md` +- configured truth-root README files such as `docs/truthmark/truth/README.md` +- configured default-area index README files such as `docs/truthmark/truth/repository/README.md` +- [docs/truthmark/templates/behavior-doc.md](../templates/behavior-doc.md) +- [docs/truthmark/templates/contract-doc.md](../templates/contract-doc.md) +- [docs/truthmark/templates/architecture-doc.md](../templates/architecture-doc.md) +- [docs/truthmark/templates/workflow-doc.md](../templates/workflow-doc.md) +- [docs/truthmark/templates/operations-doc.md](../templates/operations-doc.md) +- [docs/truthmark/templates/test-behavior-doc.md](../templates/test-behavior-doc.md) +- configured default-area bounded leaf truth docs such as `docs/truthmark/truth/repository/overview.md` +- the managed block inside [AGENTS.md](../../../AGENTS.md) +- [CLAUDE.md](../../../CLAUDE.md) +- `.agents/skills/truthmark-structure/SKILL.md` +- `.agents/skills/truthmark-structure/agents/openai.yaml` +- `.agents/skills/truthmark-document/SKILL.md` +- `.agents/skills/truthmark-document/agents/openai.yaml` +- `.agents/skills/truthmark-sync/SKILL.md` +- `.agents/skills/truthmark-sync/agents/openai.yaml` +- `.agents/skills/truthmark-realize/SKILL.md` +- `.agents/skills/truthmark-realize/agents/openai.yaml` +- `.agents/skills/truthmark-check/SKILL.md` +- `.agents/skills/truthmark-check/agents/openai.yaml` +- `.agents/skills/truthmark-preview/SKILL.md` +- `.agents/skills/truthmark-preview/agents/openai.yaml` +- `.agents/skills/truthmark-*/support/procedure.md` +- `.agents/skills/truthmark-*/support/report-template.md` +- `.agents/skills/truthmark-*/support/subagents-and-leases.md` when the workflow has generated subagent guidance +- `.agents/skills/truthmark-*/helper-manifest.yml` when the workflow declares helpers +- `.agents/skills/truthmark-*/support/helper-policy.md` when the workflow declares helpers - `.codex/agents/truth-route-auditor.toml` - `.codex/agents/truth-claim-verifier.toml` - `.codex/agents/truth-doc-reviewer.toml` @@ -133,10 +130,10 @@ Current scaffold targets: - `.github/prompts/truthmark-realize.prompt.md` - `.github/prompts/truthmark-check.prompt.md` - `.github/prompts/truthmark-preview.prompt.md` -- `.github/agents/truth-route-auditor.agent.md` -- `.github/agents/truth-claim-verifier.agent.md` -- `.github/agents/truth-doc-reviewer.agent.md` -- `.github/agents/truth-doc-writer.agent.md` +- `.github/agents/truth-route-auditor.md` +- `.github/agents/truth-claim-verifier.md` +- `.github/agents/truth-doc-reviewer.md` +- `.github/agents/truth-doc-writer.md` - `GEMINI.md` - `.gemini/skills/truthmark-structure/SKILL.md` - `.gemini/skills/truthmark-document/SKILL.md` @@ -164,19 +161,17 @@ Current scaffold targets: `instruction_targets` controls shared managed-instruction files such as `AGENTS.md`. These targets are written or refreshed whenever `truthmark init` runs with a valid config, independent of the configured platform list. `platforms` controls which platform-specific surfaces are written or refreshed. Defaults include all supported platforms: `codex`, `opencode`, `claude-code`, `github-copilot`, and `gemini-cli`. Teams should remove unused platforms from `.truthmark/config.yml` before rerunning `truthmark init`. Claude Code installs `CLAUDE.md`, project skills under `.claude/skills/`, and verifier plus leased doc-writer subagents under `.claude/agents/`; skills surface as `/truthmark-structure`, `/truthmark-document`, `/truthmark-sync`, `/truthmark-preview`, `/truthmark-realize`, and `/truthmark-check`, plus `/truthmark-portal` when Portal is enabled, while the generated project subagents provide bounded evidence checks and parent-leased truth-doc writes. GitHub Copilot installs `.github/copilot-instructions.md`, agent skills under `.github/skills/`, prompt files under `.github/prompts/`, and verifier plus leased doc-writer custom agents under `.github/agents/`; prompts and skills surface as `/truthmark-structure`, `/truthmark-document`, `/truthmark-sync`, `/truthmark-preview`, `/truthmark-realize`, and `/truthmark-check`, plus `/truthmark-portal` when Portal is enabled, in supported Copilot IDEs, while Copilot CLI can dispatch the generated `@truth-*` custom agents for bounded evidence checks or parent-leased doc shards. Gemini installs `GEMINI.md`, Agent Skills under `.gemini/skills/`, project-scoped TOML commands under `.gemini/commands/truthmark/`, and project subagents under `.gemini/agents/`; commands surface as `/truthmark:structure`, `/truthmark:document`, `/truthmark:sync`, `/truthmark:preview`, `/truthmark:realize`, and `/truthmark:check`, plus `/truthmark:portal` when Portal is enabled, in Gemini CLI and append `User focus or arguments: {{args}}` near the end of each TOML prompt. Unknown platform names are config errors. Removing a platform stops future refreshes for that platform, but `init` does not delete previously generated files. -`ensureRepoFile` is intentionally conservative: existing non-empty scaffold files are left alone unless the file is one of Truthmark's managed update surfaces. Managed update surfaces include instruction blocks, generated workflow assets, and truth-doc templates under `docs/templates/*.md`; template reruns refresh Truthmark-owned default sections while preserving project-specific custom sections and their authored order. +`ensureRepoFile` is intentionally conservative: existing non-empty scaffold files are left alone unless the file is one of Truthmark's managed update surfaces. Managed update surfaces include instruction blocks, generated workflow assets, and truth-doc templates under `docs/truthmark/templates/*.md`; template reruns refresh Truthmark-owned default sections while preserving project-specific custom sections and their authored order. The generated Truth Structure, Truth Document, Truth Sync, Truth Preview, Truth Realize, and Truth Check explicit surfaces are also managed by Truthmark and may be refreshed on rerun so the Codex skills, metadata, Claude Code project skills, GitHub Copilot skills/prompts/custom agents, Gemini skills/commands/subagents, and OpenCode skills keep matching the installed workflow contract. Generated skill packages keep `SKILL.md` compact and write heavy procedure, report-template, and subagent or lease reference material into sibling `support/*.md` files. Optional helper manifests and helper policy files are emitted only for workflows that declare helpers and only for configured skill-package platforms; helper manifests invoke installed Truthmark CLI validators such as `truthmark validate sync-report --json`, `truthmark validate document-report --json`, and `truthmark validate write-lease --json`. Generated packages do not bundle repo-local `scripts/*.mjs` helper copies. GitHub Copilot prompts and Gemini commands remain standalone entrypoints; their report examples mark helper packages unavailable unless the matching generated skill package is being used. Generated skills, support files, Codex metadata, Copilot prompt files, Copilot custom-agent files, Gemini command files, Gemini subagent files, and managed instruction blocks include the Truthmark package version that rendered them; `package.json` is the single maintained version source. After upgrading Truthmark, rerun `truthmark init` and review generated workflow diffs. -Truthmark Portal surfaces are managed by the same renderer only when normalized `truthmarkPortal.enabled` is `true`. When disabled or omitted, init emits no Portal skills, prompts, commands, or managed-instruction mention. +Truthmark Portal surfaces are managed by the same renderer only when normalized `truthmark.generated.portal.enabled` is `true`. When disabled, init emits no Portal skills, prompts, commands, or managed-instruction mention. The current managed-instruction update behavior is: - replace an existing managed Truthmark block when it is well formed -- remove older managed-looking chunks when possible +- remove malformed or duplicated managed blocks when they use the current Truthmark markers or current managed-block content - preserve manual text outside the managed block -- normalize the known legacy `Codex` preamble wording to host-neutral agent wording when refreshing an instruction file -- normalize legacy unconditional docs-map and onboarding preamble lines to conditional reads so normal sessions do not load routing docs before they are needed - append the managed block when no block exists - keep the generated workflow block as a compact automatic-Sync trigger and boundary index so it does not consume unnecessary model context in long legacy instruction files - keep detailed report examples, platform-specific invocation strings, and long workflow procedure in explicit generated skill support files or standalone prompt and command files instead of host instruction blocks @@ -188,29 +183,30 @@ Truthmark does not create `OPENCODE.md` in V1. OpenCode-compatible behavior is i Hierarchy is configured in `.truthmark/config.yml`: -- `docs.layout` is currently `hierarchical` -- `docs.roots` names the canonical doc roots and partial root maps are merged over current defaults -- `docs.routing.root_index` is the root route index path -- `docs.routing.area_files_root` is the directory for child route files -- `docs.routing.default_area` is the initial scaffolded child route basename -- `docs.routing.max_delegation_depth` must currently be `1` +- `truthmark.workspace` is the workspace root for Truthmark-owned routing, truth, templates, and generated output +- `truthmark.routes.index` is the route index path relative to the workspace +- `truthmark.routes.areas` is the directory for child route files relative to the workspace +- `truthmark.routes.default_area` is the initial scaffolded child route basename +- `truthmark.routes.max_delegation_depth` must currently be `1` +- `truthmark.truth.root` is the truth-doc root relative to the workspace +- `truthmark.templates.root` is the template root relative to the workspace -`truthmark init` creates missing structure for that hierarchy, but child route files stay governed by the root route index: if an authored non-empty root index no longer delegates the configured default child route, rerunning init does not recreate that unreferenced child route. Init does not silently move, delete, or reinterpret existing truth docs when teams change the configured roots. Those cases produce review diagnostics for manual migration. +`truthmark init` creates missing structure for that hierarchy, but child route files stay governed by the root route index: if an authored non-empty root index no longer delegates the configured default child route, rerunning init does not recreate that unreferenced child route. Init does not silently move, delete, reinterpret, or emit compatibility diagnostics for legacy truth-doc placement when teams change the configured roots. The default scaffold treats truth `README.md` files as indexes. Current behavior truth belongs in bounded leaf docs under the configured truth root, such as `//.md`. -`truthmark init` creates [docs/templates/behavior-doc.md](../templates/behavior-doc.md) when it is missing or empty and refreshes all six templates under `docs/templates/*.md` on rerun. Template refreshes replace Truthmark-owned default sections with the current professional guidance baseline, including evidence, boundary, current-state, contract, operational, verification, decision, rationale, non-goal, and maintenance prompts. Existing template preambles/frontmatter are preserved so repository-owned metadata, custom titles, source-of-truth defaults, and local introductory guidance do not churn during section refresh. Project-specific custom `##` sections are preserved and reinserted before the next default section that followed them in the authored file; trailing custom sections remain trailing. Fenced code blocks are ignored while finding `##` template sections, so examples can contain Markdown headings without being split or mistaken for Truthmark-owned sections. The default child route references the seeded leaf truth doc with fenced YAML `truth_documents` metadata and `kind: behavior` rather than relying on path inference. +`truthmark init` creates [docs/truthmark/templates/behavior-doc.md](../templates/behavior-doc.md) when it is missing or empty and refreshes all six templates under `docs/truthmark/templates/*.md` on rerun. Template refreshes replace Truthmark-owned default sections with the current professional guidance baseline, including evidence, boundary, current-state, contract, operational, verification, decision, rationale, non-goal, and maintenance prompts. Existing template preambles/frontmatter are preserved so repository-owned metadata, custom titles, source-of-truth defaults, and local introductory guidance do not churn during section refresh. Project-specific custom `##` sections are preserved and reinserted before the next default section that followed them in the authored file; trailing custom sections remain trailing. Fenced code blocks are ignored while finding `##` template sections, so examples can contain Markdown headings without being split or mistaken for Truthmark-owned sections. The default child route references the seeded leaf truth doc with fenced YAML `truth_documents` metadata and `kind: behavior` rather than relying on path inference. When creating the default bounded behavior truth doc, init reads the repository's merged behavior template and expands supported placeholders such as `{{title}}`, `{{area}}`, `{{source_of_truth}}`, `{{purpose}}`, `{{scope}}`, `{{current_behavior}}`, `{{core_rules}}`, `{{flows_and_states}}`, `{{contracts}}`, `{{decision}}`, `{{rationale}}`, `{{non_goals}}`, `{{maintenance_notes}}`, and `{{template_path}}`. The seeded leaf uses `doc_type: behavior` and `truth_kind: behavior`. Existing non-empty truth docs are preserved; existing template files are merged rather than blindly overwritten so teams can keep local truth-doc standard sections while receiving updated default guidance. Important current defaults: - default authority includes the canonical doc classes under `docs/` - default code surface in the scaffolded root and child route files starts as `src/**` -- default truth scaffolding creates an index at `/README.md`, an index at `//README.md`, six editable and refreshable templates under `docs/templates/*.md`, and a bounded leaf truth doc at `//overview.md` routed through explicit `{ path, kind }` metadata +- default truth scaffolding creates an index at `/README.md`, an index at `//README.md`, six editable and refreshable templates under `docs/truthmark/templates/*.md`, and a bounded leaf truth doc at `//overview.md` routed through explicit `{ path, kind }` metadata - default platforms are `codex`, `opencode`, `claude-code`, `github-copilot`, and `gemini-cli` - shared instruction targets are refreshed independently of platform-specific surfaces - explicit Truth Structure, Truth Document, Truth Sync, Truth Preview, Truth Realize, and Truth Check surfaces are installed only for configured platforms -- Truthmark Portal defaults to disabled; when enabled, Portal surfaces are installed only for configured platforms and use configured output/template values in generated guidance +- Truthmark Portal defaults to disabled; when enabled, Portal surfaces are installed only for configured platforms and use Truthmark-derived output/template paths in generated guidance - installed workflows are agent-native; generated skills tell agents to inspect the checkout directly -- Codex platform generation includes `.codex/agents/*.toml`, Claude Code platform generation includes `.claude/agents/*.md`, GitHub Copilot platform generation includes `.github/agents/*.agent.md`, Gemini CLI platform generation includes `.gemini/agents/*.md`, and OpenCode platform generation includes `.opencode/agents/*.md` read-only verifier agents plus `truth-doc-writer` for parent-leased Truth Sync and Truth Document shards; the acting parent agent may use them automatically when the host supports subagent dispatch, and read-only verifier agents are context-bounded so they do not preload repo-wide instruction or policy docs unless assigned as evidence +- Codex platform generation includes `.codex/agents/*.toml`, Claude Code platform generation includes `.claude/agents/*.md`, GitHub Copilot platform generation includes `.github/agents/*.md`, Gemini CLI platform generation includes `.gemini/agents/*.md`, and OpenCode platform generation includes `.opencode/agents/*.md` read-only verifier agents plus `truth-doc-writer` for parent-leased Truth Sync and Truth Document shards; the acting parent agent may use them automatically when the host supports subagent dispatch, and read-only verifier agents are context-bounded so they do not preload repo-wide instruction or policy docs unless assigned as evidence - managed instruction blocks include only compact hierarchy, decision-truth, automatic-Sync trigger, boundary reminders, and a pointer to explicit workflows; generated skill entrypoints carry invocation strings and link to support files for detailed workflow bodies - generated workflow surfaces must not demote configured repository instruction docs or optional project-local policy docs when warning agents that product truth cannot override workflow write boundaries; project-local policy docs are not universal Truthmark product files and generated wording must stay generic and config-driven - scaffolded default standards include AI-native topology repair guidance and an architecture-vs-behavior boundary so new repositories do not rely on human folder discipline @@ -222,7 +218,7 @@ Important current defaults: - all generated paths must remain inside the active repository root - generated path containment must reject symlinks that resolve outside the repository, including broken symlink leaves that would otherwise be created outside the worktree -- init must be idempotent for existing non-empty scaffold files except for managed update surfaces such as instruction blocks, generated workflow assets, and merged `docs/templates/*.md` default sections +- init must be idempotent for existing non-empty scaffold files except for managed update surfaces such as instruction blocks, generated workflow assets, and merged `docs/truthmark/templates/*.md` default sections - the command should remain safe to run repeatedly in the same repository ## Flows And States @@ -231,8 +227,8 @@ The setup flow is: 1. `truthmark config` writes or prints the repository configuration. 2. `truthmark init` requires an existing valid config and resolves the active Git worktree. -3. Init creates missing configured routing, truth-root, default-area, standards, template, and generated workflow surfaces. -4. Init refreshes managed surfaces that Truthmark owns, including managed instruction blocks, generated host workflow assets, and default sections in `docs/templates/*.md`. +3. Init creates missing configured routing, truth-root, default-area, template, and generated workflow surfaces. +4. Init refreshes managed surfaces that Truthmark owns, including managed instruction blocks, generated host workflow assets, and default sections in `docs/truthmark/templates/*.md`. 5. Init preserves repository-authored content outside managed blocks and preserves template preambles/frontmatter plus custom template sections when refreshing default template sections. 6. Init reports every created, updated, or unchanged surface as an action diagnostic in the shared command envelope. @@ -242,22 +238,23 @@ Current init JSON reporting uses: - `truth-sync` for the managed `AGENTS.md` block and generated Truth Structure, Truth Document, Truth Sync, Truth Preview, and Truth Check assets - `realization` for generated Truth Realize assets -- `authority` for [docs/truthmark/areas.md](../truthmark/areas.md) +- `area-index` for [docs/truthmark/routes/areas.md](../routes/areas.md) - `config` for the remaining scaffolded files -`truthmark config --json` and `truthmark init --json` use the shared command-result envelope described in [contracts.md](contracts.md). `truthmark init` requires a valid config and does not silently migrate existing truth-doc placement. +`truthmark config --json` and `truthmark init --json` use the shared command-result envelope described in [contracts.md](contracts.md). `truthmark init` requires a valid config and does not silently migrate or compatibility-review legacy truth-doc placement. ## Product Decisions - `truthmark config` owns the committed layout contract and must happen before `truthmark init`. - Hierarchical routing is the only scaffold model, and route ownership stays in Markdown route files rather than config. -- Init reports migration risk instead of rewriting existing truth doc placement on the user's behalf. +- Init uses the configured Truthmark hierarchy directly and does not run legacy hierarchy migration diagnostics. +- Decision (2026-05-31): Init no longer normalizes legacy instruction preambles or treats old managed-line fragments as Truthmark-owned cleanup input; only current managed markers and current managed-block content are eligible for automatic managed-block repair. - V1 uses configured shared instruction targets such as `AGENTS.md` plus generated skill or command surfaces for host compatibility instead of creating host-specific top-level instruction files for every adapter. - Managed instruction blocks are compact automatic-Sync indexes; generated skill support files, prompt files, and command files own explicit workflow procedure. - Decision (2026-05-15): Repository instruction preambles make docs-map and onboarding reads conditional, and managed instruction blocks omit platform-specific workflow invocation strings so ordinary sessions load less context. - Decision (2026-05-13): `.truthmark/config.yml` and route files are the committed hierarchy contract, so init no longer creates a low-value top-level note. -- Decision (2026-05-14): Truth-doc templates are kind-specific under `docs/templates/*.md`; `docs/templates/behavior-doc.md` is the default bounded behavior template and the other five typed templates carry kind-specific required sections. -- Decision (2026-05-30): `truthmark init` refreshes Truthmark-owned default sections in existing `docs/templates/*.md` files while preserving project-specific custom `##` sections and their authored relative order. +- Decision (2026-05-14): Truth-doc templates are kind-specific under `docs/truthmark/templates/*.md`; `docs/truthmark/templates/behavior-doc.md` is the default bounded behavior template and the other five typed templates carry kind-specific required sections. +- Decision (2026-05-30): `truthmark init` refreshes Truthmark-owned default sections in existing `docs/truthmark/templates/*.md` files while preserving project-specific custom `##` sections and their authored relative order. - Decision (2026-05-14): Truth Realize stays manual-only through explicit generated surfaces and is no longer configurable with `realization.enabled`. - Decision (2026-05-13): Default standards define architecture docs as structure and ownership truth, not a place for ordinary product behavior. @@ -267,7 +264,7 @@ This split makes the hierarchy reviewable before generated workflow behavior lan Keeping host-specific detail in generated skills and Gemini command files prevents the repository root from accumulating parallel instruction files that drift from the managed workflow contract. Keeping managed blocks terse protects ordinary agent context while preserving the automatic Sync gate, workflow boundaries, and branch-local authority. Conditional docs-map and onboarding reads keep routing guidance available without forcing every normal session to load it. -Keeping typed truth-doc templates in `docs/templates/` gives repository owners one local standard surface per truth kind while keeping generated workflow text compact as more workflow surfaces are added. Refreshing default template sections on `truthmark init` keeps those local standard surfaces aligned with current professional guidance, while preserving custom sections prevents product-specific review gates from being erased by package upgrades. +Keeping typed truth-doc templates in `docs/truthmark/templates/` gives repository owners one local standard surface per truth kind while keeping generated workflow text compact as more workflow surfaces are added. Refreshing default template sections on `truthmark init` keeps those local standard surfaces aligned with current professional guidance, while preserving custom sections prevents product-specific review gates from being erased by package upgrades. ## Non-Goals diff --git a/docs/truth/release/README.md b/docs/truthmark/truth/release/README.md similarity index 87% rename from docs/truth/release/README.md rename to docs/truthmark/truth/release/README.md index 870dd69..3f1b310 100644 --- a/docs/truth/release/README.md +++ b/docs/truthmark/truth/release/README.md @@ -3,7 +3,7 @@ status: active doc_type: index last_reviewed: 2026-05-13 source_of_truth: - - ../../truthmark/areas/release-automation.md + - ../../routes/areas/release-automation.md --- # Release Truth Docs diff --git a/docs/truth/release/automation.md b/docs/truthmark/truth/release/automation.md similarity index 96% rename from docs/truth/release/automation.md rename to docs/truthmark/truth/release/automation.md index e30142a..90894c7 100644 --- a/docs/truth/release/automation.md +++ b/docs/truthmark/truth/release/automation.md @@ -4,9 +4,9 @@ doc_type: behavior truth_kind: workflow last_reviewed: 2026-05-31 source_of_truth: - - ../../truthmark/areas/release-automation.md - - ../../../.github/workflows/ci.yml - - ../../../.github/workflows/publish.yml + - ../../routes/areas/release-automation.md + - ../../../../.github/workflows/ci.yml + - ../../../../.github/workflows/publish.yml --- # Release Automation diff --git a/docs/truth/repository/README.md b/docs/truthmark/truth/repository/README.md similarity index 64% rename from docs/truth/repository/README.md rename to docs/truthmark/truth/repository/README.md index 42701f9..8669351 100644 --- a/docs/truth/repository/README.md +++ b/docs/truthmark/truth/repository/README.md @@ -3,7 +3,7 @@ status: active doc_type: index last_reviewed: 2026-05-13 source_of_truth: - - ../../truthmark/areas/init-and-scaffold.md + - ../../routes/areas/init-and-scaffold.md --- # Repository Truth Docs @@ -15,3 +15,7 @@ README.md files are indexes, not Truth Sync targets. Keep behavior truth in boun Current leaf docs: - [Overview](overview.md) +- [Context Pack](context-pack.md) +- [Impact Set](impact-set.md) +- [Repo Index](repo-index.md) +- [Workflow State](workflow-state.md) diff --git a/docs/truthmark/truth/repository/context-pack.md b/docs/truthmark/truth/repository/context-pack.md new file mode 100644 index 0000000..6c4e8e6 --- /dev/null +++ b/docs/truthmark/truth/repository/context-pack.md @@ -0,0 +1,74 @@ +--- +status: active +doc_type: behavior +truth_kind: behavior +last_reviewed: 2026-06-01 +source_of_truth: + - ../../../../src/context-pack/build.ts + - ../../../../src/context-pack/render.ts + - ../../../../src/impact/build.ts +--- + +# ContextPack + +## Purpose + +This document protects ContextPack v0 as a bounded, derived workflow-context artifact for Truth Sync, Truth Document, and Truth Realize. + +## Scope + +This document owns ContextPack v0 behavior for Truth Sync, Truth Document, and Truth Realize workflows. + +## Current Behavior + +`truthmark context --workflow [--base ]` generates a bounded context artifact for a workflow and renders deterministic Markdown by default. When `--json` is used, the JSON envelope returns only `data.markdown` plus `data.summary` and does not include the full content-bearing `data.contextPack`. `--format json` returns a `context-pack` error diagnostic because JSON ContextPack output was removed in v2. ContextPack rejects other unsupported `--format` values with a `context-pack` error diagnostic. ContextPack includes route ownership, affected truth docs, selected source files, related tests, warnings, and allowed write paths in its internal markdown-rendering model. Truth docs and source files over 200 lines are truncated to the first 80 lines and last 40 lines with an explicit `truncated: true` marker and a review warning before markdown rendering. + +The internal ContextPack model includes `schemaVersion: context-pack/v0`. It is generated from the active checkout and, when a base ref is supplied, ImpactSet. + +## Core Rules + +- ContextPack is optional generated context and does not replace direct checkout inspection. +- ContextPack write paths restate workflow boundaries; they do not create new permissions. +- Truth Sync and Truth Document write paths include the active configured route index and selected truth docs, including non-default workspace layouts. Truth Realize write paths include the matched route code surfaces because Realize may write functional code but not truth docs or routing. +- If `.truthmark/config.yml` exists but is invalid, ContextPack includes config diagnostics as warnings and leaves `allowedWritePaths` empty instead of falling back to default write paths. +- Truth Realize without `--base` cannot infer matched code surfaces, so selected truth docs, source files, and `allowedWritePaths` are empty and ContextPack emits a review warning instead of widening to every route. +- Source files include changed files from ImpactSet when a base ref is supplied and `source_of_truth` references from selected truth docs. Glob references are expanded against the checkout. Selected truth docs and source files are content-bounded before markdown rendering. +- ContextPack-only text is not evidence. Generated docs must cite checkout files, route files, truth docs, tests, schemas, or explicit evidence blocks. +- If ContextPack conflicts with the current checkout, the checkout wins. + +## Flows And States + +`truthmark context` resolves route ownership, affected truth docs, selected source files, related tests, and write-boundary guidance from the active checkout, applies deterministic content bounds to included truth docs and source files, then renders deterministic Markdown for the selected workflow. Agents use the artifact as reviewable context and still inspect the checkout directly before acting. + +## Contracts + +`truthmark context --workflow [--base ] --json` returns the shared command envelope with rendered Markdown in `data.markdown` plus `data.summary`; it never returns `data.contextPack`, `truthDocs[*].content`, or `sourceFiles[*].content`. `--format markdown` renders deterministic Markdown. `--format json` and other unsupported formats produce a `context-pack` error diagnostic. + +## Product Decisions + +- Decision (2026-05-16): ContextPack v0 is a bounded review artifact, not memory and not a source of authority. +- Decision (2026-05-16): No-CLI workflow execution remains supported, but with weaker automation and explicit reporting. +- Decision (2026-06-01): Invalid config must not grant default write paths in ContextPack; missing config may still use the default fallback where supported. +- Decision (2026-06-12): Public JSON ContextPack output was removed in v2; `truthmark context --json` returns markdown-only command data, and `--format json` is rejected. + +## Rationale + +ContextPack makes agent context auditable without making hidden retrieval or stale generated artifacts authoritative. Keeping it derived prevents a fast path from changing ownership or write behavior. + +## Non-Goals + +- ContextPack is not repository authority. +- ContextPack does not grant permissions beyond installed workflow boundaries. +- ContextPack does not replace direct checkout inspection. + +## Maintenance Notes + +ContextPack requires the Truthmark CLI or an equivalent local runner. If unavailable, agents must follow the installed workflow manually by reading route files, truth docs, source files, and tests directly. Completion reports must say ContextPack was not generated. + +Primary implementation files: + +- `src/context-pack/build.ts` +- `src/context-pack/render.ts` +- `src/impact/build.ts` + +Update this doc when the command output, schema version, derived inputs, fallback behavior, or workflow relationship changes. diff --git a/docs/truth/repository/impact-set.md b/docs/truthmark/truth/repository/impact-set.md similarity index 97% rename from docs/truth/repository/impact-set.md rename to docs/truthmark/truth/repository/impact-set.md index d99de80..ffb171a 100644 --- a/docs/truth/repository/impact-set.md +++ b/docs/truthmark/truth/repository/impact-set.md @@ -4,9 +4,9 @@ doc_type: behavior truth_kind: behavior last_reviewed: 2026-05-16 source_of_truth: - - ../../../src/impact/build.ts - - ../../../src/impact/git-diff.ts - - ../../../src/repo-index/build.ts + - ../../../../src/impact/build.ts + - ../../../../src/impact/git-diff.ts + - ../../../../src/repo-index/build.ts --- # ImpactSet diff --git a/docs/truth/repository/overview.md b/docs/truthmark/truth/repository/overview.md similarity index 66% rename from docs/truth/repository/overview.md rename to docs/truthmark/truth/repository/overview.md index 0b7a7b0..8b0bc20 100644 --- a/docs/truth/repository/overview.md +++ b/docs/truthmark/truth/repository/overview.md @@ -2,11 +2,11 @@ status: active doc_type: behavior truth_kind: behavior -last_reviewed: 2026-05-14 +last_reviewed: 2026-06-01 source_of_truth: - - ../../truthmark/areas/init-and-scaffold.md - - ../../../src/init/init.ts - - ../../../src/templates/init-files.ts + - ../../routes/areas/init-and-scaffold.md + - ../../../../src/init/init.ts + - ../../../../src/templates/init-files.ts --- # Repository Overview @@ -17,12 +17,12 @@ This doc owns the default bounded behavior leaf that `truthmark init` scaffolds ## Scope -This doc covers the seed `docs/truth/repository/overview.md` behavior only. Broader init flow, routing files, and generated workflow surfaces stay in the main scaffold and workflow docs. +This doc covers the seed `docs/truthmark/truth/repository/overview.md` behavior only. Broader init flow, routing files, and generated workflow surfaces stay in the main scaffold and workflow docs. ## Current Behavior -- `truthmark init` creates `docs/truth/repository/overview.md` as the default bounded behavior truth doc for the configured default area. -- The scaffold pairs this leaf doc with a sibling `README.md` index under `docs/truth/repository/`. +- `truthmark init` creates `docs/truthmark/truth/repository/overview.md` as the default bounded behavior truth doc for the configured default area. +- The scaffold pairs this leaf doc with a sibling `README.md` index under `docs/truthmark/truth/repository/`. - The generated content is starter truth. Repositories are expected to replace it with repository-specific current behavior as their mapped code surface evolves. ## Core Rules @@ -38,8 +38,8 @@ This doc covers the seed `docs/truth/repository/overview.md` behavior only. Broa ## Contracts -- The default leaf path is `docs/truth//overview.md` when the configured truth root is `docs/truth` and the default area is `repository`. -- The editable content standard for this leaf comes from `docs/templates/behavior-doc.md`. +- The default leaf path is `docs/truthmark/truth//overview.md` when the configured workspace is `docs/truthmark`, the truth root is `truth`, and the default area is `repository`. +- The editable content standard for this leaf comes from `docs/truthmark/templates/behavior-doc.md`. ## Product Decisions @@ -56,5 +56,5 @@ Bounded seed docs give new repositories an immediately routeable truth target wh ## Maintenance Notes -- Keep this doc aligned with `docs/templates/behavior-doc.md` when the behavior-doc standard changes. +- Keep this doc aligned with `docs/truthmark/templates/behavior-doc.md` when the behavior-doc standard changes. - Update this doc when the default area leaf path or seeded content rules change. diff --git a/docs/truth/repository/repo-index.md b/docs/truthmark/truth/repository/repo-index.md similarity index 91% rename from docs/truth/repository/repo-index.md rename to docs/truthmark/truth/repository/repo-index.md index c4a329d..3ac2a5f 100644 --- a/docs/truth/repository/repo-index.md +++ b/docs/truthmark/truth/repository/repo-index.md @@ -4,10 +4,10 @@ doc_type: behavior truth_kind: behavior last_reviewed: 2026-05-16 source_of_truth: - - ../../../src/repo-index/build.ts - - ../../../src/repo-index/file-tree.ts - - ../../../src/repo-index/route-map.ts - - ../../../src/repo-index/types.ts + - ../../../../src/repo-index/build.ts + - ../../../../src/repo-index/file-tree.ts + - ../../../../src/repo-index/route-map.ts + - ../../../../src/repo-index/types.ts --- # RepoIndex @@ -24,7 +24,7 @@ This document owns RepoIndex v0 and RouteMap v0 behavior. RepoIndex describes th `truthmark index --json` builds a deterministic repository index from the active checkout. The command reads local files and Git metadata only. It does not start a daemon, call a remote service, use a model, or write generated artifacts by default. -RepoIndex output includes `schemaVersion: repo-index/v0`. RouteMap output includes `schemaVersion: route-map/v0` and is derived from `.truthmark/config.yml`, `docs/truthmark/areas.md`, and `docs/truthmark/areas/**/*.md`. +RepoIndex output includes `schemaVersion: repo-index/v0`. RouteMap output includes `schemaVersion: route-map/v0` and is derived from `.truthmark/config.yml`, `docs/truthmark/routes/areas.md`, and `docs/truthmark/routes/areas/**/*.md`. ## Core Rules @@ -47,7 +47,7 @@ RepoIndex output includes `schemaVersion: repo-index/v0`. RouteMap output includ ## Product Decisions - Decision (2026-05-16): RepoIndex v0 is a local deterministic acceleration layer, not a source of truth. -- Decision (2026-05-16): RouteMap v0 is aligned to `docs/truthmark/areas.md` instead of introducing a parallel ownership schema. +- Decision (2026-05-16): RouteMap v0 is aligned to `docs/truthmark/routes/areas.md` instead of introducing a parallel ownership schema. ## Rationale diff --git a/docs/truthmark/truth/repository/workflow-state.md b/docs/truthmark/truth/repository/workflow-state.md new file mode 100644 index 0000000..d6af72d --- /dev/null +++ b/docs/truthmark/truth/repository/workflow-state.md @@ -0,0 +1,85 @@ +--- +status: active +doc_type: behavior +truth_kind: behavior +last_reviewed: 2026-06-12 +source_of_truth: + - ../../../../src/workflow-state/types.ts + - ../../../../src/workflow-state/action-context.ts + - ../../../../src/workflow-state/build.ts + - ../../../../tests/workflow-state/build.test.ts + - ../../../../tests/cli/check-workflow.test.ts +--- + +# WorkflowState + +## Purpose + +This document protects WorkflowState v0 as the derived workflow-state artifact used to summarize whether a Truthmark workflow is safe to run and which bounded action context applies. + +## Scope + +This document owns the WorkflowState contract and builder behavior under `src/workflow-state/**`. It hands lower-level repository facts to RepoIndex, ImpactSet, config, and Truthmark Check, and it hands installed workflow policy text to generated workflow surfaces through the manifest and renderer layers. + +## Current Behavior + +`buildWorkflowState(cwd, { workflow, base })` returns `schemaVersion: truthmark-workflow/v0` with a full manifest workflow ID such as `truthmark-sync`. It composes the installed workflow manifest, `.truthmark/config.yml`, RepoIndex, optional ImpactSet, and Truthmark Check diagnostics into one internal state object. + +WorkflowState includes applicability, action context, changed files, affected routes, target truth docs, merged diagnostics, required and recommended checks, helper validation commands, next steps, and report sections. WorkflowState does not carry ContextPack. + +`truthmark workflow status --workflow [--base ] --json` exposes a manifest-only `truthmark-workflow/v0` state in `data.workflowState` for status-only or debug inspection. It does not include `workflowState.contextPack`, truth document content, source file content, or a full route map. Caller-supplied request metadata such as `--base` is reported in the CLI envelope under `data.request` unless a later schema change explicitly adds it to WorkflowState. + +## Core Rules + +- WorkflowState is exposed through agent-facing `workflow status` CLI JSON for focused status/debug inspection, while generated workflows rely on checked-in workflow surfaces and direct checkout inspection as their execution contract. +- Workflow IDs stay in the full manifest form (`truthmark-sync`, `truthmark-document`, `truthmark-realize`, and peers). Pass 2 rejects short ContextPack aliases such as `truth-sync`; full manifest IDs are canonical. +- Read-only workflows (`truthmark-preview` and `truthmark-check`) have mode `read-only` and no allowed write paths. +- Sync and document workflows use mode `truth-doc-write`; structure uses `route-write`; realize uses `code-write`; portal uses `portal-write` when portal output is configured. +- Missing config, ambiguous route ownership, invalid workflow IDs, or missing branch comparison data fail closed instead of widening allowed writes. +- `truthmark-sync` may select a cheap existing local Git base when the caller omits `--base`, but blocks with no allowed writes when no candidate base exists; `truthmark-realize` still blocks without `--base` because code-write paths must be derived from a bounded comparison. +- Realize forbids writes to configured route and truth documentation paths. +- Helper validation commands are copied from the workflow manifest into machine-readable action context and check metadata. +- WorkflowState output is manifest-only and has no ContextPack opt-in path. + +## Flows And States + +The builder validates the workflow ID, loads config and RepoIndex, derives ImpactSet only when a base ref is supplied, runs Truthmark Check, merges diagnostics, determines applicability, then derives action context from the manifest and bounded route/config/impact data. + +Applicability is `applicable`, `not_applicable`, `blocked`, or `ambiguous`. Ambiguous changed functional files leave target truth docs empty and direct the caller toward Truth Structure or route repair. Sync without a caller-supplied base performs cheap local base selection from existing upstream/main/master refs, and if none exists it is `blocked` with a next step to rerun with `--base ` so truth-doc write paths remain bounded. Realize without a comparison base is `blocked` with a next step to rerun with `--base ` so code-write paths remain bounded. + +## Contracts + +`WorkflowState` is a TypeScript contract exported from `src/workflow-state/types.ts`. Its schema version is `truthmark-workflow/v0`. `buildWorkflowActionContext()` derives write modes, allowed and forbidden paths, stop conditions, required evidence, helper commands, and write-lease requirements from a workflow manifest entry plus bounded route/config data. + +## Product Decisions + +- Decision (2026-06-01): WorkflowState v0 remains an internal repository-intelligence artifact in Pass 1; it does not expose OpenSpec-like lifecycle commands through the Truthmark CLI. +- Decision (2026-06-01): WorkflowState composes existing manifest, config, RepoIndex, ImpactSet, and Check systems instead of creating a separate workflow engine. +- Decision (2026-06-01): Fail-closed write boundaries are preferred over default or wildcard fallback paths whenever config, route ownership, or branch comparison data is ambiguous. +- Decision (2026-06-12): Committed surfaces, support-file progressive disclosure, direct checkout inspection, and optional focused validation commands are the normal generated-workflow execution contract. +- Decision (2026-06-12): WorkflowState does not carry ContextPack; public ContextPack JSON output was removed in v2. +- Decision (2026-06-12): OpenSpec remains research input only; Truthmark must not add an OpenSpec dependency, committed OpenSpec workspace, OPSX command surface, or generated `openspec-*` agent skills. +- Decision (2026-06-01): Pass 2 accepts only full manifest workflow IDs and rejects short ContextPack aliases instead of silently mapping them. + +## Rationale + +WorkflowState gives workflow surfaces a single machine-readable state contract. Keeping it derived preserves route files, truth docs, and implementation as the authorities, while making agent workflow decisions easier to test and audit. + +## Non-Goals + +- WorkflowState is not a source of repository truth. +- WorkflowState does not grant permissions beyond installed workflow boundaries. +- WorkflowState does not replace direct checkout inspection, route files, truth docs, or Truthmark Check. +- WorkflowState does not add proposal lifecycle commands or OpenSpec-style archive/apply behavior. + +## Maintenance Notes + +Primary implementation files: + +- `src/workflow-state/types.ts` +- `src/workflow-state/action-context.ts` +- `src/workflow-state/build.ts` +- `tests/workflow-state/build.test.ts` +- `tests/cli/check-workflow.test.ts` + +Update this doc when the WorkflowState schema, applicability states, action-context mapping, fail-closed behavior, repository-intelligence composition behavior, or generated-surface CLI validation policy changes. diff --git a/docs/truth/routing-examples.md b/docs/truthmark/truth/routing-examples.md similarity index 96% rename from docs/truth/routing-examples.md rename to docs/truthmark/truth/routing-examples.md index 0060ac7..b6bc04f 100644 --- a/docs/truth/routing-examples.md +++ b/docs/truthmark/truth/routing-examples.md @@ -4,9 +4,9 @@ doc_type: behavior truth_kind: behavior last_reviewed: 2026-05-09 source_of_truth: - - ../../src/checks/areas.ts - - ../../src/sync/classify.ts - - ../../src/routing/area-resolver.ts + - ../../../src/checks/areas.ts + - ../../../src/sync/classify.ts + - ../../../src/routing/area-resolver.ts --- # Routing Examples @@ -75,7 +75,7 @@ Agents need routeable evidence for the code surfaces that change production beha - This doc does not define a complete route map for every possible framework. - This doc does not require teams to mirror directory layout mechanically. -- This doc does not replace repository-specific routing decisions in `docs/truthmark/areas.md` and child area files. +- This doc does not replace repository-specific routing decisions in `docs/truthmark/routes/areas.md` and child area files. ## Maintenance Notes diff --git a/docs/truth/workflows/content-generation.md b/docs/truthmark/truth/workflows/content-generation.md similarity index 98% rename from docs/truth/workflows/content-generation.md rename to docs/truthmark/truth/workflows/content-generation.md index 855ef94..40f1489 100644 --- a/docs/truth/workflows/content-generation.md +++ b/docs/truthmark/truth/workflows/content-generation.md @@ -4,7 +4,7 @@ doc_type: behavior truth_kind: workflow last_reviewed: 2026-05-31 source_of_truth: - - ../../../src/generation/** + - ../../../../src/generation/** --- # Workflow Content Generation diff --git a/docs/truth/workflows/overview.md b/docs/truthmark/truth/workflows/overview.md similarity index 58% rename from docs/truth/workflows/overview.md rename to docs/truthmark/truth/workflows/overview.md index d917d46..f2bd004 100644 --- a/docs/truth/workflows/overview.md +++ b/docs/truthmark/truth/workflows/overview.md @@ -2,16 +2,18 @@ status: active doc_type: behavior truth_kind: workflow -last_reviewed: 2026-05-18 +last_reviewed: 2026-06-12 source_of_truth: - - ../../../.truthmark/config.yml - - ../../../src/agents/instructions.ts - - ../../../src/agents/workflow-manifest.ts - - ../../../src/agents/workflow-helper-validation.ts - - ../../../src/cli/program.ts - - ../../../src/cli/handlers.ts - - ../../../src/templates/workflow-surfaces.ts - - ../../../src/templates/generated-surfaces.ts + - ../../../../.truthmark/config.yml + - ../../../../src/agents/instructions.ts + - ../../../../src/agents/workflow-manifest.ts + - ../../../../src/agents/workflow-helper-validation.ts + - ../../../../src/cli/program.ts + - ../../../../src/cli/handlers.ts + - ../../../../src/templates/workflow-surfaces.ts + - ../../../../src/templates/generated-surfaces.ts + - ../../../../tests/evals/workflow-routing-cases.ts + - ../../../../tests/evals/no-cli-fallback-cases.ts --- # Installed Workflow Overview @@ -42,14 +44,17 @@ This document owns the shared installed-workflow runtime model and generated hos Installed skills, prompts, commands, and managed instruction blocks are the workflow runtime. The `truthmark` CLI installs and refreshes those surfaces and may validate artifacts afterward, but it does not orchestrate workflow execution or prepare required workflow payloads before an agent can act. -Agents inspect the checkout directly, apply workflow boundaries from committed surfaces, update only workflow-allowed files, and report what changed. +Generated workflow entrypoints, prompts, and commands use checked-in generated prose, progressive-disclosure support files, route files, truth docs, and direct checkout inspection as the normal workflow contract. The local CLI remains an optional focused validation tool for commands such as `truthmark check --json` and declared helper validators. + +No CLI command or helper output is a required prerequisite before an agent can act. Agents inspect the checkout directly, apply workflow boundaries from committed surfaces and support files, update only workflow-allowed files, and report what changed. Sync, Document, Structure, and Realize use checked-in workflow files as the contract: follow the route-first procedure, read only the config, route files, truth docs, and source evidence needed for the current changed surface, and stop on missing or ambiguous ownership instead of broadening reads or writes. ## Steps 1. `truthmark init` reads `.truthmark/config.yml` and refreshes managed instruction blocks plus configured host surfaces. 2. Generated host surfaces expose explicit manual workflows and the automatic finish-time Truth Sync guidance. -3. An agent invokes or follows a generated surface, reads the checkout directly, applies workflow write boundaries, and reports the outcome. -4. Optional CLI helpers may validate reports, build context, or index the repository, but they do not orchestrate workflow execution. +3. An agent invokes or follows a generated workflow entrypoint, prompt, or command and reads progressive-disclosure support files only as needed for the current workflow step. +4. The agent reads the checkout directly, applies committed workflow write boundaries, and reports the outcome. +5. Optional CLI helpers may validate reports, build context, or index the repository, but they do not orchestrate workflow execution and are never required before the agent can act. Current behavior notes: @@ -57,12 +62,22 @@ The default platform list includes every supported platform. Teams should remove | Platform | Generated surface | Invocation shape | | ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- | -| `codex` | `.codex/skills/truthmark-*/SKILL.md`, `.codex/skills/truthmark-*/support/*.md`, Codex metadata, and `.codex/agents/*.toml` verifier and leased doc-writer agents | `/truthmark-*` or `$truthmark-*` | +| `codex` | `.agents/skills/truthmark-*/SKILL.md`, `.agents/skills/truthmark-*/support/*.md`, Codex metadata, and `.codex/agents/*.toml` verifier and leased doc-writer agents | `/truthmark-*` or `$truthmark-*` | | `opencode` | `.opencode/skills/truthmark-*/SKILL.md`, `.opencode/skills/truthmark-*/support/*.md`, and `.opencode/agents/*.md` verifier and leased doc-writer subagents | `/skill truthmark-*` | | `claude-code` | `.claude/skills/truthmark-*/SKILL.md`, `.claude/skills/truthmark-*/support/*.md`, and `.claude/agents/*.md` verifier and leased doc-writer subagents | `/truthmark-*`; named subagents such as `truth-route-auditor` | -| `github-copilot` | `.github/skills/truthmark-*/SKILL.md`, `.github/skills/truthmark-*/support/*.md`, `.github/prompts/truthmark-*.prompt.md`, and `.github/agents/*.agent.md` verifier and leased doc-writer agents | `/truthmark-*` in supported Copilot IDEs; `@truth-*` custom agents in Copilot CLI | +| `github-copilot` | `.github/skills/truthmark-*/SKILL.md`, `.github/skills/truthmark-*/support/*.md`, `.github/prompts/truthmark-*.prompt.md`, and `.github/agents/*.md` verifier and leased doc-writer agents | `/truthmark-*` in supported Copilot IDEs; `@truth-*` custom agents in Copilot CLI | | `gemini-cli` | `.gemini/skills/truthmark-*/SKILL.md`, `.gemini/skills/truthmark-*/support/*.md`, `.gemini/commands/truthmark/*.toml`, and `.gemini/agents/*.md` verifier and leased doc-writer agents | `/truthmark:*` | +Official host documentation checked for these paths: + +| Platform | Official documentation | Path contract used by Truthmark | +| -------- | ---------------------- | -------------------------------- | +| `codex` | OpenAI Codex Skills: ; OpenAI Codex Subagents: | Codex scans repository skills from `.agents/skills` up to the repository root; project custom agents are standalone TOML files under `.codex/agents/`. | +| `opencode` | OpenCode Agent Skills: ; OpenCode Agents: | OpenCode supports project skills under `.opencode/skills//SKILL.md` and project markdown agents under `.opencode/agents/`. | +| `claude-code` | Anthropic Claude Code Skills: ; Anthropic Claude Code Subagents: | Claude Code project skills load from `.claude/skills/`; project subagents use `.claude/agents/`. | +| `github-copilot` | GitHub Copilot agent skills: ; GitHub Copilot prompt files: ; GitHub Copilot custom agents: ; GitHub Copilot repository instructions: | Copilot supports project skills under `.github/skills`, `.claude/skills`, or `.agents/skills`; prompt files live in `.github/prompts/*.prompt.md`; repository custom agents live in `.github/agents/CUSTOM-AGENT-NAME.md`; repository instructions live in `.github/copilot-instructions.md`. | +| `gemini-cli` | Gemini CLI skills: ; Gemini CLI custom commands: ; Gemini CLI subagents: ; Gemini CLI context files: | Gemini CLI supports workspace skills under `.gemini/skills/` or `.agents/skills/`, project commands under `.gemini/commands/`, project subagents under `.gemini/agents/*.md`, and repository context through `GEMINI.md`. | + Generated skill files, Gemini command files, Codex metadata, Codex custom-agent files, Claude Code subagent files, GitHub Copilot custom-agent files, Gemini subagent files, OpenCode subagent files, and managed instruction blocks include the package version from `package.json`. After upgrading Truthmark, rerun `truthmark init` and review generated workflow diffs. Skill-package hosts (`codex`, `opencode`, `claude-code`, `github-copilot`, and `gemini-cli`) may also include parseable YAML `helper-manifest.yml` and `support/helper-policy.md` when a workflow declares optional helper commands. Helpers are CLI-owned read-only accelerators invoked through argv-style `truthmark validate ... --json` commands and never workflow prerequisites. If the declared `truthmark` runner is unavailable or version-mismatched, the workflow reports a visible helper skip and continues with the generated manual fallback. Helper output is derived evidence; direct checkout inspection, workflow write boundaries, and parent workflow validation remain authoritative. Standalone Copilot prompt files and Gemini TOML command files use the same installed-CLI validator contract even though their helper manifests live in matching generated skill packages; when the runner is unavailable or skipped, their reports must show a visible skipped helper status plus manual validation. @@ -72,9 +87,11 @@ Read-only verifier agents include an explicit context boundary: they inspect onl Generated workflow descriptions are routing triggers. They use short positive trigger language plus adjacent-workflow exclusions. Skill-package hosts keep `SKILL.md` as the compact routing and quick-procedure entrypoint, then put detailed procedure, report templates, and subagent or lease instructions in generated `support/*.md` files. Standalone prompt and command hosts keep the full workflow body inline because they do not load skill-package support files. +Generated public workflow entrypoints, GitHub Copilot prompts, and Gemini commands use progressive disclosure instead of a repeated generic validation section. Top-level workflow text focuses on trigger, write boundaries, quick procedure, and support-file routing. Detailed procedure and report guidance lives in checked-in support files for skill-package hosts or inline in standalone prompt and command hosts. For Sync, Document, Structure, and Realize, direct checkout fallback remains route-first and bounded to the current changed surface: agents may read only the needed config, route files, truth docs, and source evidence, and they must block on missing or ambiguous ownership instead of broadening reads or writes. Focused validation remains workflow-specific: helper-capable workflows declare optional helper validators in `helper-manifest.yml` and `support/helper-policy.md`, while post-work verification stays in the relevant quick procedure or procedure support file. Preview and Check remain read-only and focused on the requested report rather than generic CLI caveats. + The typed workflow manifest owns generated description text, Codex-facing short descriptions and default prompts, implicit-invocation policy, positive and negative routing examples, forbidden-adjacent cases, required gates, write boundaries, and report-section expectations. Generated host surfaces and deterministic routing tests should consume that manifest rather than duplicating workflow metadata in renderer code. -Truthmark Portal surfaces are generated only when `truthmark-portal.enabled` normalizes to `true`. When enabled, configured platforms receive the `truthmark-portal` skill package, GitHub Copilot receives `.github/prompts/truthmark-portal.prompt.md`, Gemini receives `.gemini/commands/truthmark/portal.toml`, and managed instruction blocks mention Portal with manual-only wording. Portal installs no dedicated subagents in V1. +Truthmark Portal surfaces are generated only when `truthmark.generated.portal.enabled` normalizes to `true`. When enabled, configured platforms receive the `truthmark-portal` skill package, GitHub Copilot receives `.github/prompts/truthmark-portal.prompt.md`, Gemini receives `.gemini/commands/truthmark/portal.toml`, and managed instruction blocks mention Portal with manual-only wording. Portal installs no dedicated subagents in V1. Truthmark-owned workflow surfaces are generated under host-specific directories. Repo-root `skills/` files are not generated V1 workflow surfaces. @@ -82,7 +99,7 @@ Managed instruction blocks are compact automatic-Sync trigger and boundary index ## State, Retry, And Failure Behavior -Generated workflow surfaces are committed repository files. If the Truthmark package is unavailable at workflow-execution time, agents still follow the committed surfaces manually and report unavailable optional helper output. Removing a platform from config stops future refreshes for that platform but does not delete already committed surfaces. +Generated workflow surfaces are committed repository files. If the Truthmark package is unavailable at workflow-execution time, agents still follow the committed surfaces manually and use direct checkout evidence. Unavailable, stale, or failing read-only CLI helpers degrade to visible skipped helper status only when a relevant check, index, or helper validator was expected; they do not block agent action when committed workflow surfaces and direct checkout evidence are sufficient. Manual fallback for write workflows remains route-first and bounded to the current changed surface; if needed config, route files, truth docs, and source evidence cannot determine the safe owner or write boundary, the workflow blocks and reports ambiguity instead of broadening reads or writes. Removing a platform from config stops future refreshes for that platform but does not delete already committed surfaces. ## Outputs @@ -93,7 +110,7 @@ The installed runtime outputs managed instruction blocks, host-native skills/pro - Decision (2026-05-15): Installed skills, prompts, commands, and managed instruction blocks are the workflow runtime. The CLI installs and validates those surfaces but does not orchestrate Truth Sync or require helper payloads before agents can act. - Decision (2026-05-15): Managed instruction blocks stay compact enough for ordinary agent context. Non-automatic workflow procedure belongs in generated skills, prompts, and command files. - Decision (2026-05-15): Managed instruction blocks omit platform-specific invocation strings; host-specific generated workflow files remain the canonical place for invocation detail. -- Decision (2026-05-15): Truthmark follows current host discovery paths for generated workflow files: Codex uses `.codex/skills/`, Claude Code uses `.claude/skills/` and `.claude/agents/`, GitHub Copilot uses `.github/skills/`, `.github/prompts/`, and `.github/agents/`, OpenCode uses `.opencode/skills/`, Gemini CLI uses `.gemini/skills/`, `.gemini/commands/`, and `.gemini/agents/`, and repo-root `skills/` is not a generated V1 target. +- Decision (2026-05-15, updated 2026-06-12): Truthmark follows official host discovery paths for generated workflow files: Codex uses `.agents/skills/` plus `.codex/agents/`, Claude Code uses `.claude/skills/` and `.claude/agents/`, GitHub Copilot uses `.github/skills/`, `.github/prompts/`, and `.github/agents/`, OpenCode uses `.opencode/skills/` and `.opencode/agents/`, Gemini CLI uses `.gemini/skills/`, `.gemini/commands/`, and `.gemini/agents/`, and repo-root `skills/` is not a generated V1 target. - Decision (2026-05-15): Workflow descriptions are routing triggers rather than workflow summaries; adjacent-workflow exclusions belong in metadata when they prevent wrong workflow loading. - Decision (2026-05-15): Workflow metadata and routing-eval expectations live in a typed manifest so generated descriptions, host metadata, and deterministic routing tests share one structural source. - Decision (2026-05-16): Codex, Claude Code, GitHub Copilot, Gemini CLI, and OpenCode may install project-scoped read-only verifier agents plus a leased `truth-doc-writer`; parent workflows keep acceptance and diff validation ownership and do not require users to request subagents per task. @@ -103,6 +120,8 @@ The installed runtime outputs managed instruction blocks, host-native skills/pro - Decision (2026-05-16): Generated skill packages use progressive disclosure: `SKILL.md` stays compact for routing and first-step execution, while heavy procedure detail, report examples, and subagent or lease reference material move to generated support files beside the skill. - Decision (2026-05-18): Workflow helpers are optional read-only accelerators declared in generated helper manifests; current helpers are owned by the installed `truthmark` CLI and use argv-style `truthmark validate ... --json` commands rather than packaged script copies. - Decision (2026-05-25): Truthmark Portal is opt-in and manual-only; generated Portal HTML is a non-canonical human presentation surface and Markdown remains canonical. +- Decision (2026-06-12): Generated public workflow entrypoints, GitHub Copilot prompts, and Gemini commands use committed surfaces, progressive-disclosure support files, and direct checkout inspection first, with optional focused validation after relevant work is performed. +- Decision (2026-06-12): Read-only CLI helper surfaces such as `workflow status`, `context`, and `impact` must remain optional coordination aids; no CLI command becomes required before an agent can act from committed workflow surfaces and direct checkout evidence. ## Rationale diff --git a/docs/truth/workflows/shared-gates.md b/docs/truthmark/truth/workflows/shared-gates.md similarity index 89% rename from docs/truth/workflows/shared-gates.md rename to docs/truthmark/truth/workflows/shared-gates.md index 1ca6c23..37e6202 100644 --- a/docs/truth/workflows/shared-gates.md +++ b/docs/truthmark/truth/workflows/shared-gates.md @@ -4,9 +4,9 @@ doc_type: behavior truth_kind: workflow last_reviewed: 2026-05-31 source_of_truth: - - ../../../src/agents/shared.ts - - ../../../src/truth/** - - ../../../src/sync/report.ts + - ../../../../src/agents/shared.ts + - ../../../../src/truth/** + - ../../../../src/sync/report.ts --- # Shared Workflow Gates @@ -69,7 +69,7 @@ Truth Sync and Truth Document completed reports have deterministic structured pa RepoIndex, RouteMap, ImpactSet, and ContextPack are derived acceleration artifacts. They may guide routing, context selection, evidence review, and verification planning, but they do not own truth, route authority, or write permissions. -When the Truthmark CLI is unavailable, workflows must inspect `.truthmark/config.yml`, `docs/truthmark/areas.md`, child area files, changed source files, and routed truth docs directly. The workflow may proceed manually, but the completion report must say that RepoIndex, ImpactSet, ContextPack, and freshness diagnostics were not generated. +When the Truthmark CLI is unavailable, workflows must inspect `.truthmark/config.yml`, `docs/truthmark/routes/areas.md`, child area files, changed source files, and routed truth docs directly. The workflow may proceed manually, but the completion report must say that RepoIndex, ImpactSet, ContextPack, and freshness diagnostics were not generated. If a repository-intelligence artifact conflicts with the current checkout, the checkout wins. Agents rerun the CLI when available or ignore the stale artifact when it cannot be regenerated. ContextPack-only content is not evidence; generated truth docs must cite checkout files, route files, truth docs, tests, schemas, or explicit evidence blocks. @@ -81,7 +81,7 @@ Shape repair does not cover ownership splits. Broad or mixed-owner docs require ### Template And Decision Guidance -Generated workflows point to the routed truth kind's matching template under `docs/templates/`, rendered as `docs/templates/-doc.md`. Agents inspect the routed truth kind, read the matching template file, and treat the HTML comments under each template section as normative authoring guidance for that section. Shape alignment is not only heading alignment: agents write or repair section content so it satisfies the comment guidance while preserving accurate authored content. Workflows fall back to the built-in minimal truth-doc structure only when the matching template is missing. +Generated workflows point to the routed truth kind's matching template under `docs/truthmark/templates/`, rendered as `docs/truthmark/templates/-doc.md`. Agents inspect the routed truth kind, read the matching template file, and treat the HTML comments under each template section as normative authoring guidance for that section. Shape alignment is not only heading alignment: agents write or repair section content so it satisfies the comment guidance while preserving accurate authored content. Workflows fall back to the built-in minimal truth-doc structure only when the matching template is missing. Decision truth lives in the canonical doc it governs. Active decisions are dated inline when added or changed; separate active-decision ADR or planning logs are rejected. diff --git a/docs/truth/workflows/truth-check.md b/docs/truthmark/truth/workflows/truth-check.md similarity index 97% rename from docs/truth/workflows/truth-check.md rename to docs/truthmark/truth/workflows/truth-check.md index b6328d2..e3cdad9 100644 --- a/docs/truth/workflows/truth-check.md +++ b/docs/truthmark/truth/workflows/truth-check.md @@ -4,10 +4,10 @@ doc_type: behavior truth_kind: workflow last_reviewed: 2026-05-31 source_of_truth: - - ../../../src/agents/truth-check.ts - - ../../../src/checks/** - - ../../../src/agents/shared.ts - - ../../../src/templates/workflow-surfaces.ts + - ../../../../src/agents/truth-check.ts + - ../../../../src/checks/** + - ../../../../src/agents/shared.ts + - ../../../../src/templates/workflow-surfaces.ts --- # Truth Check Workflow diff --git a/docs/truth/workflows/truth-document.md b/docs/truthmark/truth/workflows/truth-document.md similarity index 93% rename from docs/truth/workflows/truth-document.md rename to docs/truthmark/truth/workflows/truth-document.md index 22342c1..90dce2f 100644 --- a/docs/truth/workflows/truth-document.md +++ b/docs/truthmark/truth/workflows/truth-document.md @@ -4,14 +4,14 @@ doc_type: behavior truth_kind: workflow last_reviewed: 2026-05-31 source_of_truth: - - ../../../src/agents/truth-document.ts - - ../../../src/agents/write-lease.ts - - ../../../src/agents/shared.ts - - ../../../src/agents/workflow-manifest.ts - - ../../../src/agents/workflow-helper-validation.ts - - ../../../src/cli/program.ts - - ../../../src/cli/handlers.ts - - ../../../src/templates/workflow-surfaces.ts + - ../../../../src/agents/truth-document.ts + - ../../../../src/agents/write-lease.ts + - ../../../../src/agents/shared.ts + - ../../../../src/agents/workflow-manifest.ts + - ../../../../src/agents/workflow-helper-validation.ts + - ../../../../src/cli/program.ts + - ../../../../src/cli/handlers.ts + - ../../../../src/templates/workflow-surfaces.ts --- # Truth Document Workflow @@ -57,7 +57,7 @@ If the candidate truth doc is broad, mixed-owner, index-like, or the documented When ownership is bounded, Truth Document creates or updates leaf truth docs, keeps behavior truth docs behavior-oriented, keeps API endpoint details in the nearest contract truth doc when that doc owns the contract, and preserves unrelated authored content. -When creating or updating a truth doc, Truth Document uses the routed `truth_kind` to select `docs/templates/-doc.md`. The HTML comments under each selected template section are normative authoring guidance for that section; Document must write content that satisfies the comment guidance while preserving supported existing claims. +When creating or updating a truth doc, Truth Document uses the routed `truth_kind` to select `docs/truthmark/templates/-doc.md`. The HTML comments under each selected template section are normative authoring guidance for that section; Document must write content that satisfies the comment guidance while preserving supported existing claims. When Truth Document restructures a bounded truth doc or runs Structure first, it inventories Product Decisions and Rationale before editing. Existing entries must be preserved in or moved to their bounded owner docs, narrowed or removed only with checkout evidence, or blocked for manual review when ownership is unclear. diff --git a/docs/truth/workflows/truth-preview.md b/docs/truthmark/truth/workflows/truth-preview.md similarity index 95% rename from docs/truth/workflows/truth-preview.md rename to docs/truthmark/truth/workflows/truth-preview.md index db7ddf2..5eafc2e 100644 --- a/docs/truth/workflows/truth-preview.md +++ b/docs/truthmark/truth/workflows/truth-preview.md @@ -4,10 +4,10 @@ doc_type: behavior truth_kind: workflow last_reviewed: 2026-05-31 source_of_truth: - - ../../../src/agents/truth-preview.ts - - ../../../src/agents/workflow-manifest.ts - - ../../../src/templates/workflow-surfaces.ts - - ../../../src/templates/generated-surfaces.ts + - ../../../../src/agents/truth-preview.ts + - ../../../../src/agents/workflow-manifest.ts + - ../../../../src/templates/workflow-surfaces.ts + - ../../../../src/templates/generated-surfaces.ts --- # Truth Preview diff --git a/docs/truth/workflows/truth-realize.md b/docs/truthmark/truth/workflows/truth-realize.md similarity index 96% rename from docs/truth/workflows/truth-realize.md rename to docs/truthmark/truth/workflows/truth-realize.md index 17efe2d..b84aa53 100644 --- a/docs/truth/workflows/truth-realize.md +++ b/docs/truthmark/truth/workflows/truth-realize.md @@ -4,9 +4,9 @@ doc_type: behavior truth_kind: workflow last_reviewed: 2026-05-31 source_of_truth: - - ../../../src/agents/prompts.ts - - ../../../src/templates/workflow-surfaces.ts - - ../../../src/realize/report.ts + - ../../../../src/agents/prompts.ts + - ../../../../src/templates/workflow-surfaces.ts + - ../../../../src/realize/report.ts --- # Truth Realize Workflow diff --git a/docs/truth/workflows/truth-structure.md b/docs/truthmark/truth/workflows/truth-structure.md similarity index 97% rename from docs/truth/workflows/truth-structure.md rename to docs/truthmark/truth/workflows/truth-structure.md index e8b4fb3..a9b4760 100644 --- a/docs/truth/workflows/truth-structure.md +++ b/docs/truthmark/truth/workflows/truth-structure.md @@ -4,10 +4,10 @@ doc_type: behavior truth_kind: workflow last_reviewed: 2026-05-31 source_of_truth: - - ../../../src/agents/truth-structure.ts - - ../../../src/agents/shared.ts - - ../../../src/templates/workflow-surfaces.ts - - ../../../src/routing/** + - ../../../../src/agents/truth-structure.ts + - ../../../../src/agents/shared.ts + - ../../../../src/templates/workflow-surfaces.ts + - ../../../../src/routing/** --- # Truth Structure Workflow diff --git a/docs/truth/workflows/truth-sync.md b/docs/truthmark/truth/workflows/truth-sync.md similarity index 94% rename from docs/truth/workflows/truth-sync.md rename to docs/truthmark/truth/workflows/truth-sync.md index 1cf3a7f..cad3ff5 100644 --- a/docs/truth/workflows/truth-sync.md +++ b/docs/truthmark/truth/workflows/truth-sync.md @@ -4,15 +4,15 @@ doc_type: behavior truth_kind: workflow last_reviewed: 2026-05-31 source_of_truth: - - ../../../src/agents/truth-sync.ts - - ../../../src/agents/write-lease.ts - - ../../../src/sync/report.ts - - ../../../src/agents/shared.ts - - ../../../src/agents/workflow-manifest.ts - - ../../../src/agents/workflow-helper-validation.ts - - ../../../src/cli/program.ts - - ../../../src/cli/handlers.ts - - ../../../src/templates/workflow-surfaces.ts + - ../../../../src/agents/truth-sync.ts + - ../../../../src/agents/write-lease.ts + - ../../../../src/sync/report.ts + - ../../../../src/agents/shared.ts + - ../../../../src/agents/workflow-manifest.ts + - ../../../../src/agents/workflow-helper-validation.ts + - ../../../../src/cli/program.ts + - ../../../../src/cli/handlers.ts + - ../../../../src/templates/workflow-surfaces.ts --- # Truth Sync Workflow @@ -60,7 +60,7 @@ Truth Sync updates active decisions and rationale in the routed canonical doc wh When Truth Sync restructures a bounded truth doc or runs Structure inline, it inventories Product Decisions and Rationale before editing. Existing entries must be preserved in or moved to their bounded owner docs, narrowed or removed only with checkout evidence, or blocked for manual review when ownership is unclear. -When Truth Sync creates, updates, or repairs a truth doc, it uses the routed `truth_kind` to select `docs/templates/-doc.md`. The HTML comments under that template's section headings are part of the authoring contract: Sync must satisfy the section intent for changed content, not just preserve or copy the headings. +When Truth Sync creates, updates, or repairs a truth doc, it uses the routed `truth_kind` to select `docs/truthmark/templates/-doc.md`. The HTML comments under that template's section headings are part of the authoring contract: Sync must satisfy the section intent for changed content, not just preserve or copy the headings. Truth Sync updates architecture docs in the same sync when changed code alters architecture-level structure or ownership. diff --git a/docs/truth/workflows/truthmark-portal.md b/docs/truthmark/truth/workflows/truthmark-portal.md similarity index 63% rename from docs/truth/workflows/truthmark-portal.md rename to docs/truthmark/truth/workflows/truthmark-portal.md index 3ab6805..1ba5b2f 100644 --- a/docs/truth/workflows/truthmark-portal.md +++ b/docs/truthmark/truth/workflows/truthmark-portal.md @@ -2,15 +2,15 @@ status: active doc_type: behavior truth_kind: workflow -last_reviewed: 2026-05-31 +last_reviewed: 2026-06-01 source_of_truth: - - ../../../src/agents/truthmark-portal.ts - - ../../../src/agents/workflow-manifest.ts - - ../../../src/templates/generated-surfaces.ts - - ../../../src/templates/workflow-surfaces.ts - - ../../../src/templates/agents-block.ts - - ../../../src/config/schema.ts - - ../../../src/config/load.ts + - ../../../../src/agents/truthmark-portal.ts + - ../../../../src/agents/workflow-manifest.ts + - ../../../../src/templates/generated-surfaces.ts + - ../../../../src/templates/workflow-surfaces.ts + - ../../../../src/templates/agents-block.ts + - ../../../../src/config/schema.ts + - ../../../../src/config/load.ts --- # Truthmark Portal Workflow @@ -29,41 +29,39 @@ Portal runs only from an explicit user request to generate, refresh, or update t ## Inputs -- `.truthmark/config.yml`, especially the namespaced `truthmark-portal` block when present +- `.truthmark/config.yml`, especially `truthmark.generated.portal.enabled` - configured route docs and Markdown truth sources selected for presentation - repository instruction, architecture, and standards Markdown when they are part of the requested Portal source set -- configured Portal template when the selected template is a repository-relative file +- determined Portal template at `${truthmark.workspace}/templates/portal.html` when present - optional local `truthmark check` or `truthmark index` output used only as supporting evidence, never as required infrastructure ## Execution Model -Portal is an agent-executed workflow that reads Markdown truth sources from the checkout and writes presentation output under the configured Portal output directory. The generated HTML, assets, and metadata are non-canonical; Markdown truth documents remain authoritative. +Portal is an agent-executed workflow that reads Markdown truth sources from the checkout and writes presentation output under the fixed Truthmark-derived Portal output directory. The generated HTML, assets, and metadata are non-canonical; Markdown truth documents remain authoritative. ## Steps 1. Confirm the user explicitly requested Portal generation or refresh. -2. Read the namespaced `truthmark-portal` config block and normalize defaults. +2. Read `truthmark.generated.portal.enabled` and normalize Truthmark-derived Portal paths. 3. Inspect Markdown truth sources from the checkout. -4. Write presentation output only under the configured Portal output directory. +4. Write presentation output only under the fixed Portal output directory. 5. Keep generated HTML, assets, and metadata non-canonical and report what was refreshed. Current behavior notes: -`.truthmark/config.yml` may contain a namespaced `truthmark-portal` block. The raw YAML key is exactly `truthmark-portal`; normalized config exposes `truthmarkPortal`. +`.truthmark/config.yml` contains Portal enablement under the required v2 `truthmark.generated.portal` block. Normalized config exposes only `truthmark.generated.portal.enabled`; Portal output is derived as `${truthmark.workspace}/generated/portal`, and the Portal template path is derived as `${truthmark.workspace}/templates/portal.html`. When the block is omitted, normalized config defaults to: ```yaml enabled: false -output: docs/truthmark-portal -template: default ``` -If the block exists but `enabled` is omitted, Portal remains disabled. `output` and `template` default independently to `docs/truthmark-portal` and `default`. +The generated default config includes the block with `enabled: false`. Portal remains disabled unless `truthmark.generated.portal.enabled` is set to `true`. -The config schema rejects non-object Portal blocks and non-string `output` or `template` values. Config loading also rejects empty, absolute, or parent-traversing Portal outputs and templates. Portal output must be a repository-relative directory and must not overlap source roots, configured instruction targets, `.truthmark/config.yml`, route files, or canonical Markdown roots. +The config schema rejects non-object Portal blocks and rejects extra custom `output` or `template` properties under `truthmark.generated.portal`. -`truthmark init` renders Portal surfaces only when `truthmarkPortal.enabled` is `true`. Enabled platform surfaces include Codex, OpenCode, Claude Code, GitHub Copilot, and Gemini skill packages; `.github/prompts/truthmark-portal.prompt.md`; and `.gemini/commands/truthmark/portal.toml`. V1 Portal installs no dedicated subagents or helper agents. +`truthmark init` renders Portal surfaces only when `truthmark.generated.portal.enabled` is `true`. Enabled platform surfaces include Codex, OpenCode, Claude Code, GitHub Copilot, and Gemini skill packages; `.github/prompts/truthmark-portal.prompt.md`; and `.gemini/commands/truthmark/portal.toml`. V1 Portal installs no dedicated subagents or helper agents. When Portal is disabled or omitted, init emits no Portal skill, prompt, or command surfaces, and generated managed instruction blocks do not mention Portal. @@ -71,7 +69,7 @@ Portal is manual-only. It is never a completion gate, never Truth Sync, and runs The workflow reads Markdown directly from the checkout and does not require the `truthmark` CLI or package. `truthmark check` or index commands may be used only as optional supporting evidence when available. Portal has no `.truthmark/index.json` dependency. -Portal writes generated non-canonical static files only under the configured output directory unless the user explicitly changes scope. The selected output directory may be replaced entirely during generation. +Portal writes generated non-canonical static files only under the fixed output directory. The output directory may be replaced entirely during generation. Generated output should be a committed multi-page static HTML site with local CSS, JavaScript, assets, and search metadata. Generated pages must include source provenance and a visible statement that Markdown remains canonical and generated HTML is presentation only. Manifest and search metadata stay under `/assets`. No remote scripts, analytics, fonts, CSS, or CDN dependencies are used by default. Pictures and screenshots require an explicit user or template request. @@ -81,11 +79,11 @@ Portal remains disabled when the config block is omitted or `enabled` is omitted ## Outputs -Portal outputs committed static HTML presentation files, supporting assets, optional metadata under the configured output directory, and a completion report. Markdown truth docs remain authoritative. +Portal outputs committed static HTML presentation files, supporting assets, optional metadata under the fixed output directory, and a completion report. Markdown truth docs remain authoritative. ## Product Decisions -- Decision (2026-05-25): Truthmark Portal is controlled by a namespaced `truthmark-portal` config block rather than a shared optional-workflows list, so enablement, output, and template selection stay together. +- Decision (2026-06-01): Truthmark Portal config only controls enablement. Output and template locations are fixed by Truthmark from `truthmark.workspace`. - Decision (2026-05-25): Portal is opt-in and manual-only; generated Portal output is a human presentation surface and must not become canonical repository truth or an automatic Sync/check gate. - Decision (2026-05-25): Portal V1 is agent-native and Markdown-native. It does not introduce a required Portal package, generated `.truthmark/index.json`, or deterministic renderer dependency. @@ -98,7 +96,7 @@ Large repositories need a human browsable entrypoint over routed truth docs, but - no automatic Portal generation after code changes - no canonical HTML truth surface - no mandatory `truthmark` binary, Portal package, remote service, or `.truthmark/index.json` -- no writes outside the configured Portal output directory by default +- no writes outside the fixed Portal output directory ## Maintenance Notes diff --git a/package-lock.json b/package-lock.json index dd22a93..9797a57 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "truthmark", - "version": "1.6.1", + "version": "2.1.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "truthmark", - "version": "1.6.1", + "version": "2.1.0", "license": "MIT", "dependencies": { "ajv": "^8.17.1", diff --git a/package.json b/package.json index 09e3f5b..8085258 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "truthmark", - "version": "1.6.1", + "version": "2.1.0", "description": "Git-native, branch-scoped truth workflow installer for local AI coding agents.", "license": "MIT", "type": "module", diff --git a/research/2026-06-01-openspec-comparison.md b/research/2026-06-01-openspec-comparison.md new file mode 100644 index 0000000..94a7692 --- /dev/null +++ b/research/2026-06-01-openspec-comparison.md @@ -0,0 +1,1168 @@ +# Truthmark × OpenSpec Deep Behavioral Research + +Date: 2026-06-01 +Truthmark repository: `/opt/data/repos/truthmark` +OpenSpec repository: `/tmp/openspec-research` (`Fission-AI/OpenSpec`, cloned locally) +Output location: `.hermes/research/2026-06-01-openspec-comparison.md` + +## Research intent + +This report compares Truthmark against Fission-AI/OpenSpec at the behavior/workflow/schema/agent level. It intentionally does **not** compare superficial README positioning, implementation languages, or repository size. + +The goal is to understand what OpenSpec does better and what Truthmark can learn **without becoming a spec-driver library** and without replicating OpenSpec's proposal/spec/design/task lifecycle. + +Truthmark's intended mission remains: a local-first, Git-native repository-truth governance layer that installs truth-aware workflows into coding-agent surfaces, validates ownership/routing/freshness, and keeps implementation-aligned truth reviewable in Git. + +OpenSpec's intended mission is different: a local spec/change lifecycle system that helps agents and humans create, apply, verify, sync, and archive proposed behavior changes through structured artifacts. + +## Methodology + +I inspected both repositories as local code, not just documentation: + +- Truthmark: `/opt/data/repos/truthmark` + - CLI command definitions and handlers + - config schema/defaults/load behavior + - init/scaffold/generation behavior + - generated agent surfaces and workflow manifest + - routing/truth-doc model + - check, impact, context-pack, freshness, evidence, and path/git containment behavior + - active `.truthmark/config.yml` +- OpenSpec: `/tmp/openspec-research` + - CLI workflow commands + - artifact graph runtime + - built-in workflow schemas + - planning-home/workspace behavior + - generated skills/commands/adapters + - Markdown parsers and validators + - archive/apply/spec-delta behavior + - tests and workflow templates + +Important caveat: Truthmark's worktree is heavily dirty and appears to contain the current v2 workspace refactor. I treated the current worktree as the active design under review. + +--- + +## Executive judgement + +OpenSpec is ahead of Truthmark in **agent-facing workflow state ergonomics**. Its strongest transferable idea is not “specs,” but the way it converts local repository state into explicit machine-readable guidance for agents: + +- `status --json` tells the agent what exists, what is ready, what is blocked, and what is next. +- `instructions --json` gives the agent exact context files, constraints, output paths, dependencies, and stop conditions. +- `actionContext` gives allowed edit roots and mode-specific constraints. +- Tool-specific generated skills/commands teach many agent hosts to use the same local CLI contract. + +Truthmark already has many of the right lower-level pieces: + +- workflow manifest with triggers, negative triggers, allowed writes, forbidden adjacency, report sections, helpers, and subagents +- strict v2 config and path containment +- routing/truth-doc ownership model +- `check`, `impact`, `context`, `validate` commands +- generated surfaces for Codex, OpenCode, Claude Code, GitHub Copilot, and Gemini CLI +- write leases and helper validators + +But Truthmark's pieces are less unified as a single agent-facing state machine. OpenSpec's advantage is that an agent can ask the tool: **what should I do next, what may I edit, and why?** Truthmark can adopt that pattern without adopting OpenSpec's artifact lifecycle. + +Highest-value improvement for Truthmark: + +> Add a Truthmark-native `workflow status/instructions --json` layer that composes the existing manifest, route map, check diagnostics, impact set, context pack, write boundaries, and validators into one explicit workflow contract for agents. + +This would improve Truthmark's mission directly: repository-truth governance becomes more deterministic, safer, and easier for agents to follow. + +--- + +## Mission comparison + +### Truthmark + +Truthmark is a repository-truth workflow layer. It is not supposed to be the feature spec, task manager, or product lifecycle tool. Its core concerns are: + +- Which source files and docs own a behavior? +- Which truth documents must change when code behavior changes? +- Which truth docs are canonical and which are generated/host surfaces? +- Which agent workflow is appropriate for the task? +- What can the agent write safely? +- Are generated agent surfaces and truth docs fresh, routed, and reviewable? + +Evidence inspected: + +- CLI description in `src/cli/program.ts`: Git-native, branch-scoped truth workflow installer for local AI coding agents. +- `src/agents/workflow-manifest.ts`: defines `truthmark-sync`, `truthmark-structure`, `truthmark-document`, `truthmark-preview`, `truthmark-realize`, `truthmark-check`, and `truthmark-portal`. +- `.truthmark/config.yml`: v2 config locates the Truthmark-owned workspace under `docs/truthmark`, with routing/truth/templates scoped inside it. +- `src/checks/*`, `src/impact/build.ts`, `src/context-pack/build.ts`: validation, routing, impact, freshness, and bounded workflow context. + +### OpenSpec + +OpenSpec is a spec/change lifecycle system. Its core concerns are: + +- Create a named change. +- Generate proposal/spec/design/task artifacts. +- Validate Markdown artifact structure and spec deltas. +- Tell agents which artifact is ready/blocked/done. +- Apply tasks/changes. +- Verify behavior against specs. +- Archive/sync deltas into canonical specs. + +Evidence inspected: + +- `schemas/spec-driven/schema.yaml`: proposal/specs/design/tasks/apply workflow artifacts. +- `src/core/artifact-graph/*`: runtime artifact graph and dependency state. +- `src/commands/workflow/status.ts` and `src/commands/workflow/instructions.ts`: agent-facing state and instructions API. +- `src/core/archive.ts` and `src/core/specs-apply.ts`: spec delta apply/archive behavior. +- `src/core/templates/workflows/*`: generated skills that guide agents through OpenSpec actions. + +### Core mission difference + +| Dimension | Truthmark | OpenSpec | +|---|---|---| +| Primary object | Repository truth, routes, evidence, governance | Proposed changes, specs, deltas, tasks | +| Default runtime | Installed agent workflows + local CLI validation | Local CLI state machine + generated workflow commands | +| Write target | Canonical truth docs/routes or functional code depending on workflow | `openspec/changes/*`, `openspec/specs/*`, task files | +| Success condition | Repo truth is aligned, routed, fresh, and reviewable | Change artifacts are complete, valid, implemented, verified, archived | +| Agent role | Keep truth aligned and constrained | Produce/apply/verify change artifacts | +| What not to become | General spec/task lifecycle | N/A; that is OpenSpec's mission | + +Truthmark should learn OpenSpec's agent-state ergonomics, not its product lifecycle. + +--- + +## Behavioral architecture comparison + +## 1. Workflow state model + +### OpenSpec behavior + +OpenSpec has an explicit artifact graph. + +Evidence: + +- `src/core/artifact-graph/types.ts` defines `ArtifactSchema` with `id`, `generates`, `description`, `template`, optional `instruction`, and `requires`. +- `src/core/artifact-graph/graph.ts` topologically sorts artifacts and computes ready/blocked/done state. +- `src/core/artifact-graph/state.ts` detects completion from generated output files. +- `schemas/spec-driven/schema.yaml` declares concrete artifacts: proposal, specs, design, tasks, apply. +- `schemas/workspace-planning/schema.yaml` declares a different planning workflow with workspace guards. + +This means OpenSpec can answer: + +- Which artifact should the agent create next? +- Which dependency blocks it? +- Which output path proves completion? +- Which apply action is unlocked? + +The workflow state is not only prose; it is computable. + +### Truthmark behavior + +Truthmark has a workflow manifest rather than an artifact graph. + +Evidence: + +- `src/agents/workflow-manifest.ts` declares workflow IDs, triggers, negative triggers, allowed writes, forbidden adjacency, report sections, helpers, and subagents. +- `src/context-pack/build.ts` computes workflow-specific allowed write paths and bounded context for `truth-sync`, `truth-document`, and `truth-realize`. +- `src/checks/check.ts`, `src/impact/build.ts`, and `src/repo-index/route-map.ts` compute truth health, affected routes, impacted source/truth surfaces, and diagnostics. + +Truthmark's state is more governance-oriented than sequence-oriented. It can identify affected routes and allowed paths, but it does not yet expose a single OpenSpec-style “ready/blocked/next action” workflow API. + +### Judgement + +OpenSpec is better at making workflow state legible to agents. Truthmark should not copy artifact DAGs, but should expose governance state in a similarly explicit way. + +Recommended Truthmark direction: + +```bash +truthmark workflow status --workflow truth-sync --base main --json +truthmark workflow instructions --workflow truth-sync --base main --json +``` + +The response should include: + +- selected workflow +- applicability and non-applicability reasons +- changed files inspected +- affected routes +- target truth docs +- allowed write paths +- forbidden write paths +- required checks/helpers +- blockers/warnings +- suggested next actions +- report template + +This reuses Truthmark's existing concepts and avoids OpenSpec-style proposal/spec artifacts. + +--- + +## 2. Agent-facing CLI contract + +### OpenSpec behavior + +OpenSpec's CLI acts like an agent API. + +Evidence: + +- `src/commands/workflow/status.ts` loads planning home, schema, change metadata, context, and returns structured status. +- `src/core/artifact-graph/instruction-loader.ts` returns rich status fields such as `planningHome`, `changeRoot`, `artifactPaths`, `affectedAreas`, `nextSteps`, `actionContext`, and `applyRequires`. +- `src/commands/workflow/instructions.ts` returns artifact-specific instructions, dependency files, template content, resolved output paths, context/rules, and unlocks. +- Generated workflow templates such as `src/core/templates/workflows/propose.ts`, `continue-change.ts`, `apply-change.ts`, and `archive-change.ts` instruct agents to call the CLI JSON endpoints before acting. + +OpenSpec's generated prompts are not the sole source of truth. They teach agents to ask the CLI for the current state and obey it. + +### Truthmark behavior + +Truthmark has useful JSON-capable commands and helper validators: + +- `truthmark check --json` +- `truthmark impact --base ... --json` +- `truthmark context --workflow ... --format json` +- `truthmark validate sync-report ... --json` +- `truthmark validate document-report ... --json` +- `truthmark validate write-lease ... --json` + +Evidence: + +- Command definitions in `src/cli/program.ts`. +- Handler validation in `src/cli/handlers.ts`. +- Helper definitions in `src/agents/workflow-manifest.ts`. +- Context pack construction in `src/context-pack/build.ts`. + +But the contract is distributed. Agents have to know which combination of commands to call and how to map them to workflow intent. + +### Judgement + +OpenSpec does better because the CLI itself presents a coherent agent-facing contract. + +Recommended Truthmark direction: + +Publish and implement a stable **Agent-Compatible CLI Contract**: + +- human/setup commands: `config`, `init` +- agent/context commands: `check`, `impact`, `context`, `validate`, future `workflow status`, future `workflow instructions` +- stable JSON fields +- best-effort fields +- missing-command degradation behavior +- examples for each installed host surface + +This is a documentation and API-contract improvement, not a spec-driver pivot. + +--- + +## 3. Action constraints and write boundaries + +### OpenSpec behavior + +OpenSpec returns explicit action context. + +Evidence: + +- `src/core/change-status-policy.ts` defines `ActionContext` with mode, source of truth, planning artifacts, linked context, allowed edit roots, whether affected-area selection is required, and constraints. +- Repo-local mode allows project-root edits. +- Workspace-planning mode has empty allowed edit roots and explicit constraints to avoid implementation edits without an allowed root. +- Generated apply/archive workflows stop on unsupported workspace modes or empty allowed roots. + +This is one of OpenSpec's strongest behaviors: agents are given not just content but an editing policy. + +### Truthmark behavior + +Truthmark already has stronger product-level write boundaries than OpenSpec in some ways: + +- `truthmark-sync`: canonical truth docs and routing files only. +- `truthmark-document`: canonical truth docs and routing files only. +- `truthmark-realize`: functional code only; must not edit truth docs/routing. +- `truthmark-preview` and `truthmark-check`: read-only. +- `truthmark-portal`: configured Portal output only. +- write leases limit doc-writing subagents. +- path containment prevents writes outside repo/worktree. + +Evidence: + +- `src/agents/workflow-manifest.ts`: workflow allowed writes and forbidden adjacency. +- `src/templates/workflow-surfaces.ts`: subagent and write-lease instructions. +- `src/fs/paths.ts` and `src/git/repository.ts`: repo containment and Git worktree path resolution. +- `src/context-pack/build.ts`: allowed write paths by workflow. + +However, Truthmark's action constraints are mostly encoded in generated prose and manifest data. They are not yet a central machine-readable response for every workflow. + +### Judgement + +Truthmark has the right governance primitives; OpenSpec packages them better for agent consumption. + +Recommended Truthmark direction: + +Every workflow status/context response should include: + +```json +{ + "workflow": "truthmark-sync", + "mode": "truth-doc-write", + "allowedWritePaths": [], + "forbiddenWritePaths": [], + "stopConditions": [], + "requiredEvidence": [], + "leaseValidationCommand": null, + "sourceOfTruth": "repository" +} +``` + +For read-only workflows, `allowedWritePaths` should be empty and `mode` should explicitly be `read-only`. + +This directly supports Truthmark's mission and does not copy OpenSpec's artifacts. + +--- + +## 4. Generated agent surfaces + +### OpenSpec behavior + +OpenSpec generates tool-native commands and skills through an adapter architecture. + +Evidence: + +- `src/core/command-generation/types.ts` separates `CommandContent` from `ToolCommandAdapter`. +- `src/core/command-generation/generator.ts` delegates file path and formatting to the adapter. +- `src/core/command-generation/registry.ts` registers adapters for multiple tools. +- Tool-specific adapters format commands for Claude, Cursor, Codex, Gemini, GitHub Copilot, OpenCode, and others. +- `src/core/init.ts` generates skills and/or commands based on profile/delivery settings. + +OpenSpec's adapter separation is maintainable. The workflow content is tool-agnostic; rendering is tool-specific. + +### Truthmark behavior + +Truthmark already generates many high-value agent surfaces: + +- Codex: `.codex/skills`, `.codex/agents`, metadata +- OpenCode: `.opencode/skills`, `.opencode/agents` +- Claude Code: `CLAUDE.md`, `.claude/skills`, `.claude/agents` +- GitHub Copilot: `.github/copilot-instructions.md`, `.github/skills`, `.github/prompts`, `.github/agents` +- Gemini CLI: `GEMINI.md`, `.gemini/skills`, `.gemini/commands`, `.gemini/agents` + +Evidence: + +- `src/templates/generated-surfaces.ts`: platform-specific surface rendering. +- `src/templates/workflow-surfaces.ts`: skill package rendering, report templates, subagent instructions, helper manifests. +- `src/config/schema.ts`: supported platforms are encoded in config schema. + +Truthmark's generated surfaces are product-aligned and strong. The implementation, however, appears more centralized and constant-heavy than OpenSpec's adapter architecture. + +### Judgement + +OpenSpec does better internally by separating platform adaptation from workflow content. + +Recommended Truthmark direction: + +Refactor generated surface implementation toward a platform adapter registry: + +- platform id +- supported surface types +- output paths +- formatting/frontmatter rules +- capability flags +- skill rendering rules +- command rendering rules +- agent/subagent rendering rules + +This is an internal maintainability improvement. It should not imply chasing OpenSpec's full tool list or broadening the product mission. + +--- + +## 5. Schema and config design + +### OpenSpec behavior + +OpenSpec supports workflow schemas that define artifact IDs, dependencies, generated paths, templates, instructions, and apply behavior. + +Evidence: + +- `schemas/spec-driven/schema.yaml`: built-in spec-driver workflow. +- `schemas/workspace-planning/schema.yaml`: workspace planning workflow. +- `src/core/artifact-graph/resolver.ts`: project-local, user override, and package built-in schema resolution. +- `src/core/artifact-graph/schema.ts`: validation for schema integrity such as missing refs, duplicates, and cycles. + +This extensibility is valuable because OpenSpec's product is workflow/spec definition. + +### Truthmark behavior + +Truthmark's v2 config is intentionally narrower and governance-specific. + +Evidence: + +- `src/config/schema.ts`: strict `version: 2`, supported platforms, workspace, routes, truth root, templates, generated portal, instruction targets, frontmatter policy, ignore policy. +- `src/config/defaults.ts`: default workspace is under `docs/truthmark`. +- `src/config/load.ts`: validates unsupported legacy shape, workspace containment, forbidden overlaps, child path restrictions, portal output overlap, and instruction targets outside the Truthmark workspace. +- `.truthmark/config.yml`: active config follows this v2 model. + +Truthmark's narrower schema is a strength. It prevents the tool from becoming a generic spec workflow engine. + +### Judgement + +OpenSpec's schema extensibility should not be copied wholesale. Truthmark should instead add constrained governance extension points. + +Good future extension points: + +- per-workflow severity tuning +- route policy hints +- evidence requirements +- frontmatter policy profiles +- report section toggles +- generated surface selection +- organization-specific required truth-doc sections + +Avoid: + +- arbitrary workflow DAGs +- arbitrary artifact templates +- OpenSpec-style changes/specs/tasks +- user-defined lifecycle engines + +--- + +## 6. Routing, ownership, and source-of-truth model + +### Truthmark behavior + +This is Truthmark's strongest unique advantage over OpenSpec. + +Evidence: + +- `src/routing/areas.ts`: truth document kinds and route area parser. +- `src/routing/area-resolver.ts`: root route index, child route files, containment, duplicate area detection, unreferenced child route diagnostics. +- `docs/truthmark/routes/areas.md`: route index delegates to multiple area files. +- `docs/truthmark/routes/areas/*.md`: area-specific ownership and code/truth mapping. +- `src/checks/areas.ts`: validates code surfaces, truth docs, unmapped functional code, route precision, topology pressure. +- `src/repo-index/route-map.ts`: emits a route map that links route id/name/key/source path/code surface/truth docs/update triggers. + +Truthmark knows which parts of the repo own which truth docs. OpenSpec's spec areas are more about capabilities/change artifacts than repository-truth ownership. + +### OpenSpec behavior + +OpenSpec has affected areas and workspace-planning area scopes, but those are part of planning/spec workflow. + +Evidence: + +- `.openspec.yaml` change metadata includes affected areas. +- `schemas/workspace-planning/schema.yaml` requires area-scoped specs and guards repo-local implementation edits. +- `src/core/planning-home.ts` distinguishes repo and workspace planning homes. + +### Judgement + +Truthmark should not trade its route ownership model for OpenSpec's spec area model. But it can learn from OpenSpec's way of surfacing affected areas in status/instructions. + +Recommended Truthmark direction: + +Workflow status should explicitly report: + +- affected routes +- owner route files +- target truth docs +- unmatched changed files +- ownership ambiguity +- route precision score +- route topology pressure + +This would turn Truthmark's internal route intelligence into agent-facing guidance. + +--- + +## 7. Validation behavior + +### OpenSpec behavior + +OpenSpec validates a specific Markdown contract deeply. + +Evidence: + +- `src/core/parsers/markdown-parser.ts`: masks fenced code blocks, parses Purpose/Requirements/Scenarios. +- `src/core/parsers/requirement-blocks.ts`: parses ADDED/MODIFIED/REMOVED/RENAMED delta sections. +- `src/core/validation/validator.ts`: validates SHALL/MUST requirements, scenarios, duplicate/conflicting requirements, structural rules, strict mode. +- `src/core/specs-apply.ts`: applies deltas in specific order and validates rebuilt specs. +- `src/core/archive.ts`: checks task progress, applies deltas, validates, and archives. + +This validation is impressive, but it is tightly coupled to OpenSpec's spec-driver model. + +### Truthmark behavior + +Truthmark validates repository-truth health rather than spec conformance. + +Evidence: + +- `src/checks/check.ts`: composes branch scope, authority, areas, frontmatter, links, decisions, generated surfaces, freshness. +- `src/checks/frontmatter.ts`: validates required/recommended fields and route kind matching. +- `src/checks/decisions.ts`: validates required sections by truth kind. +- `src/checks/generated-surfaces.ts`: validates generated surfaces and managed blocks. +- `src/freshness/check.ts`: maps impact diagnostics to freshness results. +- `src/evidence/validate.ts`: validates evidence paths/globs, existence, TypeScript symbol presence, line spans, and hashes. + +Truthmark's validation is better aligned with its mission. It should not adopt OpenSpec's SHALL/MUST delta parser. + +### Judgement + +OpenSpec's transferable advantage is not the exact validator; it is the quality of validation feedback and lifecycle integration. + +Recommended Truthmark direction: + +Add a truth health scorecard above raw diagnostics: + +- routing coverage +- ownership clarity +- evidence support +- freshness against branch diff +- generated surface freshness +- truth-doc structure +- decision/rationale preservation + +Keep the underlying validation Truthmark-specific. + +--- + +## 8. Explore/read-only workflow design + +### OpenSpec behavior + +OpenSpec's `explore` stance is productively low-ceremony: + +- read/search/investigate allowed +- no implementation +- no fixed artifact generation +- diagrams/tables/tradeoffs encouraged +- capture only if user explicitly asks + +Evidence: + +- `src/core/templates/workflows/explore.ts` and workflow docs around action-oriented commands. + +### Truthmark behavior + +Truthmark has `truthmark-preview`, which is explicit and read-only, but is narrower: it previews routing/workflow target/writes rather than offering a broader truth-discovery stance. + +Evidence: + +- `src/agents/workflow-manifest.ts`: `truthmark-preview` is read-only, explicit, not a substitute for check/gate. + +### Judgement + +OpenSpec does better in UX here. Truthmark should expand preview into a broader read-only “truth exploration” stance. + +Possible questions it should answer: + +- Which truth docs own this behavior? +- Is route ownership ambiguous? +- What evidence supports or contradicts this claim? +- Which source files should be inspected before editing? +- What truth update would likely be required after this code change? +- Which files must not be touched? + +This supports Truthmark's mission and does not require proposals/specs/tasks. + +--- + +## 9. Workspace and multi-repo behavior + +### OpenSpec behavior + +OpenSpec has a planning-home abstraction: + +- repo-local planning home +- workspace planning home +- linked repos/context +- workspace mode constraints that prevent implementation edits unless allowed roots are selected + +Evidence: + +- `src/core/planning-home.ts`: `PlanningHome` type with `kind: 'repo' | 'workspace'`. +- `src/core/workspace/foundation.ts`: workspace state with name/context/links/tools/workspace skills. +- `src/core/change-status-policy.ts`: workspace-planning mode yields empty allowed edit roots and explicit constraints. + +### Truthmark behavior + +Truthmark is intentionally branch-scoped and repo-scoped. Its path/git containment is strong: + +- Git repository discovery in `src/git/repository.ts`. +- Worktree containment and symlink-aware path checks. +- Repo-relative write guards in `src/fs/paths.ts`. +- Config workspace cannot overlap forbidden repository paths. + +### Judgement + +Truthmark should not implement OpenSpec workspaces. But it can borrow read-only external context guardrails. + +Recommended future direction: + +- Allow truth docs to cite external evidence as read-only context, if configured. +- Mark external evidence explicitly in status/check output. +- Refuse writes outside the current repository unless a future explicit multi-repo mode is deliberately designed. + +This keeps Truthmark's branch-scoped mission intact. + +--- + +## OpenSpec advantages worth learning from + +## Advantage 1: Agent-readable status and instructions + +OpenSpec's biggest advantage is that agents do not have to infer the current workflow from prose. They can ask the CLI. + +Transfer to Truthmark: + +- Add `workflow status --json` and `workflow instructions --json`. +- Make these compose existing check/impact/context/manifest results. +- Include next actions, gates, blockers, affected routes, and write constraints. + +Do not copy: + +- proposal/spec/design/task artifacts +- artifact completion by file existence +- spec archive lifecycle + +## Advantage 2: Explicit action context + +OpenSpec's `actionContext` is a clean design pattern. + +Transfer to Truthmark: + +- Return action constraints for each workflow. +- Include mode, allowed writes, forbidden writes, required evidence, and stop conditions. +- Make read-only workflows machine-readably read-only. + +Do not copy: + +- workspace apply/archive semantics +- allowed edit roots for implementation planning as a product concept + +## Advantage 3: Generated tool-native surfaces via adapters + +OpenSpec's adapter registry is a better internal architecture for multi-host generation. + +Transfer to Truthmark: + +- Refactor generated surface rendering into platform adapters. +- Keep workflow content separate from formatting. +- Add capability flags per platform. + +Do not copy: + +- expanding to every agent host before workflow quality is mature +- OpenSpec command names or behavior + +## Advantage 4: Workflow playbooks are operational, not just descriptive + +OpenSpec workflow templates tell the agent exactly what to call, read, write, verify, and report. + +Transfer to Truthmark: + +- Generate clearer per-workflow playbooks from `workflow-manifest.ts`. +- Each playbook should include first CLI calls, required evidence, allowed writes, stop conditions, and final report shape. + +Do not copy: + +- phase-gated spec lifecycle +- artifact dependency DAGs + +## Advantage 5: Human/agent CLI split + +OpenSpec is clearer about which commands are for humans and which are for agents. + +Transfer to Truthmark: + +- Document an Agent-Compatible CLI Contract. +- Stabilize JSON fields for agent use. +- Mark setup/human-only commands separately. + +Do not copy: + +- making the CLI the only runtime for workflows + +## Advantage 6: Explore mode UX + +OpenSpec's read-only explore stance is a strong low-ceremony workflow. + +Transfer to Truthmark: + +- Expand `truthmark-preview` into a broader read-only truth exploration workflow. +- Focus on ownership, route ambiguity, evidence, likely truth impact, and write boundaries. + +Do not copy: + +- using explore to create OpenSpec artifacts + +## Advantage 7: Structured verification reports + +OpenSpec's verification shape is easier to read because it groups issues by outcome and priority. + +Transfer to Truthmark: + +- Add a truth health scorecard grouping diagnostics into governance outcomes. + +Do not copy: + +- validating implementation against specs as Truthmark's mission + +## Advantage 8: Schema resolution provenance + +OpenSpec surfaces schema sources: project/user/package. + +Transfer to Truthmark: + +- For config/rules/policies, expose provenance: default, config, route file, generated surface, ignored path. +- In diagnostics, say where a rule came from. + +Do not copy: + +- arbitrary workflow schema overrides + +--- + +## What Truthmark already does better or should preserve + +## 1. Repository-truth ownership model + +Truthmark has a stronger model for mapping code surfaces to canonical truth docs and update triggers. + +Preserve: + +- route files +- truth document kinds +- code surface mapping +- update truth triggers +- unmapped surface diagnostics +- route precision/topology pressure metrics + +Do not replace these with OpenSpec affected areas. + +## 2. Separation from project docs + +The current v2 design keeps Truthmark-owned material under a dedicated workspace (`docs/truthmark`) while allowing route files to reference project-owned docs/evidence. + +Preserve: + +- Truthmark-owned routes/truth/templates/generated workspace +- project docs remain project-owned +- no broad ownership of arbitrary documentation + +## 3. Write boundaries by workflow + +Truthmark's workflow boundaries are product-critical: + +- Sync/Document write truth docs/routes. +- Realize writes code, not truth docs. +- Preview/Check are read-only. +- Portal writes configured portal output only. + +Preserve and make machine-readable. + +## 4. Local-first, Git-reviewable operation + +Truthmark's advantage is Git-native reviewability and no hosted state. + +Preserve: + +- generated surfaces committed to repo +- branch-scoped checks +- local CLI validation +- no database/server dependency + +## 5. Evidence validation + +Truthmark's evidence checks are mission-specific and valuable: + +- paths/globs inside repo +- existence +- line spans +- TS symbol presence +- hashes + +OpenSpec validates spec syntax; Truthmark validates evidence and truth alignment. Keep that distinction. + +--- + +## Specific recommendations + +## Priority 1: Add `truthmark workflow status/instructions --json` + +### Problem + +Truthmark has `check`, `impact`, `context`, and workflow manifest data, but agents do not get one unified workflow-state response. + +### Proposed shape + +```bash +truthmark workflow status --workflow truth-sync --base main --json +truthmark workflow instructions --workflow truth-sync --base main --json +``` + +Minimum JSON fields: + +```json +{ + "schemaVersion": "truthmark-workflow/v0", + "workflow": "truthmark-sync", + "applicability": { + "state": "applicable | not_applicable | blocked | ambiguous", + "reasons": [] + }, + "branchScope": {}, + "changedFiles": [], + "affectedRoutes": [], + "targetTruthDocs": [], + "actionContext": { + "mode": "read-only | truth-doc-write | route-write | code-write | portal-write", + "allowedWritePaths": [], + "forbiddenWritePaths": [], + "stopConditions": [], + "requiredEvidence": [] + }, + "checks": { + "required": [], + "recommended": [], + "helpers": [] + }, + "nextSteps": [], + "reportTemplate": {} +} +``` + +### Why this is OpenSpec-inspired but not OpenSpec-copying + +It borrows the status/instructions ergonomics, not the artifact lifecycle. + +Truthmark state is route/truth/evidence/write-boundary state, not proposal/spec/task state. + +--- + +## Priority 2: Make action constraints first-class + +### Problem + +Truthmark write boundaries exist, but they are split across manifest, generated prompts, context packs, and validators. + +### Recommendation + +Every workflow response should include an `actionContext` equivalent. + +Fields: + +- workflow mode +- allowed write paths +- forbidden write paths +- read-only assertion +- write lease requirement +- validation command for write lease +- stop conditions +- source-of-truth scope +- generated surfaces that must not be edited manually + +### Benefit + +Agents become less likely to improvise, accidentally edit generated surfaces, or mix workflows. + +--- + +## Priority 3: Generate clearer workflow playbooks from the manifest + +### Problem + +`src/agents/workflow-manifest.ts` is rich, but the generated workflow experience can be more operational. + +### Recommendation + +For each workflow, generate a playbook with: + +- when to use +- when not to use +- first CLI calls +- required evidence +- allowed writes +- stop conditions +- helper validators +- subagent delegation policy +- final report schema +- examples of correct/incorrect invocation + +### Benefit + +OpenSpec shows that workflow text should be executable guidance, not just a policy document. + +--- + +## Priority 4: Add a truth health scorecard + +### Problem + +Truthmark diagnostics are detailed but may be harder to interpret as product health. + +### Recommendation + +Add a scorecard layer over `truthmark check`: + +- Routing coverage +- Ownership clarity +- Evidence support +- Freshness against branch diff +- Generated surface freshness +- Truth-doc structure +- Decision/rationale preservation + +Each dimension should have: + +- status: pass/warn/fail/not-run +- key evidence +- top remediation +- linked raw diagnostics + +### Benefit + +OpenSpec's verify UX is easier for humans; Truthmark can offer equivalent governance clarity. + +--- + +## Priority 5: Refactor generated surfaces into adapters + +### Problem + +Truthmark supports many host surfaces, but rendering is centralized. + +### Recommendation + +Introduce a platform adapter model: + +```ts +interface TruthmarkSurfaceAdapter { + id: PlatformId; + capabilities: SurfaceCapability[]; + renderSkillPackage(...): GeneratedFile[]; + renderCommands(...): GeneratedFile[]; + renderAgents(...): GeneratedFile[]; + renderInstructionBlock(...): GeneratedFile[]; +} +``` + +### Benefit + +- Easier platform additions. +- Better parity tests. +- Cleaner handling of platform-specific frontmatter/permissions. +- Less risk when changing generated workflows. + +--- + +## Priority 6: Expand Preview into Truth Explore + +### Problem + +Truthmark Preview is useful but narrower than OpenSpec Explore. + +### Recommendation + +Add or expand a read-only workflow focused on truth discovery: + +- identify owning route/truth docs +- detect ambiguous ownership +- list source evidence to inspect +- list likely truth impacts +- warn about forbidden writes +- propose, but do not perform, a sync/document/realize path + +### Benefit + +Gives users and agents a safe investigation mode before picking a workflow. + +--- + +## Priority 7: Add optional Truth Sync Plan + +### Problem + +Truth Sync writes canonical truth docs. Reviewers benefit from seeing intent before edits. + +### Recommendation + +Before or inside `truthmark-sync`, produce a plan section: + +- code changes reviewed +- affected routes +- target truth docs +- stale claims +- proposed updates +- evidence file/line references +- no-update-needed rationale when applicable + +This can be a report section or transient output, not a persisted change object. + +### Benefit + +It borrows OpenSpec's reviewable delta intent without adding OpenSpec change directories. + +--- + +## Important non-goals + +Truthmark should **not**: + +- become a spec-driver library +- create `truthmark/changes/*` lifecycle objects +- require proposals/specs/design/tasks before implementation +- own implementation task execution +- merge delta specs into canonical specs +- implement OpenSpec archive/sync semantics +- implement arbitrary workflow DAG schemas +- govern arbitrary project docs +- replace project-specific documentation systems +- implement OpenSpec workspaces/context stores +- coordinate multi-repo change lifecycles +- require agents to use Truthmark for every coding action + +Truthmark should continue to focus on: + +- route ownership +- canonical truth docs +- evidence-backed claims +- branch-scoped freshness +- reviewable Git diffs +- generated agent surfaces +- safe write boundaries +- local-first validation +- repository-truth health + +--- + +## Behavioral overlap map + +| Overlap field | OpenSpec behavior | Truthmark behavior | Best Truthmark lesson | +|---|---|---|---| +| Local CLI | Agent state engine for spec workflow | Installer/checker/context/validator for truth workflows | Make agent-compatible workflow state explicit | +| Agent surfaces | Generated skills/commands call CLI JSON | Generated skills/prompts/agents encode workflow policy | Teach generated surfaces to consume unified JSON contract | +| Schemas/config | Workflow artifact schemas, override layers | Strict v2 governance config | Add constrained governance extension points, not arbitrary DAGs | +| Validation | Markdown spec/delta correctness | Truth routing/evidence/freshness/generated surfaces | Add scorecard and better remediation messages | +| Workspace | Repo/workspace planning homes | Repo-scoped truth workspace under project | Borrow read-only external context guardrails only | +| Status | Ready/blocked/done artifacts | Diagnostics/context/impact but distributed | Add workflow status/instructions | +| Apply/sync | Apply tasks and archive spec deltas | Sync truth docs after behavior changes | Add sync plan/report, not lifecycle artifacts | +| Explore | Read-only discovery stance | Preview routing/write targets | Expand preview into truth exploration | + +--- + +## Implementation sketch for Truthmark vNext + +### Phase 1: No new product surface, only compose existing data + +Add an internal function: + +```ts +buildWorkflowState(repo, workflow, options): WorkflowState +``` + +Inputs: + +- loaded config +- workflow manifest entry +- route map +- check result +- impact result if base provided +- context pack if supported +- generated surface status + +Outputs: + +- applicability +- affected routes +- target truth docs +- action constraints +- checks/helpers +- next steps + +Expose: + +```bash +truthmark workflow status --workflow [--base ] --json +``` + +### Phase 2: Instructions and playbooks + +Add: + +```bash +truthmark workflow instructions --workflow [--base ] --json +``` + +Return: + +- playbook section +- command sequence +- required reads +- allowed writes +- report template +- validation commands +- stop conditions + +Generate host skill support docs from the same state/playbook schema. + +### Phase 3: Scorecard + +Layer a scorecard onto `check --json` and workflow status: + +- raw diagnostics remain stable +- scorecard groups diagnostics by governance outcome +- final report becomes easier to review + +### Phase 4: Adapter refactor + +Move platform rendering from centralized branching toward adapters. Add parity tests comparing generated files before/after refactor. + +--- + +## Risks and mitigations + +## Risk: Truthmark accidentally becomes OpenSpec-lite + +Mitigation: + +- Keep workflows fixed and governance-specific. +- Do not add artifact DAGs or change folders. +- Do not require planning artifacts before code. +- Keep truth docs as reviewable evidence/decision records, not feature specs. + +## Risk: Agent JSON API becomes another unstable surface + +Mitigation: + +- Version workflow JSON: `truthmark-workflow/v0`. +- Mark stable vs experimental fields. +- Add tests around schema snapshots. + +## Risk: More commands increase cognitive load + +Mitigation: + +- Generated skills should call the commands automatically. +- Humans can keep using existing `check`, `impact`, `context`. +- `workflow status` can explain which lower-level commands it used. + +## Risk: Scorecard oversimplifies diagnostics + +Mitigation: + +- Keep raw diagnostics and file evidence. +- Scorecard should summarize, not replace. + +## Risk: Adapter refactor breaks generated surfaces + +Mitigation: + +- Snapshot all current generated outputs. +- Refactor one platform at a time. +- Require parity tests for unchanged platforms. + +--- + +## Bottom line + +OpenSpec is better at making agent workflows computable and legible. It gives agents a local state machine: status, instructions, action context, generated commands, validation, and archive/apply behavior. + +Truthmark should learn that ergonomics, not OpenSpec's spec-driver lifecycle. + +The strategic improvement is to make Truthmark's repository-truth governance equally explicit: + +- Which truth workflow applies? +- Which routes and truth docs are affected? +- Which claims need evidence? +- What can be edited? +- What must not be edited? +- What checks or helper validators must pass? +- What should the final report say? + +If Truthmark adds that agent-facing workflow contract while preserving its narrow repository-truth mission, it can gain OpenSpec's strongest workflow advantages without becoming OpenSpec. diff --git a/research/2026-06-01-openspec-improvement-passes.md b/research/2026-06-01-openspec-improvement-passes.md new file mode 100644 index 0000000..bea4921 --- /dev/null +++ b/research/2026-06-01-openspec-improvement-passes.md @@ -0,0 +1,978 @@ +# Truthmark Improvement Plans From OpenSpec Research + +> **For Hermes:** Use `subagent-driven-development` to implement these passes one pass at a time. Each pass should finish with focused tests, `npm run check` when feasible, and a Truthmark Sync review if functional source changes were made. + +Date: 2026-06-01 +Source research: `research/2026-06-01-openspec-comparison.md` +Scope: Truthmark implementation, generated agent surfaces, CLI contract, validation/reporting UX. +Non-goal: do **not** turn Truthmark into OpenSpec, a spec-driver library, a proposal/task lifecycle, or an arbitrary workflow DAG engine. + +## Goal + +Convert the OpenSpec comparison findings into staged implementation plans that improve Truthmark's own mission: local-first, Git-native repository-truth governance for coding agents. + +The highest-value theme is to make Truthmark's existing route/truth/evidence/write-boundary knowledge as computable and agent-readable as OpenSpec's `status`, `instructions`, and `actionContext`, while preserving Truthmark's narrower repository-truth mission. + +## Architecture direction + +Truthmark should add a thin workflow-state layer that composes existing systems instead of replacing them: + +- `TRUTHMARK_WORKFLOW_MANIFEST` remains the source for workflow identity, triggers, gates, helpers, report sections, subagents, and declared write boundaries. +- `buildRepoIndex()` / route map remain the source for ownership and truth-doc mapping. +- `runCheck()` / diagnostics remain the source for repository truth health. +- `buildImpactSet()` remains the source for branch-diff effects when `--base` is provided. +- `buildContextPack()` remains the source for bounded workflow context and write paths. +- New `workflow status` and `workflow instructions` commands should compose the above into an agent-facing contract. + +This is OpenSpec-inspired ergonomics, not OpenSpec behavior. Truthmark workflow state is about routes, truth docs, evidence, health, and allowed writes — not proposals, specs, design docs, tasks, archive/apply, or artifact completion by file existence. + +## Implementation principles + +1. **Compose first, refactor later.** Build the workflow-state API from current data sources before reorganizing generated-surface internals. +2. **Version the agent contract early.** Use a schema version such as `truthmark-workflow/v0` so generated agent surfaces can rely on it without pretending it is final. +3. **Keep JSON stable and prose generated from data.** Agent surfaces should teach hosts to call the CLI instead of embedding stale workflow logic. +4. **Make write boundaries machine-readable.** Every workflow status should say whether it is read-only and exactly what it may write. +5. **Keep OpenSpec non-goals visible in code review.** No `changes/`, proposal/spec/task DAGs, archive/apply semantics, arbitrary workflow schemas, or required pre-implementation planning artifacts. + +## Pass overview + +| Pass | Name | Outcome | Can ship independently? | +|---|---|---|---| +| 0 | Baseline contract and guardrails | Document and test the non-OpenSpec boundary before code changes | Yes | +| 1 | Workflow state core | New typed `WorkflowState` builder composes manifest/check/index/impact/context | Yes, internal only | +| 2 | Agent-facing CLI | `truthmark workflow status/instructions --json` expose the state contract | Yes | +| 3 | Generated playbooks consume the contract | Host surfaces call the new CLI and receive operational playbooks | Yes | +| 4 | Compact truth health scorecard | `check --json` gets a tiny diagnostic triage index; workflow-state exposure is deferred | Yes | +| 5 | Preview/Explore wording hardening | Keep `truthmark-preview`; improve read-only discovery instructions without new JSON | Yes | +| 6 | Lightweight Sync intent checklist | Add a pre-write intent section to Sync instructions/reports; no typed plan engine yet | Yes | +| 7 | Platform surface adapter refactor | Deferred internal maintainability refactor after behavior stabilizes | No — explicitly deferred | + +--- + +# Pass 0: Baseline Contract And Guardrails + +## Objective + +Before adding features, make the intended product boundary explicit so later implementation passes do not drift into OpenSpec-lite. + +## Files + +- Modify: `docs/truth/contracts.md` or the current canonical CLI/workflow contract truth doc if routing points elsewhere. +- Modify: `docs/truthmark/truth/**/*.md` only if existing routed truth docs already own CLI/workflow behavior. +- Modify: `tests/cli/help.test.ts` for absence checks if new commands are not yet implemented. +- Create: `tests/workflow-state/non-goals.test.ts` if a new test directory is acceptable, otherwise place absence tests in the closest existing CLI/workflow test file. + +## Tasks + +### Task 0.1: Record the closed product decision + +**Objective:** Make the OpenSpec-learning boundary explicit in canonical truth. + +**Steps:** + +1. Find the routed truth owner for CLI/workflow contracts: + - Inspect `docs/truthmark/routes/areas.md` and child area files when present. + - Identify the truth doc that owns `src/cli/**`, `src/agents/workflow-manifest.ts`, and generated surfaces. +2. Add a dated decision: + - Truthmark may add agent-readable workflow status/instructions/action-context behavior. + - Truthmark must not add OpenSpec-style proposal/spec/design/task lifecycle artifacts. + - Truthmark must not add arbitrary workflow DAG schemas or archive/apply semantics. +3. Keep the language product-scoped: Truthmark is a repository-truth governance layer, not an application feature. + +**Verification:** + +```bash +npm run check +npx tsx src/cli/main.ts check --json +npx tsx src/cli/main.ts index --json +``` + +Expected: no new errors. Existing unrelated review diagnostics may be reported separately. + +### Task 0.2: Add absence tests for future-only OpenSpec concepts + +**Objective:** Prevent accidental exposure of OpenSpec-like lifecycle surface while implementing the improvements. + +**Test examples:** + +- CLI help does not mention `proposal`, `spec delta`, `archive`, `apply`, `changes`, or `tasks` as Truthmark lifecycle commands. +- Default config does not include arbitrary workflow schemas or artifact DAG configuration. +- Generated workflow surfaces do not instruct agents to create `truthmark/changes/*` directories. + +**Files:** + +- Modify: `tests/cli/help.test.ts` +- Modify: `tests/init/init.test.ts` +- Modify: `tests/templates/generated-surfaces.test.ts` + +**Verification:** + +```bash +npx vitest run tests/cli/help.test.ts tests/init/init.test.ts tests/templates/generated-surfaces.test.ts +``` + +Expected: tests pass and protect the non-goals before feature work starts. + +--- + +# Pass 1: Workflow State Core + +## Objective + +Create an internal typed workflow-state builder that composes existing Truthmark data into one agent-readable model. Do not expose new CLI commands yet unless needed for tests. + +## Architecture + +Add a new internal module, for example: + +```ts +buildWorkflowState(cwd, options): Promise +``` + +The builder should be a composition layer, not a new workflow engine. + +## Proposed files + +- Create: `src/workflow-state/types.ts` +- Create: `src/workflow-state/build.ts` +- Create: `src/workflow-state/action-context.ts` +- Create: `tests/workflow-state/build.test.ts` +- Modify: `src/context-pack/types.ts` only if existing context pack types need to expose richer action constraints. +- Modify: `src/context-pack/build.ts` only if write-path derivation should be shared rather than duplicated. + +## Proposed type shape + +```ts +export type WorkflowStateSchemaVersion = "truthmark-workflow/v0"; + +export type WorkflowApplicabilityState = + | "applicable" + | "not_applicable" + | "blocked" + | "ambiguous"; + +export type WorkflowActionMode = + | "read-only" + | "truth-doc-write" + | "route-write" + | "code-write" + | "portal-write"; + +export type WorkflowActionContext = { + mode: WorkflowActionMode; + sourceOfTruth: "repository"; + allowedWritePaths: string[]; + forbiddenWritePaths: string[]; + stopConditions: string[]; + requiredEvidence: string[]; + helperValidationCommands: string[]; + writeLeaseRequired: boolean; +}; + +export type WorkflowState = { + schemaVersion: WorkflowStateSchemaVersion; + workflow: TruthmarkWorkflowId; + base: string | null; + applicability: { + state: WorkflowApplicabilityState; + reasons: string[]; + }; + changedFiles: Array<{ path: string; status?: string }>; + affectedRoutes: Array<{ + id?: string; + name?: string; + sourcePath?: string; + codeSurface: string[]; + truthDocs: string[]; + }>; + targetTruthDocs: string[]; + actionContext: WorkflowActionContext; + checks: { + required: string[]; + recommended: string[]; + helpers: string[]; + }; + diagnostics: Diagnostic[]; + nextSteps: string[]; + reportSections: string[]; +}; +``` + +## Tasks + +### Task 1.1: Add workflow-state types + +**Objective:** Define the contract in one place before implementation. + +**Files:** + +- Create: `src/workflow-state/types.ts` +- Test: `tests/workflow-state/build.test.ts` + +**Test first:** + +Add a compile-level or runtime shape test that imports the public types and asserts a minimal `WorkflowState` object can be constructed with `schemaVersion: "truthmark-workflow/v0"`. + +**Verification:** + +```bash +npx vitest run tests/workflow-state/build.test.ts +npm run typecheck +``` + +Expected before implementation: type/import failure. Expected after implementation: pass. + +### Task 1.2: Implement `actionContext` mapping from the manifest + +**Objective:** Convert each fixed Truthmark workflow into a machine-readable action policy. + +**Files:** + +- Create: `src/workflow-state/action-context.ts` +- Test: `tests/workflow-state/build.test.ts` + +**Rules:** + +- `truthmark-preview` and `truthmark-check` are `read-only` and have empty `allowedWritePaths`. +- `truthmark-sync` is `truth-doc-write` with route/truth-doc allowed writes from context/index data. +- `truthmark-document` is `truth-doc-write` or `route-write` depending on route updates required; start with `truth-doc-write` unless a later route-specific distinction is implemented. +- `truthmark-structure` is `route-write` with route files and starter truth docs only. +- `truthmark-realize` is `code-write` and must forbid truth docs/routing. +- `truthmark-portal` is `portal-write` and must only allow the configured portal output when enabled. + +**Test cases:** + +- Read-only workflows return no allowed writes. +- Realize forbids Truthmark route/truth paths. +- Sync includes helper validation commands from manifest helpers. +- Missing/invalid config produces blocked or empty write boundaries, not permissive defaults. + +**Verification:** + +```bash +npx vitest run tests/workflow-state/build.test.ts -t "action context" +``` + +### Task 1.3: Implement `buildWorkflowState()` composition + +**Objective:** Build state from existing Truthmark systems. + +**Files:** + +- Create: `src/workflow-state/build.ts` +- Modify: `src/context-pack/build.ts` only if shared helpers are needed. +- Test: `tests/workflow-state/build.test.ts` + +**Implementation outline:** + +1. Load manifest entry from `TRUTHMARK_WORKFLOW_MANIFEST`. +2. Build repo index with `buildRepoIndex(cwd)`. +3. Load config through the same path used by context/check. +4. If `base` is provided, call `buildImpactSet(rootDir, { base })`. +5. For supported workflows, call `buildContextPack(rootDir, { workflow, base })` or a shared internal write-path helper. +6. Merge diagnostics from config/index/impact/context. +7. Derive `applicability` from manifest triggers, config presence, base presence, changed-file availability, and route ambiguity diagnostics. +8. Produce `nextSteps` from blockers and manifest gates. + +**Important:** Do not invent OpenSpec-style ready/blocked artifact semantics. Applicability means “can this Truthmark workflow safely run now?” not “which artifact is next?” + +**Verification:** + +```bash +npx vitest run tests/workflow-state/build.test.ts +npm run typecheck +``` + +### Task 1.4: Add fixture coverage for missing config and ambiguous routing + +**Objective:** Ensure workflow state is fail-closed. + +**Files:** + +- Modify: `tests/helpers/temp-repo.ts` or existing repo fixture helper. +- Modify: `tests/workflow-state/build.test.ts` + +**Test cases:** + +- Missing `.truthmark/config.yml` makes Sync not applicable or blocked. +- No changed files with `--base` makes Sync not applicable. +- Unmapped changed functional code produces an ambiguity/blocker reason. +- Context-pack warnings are preserved as diagnostics. + +**Verification:** + +```bash +npx vitest run tests/workflow-state/build.test.ts +``` + +--- + +# Pass 2: Agent-Facing CLI Contract + +## Objective + +Expose the workflow-state layer through stable JSON commands that agents can call before acting. + +## Proposed CLI + +```bash +truthmark workflow status --workflow truthmark-sync --base main --json +truthmark workflow instructions --workflow truthmark-sync --base main --json +``` + +Support legacy/short workflow aliases deliberately if needed: + +- `truth-sync` -> `truthmark-sync` +- `truth-document` -> `truthmark-document` +- `truth-realize` -> `truthmark-realize` + +If aliases are supported, add tests and document them. Do not add aliases accidentally. + +## Files + +- Modify: `src/cli/program.ts` +- Modify: `src/cli/handlers.ts` +- Create: `src/workflow-state/instructions.ts` +- Modify: `src/output/render.ts` only if special rendering is needed; prefer normal `CommandResult` JSON. +- Test: `tests/cli/workflow.test.ts` +- Test: `tests/integration/agent-workflow-contract.test.ts` + +## Tasks + +### Task 2.1: Add CLI parser for `workflow status` + +**Objective:** Wire the status command to `buildWorkflowState()`. + +**Expected command result:** + +```ts +{ + command: "workflow status", + summary: "Truthmark workflow status completed for truthmark-sync.", + diagnostics, + data: { workflowState } +} +``` + +**Test first:** + +Add a subprocess test using `tests/helpers/run-cli.ts` or the existing CLI helper: + +```bash +npx tsx src/cli/main.ts workflow status --workflow truthmark-sync --json +``` + +Expected before implementation: command not found. Expected after implementation: JSON command envelope with `data.workflowState.schemaVersion === "truthmark-workflow/v0"`. + +**Verification:** + +```bash +npx vitest run tests/cli/workflow.test.ts -t "workflow status" +``` + +### Task 2.2: Add CLI parser for `workflow instructions` + +**Objective:** Give agents a workflow playbook and command sequence derived from the same state. + +**Instruction output should include:** + +- workflow id and display name +- first commands to run +- required reads +- allowed writes +- forbidden writes +- stop conditions +- helper validator commands +- report sections +- final report shape +- source state summary + +**Test first:** + +Assert `workflow instructions --workflow truthmark-sync --json` includes: + +- `data.instructions.schemaVersion` +- `data.instructions.commandSequence` +- `data.instructions.actionContext` +- `data.instructions.reportTemplate.sections` + +**Verification:** + +```bash +npx vitest run tests/cli/workflow.test.ts -t "workflow instructions" +``` + +### Task 2.3: Document the Agent-Compatible CLI Contract + +**Objective:** Make the human/agent command split explicit. + +**Files:** + +- Modify: `docs/truth/contracts.md` or routed CLI contract truth doc. +- Optionally modify: `README.md` only with a compact conceptual pointer, not a long command inventory. + +**Content:** + +- Human/setup commands: `config`, `init`. +- Agent/context commands: `check`, `index`, `impact`, `context`, `validate`, `workflow status`, `workflow instructions`. +- JSON command envelope guarantee: `command`, `summary`, `diagnostics`, `data`. +- `schemaVersion` guarantees for nested workflow state. +- Stable vs experimental fields. + +**Verification:** + +```bash +npm run check +npx tsx src/cli/main.ts check --json +npx tsx src/cli/main.ts index --json +``` + +### Task 2.4: Black-box test built CLI output + +**Objective:** Prevent source-only CLI tests from passing while built/package output is broken. + +**Files:** + +- Modify: `tests/cli/build-artifact.test.ts` or add a workflow-specific built artifact test. + +**Test:** + +1. Run build before executing `dist`. +2. Execute `node dist/main.js workflow status --workflow truthmark-check --json` from a temp project or temp cwd. +3. Assert the JSON command envelope exists and does not depend on repo-root-only assets. + +**Verification:** + +```bash +npm run build +npx vitest run tests/cli/build-artifact.test.ts +``` + +--- + +# Pass 3: Generated Playbooks Consume The Workflow Contract + +## Objective + +Update generated agent surfaces so they call `truthmark workflow status/instructions --json` before acting, rather than relying only on embedded prose. + +This is the direct transfer of OpenSpec's strongest behavior: generated skills/commands teach agents to ask the local CLI for current state. + +## Files + +- Modify: `src/templates/workflow-surfaces.ts` +- Modify: `src/templates/generated-surfaces.ts` +- Modify: `src/agents/workflow-manifest.ts` only if manifest fields need extra playbook metadata. +- Test: `tests/templates/generated-surfaces.test.ts` +- Test: `tests/init/init.test.ts` +- Test: `tests/agents/instructions.test.ts` +- Test: `tests/integration/agent-workflow-contract.test.ts` + +## Required generated-surface behavior + +For each workflow skill/command/prompt surface, add an operational first step: + +```bash +truthmark workflow status --workflow [--base ] --json +truthmark workflow instructions --workflow [--base ] --json +``` + +Generated prose must say: + +- stop if status says blocked or not applicable unless the user explicitly changes scope; +- obey `actionContext.allowedWritePaths` and `actionContext.forbiddenWritePaths`; +- use helper validator commands when present; +- do not edit generated surfaces manually; +- do not create OpenSpec-style change/spec/task artifacts. + +## Tasks + +### Task 3.1: Add renderer tests for CLI-first workflow instructions + +**Objective:** Pin the new generated-surface contract before changing renderer output. + +**Tests:** + +- Codex/OpenCode/Claude/GitHub Copilot/Gemini generated workflow surfaces mention `truthmark workflow status`. +- They mention `truthmark workflow instructions`. +- They mention `actionContext` or equivalent write-boundary JSON. +- They do not instruct creation of proposal/spec/task/change lifecycle artifacts. + +**Verification:** + +```bash +npx vitest run tests/templates/generated-surfaces.test.ts tests/agents/instructions.test.ts +``` + +### Task 3.2: Update workflow surface rendering + +**Objective:** Render the CLI-first operational playbook across all host surfaces. + +**Implementation notes:** + +- Prefer shared renderer functions in `src/templates/workflow-surfaces.ts` to avoid platform drift. +- Preserve platform-specific syntax/frontmatter. +- Do not list every generated file path in README-style docs. +- Do not hard-require optional repository files such as `.truthmark/config.yml` unless the generated surface is only emitted after proving the file exists. + +**Verification:** + +```bash +npx vitest run tests/templates/generated-surfaces.test.ts +npx vitest run tests/init/init.test.ts +``` + +### Task 3.3: Refresh generated surfaces and inspect diffs + +**Objective:** Ensure real generated outputs match renderer tests. + +**Commands:** + +```bash +npx tsx src/cli/main.ts init --json +npm run check +npx tsx src/cli/main.ts check --json +npx tsx src/cli/main.ts index --json +``` + +**Manual inspection:** + +- Generated bodies include CLI-first workflow status/instructions calls. +- Managed blocks are preserved. +- Generated outputs do not claim helper success unless the agent is instructed to run a validator and check `data.validation.ok: true`. +- No generated output implies Truthmark is an application feature rather than workflow/tooling scaffolding. + +--- + +# Pass 4: Compact Truth Health Scorecard + +## Objective + +Add a **small** scorecard layer to `check --json` so humans and agents can triage repository-truth health quickly without reading every raw diagnostic first. + +This is intentionally narrower than the original Pass 4 idea. The scorecard is not a second checker, not a grade, not a workflow-state payload, and not a new command. It is a compact index over the existing diagnostics returned by `check --json`. + +## Product decision + +Implement Pass 4 as **check-only**: + +- Add `data.scorecard` to `truthmark check --json`. +- Do **not** add `data.workflowState.scorecard` in this pass. +- Do **not** update generated playbooks in this pass. +- Keep raw diagnostics authoritative. +- Keep JSON compact enough that routine checks do not become expensive to read or paste. + +Reason: `workflow instructions` currently embeds full `workflowState`; adding fields there directly increases agent token load. Workflow-state scorecard exposure should wait until there is evidence agents need it inside workflow status/instructions. + +## Proposed dimensions + +Use stable IDs only in runtime JSON; labels/remediation can live in docs/constants. + +- `routing-coverage` +- `ownership-clarity` +- `evidence-support` +- `branch-freshness` +- `generated-surface-freshness` +- `truth-doc-structure` +- `decision-rationale-preservation` + +## Compact type shape + +```ts +export type TruthHealthScorecard = { + schemaVersion: "truthmark-scorecard/v0"; + dimensions: Array<{ + id: TruthHealthDimensionId; + status: "pass" | "warn" | "fail" | "not-run"; + diagnosticIndexes: number[]; + evidence?: string[]; // optional, capped, non-pass only + }>; +}; +``` + +Rules: + +- `diagnosticIndexes` point into the raw diagnostics returned with the same command result. +- `evidence` is optional and should be capped to 1-2 short snippets for non-pass dimensions. +- Do not emit full diagnostic text, source excerpts, labels, or remediation paragraphs in every dimension. +- `branch-freshness` is `not-run` when no `--base` was supplied. + +## Files + +- Create: `src/checks/scorecard.ts` +- Modify: `src/checks/check.ts` +- Test: `tests/checks/scorecard.test.ts` +- Modify: `tests/checks/check.test.ts` +- Modify: the routed check/validation truth doc, likely `docs/truthmark/truth/contracts.md` after route confirmation. + +Do **not** modify `src/workflow-state/**`, `src/templates/**`, generated platform surfaces, or report validators for this pass. + +## Tasks + +### Task 4.1: Add compact scorecard mapper tests + +**Objective:** Prove the scorecard is a compact triage index over existing diagnostics. + +**Tests:** + +- Shape includes `schemaVersion: "truthmark-scorecard/v0"` and the seven dimension IDs. +- Runtime dimensions include `id`, `status`, `diagnosticIndexes`, and optional capped `evidence` only. +- Error diagnostics map to `fail`; non-error mapped diagnostics map to `warn`. +- No mapped diagnostics after a relevant check ran maps to `pass`. +- Missing base maps branch freshness to `not-run`. +- `diagnosticIndexes` remain stable when one diagnostic maps to multiple dimensions. + +**Verification:** + +```bash +npx vitest run tests/checks/scorecard.test.ts +``` + +### Task 4.2: Implement the pure scorecard mapper + +**Objective:** Add the minimum implementation needed for the tests. + +**Implementation constraints:** + +- Use diagnostic category first. +- Use message/data predicates only when a category is too coarse. +- No filesystem writes, Git commands, OpenSpec runtime artifacts, external calls, or LLM judgment. +- Keep optional evidence short and capped. + +**Verification:** + +```bash +npx vitest run tests/checks/scorecard.test.ts +npm run typecheck +``` + +### Task 4.3: Include compact scorecard in `check --json` + +**Objective:** Add `data.scorecard` without changing the existing diagnostic contract. + +**Expected JSON excerpt:** + +```json +{ + "data": { + "scorecard": { + "schemaVersion": "truthmark-scorecard/v0", + "dimensions": [ + { "id": "branch-freshness", "status": "not-run", "diagnosticIndexes": [] } + ] + } + } +} +``` + +**Must preserve:** + +- top-level `diagnostics` +- `data.branchScope` +- optional `data.impactSet` +- `data.truthVisibility` + +**Verification:** + +```bash +npx vitest run tests/checks/check.test.ts tests/checks/scorecard.test.ts +npx tsx src/cli/main.ts check --json +``` + +### Task 4.4: Update routed check-output truth docs only + +**Objective:** Document the new check JSON contract without implying workflow-state support. + +**Docs:** + +- Confirm routing through `.truthmark/config.yml` and `docs/truthmark/routes/areas.md`. +- Update the routed validation/check contract doc. +- Say raw diagnostics remain authoritative. +- Say workflow-state scorecard exposure is deferred if needed to prevent ambiguity. + +**Verification:** + +```bash +npx tsx src/cli/main.ts check --json +npx tsx src/cli/main.ts index --json +``` + +--- + +# Pass 5: Preview / Truth Explore Wording Hardening + +## Objective + +Make the existing `truthmark-preview` workflow read as a safe “Truth Explore” stance for agents: inspect ownership, likely evidence, ambiguity, and recommended next workflow **without writing anything**. + +This pass should be mostly generated-instruction and workflow-copy refinement. Do not add a new workflow ID and do not add a broad `exploration` JSON object yet. + +## Product decision + +Keep the manifest id as `truthmark-preview`. Use “Truth Explore” only as user-facing wording inside Preview instructions if helpful. + +Do **not** add this proposed object in the first pass: + +```ts +exploration?: { + owningRoutes: string[]; + owningTruthDocs: string[]; + evidenceToInspect: string[]; + likelyTruthImpacts: string[]; + ambiguityWarnings: string[]; + recommendedWorkflows: string[]; +}; +``` + +Reason: most of those fields duplicate existing workflow-state concepts or require agent judgment. Large path arrays and speculative “likely impacts” would add token cost without enough new correctness. + +## Files + +- Modify: `src/agents/workflow-manifest.ts` only if Preview manifest wording/report sections need tightening. +- Modify: `src/workflow-state/instructions.ts` if generated instructions should call Preview “Truth Explore”. +- Modify: `src/templates/workflow-surfaces.ts` only for wording emitted to generated surfaces. +- Modify focused Preview/generated-surface tests that already cover Preview text. + +Do **not** add a new workflow id, new CLI command, or new workflow-state JSON object. + +## Tasks + +### Task 5.1: Tighten Preview/Explore instruction wording + +**Objective:** Make Preview clearly safe and read-only. + +**Instruction requirements:** + +- Say Preview/Explore is read-only. +- Tell agents to call `truthmark workflow status --workflow truthmark-preview --json`. +- Tell agents to inspect only enough checkout evidence to answer ownership/ambiguity/next-workflow questions. +- Tell agents to report the recommended next workflow instead of executing Sync/Document/Structure/Realize. +- Do not tell agents to edit docs, routes, code, or generated surfaces. + +**Verification:** + +```bash +npx vitest run tests/agents/truth-preview.test.ts tests/templates/generated-surfaces.test.ts +``` + +### Task 5.2: Preserve existing workflow-state contract + +**Objective:** Ensure the wording improvement does not introduce new JSON fields or broaden write permissions. + +**Checks:** + +- `truthmark-preview` remains the manifest id. +- Preview action context remains read-only. +- No `exploration` object is added. +- Generated surfaces do not imply automatic follow-on writes. + +**Verification:** + +```bash +npx vitest run tests/workflow-state/build.test.ts -t "preview" +npx tsx src/cli/main.ts workflow status --workflow truthmark-preview --json +``` + +--- + +# Pass 6: Lightweight Sync Intent Checklist + +## Objective + +Before truth-doc writes, make agents state a reviewable Sync intent: changed code reviewed, affected routes, target truth docs, intended update, evidence to verify, no-update-needed rationale, and blockers. + +This borrows OpenSpec's “reviewable intent” value without creating persistent change objects or a typed Sync Plan engine. + +## Product decision + +Start with a **checklist embedded in Sync instructions and reports**, not a `src/sync/plan.ts` builder. + +Do **not** create this typed object in the first pass: + +```ts +export type TruthSyncPlan = { + schemaVersion: "truthmark-sync-plan/v0"; + changedCodeReviewed: string[]; + affectedRoutes: string[]; + targetTruthDocs: string[]; + staleClaims: Array<...>; + proposedUpdates: string[]; + noUpdateNeededRationale: string[]; +}; +``` + +Reason: `staleClaims` and `proposedUpdates` require agent judgment and checkout inspection. A generated skeleton could look authoritative while incomplete, and it would duplicate the final Sync report. + +## Non-goal + +Do not create `truthmark/changes/*`, proposal files, task files, sync-plan files, lifecycle objects, or arbitrary workflow DAGs. The Sync intent is transient report content. + +## Files + +- Modify: `src/workflow-state/instructions.ts` +- Modify: `src/templates/workflow-surfaces.ts` +- Modify: `src/agents/workflow-manifest.ts` if report sections/templates are centralized there. +- Modify: `tests/agents/truth-sync.test.ts` +- Modify: `tests/templates/generated-surfaces.test.ts` +- Modify report validator tests only if the validator already recognizes report sections and the change is intentionally optional. + +Do **not** create `src/sync/plan.ts` in this pass. + +## Proposed report section + +```md +## Sync Intent + +- Changed code reviewed: +- Affected route/truth owner: +- Target truth docs: +- Intended update: +- Evidence to verify: +- No-update-needed rationale: +- Blockers: +``` + +## Tasks + +### Task 6.1: Add Sync Intent to generated Sync instructions + +**Objective:** Require agents to pause before truth-doc writes and summarize intent. + +**Instruction behavior:** + +- Run workflow status/instructions first. +- Fill the Sync Intent section before editing truth docs. +- If route ownership is ambiguous, block and recommend Truth Structure instead of guessing. +- Only edit allowed truth docs/routes after the intent is clear. +- Validate final report with `truthmark validate sync-report --json` when applicable. + +**Verification:** + +```bash +npx vitest run tests/agents/truth-sync.test.ts tests/templates/generated-surfaces.test.ts +``` + +### Task 6.2: Keep validator changes optional during migration + +**Objective:** Avoid breaking existing reports before all generated surfaces are refreshed. + +**Decision:** The Sync Intent section should be encouraged/recognized in this pass, not required by the validator unless all generated templates and tests are updated in the same change. + +**Verification:** + +```bash +npx vitest run tests/sync/report.test.ts tests/cli/validate.test.ts +``` + +--- + +# Pass 7: Deferred Platform Surface Adapter Refactor + +## Objective + +Defer platform adapter refactoring out of the V2 value path. It is internal maintainability work and should happen only after Passes 4-6 behavior is stable and generated-output parity tests are strong enough to catch prompt drift. + +## Deferred rationale + +Truthmark supports many host-native surfaces, and current rendering is centralized. An adapter registry may help later, but it does not directly improve repository-truth correctness now. Refactoring Codex, OpenCode, Claude Code, Copilot, and Gemini surfaces at once creates broad churn and subtle prompt-regression risk. + +## Do not implement in V2 + +Do not create these files as part of the current V2 pass sequence: + +- `src/templates/platform-adapters/types.ts` +- `src/templates/platform-adapters/registry.ts` +- `src/templates/platform-adapters/codex.ts` +- `src/templates/platform-adapters/opencode.ts` +- `src/templates/platform-adapters/claude.ts` +- `src/templates/platform-adapters/copilot.ts` +- `src/templates/platform-adapters/gemini.ts` + +## Future acceptance criteria before reopening + +Only reopen this pass when: + +1. Generated behavior from Passes 4-6 is stable. +2. Parity/snapshot tests prove generated body content, frontmatter, helper manifests, diagnostic categorization, and host-native paths do not drift. +3. The first adapter is a no-op wrapper around one existing platform renderer. +4. Platforms migrate one at a time. +5. Generated output is byte-for-byte or semantically equivalent before old central branches are removed. + +--- + +# Cross-pass acceptance criteria + +A pass is ready to merge only when: + +- It preserves Truthmark's fixed repository-truth workflow model. +- It does not add OpenSpec proposal/spec/design/task lifecycle objects. +- JSON output uses the standard command envelope: `command`, `summary`, `diagnostics`, `data`. +- New nested JSON contracts have `schemaVersion` fields. +- Read-only workflows are machine-readably read-only. +- Write workflows include allowed writes, forbidden writes, stop conditions, and helper validator commands where applicable. +- Generated surfaces instruct agents to call the CLI and obey the returned state. +- Generated surfaces do not hard-require optional repo-specific files unless proven/configured. +- Tests cover source-tree and built CLI behavior where CLI surface changes. +- Truthmark check/index are run after docs or generated-surface changes. + +# Recommended implementation order + +1. **Pass 0** first, because it prevents mission drift. +2. **Pass 1** next, because all later behavior needs the internal state model. +3. **Pass 2** next, because generated surfaces need a real CLI contract to call. +4. **Pass 3** next, because it lets agents benefit from the new contract. +5. **Pass 4** next, but only as a compact `check --json` scorecard; defer workflow-state exposure. +6. **Pass 5** next as Preview/Explore wording hardening, with no new JSON object. +7. **Pass 6** next as a lightweight Sync Intent checklist, with no typed plan engine yet. +8. **Pass 7** is deferred out of the V2 value path until generated behavior is stable and parity tests justify the refactor. + +# Defer explicitly + +Do not implement these unless a later product decision says otherwise: + +- arbitrary workflow schema files; +- artifact dependency DAGs; +- `truthmark/changes/*`; +- proposal/spec/design/task generation; +- archive/apply semantics; +- multi-repo planning homes; +- Truthmark-owned implementation task execution; +- required pre-code planning artifacts. + +# Final verification bundle + +For each completed pass, run the narrow focused tests first. For a full pass completion, run: + +```bash +npm run check +npx tsx src/cli/main.ts check --json +npx tsx src/cli/main.ts index --json +git diff --check +``` + +For CLI contract passes, also run: + +```bash +npm run build +node dist/main.js workflow status --workflow truthmark-check --json +node dist/main.js workflow instructions --workflow truthmark-check --json +``` + +For generated-surface passes, also run: + +```bash +npx tsx src/cli/main.ts init --json +npx vitest run tests/templates/generated-surfaces.test.ts tests/init/init.test.ts tests/integration/agent-workflow-contract.test.ts +``` + +# Bottom line + +The improvement path is not “copy OpenSpec.” The improvement path is: + +1. Make Truthmark's existing governance state computable. +2. Expose it through stable JSON commands for agents. +3. Teach generated host-native surfaces to consume that contract. +4. Improve human review with compact scorecards and lightweight Sync intent checklists. +5. Refactor platform rendering only after behavior is stable and the adapter refactor has a separate maintainability justification. + +This gives Truthmark OpenSpec's best workflow ergonomics while keeping Truthmark focused on repository truth, route ownership, evidence-backed claims, branch-scoped freshness, safe write boundaries, and Git-reviewable local operation. diff --git a/src/agents/instructions.ts b/src/agents/instructions.ts index 7d7fd18..4fb22cb 100644 --- a/src/agents/instructions.ts +++ b/src/agents/instructions.ts @@ -11,7 +11,7 @@ export const renderTruthStructureInstructions = ( return `### Truth Structure Use when area routing is missing, stale, broad, overloaded, catch-all, unrouteable, or explicitly requested. Invocations: ${TRUTH_STRUCTURE_EXPLICIT_INVOCATIONS} -Inspect repository layout, configured route files when present (${config.docs.routing.rootIndex}; ${config.docs.routing.areaFilesRoot}/), canonical docs, and relevant code directly. +Inspect repository layout, configured route files when present (${config.truthmark.paths.routesIndex}; ${config.truthmark.paths.routeAreasRoot}/), canonical docs, and relevant code directly. Create or repair routing and starter canonical truth docs only when useful. Use only canonical current-truth destinations for starter truth docs. Own topology pressure: split broad/catch-all routing by inferred product or behavior ownership. If the skill is unavailable, perform the same direct checkout workflow from any present config, route files, docs, and implementation.`; @@ -23,7 +23,7 @@ export const renderTruthCheckInstructions = ( return `### Truth Check Use when the user asks to audit repository truth health. Invocations: ${TRUTH_CHECK_EXPLICIT_INVOCATIONS} -Inspect truth docs, routing, implementation, and configured route files when present (${config.docs.routing.rootIndex}; ${config.docs.routing.areaFilesRoot}/). Support findings with checkout evidence, include confidence, run the truthmark check command only when available for additional validation, and inspect the checkout directly when the command is unavailable. Report files reviewed, issues, suggested fixes, evidence checked, and validation.`; +Inspect truth docs, routing, implementation, and configured route files when present (${config.truthmark.paths.routesIndex}; ${config.truthmark.paths.routeAreasRoot}/). Support findings with checkout evidence, include confidence, run the truthmark check command only when available for additional validation, and inspect the checkout directly when the command is unavailable. Report files reviewed, issues, suggested fixes, evidence checked, and validation.`; }; export const renderTruthSyncInstructions = ( @@ -40,8 +40,8 @@ Run relevant tests before finishing when functional code changes occurred. Support new or changed behavior-bearing truth claims with checkout evidence and report the evidence reviewed. Truthmark is agent-native: installed skills and this managed block are the workflow runtime. Inspect the checkout directly; truthmark CLI commands are optional validation tools after installation. Code first: code leads; truth docs follow; Truth Sync never rewrites code for alignment. -May write truth docs and configured truth routing files (${config.docs.routing.rootIndex}; ${config.docs.routing.areaFilesRoot}/) only when present; must not rewrite functional code. -Read configured route files (${config.docs.routing.rootIndex}; ${config.docs.routing.areaFilesRoot}/) only when they exist and routing resolution requires them. +May write truth docs and configured truth routing files (${config.truthmark.paths.routesIndex}; ${config.truthmark.paths.routeAreasRoot}/) only when present; must not rewrite functional code. +Read configured route files (${config.truthmark.paths.routesIndex}; ${config.truthmark.paths.routeAreasRoot}/) only when they exist and routing resolution requires them. If routing is missing, stale, broad, overloaded, catch-all, or cannot map changed code to a bounded truth owner, run Truth Structure before syncing when repair is safe and in scope; otherwise block and recommend Truth Structure. If mapped truth is missing, extend mapped truth docs first, create an area-local truth doc second, and create a new area only as a last resort. Skip only for: ${TRUTH_SYNC_SKIP_REASONS.join("; ")}.`; diff --git a/src/agents/shared.ts b/src/agents/shared.ts index 4091530..bad5709 100644 --- a/src/agents/shared.ts +++ b/src/agents/shared.ts @@ -26,12 +26,12 @@ export const REPOSITORY_INTELLIGENCE_INSTRUCTIONS = [ ].join("\n"); export const FEATURE_DOC_TEMPLATE_INSTRUCTIONS = [ - "When creating or updating a truth doc, inspect the routed truth kind and use the matching `docs/templates/-doc.md` template.", + "When creating or updating a truth doc, inspect the routed truth kind and use the matching template under the configured Truthmark templates root.", "Supported kinds: behavior, contract, architecture, workflow, operations, and test-behavior.", "Treat the HTML comments under each template section as normative authoring guidance for that section.", "Align existing docs to that template and write or repair section content so it satisfies the comment guidance while preserving accurate authored content.", "If the template is missing, use Scope, Product Decisions, Rationale, and the kind-specific current-truth section.", - "Teams may edit the template files under docs/templates/ to define their local truth-doc standards.", + "Teams may edit template files under the configured Truthmark templates root to define their local truth-doc standards.", ].join("\n"); export const renderTruthDocOwnershipGateSection = ( @@ -269,8 +269,8 @@ export const renderHierarchySummary = (config: TruthmarkConfig): string => { return [ "Truthmark hierarchy hints:", "- Config, when present: .truthmark/config.yml", - `- Root route index, when present: ${config.docs.routing.rootIndex}`, - `- Area route files, when present: ${config.docs.routing.areaFilesRoot}/**/*.md`, + `- Root route index, when present: ${config.truthmark.paths.routesIndex}`, + `- Area route files, when present: ${config.truthmark.paths.routeAreasRoot}/**/*.md`, `- Truth docs, when present: ${truthRoot}/**/*.md`, ].join("\n"); }; diff --git a/src/agents/truth-check.ts b/src/agents/truth-check.ts index e973c60..907728c 100644 --- a/src/agents/truth-check.ts +++ b/src/agents/truth-check.ts @@ -24,7 +24,7 @@ export const TRUTH_CHECK_EXPLICIT_INVOCATIONS = const renderTruthCheckReportExample = ( config: TruthmarkConfig = defaultAgentConfig(), ): string => { - const rootRouteIndex = config.docs.routing.rootIndex; + const rootRouteIndex = config.truthmark.paths.routesIndex; return `Truth Check: completed Files reviewed: @@ -103,7 +103,7 @@ Truth Check is agent-led: - inspect .truthmark/config.yml and configured route files only when they exist; then inspect canonical docs and relevant implementation directly - ${EVIDENCE_AUTHORITY_INSTRUCTIONS} -- inspect the configured root route index at ${config.docs.routing.rootIndex} and relevant child route files under ${config.docs.routing.areaFilesRoot}/ when they exist +- inspect the configured root route index at ${config.truthmark.paths.routesIndex} and relevant child route files under ${config.truthmark.paths.routeAreasRoot}/ when they exist - check that current docs describe current code rather than historical plans - check that route files map code surfaces to canonical truth docs when route files exist - check for broad, catch-all, index-like, or mixed-owner truth docs and report them as topology issues requiring Truth Structure diff --git a/src/agents/truth-document.ts b/src/agents/truth-document.ts index 601a400..677b6f8 100644 --- a/src/agents/truth-document.ts +++ b/src/agents/truth-document.ts @@ -40,7 +40,7 @@ Implementation reviewed: - src/routing/area-resolver.ts Ownership reviewed: -- ${config.docs.routing.rootIndex} +- ${config.truthmark.paths.routesIndex} Truth docs created: - ${truthDocsRoot}/contracts.md @@ -52,14 +52,14 @@ Truth docs restructured: - ${truthDocsRoot}/check-diagnostics.md Routing updated: -- ${config.docs.routing.rootIndex} +- ${config.truthmark.paths.routesIndex} ${renderClaimEvidenceCheckedSection([ { claim: "Route resolution behavior is documented in the contracts truth doc.", evidence: [ "src/routing/area-resolver.ts:14", - `${config.docs.routing.rootIndex}:9`, + `${config.truthmark.paths.routesIndex}:9`, ], result: "supported", }, @@ -131,7 +131,7 @@ Truth Document is manual and implementation-first: - inspect .truthmark/config.yml and configured route files only when they exist; then inspect existing canonical docs, implementation code, and tests directly - ${EVIDENCE_AUTHORITY_INSTRUCTIONS} - document current implemented behavior; do not invent future behavior or planned endpoints -- may write canonical truth docs and ${config.docs.routing.rootIndex} or relevant child route files only +- may write canonical truth docs and ${config.truthmark.paths.routesIndex} or relevant child route files only - must not write functional code - when routing is missing, stale, broad, overloaded, catch-all, or cannot map the behavior to a bounded truth owner, run Truth Structure first when routing repair is safe and in scope - block and recommend Truth Structure when routing repair is unsafe, ambiguous, or outside the task boundary diff --git a/src/agents/truth-preview.ts b/src/agents/truth-preview.ts index 5324425..9505e07 100644 --- a/src/agents/truth-preview.ts +++ b/src/agents/truth-preview.ts @@ -34,7 +34,7 @@ Why this workflow: - forbidden adjacency considered: must not edit functional code Likely route owner: -- route file: ${config.docs.routing.rootIndex} +- route file: ${config.truthmark.paths.routesIndex} - truth doc: ${truthDocsRoot}/example.md - confidence: medium @@ -82,8 +82,8 @@ Purpose: Read: - .truthmark/config.yml, only when present -- ${config.docs.routing.rootIndex}, only when present -- relevant child route files under ${config.docs.routing.areaFilesRoot}/, only when present +- ${config.truthmark.paths.routesIndex}, only when present +- relevant child route files under ${config.truthmark.paths.routeAreasRoot}/, only when present - relevant truth docs and implementation files needed to preview ownership - ${EVIDENCE_AUTHORITY_INSTRUCTIONS} diff --git a/src/agents/truth-structure.ts b/src/agents/truth-structure.ts index 55be542..7eb5830 100644 --- a/src/agents/truth-structure.ts +++ b/src/agents/truth-structure.ts @@ -34,11 +34,11 @@ export const renderTruthStructureReportExample = ( Topology reviewed: - controllers: src/auth/** - docs root: ${truthDocsRoot} -- route files: ${config.docs.routing.rootIndex} +- route files: ${config.truthmark.paths.routesIndex} Areas reviewed: - src/auth/** Routing updated: -- ${config.docs.routing.rootIndex} +- ${config.truthmark.paths.routesIndex} Initial truth boundary: - Area: Authentication - Code: src/auth/** @@ -53,7 +53,7 @@ Truth docs restructured: ${renderClaimEvidenceCheckedSection([ { claim: "Session behavior belongs to a dedicated Authentication truth owner.", - evidence: ["src/auth/**", `${config.docs.routing.rootIndex}:7`], + evidence: ["src/auth/**", `${config.truthmark.paths.routesIndex}:7`], result: "supported", }, ])} @@ -99,15 +99,15 @@ Invocations: ${TRUTH_STRUCTURE_EXPLICIT_INVOCATIONS} Truth Structure is agent-native: - inspect repository layout, current docs, Truthmark config and route files when present, and relevant code directly - ${EVIDENCE_AUTHORITY_INSTRUCTIONS} -- inspect the configured root route index at ${config.docs.routing.rootIndex} and relevant child route files under ${config.docs.routing.areaFilesRoot}/ when they exist +- inspect the configured root route index at ${config.truthmark.paths.routesIndex} and relevant child route files under ${config.truthmark.paths.routeAreasRoot}/ when they exist - define areas by product or behavior ownership, not by mechanical directory mirroring -- create or repair ${config.docs.routing.rootIndex} +- create or repair ${config.truthmark.paths.routesIndex} - create starter truth docs when useful and when they belong in the canonical current-truth surface - Starter truth docs must use closed YAML frontmatter bounded by opening and closing --- lines; include status, doc_type, last_reviewed, and source_of_truth inside that frontmatter. - Starter truth docs must include ## Product Decisions and ## Rationale sections. ${subagentMode} ${FEATURE_DOC_TEMPLATE_INSTRUCTIONS} -- use ${truthDocsRoot}/**, docs/architecture/**, or docs/standards/** for current truth destinations +- use ${truthDocsRoot}/** for current truth destinations - use only canonical current-truth destinations for starter truth docs - keep active Product Decisions and Rationale in the canonical doc that owns the behavior - preserve unrelated authored content @@ -142,7 +142,7 @@ Topology pressure signals: - the configured truth root has many direct non-index docs - a changed controller, route, or service cannot map to a specific behavior doc - Truth Sync would need to create a new generic truth doc because routing is too broad -- endpoint or controller names reveal domains missing from ${config.docs.routing.areaFilesRoot}/** +- endpoint or controller names reveal domains missing from ${config.truthmark.paths.routeAreasRoot}/** Use these review thresholds as guidance: - more than 10 direct truth docs in one folder - more than 15 leaf areas in one child route file @@ -151,7 +151,7 @@ Use these review thresholds as guidance: Repair rules: - split broad, overloaded, or catch-all areas into behavior-owned child route files - split mixed-owner truth docs into bounded owner docs before adding new behavior claims -- create route files under ${config.docs.routing.areaFilesRoot}/ when a product/domain boundary is clear +- create route files under ${config.truthmark.paths.routeAreasRoot}/ when a product/domain boundary is clear - create behavior truth docs under the configured truth root only when behavior lacks a current doc - README.md files are indexes, not Truth Sync targets - prefer bounded leaf truth docs at //.md diff --git a/src/agents/truth-sync.ts b/src/agents/truth-sync.ts index 142db13..36b1f70 100644 --- a/src/agents/truth-sync.ts +++ b/src/agents/truth-sync.ts @@ -39,7 +39,7 @@ The parent provides the task focus, explicit write lease, and any repository con Worker rules: - require a write lease with workflow, worker, shard, objective, requiredReads, allowedWrites, forbiddenWrites, evidenceRequired, verification, and reportFields before editing - inspect relevant staged, unstaged, and untracked functional code directly -- inspect .truthmark/config.yml and configured route files (${config.docs.routing.rootIndex}; ${config.docs.routing.areaFilesRoot}/) only when they exist; then inspect canonical truth docs directly +- inspect .truthmark/config.yml and configured route files (${config.truthmark.paths.routesIndex}; ${config.truthmark.paths.routeAreasRoot}/) only when they exist; then inspect canonical truth docs directly - Code verification is parent-owned; report what was run or why it was not run - may write only leased truth docs and leased truth routing files for Truth Sync alignment - must not rewrite functional code or generated host surfaces @@ -173,12 +173,12 @@ Report completion in this shape: ${renderMarkdownExample( renderTruthSyncCompletedReport({ changedCode: ["src/auth/session.ts"], - ownershipReviewed: [config.docs.routing.rootIndex], + ownershipReviewed: [config.truthmark.paths.routesIndex], truthDocsUpdated: [`${truthDocsRoot}/repository/overview.md`], evidenceChecked: [ { claim: "Session timeout behavior is documented in the mapped repository truth doc.", - evidence: ["src/auth/session.ts:12", `${config.docs.routing.rootIndex}:11`], + evidence: ["src/auth/session.ts:12", `${config.truthmark.paths.routesIndex}:11`], result: "supported", }, ], @@ -190,7 +190,7 @@ Blocked report example: ${renderMarkdownExample( renderTruthSyncBlockedReport({ reason: "routing repair is not allowed", - manualReviewFiles: [config.docs.routing.rootIndex], + manualReviewFiles: [config.truthmark.paths.routesIndex], nextAction: "update routing metadata and rerun Truth Sync", }), )}`; diff --git a/src/agents/truthmark-portal.ts b/src/agents/truthmark-portal.ts index ef48cbb..feee21b 100644 --- a/src/agents/truthmark-portal.ts +++ b/src/agents/truthmark-portal.ts @@ -10,13 +10,13 @@ export const renderTruthmarkPortalSkillBody = ( config: TruthmarkConfig = defaultAgentConfig(), ): string => { const workflow = getTruthmarkWorkflow("truthmark-portal"); - const output = config.truthmarkPortal.output; - const template = config.truthmarkPortal.template; + const output = config.truthmark.paths.portalOutput; + const template = config.truthmark.paths.portalTemplate; return `--- name: truthmark-portal description: ${workflow.description} -argument-hint: Optional output path, template, or portal generation focus +argument-hint: Optional portal generation focus user-invocable: true truthmark-version: ${TRUTHMARK_VERSION} --- @@ -32,9 +32,9 @@ Core rules: - Markdown remains canonical; generated HTML is presentation only. - Read Markdown directly from the checkout; the workflow does not require the truthmark CLI or package. - truthmark check/index may be used only as optional supporting evidence when available. -- Default output is docs/truthmark-portal; configured output is ${output}. -- Configured template is ${template}; use default built-in template instructions when the template is default. -- The workflow may replace the entire output directory, but writes are limited to the configured Portal output directory only unless the user changes scope. +- Determined Portal output is ${output}. +- Determined Portal template path is ${template}; use built-in template instructions if that file is absent. +- The workflow may replace the entire output directory, but writes are limited to the fixed Portal output directory only. - Portal writes are generated non-canonical static files for human browsing. - Generate a committed multi-page static HTML site with local CSS, JavaScript, assets, and search metadata under the output directory. - Use no remote dependencies by default: no remote scripts, analytics, fonts, CSS, or CDN assets. @@ -46,8 +46,8 @@ Core rules: Workflow: 1. Confirm the user explicitly requested Portal generation or refresh. -2. Inspect .truthmark/config.yml and configured route docs only when they exist; read repository instruction files when present, truth docs, architecture docs, standards docs, and the configured Portal template when it is a repo-relative file. -3. Validate the selected output path is repo-relative, non-empty, inside the repository, and does not overlap canonical docs, source roots, routing files, or instruction targets. +2. Inspect .truthmark/config.yml and configured route docs only when they exist; read repository instruction files when present, truth docs, architecture docs, standards docs, and the determined Portal template when present. +3. Validate the determined output path is repo-relative, non-empty, inside the repository, and does not overlap canonical docs, source roots, routing files, or instruction targets. 4. Plan the generated page inventory, diagrams/assets, source docs reviewed, and skipped or ambiguous docs. 5. Replace or write only under ${output}; do not edit canonical Markdown, routing, source code, or instruction files unless the user explicitly changes scope. 6. Generate the multi-page static site with local assets/search metadata and visible source provenance. diff --git a/src/agents/workflow-manifest.ts b/src/agents/workflow-manifest.ts index d358683..3faaa86 100644 --- a/src/agents/workflow-manifest.ts +++ b/src/agents/workflow-manifest.ts @@ -348,7 +348,7 @@ export const TRUTHMARK_WORKFLOW_MANIFEST = { "generate the Truthmark Portal", "refresh the committed HTML docs site", "create a browsable project map from Truthmark docs", - "update docs/truthmark-portal", + "update the Truthmark Portal output", "make a human-readable static site from the truth docs", ], negativeTriggers: [ @@ -362,7 +362,7 @@ export const TRUTHMARK_WORKFLOW_MANIFEST = { forbiddenAdjacency: [ "must not run as a completion gate", "must not replace Truth Sync, Truth Check, Truth Document, Truth Realize, or Truth Structure", - "must not write outside the configured Portal output directory unless the user changes scope", + "must not write outside the fixed Portal output directory", ], requiredGates: [ "manual-only invocation", @@ -370,7 +370,7 @@ export const TRUTHMARK_WORKFLOW_MANIFEST = { "Markdown canonical statement", "source provenance", ], - allowedWrites: ["configured Portal output directory only"], + allowedWrites: ["fixed Portal output directory only"], reportSections: [ "Output path", "Page count", diff --git a/src/checks/areas.ts b/src/checks/areas.ts index 17a40b6..5108082 100644 --- a/src/checks/areas.ts +++ b/src/checks/areas.ts @@ -85,8 +85,8 @@ export const checkAreas = async ( config: TruthmarkConfig, ): Promise => { const routing = await resolveAreaRouting(rootDir, { - rootIndex: config.docs.routing.rootIndex, - areaFilesRoot: config.docs.routing.areaFilesRoot, + rootIndex: config.truthmark.paths.routesIndex, + areaFilesRoot: config.truthmark.paths.routeAreasRoot, truthDocsRoot: resolveTruthDocsRoot(config), }); diff --git a/src/checks/authority.ts b/src/checks/authority.ts index 6def874..cb8a91b 100644 --- a/src/checks/authority.ts +++ b/src/checks/authority.ts @@ -28,15 +28,15 @@ export type AuthorityCheckResult = { diagnostics: Diagnostic[]; }; -export const checkAuthority = async ( +export const checkControlledPaths = async ( rootDir: string, - config: TruthmarkConfig, + controlledPaths: string[], ): Promise => { const diagnostics: Diagnostic[] = []; const orderedPaths: string[] = []; const seenPaths = new Set(); - for (const entry of config.authority) { + for (const entry of controlledPaths) { if (looksLikeGlob(entry)) { try { resolveRepoPath(rootDir, entry); @@ -44,7 +44,7 @@ export const checkAuthority = async ( diagnostics.push({ category: "authority", severity: "error", - message: `Authority entry ${entry} must stay inside the repository root.`, + message: `Truthmark-controlled path ${entry} must stay inside the repository root.`, file: entry, }); continue; @@ -56,7 +56,7 @@ export const checkAuthority = async ( diagnostics.push({ category: "authority", severity: "review", - message: `Authority glob ${entry} did not match any files.`, + message: `Truthmark-controlled glob ${entry} did not match any files.`, file: entry, }); } @@ -69,7 +69,7 @@ export const checkAuthority = async ( diagnostics.push({ category: "authority", severity: "error", - message: `Authority path ${match} must stay inside the repository root.`, + message: `Truthmark-controlled path ${match} must stay inside the repository root.`, file: match, }); continue; @@ -93,7 +93,7 @@ export const checkAuthority = async ( diagnostics.push({ category: "authority", severity: "error", - message: `Authority entry ${entry} must stay inside the repository root.`, + message: `Truthmark-controlled path ${entry} must stay inside the repository root.`, file: entry, }); continue; @@ -103,7 +103,7 @@ export const checkAuthority = async ( diagnostics.push({ category: "authority", severity: "error", - message: `Missing authority file ${entry}.`, + message: `Missing Truthmark-controlled file ${entry}.`, file: entry, }); continue; @@ -120,3 +120,10 @@ export const checkAuthority = async ( diagnostics, }; }; + +export const checkAuthority = async ( + rootDir: string, + config: TruthmarkConfig, +): Promise => { + return checkControlledPaths(rootDir, config.truthmark.controlledPaths); +}; diff --git a/src/checks/branch-scope.ts b/src/checks/branch-scope.ts index 6f8160b..6a6a44a 100644 --- a/src/checks/branch-scope.ts +++ b/src/checks/branch-scope.ts @@ -3,7 +3,7 @@ import fs from "node:fs/promises"; import fg from "fast-glob"; import { loadConfig } from "../config/load.js"; -import { DEFAULT_DOCS_HIERARCHY } from "../config/defaults.js"; +import { createDefaultConfig } from "../config/defaults.js"; import { resolveWorktreePath, getGitRepository } from "../git/repository.js"; import { hashText } from "../markdown/hash.js"; @@ -63,10 +63,10 @@ export const getBranchScopeData = async (cwd: string): Promise const repository = await getGitRepository(cwd); const relevantFileHashes: Record = {}; const loadResult = await loadConfig(repository.worktreePath); - const rootIndex = - loadResult.config?.docs.routing.rootIndex ?? DEFAULT_DOCS_HIERARCHY.routing.root_index; + const defaultConfig = createDefaultConfig(); + const rootIndex = loadResult.config?.truthmark.paths.routesIndex ?? defaultConfig.truthmark.paths.routesIndex; const areaFilesRoot = - loadResult.config?.docs.routing.areaFilesRoot ?? DEFAULT_DOCS_HIERARCHY.routing.area_files_root; + loadResult.config?.truthmark.paths.routeAreasRoot ?? defaultConfig.truthmark.paths.routeAreasRoot; const relevantFiles = new Set([...RELEVANT_BRANCH_SCOPE_FILES, rootIndex]); const routeFiles = await fg([`${areaFilesRoot}/**/*.md`], { cwd: repository.worktreePath, diff --git a/src/checks/check.ts b/src/checks/check.ts index 999c7f7..d973e20 100644 --- a/src/checks/check.ts +++ b/src/checks/check.ts @@ -9,6 +9,8 @@ import { checkAreas } from "./areas.js"; import { checkDecisionSections } from "./decisions.js"; import { checkGeneratedSurfaces } from "./generated-surfaces.js"; import { checkFreshness } from "../freshness/check.js"; +import { validateEvidenceReferences } from "../evidence/validate.js"; +import { buildTruthHealthScorecard } from "./scorecard.js"; export type CheckOptions = { base?: string; @@ -32,12 +34,24 @@ export const runCheck = async (cwd: string, options: CheckOptions = {}): Promise const loadResult = await loadConfig(rootDir); if (!loadResult.config) { + const scorecard = buildTruthHealthScorecard(loadResult.diagnostics, { + branchFreshnessRan: false, + branchFreshnessNotRunReason: options.base ? "config unavailable" : "base not supplied", + routingChecksRan: false, + ownershipChecksRan: false, + evidenceChecksRan: false, + generatedSurfaceChecksRan: false, + truthDocStructureChecksRan: false, + decisionRationaleChecksRan: false, + }); + return { command: "check", summary: summarizeDiagnostics(loadResult.diagnostics), diagnostics: loadResult.diagnostics, data: { branchScope, + scorecard, }, }; } @@ -59,6 +73,7 @@ export const runCheck = async (cwd: string, options: CheckOptions = {}): Promise areas.truthDocumentEntries, ); const generatedSurfaces = await checkGeneratedSurfaces(rootDir, loadResult.config); + const sourceTraceability = await validateEvidenceReferences(rootDir, areas.truthDocumentPaths); const freshness = options.base ? await checkFreshness(rootDir, loadResult.config, areas.truthDocumentPaths, options.base) : null; @@ -70,6 +85,7 @@ export const runCheck = async (cwd: string, options: CheckOptions = {}): Promise ...areas.diagnostics, ...decisionSections, ...generatedSurfaces, + ...sourceTraceability, ...(freshness?.diagnostics ?? []), ]; const truthVisibility = { @@ -86,6 +102,11 @@ export const runCheck = async (cwd: string, options: CheckOptions = {}): Promise topologyPressureCount: areas.topologyPressureCount, freshnessDiagnosticCount: freshness?.diagnostics.length ?? 0, }; + const scorecard = buildTruthHealthScorecard(diagnostics, { + branchFreshnessRan: Boolean(freshness), + branchFreshnessNotRunReason: options.base ? "freshness checker skipped" : "base not supplied", + evidenceChecksRan: true, + }); return { command: "check", @@ -94,6 +115,7 @@ export const runCheck = async (cwd: string, options: CheckOptions = {}): Promise data: { branchScope, truthVisibility, + scorecard, ...(freshness ? { impactSet: freshness.impactSet } : {}), }, }; diff --git a/src/checks/decisions.ts b/src/checks/decisions.ts index 07e7a95..b814e08 100644 --- a/src/checks/decisions.ts +++ b/src/checks/decisions.ts @@ -105,13 +105,7 @@ const kindSpecificHeadingMessages = ( }; const decisionTruthGlobs = (config: TruthmarkConfig): string[] => { - return [ - config.docs.roots.architecture, - resolveTruthDocsRoot(config), - config.docs.roots.api, - ] - .filter((root): root is string => Boolean(root)) - .map((root) => `${root}/**/*.md`); + return [`${resolveTruthDocsRoot(config)}/**/*.md`]; }; const isDecisionTruthCandidate = (config: TruthmarkConfig, filePath: string): boolean => { diff --git a/src/checks/scorecard.ts b/src/checks/scorecard.ts new file mode 100644 index 0000000..76f16ba --- /dev/null +++ b/src/checks/scorecard.ts @@ -0,0 +1,218 @@ +import type { Diagnostic } from "../output/diagnostic.js"; + +export const TRUTH_HEALTH_SCORECARD_SCHEMA_VERSION = "truthmark-scorecard/v0" as const; + +export const TRUTH_HEALTH_DIMENSION_IDS = [ + "routing-coverage", + "ownership-clarity", + "source-traceability", + "branch-freshness", + "generated-surface-freshness", + "truth-doc-structure", + "decision-rationale-preservation", +] as const; + +export type TruthHealthDimensionId = (typeof TRUTH_HEALTH_DIMENSION_IDS)[number]; + +export type TruthHealthDimensionStatus = "pass" | "warn" | "fail" | "not-run"; + +export type TruthHealthScorecardDimension = { + id: TruthHealthDimensionId; + status: TruthHealthDimensionStatus; + diagnosticIndexes: number[]; + evidence?: string[]; +}; + +export type TruthHealthScorecard = { + schemaVersion: typeof TRUTH_HEALTH_SCORECARD_SCHEMA_VERSION; + dimensions: TruthHealthScorecardDimension[]; +}; + +export type TruthHealthScorecardContext = { + branchFreshnessRan: boolean; + branchFreshnessNotRunReason?: string; + routingChecksRan?: boolean; + ownershipChecksRan?: boolean; + evidenceChecksRan?: boolean; + generatedSurfaceChecksRan?: boolean; + truthDocStructureChecksRan?: boolean; + decisionRationaleChecksRan?: boolean; +}; + +const EVIDENCE_LIMIT = 2; + +const textIncludesAny = (text: string, needles: string[]): boolean => { + const normalized = text.toLowerCase(); + return needles.some((needle) => normalized.includes(needle)); +}; + +const diagnosticText = (diagnostic: Diagnostic): string => { + const dataText = diagnostic.data ? JSON.stringify(diagnostic.data) : ""; + return `${diagnostic.message} ${diagnostic.file ?? ""} ${diagnostic.area ?? ""} ${dataText}`; +}; + +const isRouteAmbiguityDiagnostic = (diagnostic: Diagnostic): boolean => + diagnostic.category === "context-pack" && + textIncludesAny(diagnosticText(diagnostic), [ + "route", + "routing", + "ownership", + "write boundary", + "allowed write", + ]); + +const isSourceTraceabilityDiagnostic = (diagnostic: Diagnostic): boolean => + diagnostic.category === "source-traceability" || + (diagnostic.category === "links" && + textIncludesAny(diagnosticText(diagnostic), [ + "source_of_truth", + "source of truth", + "source evidence", + "evidence", + ])); + +const isMarkdownShapeDiagnostic = (diagnostic: Diagnostic): boolean => + diagnostic.category === "authority" && + textIncludesAny(diagnosticText(diagnostic), ["markdown", "heading", "section"]); + +const isOwnershipFreshnessDiagnostic = (diagnostic: Diagnostic): boolean => + diagnostic.category === "freshness" && + textIncludesAny(diagnosticText(diagnostic), [ + "route", + "routing", + "ownership", + "truth owner", + "truth ownership", + "affected truth document", + ]); + +const isDecisionRationaleDiagnostic = (diagnostic: Diagnostic): boolean => + diagnostic.category === "doc-structure" && + textIncludesAny(diagnosticText(diagnostic), ["product decisions", "rationale"]); + +const mapsToDimension = ( + diagnostic: Diagnostic, + dimensionId: TruthHealthDimensionId, +): boolean => { + switch (dimensionId) { + case "routing-coverage": + return ["config", "authority", "area-index", "coverage", "repo-index"].includes( + diagnostic.category, + ); + case "ownership-clarity": + return ( + ["config", "area-index", "coverage", "impact"].includes(diagnostic.category) || + isRouteAmbiguityDiagnostic(diagnostic) || + isOwnershipFreshnessDiagnostic(diagnostic) + ); + case "source-traceability": + return isSourceTraceabilityDiagnostic(diagnostic); + case "branch-freshness": + return diagnostic.category === "freshness"; + case "generated-surface-freshness": + return diagnostic.category === "config" || diagnostic.category === "generated-surface"; + case "truth-doc-structure": + return ( + diagnostic.category === "config" || + diagnostic.category === "frontmatter" || + diagnostic.category === "links" || + diagnostic.category === "doc-structure" || + isMarkdownShapeDiagnostic(diagnostic) + ); + case "decision-rationale-preservation": + return isDecisionRationaleDiagnostic(diagnostic); + } +}; + +const checkerRanForDimension = ( + dimensionId: TruthHealthDimensionId, + context: TruthHealthScorecardContext, +): boolean => { + switch (dimensionId) { + case "routing-coverage": + return context.routingChecksRan ?? true; + case "ownership-clarity": + return context.ownershipChecksRan ?? true; + case "source-traceability": + return context.evidenceChecksRan ?? true; + case "branch-freshness": + return context.branchFreshnessRan; + case "generated-surface-freshness": + return context.generatedSurfaceChecksRan ?? true; + case "truth-doc-structure": + return context.truthDocStructureChecksRan ?? true; + case "decision-rationale-preservation": + return context.decisionRationaleChecksRan ?? true; + } +}; + +const statusForDiagnostics = ( + diagnostics: Diagnostic[], + diagnosticIndexes: number[], + checkerRan: boolean, +): TruthHealthDimensionStatus => { + if (diagnosticIndexes.length > 0) { + return diagnosticIndexes.some((index) => diagnostics[index]?.severity === "error") + ? "fail" + : "warn"; + } + + return checkerRan ? "pass" : "not-run"; +}; + +const evidenceForDiagnostics = ( + diagnostics: Diagnostic[], + diagnosticIndexes: number[], + status: TruthHealthDimensionStatus, + dimensionId: TruthHealthDimensionId, + context: TruthHealthScorecardContext, +): string[] | undefined => { + if (status === "pass") { + return undefined; + } + + if (diagnosticIndexes.length === 0) { + if (dimensionId === "branch-freshness") { + return [context.branchFreshnessNotRunReason ?? "base not supplied"]; + } + + return ["checker not run"]; + } + + return diagnosticIndexes.slice(0, EVIDENCE_LIMIT).map((index) => { + const diagnostic = diagnostics[index]; + const subject = diagnostic.file ?? diagnostic.area; + return subject ? `${diagnostic.category}:${subject}` : diagnostic.category; + }); +}; + +export const buildTruthHealthScorecard = ( + diagnostics: Diagnostic[], + context: TruthHealthScorecardContext, +): TruthHealthScorecard => ({ + schemaVersion: TRUTH_HEALTH_SCORECARD_SCHEMA_VERSION, + dimensions: TRUTH_HEALTH_DIMENSION_IDS.map((dimensionId) => { + const diagnosticIndexes = diagnostics.flatMap((diagnostic, index) => + mapsToDimension(diagnostic, dimensionId) ? [index] : [], + ); + const status = statusForDiagnostics( + diagnostics, + diagnosticIndexes, + checkerRanForDimension(dimensionId, context), + ); + const evidence = evidenceForDiagnostics( + diagnostics, + diagnosticIndexes, + status, + dimensionId, + context, + ); + + return { + id: dimensionId, + status, + diagnosticIndexes, + ...(evidence ? { evidence } : {}), + }; + }), +}); diff --git a/src/cli/handlers.ts b/src/cli/handlers.ts index b328403..aaa79ed 100644 --- a/src/cli/handlers.ts +++ b/src/cli/handlers.ts @@ -6,6 +6,11 @@ import { buildImpactSet } from "../impact/build.js"; import { buildContextPack } from "../context-pack/build.js"; import { renderContextPackMarkdown } from "../context-pack/render.js"; import type { ContextPackWorkflow } from "../context-pack/types.js"; +import { + TRUTHMARK_WORKFLOW_IDS, + type TruthmarkWorkflowId, +} from "../agents/workflow-manifest.js"; +import { buildWorkflowState } from "../workflow-state/build.js"; import fs from "node:fs/promises"; import { @@ -77,10 +82,36 @@ const isContextPackWorkflow = (value: unknown): value is ContextPackWorkflow => return value === "truth-sync" || value === "truth-document" || value === "truth-realize"; }; -const isContextPackFormat = (value: unknown): value is "json" | "markdown" | undefined => { - return value === undefined || value === "json" || value === "markdown"; +const isContextMarkdownFormat = (value: unknown): value is "markdown" | undefined => { + return value === undefined || value === "markdown"; }; +const isTruthmarkWorkflowId = (value: unknown): value is TruthmarkWorkflowId => { + return typeof value === "string" && TRUTHMARK_WORKFLOW_IDS.includes(value as TruthmarkWorkflowId); +}; + +const invalidWorkflowResult = ( + command: "workflow status", + workflow: string | undefined, +): CommandResult => ({ + command, + summary: workflow + ? `Truthmark workflow requires a supported full workflow ID; received ${workflow}.` + : "Truthmark workflow requires --workflow.", + diagnostics: [ + { + category: "workflow-state", + severity: "error", + message: workflow + ? `Unknown Truthmark workflow: ${workflow}. Use a canonical full manifest ID such as truthmark-sync or truthmark-check.` + : `truthmark ${command} requires --workflow .`, + }, + ], + data: { + request: workflow ? { workflow } : {}, + }, +}); + const readHelperFile = async (filePath: string, helper: string): Promise => { try { return await fs.readFile(filePath, "utf8"); @@ -140,7 +171,21 @@ export const runContext = async (options: { }; } - if (!isContextPackFormat(options.format)) { + if (options.format === "json") { + return { + command: "context", + summary: "Truthmark context no longer supports JSON ContextPack output.", + diagnostics: [ + { + category: "context-pack", + severity: "error", + message: "JSON ContextPack output was removed in v2; use --format markdown.", + }, + ], + }; + } + + if (!isContextMarkdownFormat(options.format)) { return { command: "context", summary: "Truthmark context requires a supported --format value.", @@ -148,7 +193,7 @@ export const runContext = async (options: { { category: "context-pack", severity: "error", - message: "truthmark context requires --format json or markdown.", + message: "truthmark context supports only --format markdown; JSON ContextPack output was removed in v2.", }, ], }; @@ -160,13 +205,43 @@ export const runContext = async (options: { }); const diagnostics = contextPack.warnings; + const summary = `Truthmark context generated ${contextPack.workflow} ContextPack with ${diagnostics.length} warnings.`; + const markdown = renderContextPackMarkdown(contextPack); + return { command: "context", - summary: `Truthmark context generated ${contextPack.workflow} ContextPack with ${diagnostics.length} warnings.`, + summary, diagnostics, data: { - contextPack, - ...(options.format === "markdown" ? { markdown: renderContextPackMarkdown(contextPack) } : {}), + markdown, + summary, + }, + }; +}; + +export const runWorkflowStatus = async (options: { + workflow?: string; + base?: string; +}): Promise => { + if (!isTruthmarkWorkflowId(options.workflow)) { + return invalidWorkflowResult("workflow status", options.workflow); + } + + const workflowState = await buildWorkflowState(process.cwd(), { + workflow: options.workflow, + ...(options.base ? { base: options.base } : {}), + }); + + return { + command: "workflow status", + summary: `Truthmark workflow status completed for ${options.workflow}.`, + diagnostics: workflowState.diagnostics, + data: { + request: { + workflow: options.workflow, + ...(options.base ? { base: options.base } : {}), + }, + workflowState, }, }; }; diff --git a/src/cli/program.ts b/src/cli/program.ts index bc500f8..f3641c0 100644 --- a/src/cli/program.ts +++ b/src/cli/program.ts @@ -12,6 +12,7 @@ import { runValidateDocumentReport, runValidateSyncReport, runValidateWriteLease, + runWorkflowStatus, } from "./handlers.js"; import type { WorkflowHelperValidationResult } from "../agents/workflow-helper-validation.js"; @@ -38,6 +39,11 @@ type ContextOptions = OutputOptions & { format?: string; }; +type WorkflowOptions = OutputOptions & { + workflow?: string; + base?: string; +}; + const markFailedWhenErrorDiagnosticsExist = (result: CommandResult): void => { if (result.diagnostics.some((diagnostic) => diagnostic.severity === "error")) { process.exitCode = 1; @@ -50,7 +56,7 @@ const writeResult = (result: CommandResult, options: OutputOptions): void => { markFailedWhenErrorDiagnosticsExist(result); }; const writeContextResult = (result: CommandResult, options: ContextOptions): void => { - if (!options.json && options.format === "markdown" && typeof result.data?.markdown === "string") { + if (!options.json && typeof result.data?.markdown === "string") { process.stdout.write(result.data.markdown); markFailedWhenErrorDiagnosticsExist(result); return; @@ -153,7 +159,7 @@ export const buildProgram = (): Command => { .description("Generate a bounded workflow context pack.") .requiredOption("--workflow ", "Workflow name: truth-sync, truth-document, or truth-realize") .option("--base ", "Base Git ref for impact-backed packs") - .option("--format ", "Output format: json or markdown", "json"), + .option("--format ", "Output format: markdown", "markdown"), ).action(async (options: ContextOptions) => { writeContextResult( await runContext({ @@ -165,6 +171,26 @@ export const buildProgram = (): Command => { ); }); + const workflow = program + .command("workflow") + .description("Inspect agent-facing Truthmark workflow state."); + + addJsonOption( + workflow + .command("status") + .description("Return schema-versioned workflow state for a canonical workflow ID.") + .option("--workflow ", "Canonical workflow ID, such as truthmark-sync") + .option("--base ", "Base Git ref for impact-backed workflow state"), + ).action(async (options: WorkflowOptions) => { + writeResult( + await runWorkflowStatus({ + workflow: options.workflow, + base: options.base, + }), + options, + ); + }); + const validate = program .command("validate") .description("Run optional Truthmark workflow helper validators from the installed CLI."); diff --git a/src/config/defaults.ts b/src/config/defaults.ts index 22bb07b..323e866 100644 --- a/src/config/defaults.ts +++ b/src/config/defaults.ts @@ -1,47 +1,40 @@ import { DEFAULT_PLATFORMS, type TruthmarkConfig } from "./schema.js"; -export const DEFAULT_DOCS_HIERARCHY = { - layout: "hierarchical", - roots: { - ai: "docs/ai", - standards: "docs/standards", - architecture: "docs/architecture", - truth: "docs/truth", - }, - routing: { - root_index: "docs/truthmark/areas.md", - area_files_root: "docs/truthmark/areas", +export const DEFAULT_TRUTHMARK_WORKSPACE = { + workspace: "docs/truthmark", + routes: { + index: "routes/areas.md", + areas: "routes/areas", default_area: "repository", max_delegation_depth: 1, }, + truth: { + root: "truth", + }, + templates: { + root: "templates", + }, + generated: { + portal: { + enabled: false, + }, + }, } as const; -const DEFAULT_AUTHORITY = [ - DEFAULT_DOCS_HIERARCHY.routing.root_index, - `${DEFAULT_DOCS_HIERARCHY.routing.area_files_root}/**/*.md`, - `${DEFAULT_DOCS_HIERARCHY.roots.ai}/**/*.md`, - `${DEFAULT_DOCS_HIERARCHY.roots.standards}/**/*.md`, - `${DEFAULT_DOCS_HIERARCHY.roots.architecture}/**/*.md`, - `${DEFAULT_DOCS_HIERARCHY.roots.truth}/**/*.md`, -] as const; - export const DEFAULT_INSTRUCTION_TARGETS = ["AGENTS.md"] as const; -export const DEFAULT_TRUTHMARK_PORTAL = { - enabled: false, - output: "docs/truthmark-portal", - template: "default", -} as const; - export const createDefaultRawConfig = () => ({ - version: 1 as const, + version: 2 as const, platforms: [...DEFAULT_PLATFORMS], - docs: { - layout: DEFAULT_DOCS_HIERARCHY.layout, - roots: { ...DEFAULT_DOCS_HIERARCHY.roots }, - routing: { ...DEFAULT_DOCS_HIERARCHY.routing }, + truthmark: { + workspace: DEFAULT_TRUTHMARK_WORKSPACE.workspace, + routes: { ...DEFAULT_TRUTHMARK_WORKSPACE.routes }, + truth: { ...DEFAULT_TRUTHMARK_WORKSPACE.truth }, + templates: { ...DEFAULT_TRUTHMARK_WORKSPACE.templates }, + generated: { + portal: { ...DEFAULT_TRUTHMARK_WORKSPACE.generated.portal }, + }, }, - authority: [...DEFAULT_AUTHORITY], instruction_targets: [...DEFAULT_INSTRUCTION_TARGETS], frontmatter: { required: [], @@ -51,21 +44,37 @@ export const createDefaultRawConfig = () => ({ }); export const createDefaultConfig = (): TruthmarkConfig => ({ - version: 1, + version: 2, platforms: [...DEFAULT_PLATFORMS], - docs: { - layout: DEFAULT_DOCS_HIERARCHY.layout, - roots: { ...DEFAULT_DOCS_HIERARCHY.roots }, - routing: { - rootIndex: DEFAULT_DOCS_HIERARCHY.routing.root_index, - areaFilesRoot: DEFAULT_DOCS_HIERARCHY.routing.area_files_root, - defaultArea: DEFAULT_DOCS_HIERARCHY.routing.default_area, - maxDelegationDepth: DEFAULT_DOCS_HIERARCHY.routing.max_delegation_depth, + truthmark: { + workspace: DEFAULT_TRUTHMARK_WORKSPACE.workspace, + routes: { + index: DEFAULT_TRUTHMARK_WORKSPACE.routes.index, + areas: DEFAULT_TRUTHMARK_WORKSPACE.routes.areas, + defaultArea: DEFAULT_TRUTHMARK_WORKSPACE.routes.default_area, + maxDelegationDepth: DEFAULT_TRUTHMARK_WORKSPACE.routes.max_delegation_depth, }, + truth: { root: DEFAULT_TRUTHMARK_WORKSPACE.truth.root }, + templates: { root: DEFAULT_TRUTHMARK_WORKSPACE.templates.root }, + generated: { + portal: { ...DEFAULT_TRUTHMARK_WORKSPACE.generated.portal }, + }, + paths: { + routesIndex: "docs/truthmark/routes/areas.md", + routeAreasRoot: "docs/truthmark/routes/areas", + truthRoot: "docs/truthmark/truth", + templatesRoot: "docs/truthmark/templates", + portalOutput: "docs/truthmark/generated/portal", + portalTemplate: "docs/truthmark/templates/portal.html", + }, + controlledPaths: [ + "docs/truthmark/routes/areas.md", + "docs/truthmark/routes/areas/**/*.md", + "docs/truthmark/truth/**/*.md", + "docs/truthmark/templates/*.md", + ], }, - authority: [...DEFAULT_AUTHORITY], instructionTargets: [...DEFAULT_INSTRUCTION_TARGETS], - truthmarkPortal: { ...DEFAULT_TRUTHMARK_PORTAL }, frontmatter: { required: [], recommended: ["status", "doc_type", "last_reviewed", "source_of_truth"], diff --git a/src/config/load.ts b/src/config/load.ts index 8026d2f..ba3b8e6 100644 --- a/src/config/load.ts +++ b/src/config/load.ts @@ -6,11 +6,7 @@ import { parse } from "yaml"; import type { Diagnostic } from "../output/diagnostic.js"; import { resolveRepoPath } from "../fs/paths.js"; -import { - DEFAULT_DOCS_HIERARCHY, - DEFAULT_INSTRUCTION_TARGETS, - DEFAULT_TRUTHMARK_PORTAL, -} from "./defaults.js"; +import { DEFAULT_INSTRUCTION_TARGETS } from "./defaults.js"; import { DEFAULT_PLATFORMS, type RawTruthmarkConfig, @@ -28,20 +24,16 @@ export type LoadConfigResult = { configPath: string; }; -const toConfigDiagnostic = (message: string, file: string): Diagnostic => { - return { - category: "config", - severity: "error", - message, - file, - }; -}; +const toConfigDiagnostic = (message: string, file: string): Diagnostic => ({ + category: "config", + severity: "error", + message, + file, +}); -const normalizeRepoRelativePath = (value: string): string => { +export const normalizeRepoRelativePath = (value: string): string => { const slashNormalized = value.replace(/\\/gu, "/"); - const pathNormalized = path.posix.normalize(slashNormalized).replace(/\/+$/u, ""); - - return pathNormalized; + return path.posix.normalize(slashNormalized).replace(/\/+$/u, ""); }; const isUnsafeRepoRelativePath = (value: string): boolean => { @@ -62,6 +54,14 @@ const isUnsafeRepoRelativePath = (value: string): boolean => { ); }; +const joinWorkspacePath = (workspace: string, childPath: string): string => { + return normalizeRepoRelativePath(`${workspace}/${childPath}`); +}; + +const portalOutputFor = (workspace: string): string => joinWorkspacePath(workspace, "generated/portal"); + +const portalTemplateFor = (templatesRoot: string): string => joinWorkspacePath(templatesRoot, "portal.html"); + const pathsOverlap = (left: string, right: string): boolean => { const normalizedLeft = normalizeRepoRelativePath(left); const normalizedRight = normalizeRepoRelativePath(right); @@ -73,59 +73,39 @@ const pathsOverlap = (left: string, right: string): boolean => { ); }; -const portalForbiddenOutputRoots = (rawConfig: RawTruthmarkConfig): string[] => { - const rawDocs = rawConfig.docs; - const docsRoots = rawDocs?.roots ?? {}; - const routing = rawDocs?.routing ?? DEFAULT_DOCS_HIERARCHY.routing; +const CONFIG_PATH = ".truthmark/config.yml"; +const FORBIDDEN_WORKSPACE_OVERLAPS = [ + ".git", + ".truthmark", + "package.json", + "package-lock.json", + "pnpm-lock.yaml", + "yarn.lock", + "src", + "tests", +] as const; - return [ - "src", - DEFAULT_DOCS_HIERARCHY.roots.ai, - DEFAULT_DOCS_HIERARCHY.roots.standards, - DEFAULT_DOCS_HIERARCHY.roots.architecture, - DEFAULT_DOCS_HIERARCHY.roots.truth, - ...Object.values(docsRoots), - routing.root_index, - routing.area_files_root, - ".truthmark/config.yml", - "AGENTS.md", - "CLAUDE.md", - "GEMINI.md", - ".github/copilot-instructions.md", - ...(rawConfig.instruction_targets ?? DEFAULT_INSTRUCTION_TARGETS), - ]; -}; - -const validatePortalConfig = ( - rawConfig: RawTruthmarkConfig, - configPath: string, -): Diagnostic[] => { - const portal = rawConfig["truthmark-portal"]; - - if (portal === undefined) { +const unsupportedShapeDiagnostics = (parsedConfig: unknown, configPath: string): Diagnostic[] => { + if (!parsedConfig || typeof parsedConfig !== "object" || Array.isArray(parsedConfig)) { return []; } + const record = parsedConfig as Record; const diagnostics: Diagnostic[] = []; - const output = portal.output ?? DEFAULT_TRUTHMARK_PORTAL.output; - const template = portal.template ?? DEFAULT_TRUTHMARK_PORTAL.template; - if ( - isUnsafeRepoRelativePath(output) || - portalForbiddenOutputRoots(rawConfig).some((forbidden) => pathsOverlap(output, forbidden)) - ) { + if (record.version !== 2) { diagnostics.push( toConfigDiagnostic( - "truthmark-portal.output must be a non-empty repo-relative directory that does not overlap source, instruction, routing, or canonical docs roots.", + "Unsupported Truthmark config shape. This release requires version: 2 with a truthmark workspace block.", configPath, ), ); } - if (template !== "default" && isUnsafeRepoRelativePath(template)) { + if ("docs" in record || "authority" in record) { diagnostics.push( toConfigDiagnostic( - "truthmark-portal.template must be 'default' or a non-empty repo-relative template path without absolute or parent traversal segments.", + "Unsupported Truthmark config shape. Remove old docs.roots and legacy authority settings; use version: 2 truthmark.workspace paths.", configPath, ), ); @@ -134,34 +114,122 @@ const validatePortalConfig = ( return diagnostics; }; +const validateWorkspacePaths = ( + rawConfig: RawTruthmarkConfig, + configPath: string, +): Diagnostic[] => { + const diagnostics: Diagnostic[] = []; + const workspace = normalizeRepoRelativePath(rawConfig.truthmark.workspace); + const childPaths = [ + ["truthmark.routes.index", rawConfig.truthmark.routes.index], + ["truthmark.routes.areas", rawConfig.truthmark.routes.areas], + ["truthmark.truth.root", rawConfig.truthmark.truth.root], + ["truthmark.templates.root", rawConfig.truthmark.templates.root], + ] as const; + + if ( + isUnsafeRepoRelativePath(rawConfig.truthmark.workspace) || + FORBIDDEN_WORKSPACE_OVERLAPS.some((forbidden) => pathsOverlap(workspace, forbidden)) + ) { + diagnostics.push( + toConfigDiagnostic( + "truthmark.workspace must be a non-empty repo-relative directory that does not overlap repository control, package, source, test, or instruction paths.", + configPath, + ), + ); + } + + for (const [name, value] of childPaths) { + if (isUnsafeRepoRelativePath(value)) { + diagnostics.push( + toConfigDiagnostic( + `${name} must be a non-empty path relative to truthmark.workspace without absolute or parent traversal segments.`, + configPath, + ), + ); + } + } + + const portalOutput = normalizeRepoRelativePath("generated/portal"); + const controlledWorkspaceChildren = [ + ["truthmark.routes.index", rawConfig.truthmark.routes.index], + ["truthmark.routes.areas", rawConfig.truthmark.routes.areas], + ["truthmark.truth.root", rawConfig.truthmark.truth.root], + ["truthmark.templates.root", rawConfig.truthmark.templates.root], + ] as const; + + for (const [name, value] of controlledWorkspaceChildren) { + if (pathsOverlap(portalOutput, value)) { + diagnostics.push( + toConfigDiagnostic( + `Truthmark Portal output ${portalOutputFor(workspace)} must not overlap ${name}; Portal output is generated and must stay outside controlled truth, routing, and template paths.`, + configPath, + ), + ); + } + } + + for (const target of rawConfig.instruction_targets ?? DEFAULT_INSTRUCTION_TARGETS) { + if (isUnsafeRepoRelativePath(target) || pathsOverlap(workspace, target)) { + diagnostics.push( + toConfigDiagnostic( + "instruction_targets must be repo-relative files outside truthmark.workspace.", + configPath, + ), + ); + } + } + + return diagnostics; +}; + const normalizeConfig = (rawConfig: RawTruthmarkConfig): TruthmarkConfig => { - const rawDocs = rawConfig.docs ?? { - layout: DEFAULT_DOCS_HIERARCHY.layout, - roots: { ...DEFAULT_DOCS_HIERARCHY.roots }, - routing: { ...DEFAULT_DOCS_HIERARCHY.routing }, - }; - const roots: Record = { ...DEFAULT_DOCS_HIERARCHY.roots, ...rawDocs.roots }; + const workspace = normalizeRepoRelativePath(rawConfig.truthmark.workspace); + const routesIndex = joinWorkspacePath(workspace, rawConfig.truthmark.routes.index); + const routeAreasRoot = joinWorkspacePath(workspace, rawConfig.truthmark.routes.areas); + const truthRoot = joinWorkspacePath(workspace, rawConfig.truthmark.truth.root); + const templatesRoot = joinWorkspacePath(workspace, rawConfig.truthmark.templates.root); + const portalOutput = portalOutputFor(workspace); + const portalTemplate = portalTemplateFor(templatesRoot); return { version: rawConfig.version, platforms: rawConfig.platforms ?? [...DEFAULT_PLATFORMS], - docs: { - layout: rawDocs.layout, - roots, - routing: { - rootIndex: rawDocs.routing.root_index, - areaFilesRoot: rawDocs.routing.area_files_root, - defaultArea: rawDocs.routing.default_area, - maxDelegationDepth: rawDocs.routing.max_delegation_depth, + truthmark: { + workspace, + routes: { + index: normalizeRepoRelativePath(rawConfig.truthmark.routes.index), + areas: normalizeRepoRelativePath(rawConfig.truthmark.routes.areas), + defaultArea: rawConfig.truthmark.routes.default_area, + maxDelegationDepth: rawConfig.truthmark.routes.max_delegation_depth, }, + truth: { + root: normalizeRepoRelativePath(rawConfig.truthmark.truth.root), + }, + templates: { + root: normalizeRepoRelativePath(rawConfig.truthmark.templates.root), + }, + generated: { + portal: { + enabled: rawConfig.truthmark.generated.portal.enabled, + }, + }, + paths: { + routesIndex, + routeAreasRoot, + truthRoot, + templatesRoot, + portalOutput, + portalTemplate, + }, + controlledPaths: [ + routesIndex, + `${routeAreasRoot}/**/*.md`, + `${truthRoot}/**/*.md`, + `${templatesRoot}/*.md`, + ], }, - authority: rawConfig.authority, instructionTargets: rawConfig.instruction_targets ?? [...DEFAULT_INSTRUCTION_TARGETS], - truthmarkPortal: { - enabled: rawConfig["truthmark-portal"]?.enabled ?? DEFAULT_TRUTHMARK_PORTAL.enabled, - output: rawConfig["truthmark-portal"]?.output ?? DEFAULT_TRUTHMARK_PORTAL.output, - template: rawConfig["truthmark-portal"]?.template ?? DEFAULT_TRUTHMARK_PORTAL.template, - }, frontmatter: { required: rawConfig.frontmatter?.required ?? [], recommended: rawConfig.frontmatter?.recommended ?? [], @@ -171,8 +239,7 @@ const normalizeConfig = (rawConfig: RawTruthmarkConfig): TruthmarkConfig => { }; export const loadConfig = async (rootDir: string): Promise => { - const configPath = ".truthmark/config.yml"; - const absolutePath = resolveRepoPath(rootDir, configPath); + const absolutePath = resolveRepoPath(rootDir, CONFIG_PATH); let source: string; @@ -183,8 +250,8 @@ export const loadConfig = async (rootDir: string): Promise => return { status: "missing", config: null, - diagnostics: [toConfigDiagnostic("Missing .truthmark/config.yml.", configPath)], - configPath, + diagnostics: [toConfigDiagnostic("Missing .truthmark/config.yml.", CONFIG_PATH)], + configPath: CONFIG_PATH, }; } @@ -202,10 +269,20 @@ export const loadConfig = async (rootDir: string): Promise => diagnostics: [ toConfigDiagnostic( `Invalid YAML: ${error instanceof Error ? error.message : String(error)}`, - configPath, + CONFIG_PATH, ), ], - configPath, + configPath: CONFIG_PATH, + }; + } + + const unsupportedDiagnostics = unsupportedShapeDiagnostics(parsedConfig, CONFIG_PATH); + if (unsupportedDiagnostics.length > 0) { + return { + status: "invalid", + config: null, + diagnostics: unsupportedDiagnostics, + configPath: CONFIG_PATH, }; } @@ -225,23 +302,20 @@ export const loadConfig = async (rootDir: string): Promise => ? `${propertyPath} additional property ${additionalProperty} is not allowed` : `${propertyPath} ${error.message ?? "is invalid"}`.trim(); - return toConfigDiagnostic(message, configPath); + return toConfigDiagnostic(message, CONFIG_PATH); }), - configPath, + configPath: CONFIG_PATH, }; } - const portalDiagnostics = validatePortalConfig( - parsedConfig as RawTruthmarkConfig, - configPath, - ); + const pathDiagnostics = validateWorkspacePaths(parsedConfig as RawTruthmarkConfig, CONFIG_PATH); - if (portalDiagnostics.length > 0) { + if (pathDiagnostics.length > 0) { return { status: "invalid", config: null, - diagnostics: portalDiagnostics, - configPath, + diagnostics: pathDiagnostics, + configPath: CONFIG_PATH, }; } @@ -249,6 +323,6 @@ export const loadConfig = async (rootDir: string): Promise => status: "loaded", config: normalizeConfig(parsedConfig as RawTruthmarkConfig), diagnostics: [], - configPath, + configPath: CONFIG_PATH, }; }; diff --git a/src/config/schema.ts b/src/config/schema.ts index 071df30..9f20036 100644 --- a/src/config/schema.ts +++ b/src/config/schema.ts @@ -19,47 +19,62 @@ export const DEFAULT_PLATFORMS = [ ] as const satisfies readonly TruthmarkPlatform[]; -type RawDocsHierarchyConfig = { - layout: "hierarchical"; - roots: Record; - routing: { - root_index: string; - area_files_root: string; +type TruthmarkPortalConfig = { + enabled: boolean; +}; + +type RawTruthmarkWorkspaceConfig = { + workspace: string; + routes: { + index: string; + areas: string; default_area: string; max_delegation_depth: 1; }; -}; - -type DocsHierarchyConfig = { - layout: "hierarchical"; - roots: Record; - routing: { - rootIndex: string; - areaFilesRoot: string; - defaultArea: string; - maxDelegationDepth: 1; + truth: { + root: string; + }; + templates: { + root: string; + }; + generated: { + portal: TruthmarkPortalConfig; }; }; -type RawTruthmarkPortalConfig = { - enabled?: boolean; - output?: string; - template?: string; -}; - -type TruthmarkPortalConfig = { - enabled: boolean; - output: string; - template: string; +type TruthmarkWorkspaceConfig = { + workspace: string; + routes: { + index: string; + areas: string; + defaultArea: string; + maxDelegationDepth: 1; + }; + truth: { + root: string; + }; + templates: { + root: string; + }; + generated: { + portal: TruthmarkPortalConfig; + }; + paths: { + routesIndex: string; + routeAreasRoot: string; + truthRoot: string; + templatesRoot: string; + portalOutput: string; + portalTemplate: string; + }; + controlledPaths: string[]; }; export type RawTruthmarkConfig = { - version: 1; + version: 2; platforms?: TruthmarkPlatform[]; - docs?: RawDocsHierarchyConfig; - authority: string[]; + truthmark: RawTruthmarkWorkspaceConfig; instruction_targets?: string[]; - "truthmark-portal"?: RawTruthmarkPortalConfig; frontmatter?: { required?: string[]; recommended?: string[]; @@ -68,12 +83,10 @@ export type RawTruthmarkConfig = { }; export type TruthmarkConfig = { - version: 1; + version: 2; platforms: TruthmarkPlatform[]; - docs: DocsHierarchyConfig; - authority: string[]; + truthmark: TruthmarkWorkspaceConfig; instructionTargets: string[]; - truthmarkPortal: TruthmarkPortalConfig; frontmatter: { required: string[]; recommended: string[]; @@ -84,11 +97,11 @@ export type TruthmarkConfig = { export const truthmarkConfigSchema = { type: "object", additionalProperties: false, - required: ["version", "authority"], + required: ["version", "truthmark"], properties: { version: { type: "integer", - const: 1, + const: 2, }, platforms: { type: "array", @@ -99,52 +112,58 @@ export const truthmarkConfigSchema = { }, minItems: 1, }, - docs: { + truthmark: { type: "object", - nullable: true, additionalProperties: false, - required: ["layout", "roots", "routing"], + required: ["workspace", "routes", "truth", "templates", "generated"], properties: { - layout: { + workspace: { type: "string", - const: "hierarchical", }, - roots: { - type: "object", - required: [], - additionalProperties: { - type: "string", - }, - }, - routing: { + routes: { type: "object", additionalProperties: false, - required: ["root_index", "area_files_root", "default_area", "max_delegation_depth"], + required: ["index", "areas", "default_area", "max_delegation_depth"], properties: { - root_index: { - type: "string", - }, - area_files_root: { - type: "string", - }, - default_area: { - type: "string", - }, - max_delegation_depth: { - type: "integer", - const: 1, + index: { type: "string" }, + areas: { type: "string" }, + default_area: { type: "string" }, + max_delegation_depth: { type: "integer", const: 1 }, + }, + }, + truth: { + type: "object", + additionalProperties: false, + required: ["root"], + properties: { + root: { type: "string" }, + }, + }, + templates: { + type: "object", + additionalProperties: false, + required: ["root"], + properties: { + root: { type: "string" }, + }, + }, + generated: { + type: "object", + additionalProperties: false, + required: ["portal"], + properties: { + portal: { + type: "object", + additionalProperties: false, + required: ["enabled"], + properties: { + enabled: { type: "boolean" }, + }, }, }, }, }, }, - authority: { - type: "array", - items: { - type: "string", - }, - minItems: 1, - }, instruction_targets: { type: "array", nullable: true, @@ -152,22 +171,6 @@ export const truthmarkConfigSchema = { type: "string", }, }, - "truthmark-portal": { - type: "object", - additionalProperties: false, - required: [], - properties: { - enabled: { - type: "boolean", - }, - output: { - type: "string", - }, - template: { - type: "string", - }, - }, - }, frontmatter: { type: "object", nullable: true, diff --git a/src/context-pack/build.ts b/src/context-pack/build.ts index 077a840..4a9981f 100644 --- a/src/context-pack/build.ts +++ b/src/context-pack/build.ts @@ -4,6 +4,8 @@ import path from "node:path"; import fg from "fast-glob"; import { buildImpactSet } from "../impact/build.js"; +import { createDefaultConfig } from "../config/defaults.js"; +import { loadConfig } from "../config/load.js"; import type { ImpactSet } from "../impact/types.js"; import type { Diagnostic } from "../output/diagnostic.js"; import { buildRepoIndex } from "../repo-index/build.js"; @@ -47,14 +49,27 @@ const readIfExists = async (rootDir: string, filePath: string): Promise { + const lines = content.split("\n"); + + if (lines.length <= 200) { + return { content, truncated: false }; + } + + return { + content: [...lines.slice(0, 80), "...", ...lines.slice(-40)].join("\n"), + truncated: true, + }; +}; + const boundedContent = ( filePath: string, content: string, warnings: Diagnostic[], ): ContextSourceFile => { - const lines = content.split("\n"); + const bounded = boundContent(content); - if (lines.length <= 200) { + if (!bounded.truncated) { return { path: filePath, content, truncated: false }; } @@ -67,7 +82,7 @@ const boundedContent = ( return { path: filePath, - content: [...lines.slice(0, 80), "...", ...lines.slice(-40)].join("\n"), + content: bounded.content, truncated: true, }; }; @@ -75,13 +90,23 @@ const boundedContent = ( const documentsFor = async ( rootDir: string, paths: string[], + warnings: Diagnostic[], ): Promise => { const documents: ContextDocument[] = []; for (const filePath of uniqueSorted(paths)) { const content = await readIfExists(rootDir, filePath); if (content !== null) { - documents.push({ path: filePath, content }); + const bounded = boundContent(content); + if (bounded.truncated) { + warnings.push({ + category: "context-pack", + severity: "review", + message: `Context truth doc ${filePath} was truncated to fit ContextPack v0 bounds.`, + file: filePath, + }); + } + documents.push({ path: filePath, content: bounded.content, truncated: bounded.truncated }); } } @@ -143,15 +168,16 @@ const sourceOfTruthPathsFor = async ( const writePathsFor = ( workflow: ContextPackOptions["workflow"], + routeIndexPath: string, truthDocs: string[], routes: ContextRoute[], ): string[] => { if (workflow === "truth-sync") { - return uniqueSorted(["docs/truthmark/areas.md", ...truthDocs]); + return uniqueSorted([routeIndexPath, ...truthDocs]); } if (workflow === "truth-document") { - return uniqueSorted(["docs/truthmark/areas.md", ...truthDocs]); + return uniqueSorted([routeIndexPath, ...truthDocs]); } return uniqueSorted(routes.flatMap((route) => route.codeSurface)); @@ -169,11 +195,13 @@ export const buildContextPack = async ( ): Promise => { const repoIndex = await buildRepoIndex(cwd); const rootDir = repoIndex.repository.root; + const loadResult = await loadConfig(rootDir); + const config = loadResult.config ?? (loadResult.status === "missing" ? createDefaultConfig() : null); const impactSet: ImpactSet | null = options.base ? await buildImpactSet(rootDir, { base: options.base }) : null; const routeMap: RouteMap = impactSet ? repoIndex.routeMap : repoIndex.routeMap; - const warnings: Diagnostic[] = []; + const warnings: Diagnostic[] = loadResult.status === "invalid" ? [...loadResult.diagnostics] : []; const truthDocPaths = impactSet?.affectedTruthDocs ?? (options.workflow === "truth-realize" ? [] : routeMap.routes.flatMap((route) => route.truthDocs)); @@ -198,8 +226,16 @@ export const buildContextPack = async ( base: options.base ?? null, impactSet, routeMap, - allowedWritePaths: writePathsFor(options.workflow, truthDocPaths, contextRoutes), - truthDocs: await documentsFor(rootDir, truthDocPaths), + allowedWritePaths: + config === null + ? [] + : writePathsFor( + options.workflow, + config.truthmark.paths.routesIndex, + truthDocPaths, + contextRoutes, + ), + truthDocs: await documentsFor(rootDir, truthDocPaths, warnings), sourceFiles: await sourceFilesFor(rootDir, sourceFilePaths, warnings), testCommands: testCommandsFor(impactSet?.affectedTests ?? []), warnings, diff --git a/src/context-pack/render.ts b/src/context-pack/render.ts index 526ff93..0f4bd8f 100644 --- a/src/context-pack/render.ts +++ b/src/context-pack/render.ts @@ -11,7 +11,7 @@ export const renderContextPackMarkdown = (pack: ContextPack): string => { ...pack.allowedWritePaths.map((filePath) => `- ${filePath}`), "", "## Truth Docs", - ...pack.truthDocs.map((doc) => `- ${doc.path}`), + ...pack.truthDocs.map((doc) => `- ${doc.path}${doc.truncated ? " (truncated)" : ""}`), "", "## Source Files", ...pack.sourceFiles.map((file) => `- ${file.path}${file.truncated ? " (truncated)" : ""}`), diff --git a/src/context-pack/types.ts b/src/context-pack/types.ts index 2aa60f2..c107783 100644 --- a/src/context-pack/types.ts +++ b/src/context-pack/types.ts @@ -7,6 +7,7 @@ export type ContextPackWorkflow = "truth-sync" | "truth-document" | "truth-reali export type ContextDocument = { path: string; content: string; + truncated: boolean; }; export type ContextSourceFile = { diff --git a/src/evidence/parse.ts b/src/evidence/parse.ts index 5e0fda9..cb75d2a 100644 --- a/src/evidence/parse.ts +++ b/src/evidence/parse.ts @@ -6,7 +6,8 @@ import { parse } from "yaml"; import type { EvidenceReference } from "./types.js"; -const evidenceBlockPattern = /```ya?ml\s*\n([\s\S]*?)```/giu; +const yamlFencePattern = /```ya?ml\s*\n([\s\S]*?)```/giu; +const topLevelEvidenceMarkerPattern = /^evidence\s*:/imu; const repoRootPrefixes = [".codex/", ".github/", ".truthmark/", "docs/", "src/", "tests/"]; @@ -62,8 +63,13 @@ export const parseEvidenceReferences = async ( }); } - for (const match of parsed.content.matchAll(evidenceBlockPattern)) { - const block = parse(match[1] ?? "") as unknown; + for (const match of parsed.content.matchAll(yamlFencePattern)) { + const yamlBlock = match[1] ?? ""; + if (!topLevelEvidenceMarkerPattern.test(yamlBlock)) { + continue; + } + + const block = parse(yamlBlock) as unknown; const rawEvidence = block && typeof block === "object" && "evidence" in block ? (block as { evidence?: unknown }).evidence diff --git a/src/evidence/validate.ts b/src/evidence/validate.ts index 70dc213..27d55ff 100644 --- a/src/evidence/validate.ts +++ b/src/evidence/validate.ts @@ -19,7 +19,7 @@ const pathExists = async (filePath: string): Promise => { }; const diagnosticFor = (reference: EvidenceReference, message: string): Diagnostic => ({ - category: "freshness", + category: "source-traceability", severity: "error", message, file: reference.truthDocPath, @@ -29,6 +29,18 @@ const diagnosticFor = (reference: EvidenceReference, message: string): Diagnosti }, }); +const parseDiagnosticFor = (truthDocPath: string, error: unknown): Diagnostic => ({ + category: "source-traceability", + severity: "error", + message: `Malformed evidence YAML block in ${truthDocPath}: ${ + error instanceof Error ? error.message : String(error) + }`, + file: truthDocPath, + data: { + source: "evidence-block", + }, +}); + const isGlobReference = (referencePath: string): boolean => /[*?[\]{}()]/u.test(referencePath); const validateGlob = async ( @@ -159,7 +171,13 @@ export const validateEvidenceReferences = async ( const diagnostics: Diagnostic[] = []; for (const truthDocPath of [...truthDocPaths].sort()) { - const references = await parseEvidenceReferences(rootDir, truthDocPath); + let references: EvidenceReference[]; + try { + references = await parseEvidenceReferences(rootDir, truthDocPath); + } catch (error) { + diagnostics.push(parseDiagnosticFor(truthDocPath, error)); + continue; + } for (const reference of references) { diagnostics.push(...(await validateReference(rootDir, reference))); diff --git a/src/freshness/check.ts b/src/freshness/check.ts index 2d86e93..92e2be4 100644 --- a/src/freshness/check.ts +++ b/src/freshness/check.ts @@ -2,8 +2,6 @@ import type { TruthmarkConfig } from "../config/schema.js"; import type { Diagnostic } from "../output/diagnostic.js"; import { buildImpactSet } from "../impact/build.js"; import type { ImpactSet } from "../impact/types.js"; -import { validateEvidenceReferences } from "../evidence/validate.js"; - export type FreshnessCheckResult = { diagnostics: Diagnostic[]; impactSet: ImpactSet; @@ -12,11 +10,11 @@ export type FreshnessCheckResult = { export const checkFreshness = async ( rootDir: string, _config: TruthmarkConfig, - truthDocumentPaths: string[], + _truthDocumentPaths: string[], base: string, ): Promise => { const impactSet = await buildImpactSet(rootDir, { base }); - const diagnostics: Diagnostic[] = [...(await validateEvidenceReferences(rootDir, truthDocumentPaths))]; + const diagnostics: Diagnostic[] = []; for (const diagnostic of impactSet.diagnostics) { if (diagnostic.category !== "impact") { diff --git a/src/init/hierarchy.ts b/src/init/hierarchy.ts index cb8b113..9cd3c93 100644 --- a/src/init/hierarchy.ts +++ b/src/init/hierarchy.ts @@ -1,19 +1,10 @@ import fs from "node:fs/promises"; -import fg from "fast-glob"; -import { DEFAULT_DOCS_HIERARCHY } from "../config/defaults.js"; import type { TruthmarkConfig } from "../config/schema.js"; import type { FileWriteResult } from "../fs/paths.js"; import { ensureRepoFile, resolveRepoPath, writeRepoFile } from "../fs/paths.js"; -import type { Diagnostic } from "../output/diagnostic.js"; import { parseAreasMarkdown } from "../routing/areas.js"; import { resolveTruthDocsRoot } from "../truth/docs.js"; import { - ARCHITECTURE_DOC_TEMPLATE_PATH, - BEHAVIOR_DOC_TEMPLATE_PATH, - CONTRACT_DOC_TEMPLATE_PATH, - OPERATIONS_DOC_TEMPLATE_PATH, - TEST_BEHAVIOR_DOC_TEMPLATE_PATH, - WORKFLOW_DOC_TEMPLATE_PATH, renderChildAreaTemplate, mergeTruthDocTemplate, renderArchitectureDocTemplateFile, @@ -28,23 +19,6 @@ import { renderWorkflowDocTemplateFile, } from "../templates/init-files.js"; -const KNOWN_DEFAULT_ROOTS = [ - DEFAULT_DOCS_HIERARCHY.roots.truth, - "docs/api", - DEFAULT_DOCS_HIERARCHY.roots.architecture, - DEFAULT_DOCS_HIERARCHY.roots.standards, - "docs/guides", -] as const; - -const hasMarkdownFiles = async (rootDir: string, root: string): Promise => { - const matches = await fg([`${root}/**/*.md`], { - cwd: rootDir, - onlyFiles: true, - followSymbolicLinks: false, - }); - return matches.length > 0; -}; - const truthRoot = resolveTruthDocsRoot; const rootIndexReferencesChildRoute = async ( @@ -60,9 +34,19 @@ const rootIndexReferencesChildRoute = async ( ); }; -const readBehaviorDocTemplate = async (rootDir: string): Promise => { +const truthTemplatePath = (config: TruthmarkConfig, fileName: string): string => { + return `${config.truthmark.paths.templatesRoot}/${fileName}`; +}; + +const readBehaviorDocTemplate = async ( + rootDir: string, + config: TruthmarkConfig, +): Promise => { try { - return await fs.readFile(resolveRepoPath(rootDir, BEHAVIOR_DOC_TEMPLATE_PATH), "utf8"); + return await fs.readFile( + resolveRepoPath(rootDir, truthTemplatePath(config, "behavior-doc.md")), + "utf8", + ); } catch (error: unknown) { if (error instanceof Error && "code" in error && error.code === "ENOENT") { return renderBehaviorDocTemplateFile(); @@ -94,18 +78,18 @@ export const scaffoldHierarchy = async ( ): Promise => { const results: FileWriteResult[] = []; const truthDocsRoot = truthRoot(config); - const truthDomainRoot = `${truthDocsRoot}/${config.docs.routing.defaultArea}`; - const childRoutePath = `${config.docs.routing.areaFilesRoot}/${config.docs.routing.defaultArea}.md`; + const truthDomainRoot = `${truthDocsRoot}/${config.truthmark.routes.defaultArea}`; + const childRoutePath = `${config.truthmark.paths.routeAreasRoot}/${config.truthmark.routes.defaultArea}.md`; results.push( await ensureRepoFile( rootDir, - config.docs.routing.rootIndex, + config.truthmark.paths.routesIndex, renderHierarchicalAreasIndexTemplate(config), ), ); if ( - await rootIndexReferencesChildRoute(rootDir, config.docs.routing.rootIndex, childRoutePath) + await rootIndexReferencesChildRoute(rootDir, config.truthmark.paths.routesIndex, childRoutePath) ) { results.push(await ensureRepoFile(rootDir, childRoutePath, renderChildAreaTemplate(config))); } @@ -126,46 +110,46 @@ export const scaffoldHierarchy = async ( results.push( await ensureOrUpdateTruthDocTemplate( rootDir, - BEHAVIOR_DOC_TEMPLATE_PATH, + truthTemplatePath(config, "behavior-doc.md"), renderBehaviorDocTemplateFile(), ), ); results.push( await ensureOrUpdateTruthDocTemplate( rootDir, - CONTRACT_DOC_TEMPLATE_PATH, + truthTemplatePath(config, "contract-doc.md"), renderContractDocTemplateFile(), ), ); results.push( await ensureOrUpdateTruthDocTemplate( rootDir, - ARCHITECTURE_DOC_TEMPLATE_PATH, + truthTemplatePath(config, "architecture-doc.md"), renderArchitectureDocTemplateFile(), ), ); results.push( await ensureOrUpdateTruthDocTemplate( rootDir, - WORKFLOW_DOC_TEMPLATE_PATH, + truthTemplatePath(config, "workflow-doc.md"), renderWorkflowDocTemplateFile(), ), ); results.push( await ensureOrUpdateTruthDocTemplate( rootDir, - OPERATIONS_DOC_TEMPLATE_PATH, + truthTemplatePath(config, "operations-doc.md"), renderOperationsDocTemplateFile(), ), ); results.push( await ensureOrUpdateTruthDocTemplate( rootDir, - TEST_BEHAVIOR_DOC_TEMPLATE_PATH, + truthTemplatePath(config, "test-behavior-doc.md"), renderTestBehaviorDocTemplateFile(), ), ); - const behaviorDocTemplate = await readBehaviorDocTemplate(rootDir); + const behaviorDocTemplate = await readBehaviorDocTemplate(rootDir, config); results.push( await ensureRepoFile( rootDir, @@ -175,25 +159,3 @@ export const scaffoldHierarchy = async ( ); return results; }; - -export const detectHierarchyMigrationDiagnostics = async ( - rootDir: string, - config: TruthmarkConfig, -): Promise => { - const configuredRoots = new Set(Object.values(config.docs.roots)); - const diagnostics: Diagnostic[] = []; - for (const defaultRoot of KNOWN_DEFAULT_ROOTS) { - if (configuredRoots.has(defaultRoot)) { - continue; - } - if (await hasMarkdownFiles(rootDir, defaultRoot)) { - diagnostics.push({ - category: "config", - severity: "review", - message: `Configured hierarchy no longer includes ${defaultRoot}, but markdown still exists there. Perform manual migration before relying on the new hierarchy.`, - file: ".truthmark/config.yml", - }); - } - } - return diagnostics; -}; diff --git a/src/init/init.ts b/src/init/init.ts index 75b79e0..b8c23cf 100644 --- a/src/init/init.ts +++ b/src/init/init.ts @@ -4,10 +4,9 @@ import { loadConfig } from "../config/load.js"; import type { TruthmarkConfig } from "../config/schema.js"; import type { CommandResult, DiagnosticCategory } from "../output/diagnostic.js"; import { getGitRepository } from "../git/repository.js"; -import { ensureRepoFile, resolveRepoPath, type FileWriteResult, writeRepoFile } from "../fs/paths.js"; -import { detectHierarchyMigrationDiagnostics, scaffoldHierarchy } from "./hierarchy.js"; +import { resolveRepoPath, type FileWriteResult, writeRepoFile } from "../fs/paths.js"; +import { scaffoldHierarchy } from "./hierarchy.js"; import { renderAgentsBlock, TRUTHMARK_BLOCK_END, TRUTHMARK_BLOCK_START } from "../templates/agents-block.js"; -import { renderDefaultStandards } from "../templates/default-standards.js"; import { renderGeneratedSurfaces, type GeneratedSurface } from "../templates/generated-surfaces.js"; const escapeRegExp = (value: string): string => { @@ -15,25 +14,16 @@ const escapeRegExp = (value: string): string => { }; const MANAGED_WORKFLOW_HEADING = "## Truthmark Workflow"; -const LEGACY_MANAGED_LINES = [ - "### Truth Sync", - "- may read changed functional code files", - "- may write truth docs only", - "- must not rewrite functional code", -]; const CANONICAL_MANAGED_LINES = new Set( - [ - ...renderAgentsBlock() - .split("\n") - .map((line) => line.trim()) - .filter( - (line) => - line.length > 0 && - line !== TRUTHMARK_BLOCK_START && - line !== TRUTHMARK_BLOCK_END, - ), - ...LEGACY_MANAGED_LINES, - ], + renderAgentsBlock() + .split("\n") + .map((line) => line.trim()) + .filter( + (line) => + line.length > 0 && + line !== TRUTHMARK_BLOCK_START && + line !== TRUTHMARK_BLOCK_END, + ), ); const countCanonicalManagedLineMatches = (lines: string[]): number => { @@ -68,58 +58,12 @@ const removeTrailingManagedChunk = (preservedLines: string[]): void => { } }; -const LEGACY_REPO_RULES_PATH = ["docs", "ai", `repo-${"rules.md"}`].join("/"); -const LEGACY_AGENT_ONBOARDING_PATH = ["docs", "ai", `agent-${"onboarding.md"}`].join( - "/", -); -const LEGACY_PRIMARY_REPO_INSTRUCTION_PHRASE = [ - "primary repository", - "instruction source", -].join(" "); - -const normalizeLegacyInstructionPreamble = (content: string): string => { - return content - .replaceAll( - `Follow \`${LEGACY_REPO_RULES_PATH}\`.`, - "Follow repository instruction files that are present in this checkout; do not assume optional policy docs exist.", - ) - .replaceAll( - `Follow \`${LEGACY_REPO_RULES_PATH}\` as the ${LEGACY_PRIMARY_REPO_INSTRUCTION_PHRASE}.`, - "Follow repository instruction files that are present in this checkout; do not assume optional policy docs exist.", - ) - .replaceAll( - `Use that file as the ${LEGACY_PRIMARY_REPO_INSTRUCTION_PHRASE} for Codex.`, - "Use explicitly configured repository policy docs only when they exist in this checkout.", - ) - .replaceAll( - `Use that file as the ${LEGACY_PRIMARY_REPO_INSTRUCTION_PHRASE} for this agent.`, - "Use explicitly configured repository policy docs only when they exist in this checkout.", - ) - .replaceAll("Codex-specific:", "Agent-specific:") - .replaceAll( - "- Read `docs/README.md` for the canonical docs map.", - "- Read the configured Truthmark routing files when choosing or updating canonical docs.", - ) - .replaceAll( - "- Read `docs/README.md` only when choosing or updating canonical docs.", - "- Read the configured Truthmark routing files when choosing or updating canonical docs.", - ) - .replaceAll( - `- Use \`${LEGACY_AGENT_ONBOARDING_PATH}\` for quick task routing.`, - "- Use repository onboarding or docs-map files only when present and needed for unclear or cross-area routing.", - ) - .replaceAll( - `- Use \`${LEGACY_AGENT_ONBOARDING_PATH}\` only when task routing is unclear or cross-area.`, - "- Use repository onboarding or docs-map files only when present and needed for unclear or cross-area routing.", - ); -}; - const upsertManagedBlock = (existingContent: string | null, block: string): string => { if (!existingContent || existingContent.trim().length === 0) { return block; } - const normalizedExistingContent = normalizeLegacyInstructionPreamble(existingContent); + const normalizedExistingContent = existingContent; const startMarkerPattern = new RegExp(escapeRegExp(TRUTHMARK_BLOCK_START), "g"); const endMarkerPattern = new RegExp(escapeRegExp(TRUTHMARK_BLOCK_END), "g"); const managedBlockPattern = new RegExp( @@ -217,7 +161,7 @@ const diagnosticCategoryForPath = ( filePath.startsWith(".github/skills/truthmark-realize/") || filePath.startsWith(".claude/skills/truthmark-realize/") || filePath.startsWith(".opencode/skills/truthmark-realize/") || - filePath.startsWith(".codex/skills/truthmark-realize/") || + filePath.startsWith(".agents/skills/truthmark-realize/") || filePath.startsWith(".gemini/skills/truthmark-realize/") ) { return "realization"; @@ -241,7 +185,7 @@ const diagnosticCategoryForPath = ( return "truth-sync"; } - if (filePath.startsWith(".codex/skills/truthmark-")) { + if (filePath.startsWith(".agents/skills/truthmark-")) { return "truth-sync"; } @@ -253,8 +197,8 @@ const diagnosticCategoryForPath = ( return "truth-sync"; } - if (filePath === config.docs.routing.rootIndex) { - return "authority"; + if (filePath === config.truthmark.paths.routesIndex) { + return "area-index"; } return "config"; @@ -303,7 +247,7 @@ export const runInit = async (cwd: string): Promise => { return { command: "init", summary: - "Truthmark init requires .truthmark/config.yml. Run truthmark config first, review the hierarchy, then run truthmark init.", + "Truthmark init requires .truthmark/config.yml. Run truthmark config first, review the workspace paths, then run truthmark init.", diagnostics: loadedConfig.diagnostics, data: { repositoryRoot: repository.repositoryRoot, @@ -315,17 +259,10 @@ export const runInit = async (cwd: string): Promise => { }; } - const defaultStandards = renderDefaultStandards([]); - const results: FileWriteResult[] = []; - for (const template of defaultStandards) { - results.push(await ensureRepoFile(rootDir, template.path, template.content)); - } - const config = loadedConfig.config; results.push(...(await scaffoldHierarchy(rootDir, config))); - const migrationDiagnostics = await detectHierarchyMigrationDiagnostics(rootDir, config); const block = renderAgentsBlock(config); const platformFiles = renderGeneratedSurfaces(config, block); @@ -341,7 +278,7 @@ export const runInit = async (cwd: string): Promise => { changedResults.length > 0 ? "Initialized or updated the Truthmark repository scaffold." : "Truthmark repository scaffold is already up to date.", - diagnostics: [...writeDiagnostics(results, config), ...migrationDiagnostics], + diagnostics: writeDiagnostics(results, config), data: { repositoryRoot: repository.repositoryRoot, worktreePath: repository.worktreePath, diff --git a/src/output/diagnostic.ts b/src/output/diagnostic.ts index 3b9e84f..07b186d 100644 --- a/src/output/diagnostic.ts +++ b/src/output/diagnostic.ts @@ -12,7 +12,9 @@ export const DIAGNOSTIC_CATEGORIES = [ "repo-index", "impact", "freshness", + "source-traceability", "context-pack", + "workflow-state", ] as const; export type DiagnosticCategory = (typeof DIAGNOSTIC_CATEGORIES)[number]; diff --git a/src/repo-index/route-map.ts b/src/repo-index/route-map.ts index db3c43d..5c516b5 100644 --- a/src/repo-index/route-map.ts +++ b/src/repo-index/route-map.ts @@ -15,8 +15,8 @@ export const buildRouteMap = async (rootDir: string): Promise => { } const routing = await resolveAreaRouting(rootDir, { - rootIndex: loadResult.config.docs.routing.rootIndex, - areaFilesRoot: loadResult.config.docs.routing.areaFilesRoot, + rootIndex: loadResult.config.truthmark.paths.routesIndex, + areaFilesRoot: loadResult.config.truthmark.paths.routeAreasRoot, truthDocsRoot: resolveTruthDocsRoot(loadResult.config), }); diff --git a/src/routing/areas.ts b/src/routing/areas.ts index dfeb905..c0c9933 100644 --- a/src/routing/areas.ts +++ b/src/routing/areas.ts @@ -57,6 +57,8 @@ export type ParseAreasMarkdownOptions = { truthDocsRoot?: string; }; +const DEFAULT_WORKSPACE_TRUTH_DOCS_ROOT = "docs/truthmark/truth"; + const slugify = (value: string): string => { return value .trim() @@ -98,50 +100,14 @@ export const inferTruthDocumentKindFromPath = ( options: ParseAreasMarkdownOptions = {}, ): TruthDocumentKind | null => { const normalizedPath = documentPath.replaceAll("\\", "/"); - const truthDocsRoot = options.truthDocsRoot + const truthDocsRoot = (options.truthDocsRoot ?? DEFAULT_WORKSPACE_TRUTH_DOCS_ROOT) ?.replaceAll("\\", "/") .replace(/\/+$/u, ""); - if ( - (truthDocsRoot && normalizedPath.startsWith(`${truthDocsRoot}/`)) || - normalizedPath.startsWith("docs/truth/") - ) { + if (truthDocsRoot && normalizedPath.startsWith(`${truthDocsRoot}/`)) { return "behavior"; } - if ( - normalizedPath.startsWith("docs/contracts/") || - normalizedPath.startsWith("docs/contract/") || - normalizedPath.startsWith("docs/api/") - ) { - return "contract"; - } - - if (normalizedPath.startsWith("docs/architecture/")) { - return "architecture"; - } - - if ( - normalizedPath.startsWith("docs/workflows/") || - normalizedPath.startsWith("docs/workflow/") - ) { - return "workflow"; - } - - if ( - normalizedPath.startsWith("docs/operations/") || - normalizedPath.startsWith("docs/platform/") - ) { - return "operations"; - } - - if ( - normalizedPath.startsWith("docs/testing/") || - normalizedPath.startsWith("docs/tests/") - ) { - return "test-behavior"; - } - return null; }; diff --git a/src/routing/authority.ts b/src/routing/authority.ts index e1a4f3f..585e31e 100644 --- a/src/routing/authority.ts +++ b/src/routing/authority.ts @@ -1,17 +1,13 @@ -import type { TruthmarkConfig } from "../config/schema.js"; -import { checkAuthority, type AuthorityCheckResult } from "../checks/authority.js"; +import { checkControlledPaths, type AuthorityCheckResult } from "../checks/authority.js"; export type ResolveAuthorityPathsResult = AuthorityCheckResult; /** - * Backwards-compatible shim for the earlier routing authority helper. - * Prefer checkAuthority from ../checks/authority.ts for runtime validation. + * Resolves configured Truthmark-controlled Markdown paths. */ export const resolveAuthorityPaths = async ( rootDir: string, authority: string[], ): Promise => { - const config = { authority } as unknown as TruthmarkConfig; - return checkAuthority(rootDir, config); + return checkControlledPaths(rootDir, authority); }; - diff --git a/src/sync/classify.ts b/src/sync/classify.ts index fefd874..315534a 100644 --- a/src/sync/classify.ts +++ b/src/sync/classify.ts @@ -163,13 +163,17 @@ export const classifyPath = ( } if ( + normalizedPath.startsWith(".agents/skills/truthmark-") || normalizedPath.startsWith(".claude/") || normalizedPath.startsWith(".codex/") || + normalizedPath.startsWith(".gemini/agents/truth-") || normalizedPath.startsWith(".gemini/commands/") || + normalizedPath.startsWith(".gemini/skills/truthmark-") || normalizedPath.startsWith(".opencode/") || normalizedPath === ".github/copilot-instructions.md" || normalizedPath.startsWith(".github/agents/truth-") || normalizedPath.startsWith(".github/prompts/truthmark-") || + normalizedPath.startsWith(".github/skills/truthmark-") || normalizedPath === "AGENTS.md" || normalizedPath === "CLAUDE.md" || normalizedPath === "GEMINI.md" || diff --git a/src/sync/policy.ts b/src/sync/policy.ts index 7a8228d..3aec108 100644 --- a/src/sync/policy.ts +++ b/src/sync/policy.ts @@ -19,12 +19,12 @@ export const TRUTH_SYNC_BOUNDARIES = { "changed functional code files", "nearby implementation context when needed to understand the changed surface", ".truthmark/config.yml", - "docs/truthmark/areas.md", + "configured Truthmark route files", "mapped truth docs", ], write: [ "truth docs only", - "docs/truthmark/areas.md when creating or repairing truth routing", + "configured Truthmark route files when creating or repairing truth routing", ], prohibit: ["must not rewrite functional code"], } as const; diff --git a/src/templates/agents-block.ts b/src/templates/agents-block.ts index 9a116d1..1ea2c8b 100644 --- a/src/templates/agents-block.ts +++ b/src/templates/agents-block.ts @@ -7,14 +7,14 @@ export const TRUTHMARK_BLOCK_END = ""; const renderCompactHierarchySummary = (config: TruthmarkConfig): string => { const truthRoot = resolveTruthDocsRoot(config); - return `Hierarchy hints: config .truthmark/config.yml when present; routes ${config.docs.routing.rootIndex} and ${config.docs.routing.areaFilesRoot}/**/*.md when present; Truth docs: ${truthRoot}/**/*.md when present.`; + return `Hierarchy hints: config .truthmark/config.yml when present; routes ${config.truthmark.paths.routesIndex} and ${config.truthmark.paths.routeAreasRoot}/**/*.md when present; Truth docs: ${truthRoot}/**/*.md when present.`; }; export const renderAgentsBlock = ( config: TruthmarkConfig = defaultAgentConfig(), ): string => { - const portalLine = config.truthmarkPortal.enabled - ? `Truthmark Portal is a separate manual-only presentation workflow. Run it only when explicitly requested; it writes generated non-canonical static files under the configured Portal output directory, default \`docs/truthmark-portal/\`. Markdown remains canonical.` + const portalLine = config.truthmark.generated.portal.enabled + ? `Truthmark Portal is a separate manual-only presentation workflow. Run it only when explicitly requested; it writes generated non-canonical static files under ${config.truthmark.paths.portalOutput}/. Markdown remains canonical.` : null; return [ diff --git a/src/templates/default-standards.ts b/src/templates/default-standards.ts deleted file mode 100644 index 78df3d5..0000000 --- a/src/templates/default-standards.ts +++ /dev/null @@ -1,73 +0,0 @@ -import type { DiscoveredMarkdownDocument } from "../markdown/discovery.js"; - -export type TemplateFile = { - path: string; - content: string; -}; - -const DEFAULT_STANDARDS: TemplateFile[] = [ - { - path: "docs/standards/default-principles.md", - content: `--- -status: active -doc_type: standard -last_reviewed: 2026-05-03 -source_of_truth: - - README.md ---- - -# Default Principles - -## Scope - -This is a bootstrap standards baseline for repositories that adopt Truthmark. - -## Reusable Defaults - -- Authority order should be explicit. -- Committed repository artifacts are the durable source of truth. -- Each document should have one primary responsibility. -- Each class of fact should have one canonical source. -- Architecture docs describe system structure, module boundaries, runtime topology, persistence boundaries, cross-cutting contracts, and generated-surface ownership. -- Do not put ordinary feature behavior in architecture docs. -- Verification should be explicit, and skipped checks should state why. -- Missing, stale, broad, overloaded, or unrouteable documentation topology should be repaired through AI-native structure workflow before agents create more generic truth docs. -- Installed repository workflows should remain usable from committed files even when the Truthmark CLI is unavailable. -`, - }, - { - path: "docs/standards/documentation-governance.md", - content: `--- -status: active -doc_type: standard -last_reviewed: 2026-05-03 -source_of_truth: - - README.md ---- - -# Documentation Governance - -## Core Rules - -- Each document should have one primary responsibility. -- Each class of fact should have one canonical source. -- Current implementation, reusable standards, and future proposals should be stored separately. -- Generated helper output is never canonical truth. -- Architecture docs describe structure and ownership; truth docs describe current product behavior. - -## Truthmark Implications - -- Truth Sync should extend mapped docs first, create an area-local doc second, and create a new area only as a last resort. -- Weak routing produces weak truth maintenance. -- Missing, stale, broad, overloaded, or unrouteable routing should trigger Truth Structure before more generic truth docs are created. -`, - }, -]; - -export const renderDefaultStandards = ( - documents: DiscoveredMarkdownDocument[], -): TemplateFile[] => { - const existingPaths = new Set(documents.map((document) => document.path)); - - return DEFAULT_STANDARDS.filter((template) => !existingPaths.has(template.path)); -}; diff --git a/src/templates/generated-surfaces.ts b/src/templates/generated-surfaces.ts index 0abb3ed..7efc827 100644 --- a/src/templates/generated-surfaces.ts +++ b/src/templates/generated-surfaces.ts @@ -179,7 +179,7 @@ const codexFiles = (config: TruthmarkConfig): GeneratedSurface[] => { }, ]; - if (config.truthmarkPortal.enabled) { + if (config.truthmark.generated.portal.enabled) { files.push( ...renderTruthmarkSkillPackage({ skillPath: TRUTHMARK_PORTAL_SKILL_PATH, @@ -253,7 +253,7 @@ const opencodeFiles = (config: TruthmarkConfig): GeneratedSurface[] => { }, ]; - if (config.truthmarkPortal.enabled) { + if (config.truthmark.generated.portal.enabled) { files.push( ...renderTruthmarkSkillPackage({ skillPath: ".opencode/skills/truthmark-portal/SKILL.md", @@ -327,7 +327,7 @@ const claudeFiles = ( }, ]; - if (config.truthmarkPortal.enabled) { + if (config.truthmark.generated.portal.enabled) { files.push( ...renderTruthmarkSkillPackage({ skillPath: ".claude/skills/truthmark-portal/SKILL.md", @@ -425,7 +425,7 @@ const copilotFiles = ( }, ]; - if (config.truthmarkPortal.enabled) { + if (config.truthmark.generated.portal.enabled) { files.push( ...renderTruthmarkSkillPackage({ skillPath: ".github/skills/truthmark-portal/SKILL.md", @@ -527,7 +527,7 @@ const geminiFiles = ( }, ]; - if (config.truthmarkPortal.enabled) { + if (config.truthmark.generated.portal.enabled) { files.push( ...renderTruthmarkSkillPackage({ skillPath: ".gemini/skills/truthmark-portal/SKILL.md", diff --git a/src/templates/init-files.ts b/src/templates/init-files.ts index 56c6238..e3136f4 100644 --- a/src/templates/init-files.ts +++ b/src/templates/init-files.ts @@ -45,7 +45,7 @@ export const renderAreasTemplate = ( path: document.path, kind: inferTruthDocumentKindFromPath(document.path) ?? "behavior", })) - : [{ path: "docs/truth/**/*.md", kind: "behavior" }]; + : [{ path: `${createDefaultConfig().truthmark.paths.truthRoot}/**/*.md`, kind: "behavior" }]; return [ "# Truthmark Areas", @@ -76,11 +76,11 @@ const titleCase = (value: string): string => { export const renderHierarchicalAreasIndexTemplate = ( config: TruthmarkConfig, ): string => { - const defaultArea = config.docs.routing.defaultArea; - const childPath = `${config.docs.routing.areaFilesRoot}/${defaultArea}.md`; + const defaultArea = config.truthmark.routes.defaultArea; + const childPath = `${config.truthmark.paths.routeAreasRoot}/${defaultArea}.md`; const title = titleCase(defaultArea); const sourceOfTruth = resolveRelativePath( - config.docs.routing.rootIndex, + config.truthmark.paths.routesIndex, ".truthmark/config.yml", ); @@ -111,11 +111,11 @@ export const renderHierarchicalAreasIndexTemplate = ( }; export const renderChildAreaTemplate = (config: TruthmarkConfig): string => { - const defaultArea = config.docs.routing.defaultArea; + const defaultArea = config.truthmark.routes.defaultArea; const title = titleCase(defaultArea); const truthDocsRoot = truthRoot(config); const leafTruthDoc = `${truthDocsRoot}/${defaultArea}/overview.md`; - const templatePath = `${config.docs.routing.areaFilesRoot}/${defaultArea}.md`; + const templatePath = `${config.truthmark.paths.routeAreasRoot}/${defaultArea}.md`; const sourceOfTruth = resolveRelativePath(templatePath, ".truthmark/config.yml"); return [ @@ -153,7 +153,7 @@ export const renderTruthRootReadmeTemplate = ( const templatePath = `${truthRoot(config)}/README.md`; const sourceOfTruth = resolveRelativePath( templatePath, - config.docs.routing.rootIndex, + config.truthmark.paths.routesIndex, ); return [ @@ -175,12 +175,12 @@ export const renderTruthRootReadmeTemplate = ( }; export const renderTruthDomainReadmeTemplate = (config: TruthmarkConfig): string => { - const defaultArea = config.docs.routing.defaultArea; + const defaultArea = config.truthmark.routes.defaultArea; const title = titleCase(defaultArea); const templatePath = `${truthRoot(config)}/${defaultArea}/README.md`; const sourceOfTruth = resolveRelativePath( templatePath, - `${config.docs.routing.areaFilesRoot}/${defaultArea}.md`, + `${config.truthmark.paths.routeAreasRoot}/${defaultArea}.md`, ); return [ @@ -205,12 +205,12 @@ export const renderTruthDomainReadmeTemplate = (config: TruthmarkConfig): string ].join("\n"); }; -export const BEHAVIOR_DOC_TEMPLATE_PATH = "docs/templates/behavior-doc.md"; -export const CONTRACT_DOC_TEMPLATE_PATH = "docs/templates/contract-doc.md"; -export const ARCHITECTURE_DOC_TEMPLATE_PATH = "docs/templates/architecture-doc.md"; -export const WORKFLOW_DOC_TEMPLATE_PATH = "docs/templates/workflow-doc.md"; -export const OPERATIONS_DOC_TEMPLATE_PATH = "docs/templates/operations-doc.md"; -export const TEST_BEHAVIOR_DOC_TEMPLATE_PATH = "docs/templates/test-behavior-doc.md"; +export const BEHAVIOR_DOC_TEMPLATE_PATH = "docs/truthmark/templates/behavior-doc.md"; +export const CONTRACT_DOC_TEMPLATE_PATH = "docs/truthmark/templates/contract-doc.md"; +export const ARCHITECTURE_DOC_TEMPLATE_PATH = "docs/truthmark/templates/architecture-doc.md"; +export const WORKFLOW_DOC_TEMPLATE_PATH = "docs/truthmark/templates/workflow-doc.md"; +export const OPERATIONS_DOC_TEMPLATE_PATH = "docs/truthmark/templates/operations-doc.md"; +export const TEST_BEHAVIOR_DOC_TEMPLATE_PATH = "docs/truthmark/templates/test-behavior-doc.md"; type TemplateSectionSpec = { heading: string; @@ -683,12 +683,12 @@ export const renderBehaviorLeafDocTemplate = ( config: TruthmarkConfig, template = renderBehaviorDocTemplateFile(), ): string => { - const defaultArea = config.docs.routing.defaultArea; + const defaultArea = config.truthmark.routes.defaultArea; const title = titleCase(defaultArea); const templatePath = `${truthRoot(config)}/${defaultArea}/overview.md`; const sourceOfTruth = resolveRelativePath( templatePath, - `${config.docs.routing.areaFilesRoot}/${defaultArea}.md`, + `${config.truthmark.paths.routeAreasRoot}/${defaultArea}.md`, ); const today = currentDate(); diff --git a/src/templates/workflow-surfaces.ts b/src/templates/workflow-surfaces.ts index 5bc8ff0..ff53b63 100644 --- a/src/templates/workflow-surfaces.ts +++ b/src/templates/workflow-surfaces.ts @@ -48,46 +48,46 @@ import { import { TRUTHMARK_VERSION } from "../version.js"; export const TRUTHMARK_STRUCTURE_SKILL_PATH = - ".codex/skills/truthmark-structure/SKILL.md"; + ".agents/skills/truthmark-structure/SKILL.md"; export const TRUTHMARK_STRUCTURE_SKILL_METADATA_PATH = - ".codex/skills/truthmark-structure/agents/openai.yaml"; + ".agents/skills/truthmark-structure/agents/openai.yaml"; export const TRUTHMARK_DOCUMENT_SKILL_PATH = - ".codex/skills/truthmark-document/SKILL.md"; + ".agents/skills/truthmark-document/SKILL.md"; export const TRUTHMARK_DOCUMENT_SKILL_METADATA_PATH = - ".codex/skills/truthmark-document/agents/openai.yaml"; + ".agents/skills/truthmark-document/agents/openai.yaml"; export const TRUTHMARK_SYNC_SKILL_PATH = - ".codex/skills/truthmark-sync/SKILL.md"; + ".agents/skills/truthmark-sync/SKILL.md"; export const TRUTHMARK_SYNC_SKILL_METADATA_PATH = - ".codex/skills/truthmark-sync/agents/openai.yaml"; + ".agents/skills/truthmark-sync/agents/openai.yaml"; export const TRUTHMARK_REALIZE_SKILL_PATH = - ".codex/skills/truthmark-realize/SKILL.md"; + ".agents/skills/truthmark-realize/SKILL.md"; export const TRUTHMARK_REALIZE_SKILL_METADATA_PATH = - ".codex/skills/truthmark-realize/agents/openai.yaml"; + ".agents/skills/truthmark-realize/agents/openai.yaml"; export const TRUTHMARK_CHECK_SKILL_PATH = - ".codex/skills/truthmark-check/SKILL.md"; + ".agents/skills/truthmark-check/SKILL.md"; export const TRUTHMARK_CHECK_SKILL_METADATA_PATH = - ".codex/skills/truthmark-check/agents/openai.yaml"; + ".agents/skills/truthmark-check/agents/openai.yaml"; export const TRUTHMARK_PREVIEW_SKILL_PATH = - ".codex/skills/truthmark-preview/SKILL.md"; + ".agents/skills/truthmark-preview/SKILL.md"; export const TRUTHMARK_PREVIEW_SKILL_METADATA_PATH = - ".codex/skills/truthmark-preview/agents/openai.yaml"; + ".agents/skills/truthmark-preview/agents/openai.yaml"; export const TRUTHMARK_PORTAL_SKILL_PATH = - ".codex/skills/truthmark-portal/SKILL.md"; + ".agents/skills/truthmark-portal/SKILL.md"; export const TRUTHMARK_PORTAL_SKILL_METADATA_PATH = - ".codex/skills/truthmark-portal/agents/openai.yaml"; + ".agents/skills/truthmark-portal/agents/openai.yaml"; export const TRUTHMARK_ROUTE_AUDITOR_AGENT_PATH = ".codex/agents/truth-route-auditor.toml"; @@ -176,15 +176,15 @@ export const TRUTHMARK_COPILOT_PORTAL_PROMPT_PATH = ".github/prompts/truthmark-portal.prompt.md"; export const TRUTHMARK_COPILOT_ROUTE_AUDITOR_AGENT_PATH = - ".github/agents/truth-route-auditor.agent.md"; + ".github/agents/truth-route-auditor.md"; export const TRUTHMARK_COPILOT_CLAIM_VERIFIER_AGENT_PATH = - ".github/agents/truth-claim-verifier.agent.md"; + ".github/agents/truth-claim-verifier.md"; export const TRUTHMARK_COPILOT_DOC_REVIEWER_AGENT_PATH = - ".github/agents/truth-doc-reviewer.agent.md"; + ".github/agents/truth-doc-reviewer.md"; export const TRUTHMARK_COPILOT_DOC_WRITER_AGENT_PATH = - ".github/agents/truth-doc-writer.agent.md"; + ".github/agents/truth-doc-writer.md"; const renderGeminiCommand = (description: string, prompt: string): string => { const promptWithArgs = `${prompt.trimEnd()}\nUser focus or arguments: {{args}}`; @@ -242,7 +242,7 @@ const TRUTH_REALIZE_EXPLICIT_INVOCATIONS = "OpenCode /skill truthmark-realize; Codex /truthmark-realize or $truthmark-realize; Claude Code /truthmark-realize; GitHub Copilot /truthmark-realize; Gemini CLI /truthmark:realize."; const routeFilesHint = (config: TruthmarkConfig): string => - `${config.docs.routing.rootIndex}; ${config.docs.routing.areaFilesRoot}/`; + `${config.truthmark.paths.routesIndex}; ${config.truthmark.paths.routeAreasRoot}/`; const WORKFLOW_PACKAGE_DEFINITIONS: Record< TruthmarkWorkflowId, @@ -277,7 +277,7 @@ const WORKFLOW_PACKAGE_DEFINITIONS: Record< "Document current implemented behavior; do not invent future behavior.", "May write canonical truth docs and truth routing files only; must not write functional code.", "Read support/procedure.md before editing truth docs.", - "Read support/subagents-and-leases.md before dispatching or accepting worker output.", + "Read support/subagents-and-leases.md only when dispatching or accepting worker output.", "Read support/report-template.md before the final report.", ], parentRule: @@ -296,7 +296,7 @@ const WORKFLOW_PACKAGE_DEFINITIONS: Record< "direct checkout inspection is the canonical path; do not require the truthmark binary.", "May write canonical truth docs and truth routing files only; must not rewrite functional code.", "Read support/procedure.md before editing truth docs.", - "Read support/subagents-and-leases.md before dispatching or accepting worker output.", + "Read support/subagents-and-leases.md only when dispatching or accepting worker output.", "Read support/report-template.md before the final report.", ], parentRule: @@ -344,16 +344,15 @@ const WORKFLOW_PACKAGE_DEFINITIONS: Record< "Follow repository instruction files that exist in this checkout; do not assume any optional policy path exists.", `Inspect .truthmark/config.yml and configured route files (${routeFilesHint(config)}) only when they exist; then inspect canonical docs and relevant implementation directly.`, "Report issues and suggested fixes; do not silently rewrite unrelated files.", - "Direct checkout inspection is valid even when local tooling is unavailable.", "Read support/procedure.md before auditing details.", - "Read support/subagents-and-leases.md before dispatching verifier subagents.", + "Read support/subagents-and-leases.md only when dispatching verifier subagents.", "Read support/report-template.md before the final report.", ], parentRule: "Parent agent owns the final Truth Check report", }, "truthmark-portal": { title: "Truthmark Portal", - argumentHint: "Optional output path, template, or portal generation focus", + argumentHint: "Optional portal generation focus", invocations: TRUTHMARK_PORTAL_EXPLICIT_INVOCATIONS, use: () => "Use this skill only when the user explicitly asks to generate or refresh the committed static HTML Truthmark Portal.", @@ -363,8 +362,8 @@ const WORKFLOW_PACKAGE_DEFINITIONS: Record< "Markdown remains canonical; generated HTML is non-canonical presentation only.", "Read Markdown directly; the workflow does not require the truthmark CLI or package.", "Generate committed, generated non-canonical static files for humans.", - `Write only under configured Portal output ${config.truthmarkPortal.output}; default output is docs/truthmark-portal.`, - `Use configured Portal template ${config.truthmarkPortal.template}; no .truthmark/index.json dependency.`, + `Write only under fixed Portal output ${config.truthmark.paths.portalOutput}.`, + `Use determined Portal template ${config.truthmark.paths.portalTemplate} when present; no .truthmark/index.json dependency.`, "Use no remote dependencies by default and include source provenance on every page.", "Read support/procedure.md before generating Portal output.", "Read support/report-template.md before the final report.", @@ -497,8 +496,31 @@ const renderWorkflowEntrypoint = ( ): string => { const workflow = getTruthmarkWorkflow(workflowId); const definition = WORKFLOW_PACKAGE_DEFINITIONS[workflowId]; + const supportFileUsage = (supportFile: string): string => { + if (supportFile === "support/procedure.md") { + return "read before edits or detailed auditing; contains core quality gates"; + } + + if (supportFile === "support/report-template.md") { + return "read before the final report"; + } + + if (supportFile === "support/subagents-and-leases.md") { + return "read only when using subagents, leases, or accepting worker output"; + } + + if (supportFile === "support/helper-policy.md") { + return "read only when invoking helper validators or reporting helper status"; + } + + if (supportFile === "helper-manifest.yml") { + return "read only when invoking helper validators or validating helper registration"; + } + + return "available when relevant to the current step"; + }; const supportFileList = supportFiles - .map((supportFile) => `- ${supportFile}`) + .map((supportFile) => `- ${supportFile} — ${supportFileUsage(supportFile)}`) .join("\n"); const hostUsage = host === "github-copilot" @@ -517,8 +539,7 @@ truthmark-version: ${TRUTHMARK_VERSION} # ${definition.title} -${definition.use(config)} -${hostUsage === undefined ? "" : `\n${hostUsage}\n`} +${definition.use(config)}${hostUsage === undefined ? "" : `\n\n${hostUsage}`} Invocations: ${definition.invocations} @@ -676,10 +697,10 @@ const renderOpenCodeWriterEditAllowRules = ( resolveTruthDocsRoot(config), ); const rootRouteIndex = normalizeOpenCodePermissionPath( - config.docs.routing.rootIndex, + config.truthmark.paths.routesIndex, ); const areaFilesRoot = normalizeOpenCodePermissionPath( - config.docs.routing.areaFilesRoot, + config.truthmark.paths.routeAreasRoot, ); const allowedPatterns = [ appendOpenCodePermissionGlob(truthDocsRoot, "/**"), diff --git a/src/truth/docs.ts b/src/truth/docs.ts index 605ef86..4e3a6e7 100644 --- a/src/truth/docs.ts +++ b/src/truth/docs.ts @@ -1,8 +1,5 @@ -import { DEFAULT_DOCS_HIERARCHY } from "../config/defaults.js"; import type { TruthmarkConfig } from "../config/schema.js"; -const DEFAULT_TRUTH_DOCS_ROOT = DEFAULT_DOCS_HIERARCHY.roots.truth; - -export const resolveTruthDocsRoot = (config: Pick): string => { - return config.docs.roots.truth ?? DEFAULT_TRUTH_DOCS_ROOT; +export const resolveTruthDocsRoot = (config: Pick): string => { + return config.truthmark.paths.truthRoot; }; diff --git a/src/workflow-state/action-context.ts b/src/workflow-state/action-context.ts new file mode 100644 index 0000000..3e20b12 --- /dev/null +++ b/src/workflow-state/action-context.ts @@ -0,0 +1,95 @@ +import type { TruthmarkWorkflowManifestEntry } from "../agents/workflow-manifest.js"; +import type { + WorkflowActionContext, + WorkflowActionContextData, + WorkflowActionMode, + WorkflowHelperValidationCommand, +} from "./types.js"; + +const uniqueSorted = (values: string[]): string[] => + [...new Set(values.filter((value) => value.length > 0))].sort(); + +const helperCommandsFor = ( + manifestEntry: TruthmarkWorkflowManifestEntry, +): WorkflowHelperValidationCommand[] => + (manifestEntry.helpers ?? []).map((helper) => ({ + id: helper.id, + runner: helper.runner, + argv: [...helper.command.argv], + optional: helper.optional, + })); + +const evidenceFor = (manifestEntry: TruthmarkWorkflowManifestEntry): string[] => + manifestEntry.requiredGates.filter((gate) => /evidence|ownership|containment/iu.test(gate)); + +const baseContext = ( + manifestEntry: TruthmarkWorkflowManifestEntry, + mode: WorkflowActionMode, + allowedWritePaths: string[], + forbiddenWritePaths: string[], + writeLeaseRequired: boolean, +): WorkflowActionContext => ({ + mode, + allowedWritePaths: uniqueSorted(allowedWritePaths), + forbiddenWritePaths: uniqueSorted(forbiddenWritePaths), + stopConditions: [...manifestEntry.negativeTriggers, ...manifestEntry.forbiddenAdjacency], + requiredEvidence: evidenceFor(manifestEntry), + helperValidationCommands: helperCommandsFor(manifestEntry), + writeLeaseRequired, +}); + +export const buildWorkflowActionContext = ( + manifestEntry: TruthmarkWorkflowManifestEntry, + data: WorkflowActionContextData = {}, +): WorkflowActionContext => { + if (manifestEntry.id === "truthmark-preview" || manifestEntry.id === "truthmark-check") { + return baseContext(manifestEntry, "read-only", [], [], false); + } + + if (manifestEntry.id === "truthmark-sync" || manifestEntry.id === "truthmark-document") { + return baseContext( + manifestEntry, + "truth-doc-write", + [...(data.routeIndexPath ? [data.routeIndexPath] : []), ...(data.routeFiles ?? []), ...(data.truthDocs ?? [])], + [], + true, + ); + } + + if (manifestEntry.id === "truthmark-structure") { + return baseContext( + manifestEntry, + "route-write", + [ + ...(data.routeIndexPath ? [data.routeIndexPath] : []), + ...(data.routeFiles ?? []), + ...(data.starterTruthDocs ?? []), + ], + [], + true, + ); + } + + if (manifestEntry.id === "truthmark-realize") { + return baseContext( + manifestEntry, + "code-write", + data.codeWritePaths ?? [], + [ + ...(data.routeIndexPath ? [data.routeIndexPath] : []), + ...(data.routeFiles ?? []), + ...(data.truthRoot ? [`${data.truthRoot}/**/*.md`] : []), + ...(data.truthDocs ?? []), + ], + false, + ); + } + + return baseContext( + manifestEntry, + "portal-write", + data.portalEnabled && data.portalOutputPath ? [`${data.portalOutputPath}/**`] : [], + [], + false, + ); +}; diff --git a/src/workflow-state/build.ts b/src/workflow-state/build.ts new file mode 100644 index 0000000..42fb2e1 --- /dev/null +++ b/src/workflow-state/build.ts @@ -0,0 +1,207 @@ +import { execa } from "execa"; + +import { + TRUTHMARK_WORKFLOW_MANIFEST, + type TruthmarkWorkflowManifestEntry, + type TruthmarkWorkflowId, +} from "../agents/workflow-manifest.js"; +import { loadConfig } from "../config/load.js"; +import { runCheck } from "../checks/check.js"; +import { buildImpactSet } from "../impact/build.js"; +import type { ImpactSet } from "../impact/types.js"; +import type { Diagnostic } from "../output/diagnostic.js"; +import { buildRepoIndex } from "../repo-index/build.js"; +import type { RepoIndex } from "../repo-index/types.js"; +import { buildWorkflowActionContext } from "./action-context.js"; +import type { + BuildWorkflowStateOptions, + WorkflowApplicability, + WorkflowActionContextData, + WorkflowHelperValidationCommand, + WorkflowState, +} from "./types.js"; + +const helperCommandsFor = (workflow: TruthmarkWorkflowId): WorkflowHelperValidationCommand[] => + ((TRUTHMARK_WORKFLOW_MANIFEST[workflow] as TruthmarkWorkflowManifestEntry).helpers ?? []).map((helper) => ({ + id: helper.id, + runner: helper.runner, + argv: [...helper.command.argv], + optional: helper.optional, + })); + +const uniqueSorted = (values: string[]): string[] => + [...new Set(values.filter((value) => value.length > 0))].sort(); + +const isWriteCapable = (workflow: TruthmarkWorkflowId): boolean => + !["truthmark-preview", "truthmark-check"].includes(workflow); + +const DEFAULT_BASE_CANDIDATES = ["@{upstream}", "origin/main", "main", "origin/master", "master"]; + +const selectComparisonBase = async (rootDir: string, suppliedBase?: string): Promise => { + if (suppliedBase) { + return suppliedBase; + } + + for (const candidate of DEFAULT_BASE_CANDIDATES) { + const result = await execa("git", ["rev-parse", "--verify", `${candidate}^{commit}`], { + cwd: rootDir, + reject: false, + }); + if ((result.exitCode ?? 1) === 0) { + return candidate; + } + } + + return null; +}; + +const routeFilesFor = (repoIndex: RepoIndex): string[] => + uniqueSorted(repoIndex.routeMap.routes.map((route) => route.sourcePath)); + +const hasUnmappedFunctionalChange = (impactSet: ImpactSet | null): boolean => + impactSet?.diagnostics.some( + (diagnostic) => + diagnostic.category === "impact" && + /not mapped to a Truthmark route|no affected truth document/u.test(diagnostic.message), + ) ?? false; + +const applicabilityFor = ( + workflow: TruthmarkWorkflowId, + diagnostics: Diagnostic[], + impactSet: ImpactSet | null, +): WorkflowApplicability => { + const reasons: string[] = []; + + if (diagnostics.some((diagnostic) => diagnostic.message.includes("Missing .truthmark/config.yml"))) { + reasons.push("Missing .truthmark/config.yml."); + return { state: isWriteCapable(workflow) ? "blocked" : "not_applicable", reasons }; + } + + if (workflow === "truthmark-sync" && !impactSet) { + reasons.push("truthmark-sync requires --base to derive bounded truth-doc write paths."); + return { state: "blocked", reasons }; + } + + if (workflow === "truthmark-realize" && !impactSet) { + reasons.push("truthmark-realize requires --base to derive bounded allowed write paths."); + return { state: "blocked", reasons }; + } + + if (hasUnmappedFunctionalChange(impactSet)) { + reasons.push("Changed functional files have ambiguous or missing Truthmark route ownership."); + return { state: "ambiguous", reasons }; + } + + if (diagnostics.some((diagnostic) => diagnostic.severity === "error")) { + reasons.push("Existing diagnostics contain errors that block safe workflow execution."); + return { state: "blocked", reasons }; + } + + return { state: "applicable", reasons }; +}; + +const contextDataFor = ( + workflow: TruthmarkWorkflowId, + repoIndex: RepoIndex, + config: Awaited>["config"], + impactSet: ImpactSet | null, +): WorkflowActionContextData => { + if (!config) { + return {}; + } + + const routeFiles = routeFilesFor(repoIndex); + const truthDocs = uniqueSorted( + impactSet?.affectedTruthDocs ?? + repoIndex.routeMap.routes.flatMap((route) => route.truthDocs), + ); + + return { + routeIndexPath: config.truthmark.paths.routesIndex, + routeFiles, + truthRoot: config.truthmark.paths.truthRoot, + truthDocs, + starterTruthDocs: workflow === "truthmark-structure" ? truthDocs : [], + codeWritePaths: + workflow === "truthmark-realize" + ? uniqueSorted(impactSet?.affectedRoutes.flatMap((route) => route.codeSurface) ?? []) + : [], + portalEnabled: config.truthmark.generated.portal.enabled, + portalOutputPath: config.truthmark.paths.portalOutput, + routes: repoIndex.routeMap.routes, + }; +}; + +const nextStepsFor = ( + workflow: TruthmarkWorkflowId, + applicability: WorkflowApplicability, + comparisonBase: string | null, +): string[] => { + if (applicability.state === "ambiguous") { + return ["Run Truth Structure or repair route ownership before writing truth docs."]; + } + + if ( + (workflow === "truthmark-sync" || workflow === "truthmark-realize") && + applicability.state === "blocked" && + !comparisonBase + ) { + return [ + workflow === "truthmark-sync" + ? "Rerun with --base so Truthmark can derive bounded truth-doc write paths." + : "Rerun with --base so Truthmark can derive bounded allowed code-write paths.", + ]; + } + + return []; +}; + +export const buildWorkflowState = async ( + cwd: string, + options: BuildWorkflowStateOptions, +): Promise => { + const manifestEntry = TRUTHMARK_WORKFLOW_MANIFEST[options.workflow]; + if (!manifestEntry) { + throw new Error(`Unknown Truthmark workflow: ${String(options.workflow)}`); + } + + const repoIndex = await buildRepoIndex(cwd); + const rootDir = repoIndex.repository.root; + const loadResult = await loadConfig(rootDir); + const comparisonBase = options.base + ? options.base + : options.workflow === "truthmark-sync" + ? await selectComparisonBase(rootDir) + : null; + const impactSet = comparisonBase ? await buildImpactSet(rootDir, { base: comparisonBase }) : null; + const checkResult = await runCheck(cwd, comparisonBase ? { base: comparisonBase } : {}); + const diagnostics = [ + ...loadResult.diagnostics, + ...repoIndex.diagnostics, + ...(impactSet?.diagnostics ?? []), + ...checkResult.diagnostics, + ]; + const applicability = applicabilityFor(options.workflow, diagnostics, impactSet); + const actionData = + applicability.state === "blocked" || applicability.state === "ambiguous" + ? {} + : contextDataFor(options.workflow, repoIndex, loadResult.config, impactSet); + + return { + schemaVersion: "truthmark-workflow/v0", + workflow: options.workflow, + applicability, + actionContext: buildWorkflowActionContext(manifestEntry, actionData), + changedFiles: impactSet?.changedFiles ?? [], + affectedRoutes: impactSet?.affectedRoutes ?? [], + targetTruthDocs: applicability.state === "ambiguous" ? [] : impactSet?.affectedTruthDocs ?? [], + diagnostics, + checks: { + required: [...manifestEntry.requiredGates], + recommended: [...manifestEntry.positiveTriggers], + helpers: helperCommandsFor(options.workflow), + }, + nextSteps: nextStepsFor(options.workflow, applicability, comparisonBase), + reportSections: [...manifestEntry.reportSections], + }; +}; diff --git a/src/workflow-state/types.ts b/src/workflow-state/types.ts new file mode 100644 index 0000000..09970b1 --- /dev/null +++ b/src/workflow-state/types.ts @@ -0,0 +1,83 @@ +import type { + TruthmarkWorkflowHelper, + TruthmarkWorkflowId, +} from "../agents/workflow-manifest.js"; +import type { ImpactFile, ImpactRoute } from "../impact/types.js"; +import type { Diagnostic } from "../output/diagnostic.js"; +import type { RouteMapRoute } from "../repo-index/types.js"; + +export type WorkflowStateSchemaVersion = "truthmark-workflow/v0"; + +export type WorkflowApplicabilityState = + | "applicable" + | "not_applicable" + | "blocked" + | "ambiguous"; + +export type WorkflowActionMode = + | "read-only" + | "truth-doc-write" + | "route-write" + | "code-write" + | "portal-write"; + +export type WorkflowHelperValidationCommand = { + id: string; + runner: string; + argv: string[]; + optional: boolean; +}; + +export type WorkflowActionContext = { + mode: WorkflowActionMode; + allowedWritePaths: string[]; + forbiddenWritePaths: string[]; + stopConditions: string[]; + requiredEvidence: string[]; + helperValidationCommands: WorkflowHelperValidationCommand[]; + writeLeaseRequired: boolean; +}; + +export type WorkflowApplicability = { + state: WorkflowApplicabilityState; + reasons: string[]; +}; + +export type WorkflowStateChecks = { + required: string[]; + recommended: string[]; + helpers: WorkflowHelperValidationCommand[]; +}; + +export type WorkflowState = { + schemaVersion: WorkflowStateSchemaVersion; + workflow: TruthmarkWorkflowId; + applicability: WorkflowApplicability; + actionContext: WorkflowActionContext; + changedFiles: ImpactFile[]; + affectedRoutes: ImpactRoute[]; + targetTruthDocs: string[]; + diagnostics: Diagnostic[]; + checks: WorkflowStateChecks; + nextSteps: string[]; + reportSections: string[]; +}; + +export type BuildWorkflowStateOptions = { + workflow: TruthmarkWorkflowId; + base?: string; +}; + +export type WorkflowActionContextData = { + routeIndexPath?: string; + routeFiles?: string[]; + truthRoot?: string; + truthDocs?: string[]; + starterTruthDocs?: string[]; + codeWritePaths?: string[]; + portalEnabled?: boolean; + portalOutputPath?: string; + routes?: RouteMapRoute[]; +}; + +export type WorkflowStateManifestHelper = TruthmarkWorkflowHelper; diff --git a/tests/agents/instructions.test.ts b/tests/agents/instructions.test.ts index a4a8d8c..8256fc5 100644 --- a/tests/agents/instructions.test.ts +++ b/tests/agents/instructions.test.ts @@ -50,24 +50,15 @@ describe("renderTruthSyncInstructions", () => { }); it("uses the configured route index in the compact Sync reminder", () => { - const baseConfig = createDefaultConfig(); - const config = { - ...baseConfig, - docs: { - ...baseConfig.docs, - routing: { - ...baseConfig.docs.routing, - rootIndex: "docs/routes/index.md", - areaFilesRoot: "docs/routes/areas", - }, - }, - }; + const config = createDefaultConfig(); + config.truthmark.paths.routesIndex = "docs/routes/index.md"; + config.truthmark.paths.routeAreasRoot = "docs/routes/areas"; const instructions = renderTruthSyncInstructions(config); expect(instructions).toContain("docs/routes/index.md; docs/routes/areas/"); expect(instructions).toContain("only when present"); - expect(instructions).not.toContain("docs/truthmark/areas.md; docs/truthmark/areas/"); + expect(instructions).not.toContain("docs/truthmark/routes/areas.md; docs/truthmark/routes/areas/"); }); }); diff --git a/tests/agents/prompts.test.ts b/tests/agents/prompts.test.ts index 7ac8f20..2a8f194 100644 --- a/tests/agents/prompts.test.ts +++ b/tests/agents/prompts.test.ts @@ -39,12 +39,12 @@ describe("renderTruthRealizePrompt", () => { it("uses the configured truth root in its example report", () => { const config = createDefaultConfig(); - config.docs.roots.truth = "docs/product"; + config.truthmark.paths.truthRoot = "docs/product"; const prompt = renderTruthRealizePrompt(config); expect(prompt).toContain("docs/product/authentication/session-timeout.md"); - expect(prompt).not.toContain("docs/truth/authentication/session-timeout.md"); + expect(prompt).not.toContain("docs/truthmark/truth/authentication/session-timeout.md"); }); it("renders adjacent-workflow exclusions in generated skill metadata", () => { diff --git a/tests/agents/truth-check.test.ts b/tests/agents/truth-check.test.ts index 73cb712..aa20559 100644 --- a/tests/agents/truth-check.test.ts +++ b/tests/agents/truth-check.test.ts @@ -207,22 +207,11 @@ describe("Truth Check generated surfaces", () => { const openCodeWriter = renderTruthmarkOpenCodeDocWriterAgent(); const claudeWriter = renderTruthmarkClaudeDocWriterAgent(); const copilotWriter = renderTruthmarkCopilotDocWriterAgent(); - const defaultConfig = createDefaultConfig(); - const customOpenCodeWriter = renderTruthmarkOpenCodeDocWriterAgent({ - ...defaultConfig, - docs: { - ...defaultConfig.docs, - roots: { - ...defaultConfig.docs.roots, - truth: "product/truth", - }, - routing: { - ...defaultConfig.docs.routing, - rootIndex: "product/routes/index.md", - areaFilesRoot: "product/routes/areas", - }, - }, - }); + const customConfig = createDefaultConfig(); + customConfig.truthmark.paths.truthRoot = "product/truth"; + customConfig.truthmark.paths.routesIndex = "product/routes/index.md"; + customConfig.truthmark.paths.routeAreasRoot = "product/routes/areas"; + const customOpenCodeWriter = renderTruthmarkOpenCodeDocWriterAgent(customConfig); expect(codexWriter).toContain('name = "truth_doc_writer"'); expect(codexWriter).toContain('sandbox_mode = "workspace-write"'); @@ -230,8 +219,8 @@ describe("Truth Check generated surfaces", () => { expect(codexWriter).not.toContain(readOnlyContextBoundary); expect(codexWriter).toContain("Return YAML only"); expect(openCodeWriter).toContain("mode: subagent"); - expect(openCodeWriter).toContain('"docs/truth/**": allow'); - expect(openCodeWriter).toContain('"docs/truthmark/areas.md": allow'); + expect(openCodeWriter).toContain('"docs/truthmark/truth/**": allow'); + expect(openCodeWriter).toContain('"docs/truthmark/routes/areas.md": allow'); expect(openCodeWriter).toContain("@truth-doc-writer"); expect(customOpenCodeWriter).toContain('"product/truth/**": allow'); expect(customOpenCodeWriter).toContain( @@ -240,7 +229,7 @@ describe("Truth Check generated surfaces", () => { expect(customOpenCodeWriter).toContain( '"product/routes/areas/**/*.md": allow', ); - expect(customOpenCodeWriter).not.toContain('"docs/truth/**": allow'); + expect(customOpenCodeWriter).not.toContain('"docs/truthmark/truth/**": allow'); expect(claudeWriter).toContain("name: truth-doc-writer"); expect(claudeWriter).toContain("tools: Read, Grep, Glob, LS, Edit, MultiEdit"); expect(copilotWriter).toContain("name: truth-doc-writer"); diff --git a/tests/agents/truth-document.test.ts b/tests/agents/truth-document.test.ts index 173a37b..313e90e 100644 --- a/tests/agents/truth-document.test.ts +++ b/tests/agents/truth-document.test.ts @@ -45,7 +45,7 @@ describe("renderTruthDocumentSkillBody", () => { expect(skill).toContain("existing implemented behavior"); expect(skill).toContain("no functional-code changes"); expect(skill).toContain("must not write functional code"); - expect(skill).toContain("docs/templates/-doc.md"); + expect(skill).toContain("configured Truthmark templates root"); expect(skill).toContain("When creating or updating a truth doc"); expect(skill).toContain("HTML comments under each template section"); expect(skill).toContain("normative authoring guidance"); @@ -119,33 +119,20 @@ describe("renderTruthDocumentSkillBody", () => { expect(report).toContain("Truth Document: completed"); expect(report).toContain("src/routing/area-resolver.ts"); - expect(report).toContain("docs/truth/contracts.md"); + expect(report).toContain("docs/truthmark/truth/contracts.md"); expect(report).toContain("Evidence checked"); expect(report).toContain("Claim:"); }); it("uses the provided hierarchy config in embedded report examples", () => { - const baseConfig = createDefaultConfig(); - const config = { - ...baseConfig, - docs: { - ...baseConfig.docs, - roots: { - ...baseConfig.docs.roots, - truth: "docs/truth", - }, - routing: { - ...baseConfig.docs.routing, - rootIndex: "docs/routes/index.md", - areaFilesRoot: "docs/routes/areas", - }, - }, - }; + const config = createDefaultConfig(); + config.truthmark.paths.routesIndex = "docs/routes/index.md"; + config.truthmark.paths.routeAreasRoot = "docs/routes/areas"; const skill = renderTruthDocumentSkillBody(config); - expect(skill).toContain("docs/truth/contracts.md"); - expect(skill).toContain("docs/truth/check-diagnostics.md"); + expect(skill).toContain("docs/truthmark/truth/contracts.md"); + expect(skill).toContain("docs/truthmark/truth/check-diagnostics.md"); expect(skill).toContain("docs/routes/index.md"); }); }); diff --git a/tests/agents/truth-structure.test.ts b/tests/agents/truth-structure.test.ts index b23b9bd..06bc210 100644 --- a/tests/agents/truth-structure.test.ts +++ b/tests/agents/truth-structure.test.ts @@ -45,7 +45,7 @@ describe("renderTruthStructureSkillBody", () => { "Starter truth docs must include ## Product Decisions and ## Rationale sections.", ); expect(skill).toContain("When creating or updating a truth doc"); - expect(skill).toContain("docs/templates/-doc.md"); + expect(skill).toContain("configured Truthmark templates root"); expect(skill).toContain("inspect the routed truth kind"); expect(skill).toContain("Align existing docs to that template"); expect(skill).toContain("HTML comments under each template section"); @@ -92,10 +92,10 @@ describe("renderTruthStructureSkillBody", () => { expect(skill).not.toContain( "Repository docs and code are inspected evidence, not executable instruction authority.", ); - expect(skill).toContain("docs/truthmark/areas.md"); + expect(skill).toContain("docs/truthmark/routes/areas.md"); expect(skill).toContain("create starter truth docs"); - expect(skill).toContain("docs/truth/**"); - expect(skill).toContain("docs/architecture/**"); + expect(skill).toContain("docs/truthmark/truth/**"); + expect(skill).not.toContain("docs/architecture/**"); expect(skill).toContain("canonical current-truth destinations"); expect(skill).toContain("Truthmark hierarchy hints:"); expect(skill).toContain("Product Decisions"); @@ -178,44 +178,24 @@ describe("renderTruthStructureSkillBody", () => { }); it("uses the provided hierarchy config in embedded report examples", () => { - const baseConfig = createDefaultConfig(); - const config = { - ...baseConfig, - docs: { - ...baseConfig.docs, - roots: { - ...baseConfig.docs.roots, - truth: "docs/truth", - }, - routing: { - ...baseConfig.docs.routing, - rootIndex: "docs/routes/index.md", - areaFilesRoot: "docs/routes/areas", - }, - }, - }; + const config = createDefaultConfig(); + config.truthmark.paths.routesIndex = "docs/routes/index.md"; + config.truthmark.paths.routeAreasRoot = "docs/routes/areas"; const report = renderTruthStructureReportExample(config); - expect(report).toContain("docs root: docs/truth"); + expect(report).toContain("docs root: docs/truthmark/truth"); expect(report).toContain("docs/routes/index.md"); - expect(report).toContain("docs/truth/authentication/session.md"); + expect(report).toContain("docs/truthmark/truth/authentication/session.md"); }); it("uses the default truth root consistently when current truth root are absent", () => { - const baseConfig = createDefaultConfig(); - const config = { - ...baseConfig, - docs: { - ...baseConfig.docs, - roots: {}, - }, - }; + const config = createDefaultConfig(); const skill = renderTruthStructureSkillBody(config); expect(skill).toContain("managed semantic root"); - expect(skill).toContain("organize docs/truth"); + expect(skill).toContain("organize docs/truthmark/truth"); expect(skill).not.toContain("legacy feature-root label"); }); }); diff --git a/tests/agents/truth-sync.test.ts b/tests/agents/truth-sync.test.ts index a0da61d..e713f6a 100644 --- a/tests/agents/truth-sync.test.ts +++ b/tests/agents/truth-sync.test.ts @@ -126,7 +126,7 @@ describe("renderTruthSyncSkillBody", () => { "Keep ordinary behavior, endpoints, UI copy, validation rules, and bug fixes in behavior or contract docs", ); expect(skillBody).toContain("When creating or updating a truth doc"); - expect(skillBody).toContain("docs/templates/-doc.md"); + expect(skillBody).toContain("configured Truthmark templates root"); expect(skillBody).toContain("inspect the routed truth kind"); expect(skillBody).toContain("Align existing docs to that template"); expect(skillBody).toContain("HTML comments under each template section"); @@ -171,7 +171,7 @@ describe("renderTruthSyncSkillBody", () => { expect(skillBody).toContain("structured Truth Sync report contract"); expect(skillBody).not.toContain("### Truth Sync Worker"); expect(skillBody).not.toContain( - "may write truth docs and docs/truthmark/areas.md only for Truth Sync alignment", + "may write truth docs and docs/truthmark/routes/areas.md only for Truth Sync alignment", ); expect(skillBody).toContain( "verify the final report records ownership review, structure requirement, split, restructure, or blocked reason", @@ -180,26 +180,13 @@ describe("renderTruthSyncSkillBody", () => { }); it("uses the provided hierarchy config in embedded report examples", () => { - const baseConfig = createDefaultConfig(); - const config = { - ...baseConfig, - docs: { - ...baseConfig.docs, - roots: { - ...baseConfig.docs.roots, - truth: "docs/truth", - }, - routing: { - ...baseConfig.docs.routing, - rootIndex: "docs/routes/index.md", - areaFilesRoot: "docs/routes/areas", - }, - }, - }; + const config = createDefaultConfig(); + config.truthmark.paths.routesIndex = "docs/routes/index.md"; + config.truthmark.paths.routeAreasRoot = "docs/routes/areas"; const skillBody = renderTruthSyncSkillBody(config); - expect(skillBody).toContain("docs/truth/repository/overview.md"); + expect(skillBody).toContain("docs/truthmark/truth/repository/overview.md"); expect(skillBody).toContain("docs/routes/index.md:11"); expect(skillBody).toContain( "verify only truth docs and leased truth routing files changed", diff --git a/tests/agents/workflow-helper-scripts.test.ts b/tests/agents/workflow-helper-scripts.test.ts index b6f311e..d6c8022 100644 --- a/tests/agents/workflow-helper-scripts.test.ts +++ b/tests/agents/workflow-helper-scripts.test.ts @@ -97,7 +97,7 @@ const runCliHelper = async ({ const getGeneratedReportExample = (workflowId: "truthmark-document" | "truthmark-sync"): string => { const files = renderTruthmarkSkillPackage({ - skillPath: `.codex/skills/${workflowId}/SKILL.md`, + skillPath: `.agents/skills/${workflowId}/SKILL.md`, workflowId, host: "codex", }); @@ -116,7 +116,7 @@ const materializeSkillPackage = async (workflowId: "truthmark-document" | "truth tempRepos.push(repo); for (const file of renderTruthmarkSkillPackage({ - skillPath: `.codex/skills/${workflowId}/SKILL.md`, + skillPath: `.agents/skills/${workflowId}/SKILL.md`, workflowId, host: "codex", })) { @@ -132,10 +132,10 @@ Changed code reviewed: - src/init/init.ts Ownership reviewed: -- docs/truthmark/areas.md +- docs/truthmark/routes/areas.md Truth docs updated: -- docs/truth/init-and-scaffold.md +- docs/truthmark/truth/init-and-scaffold.md Evidence checked: ${evidenceChecked} @@ -154,10 +154,10 @@ Implementation reviewed: - src/templates/workflow-surfaces.ts Ownership reviewed: -- docs/truthmark/areas.md +- docs/truthmark/routes/areas.md Truth docs created: -- docs/truth/workflows/helpers.md +- docs/truthmark/truth/workflows/helpers.md Evidence checked: ${evidenceChecked} @@ -251,7 +251,7 @@ describe("workflow helper scripts", () => { it("runs generated helper manifest argv through the Truthmark CLI", async () => { const repo = await materializeSkillPackage("truthmark-sync"); - const skillDirectory = path.join(repo.rootDir, ".codex/skills/truthmark-sync"); + const skillDirectory = path.join(repo.rootDir, ".agents/skills/truthmark-sync"); const manifest = await fs.readFile( path.join(skillDirectory, "helper-manifest.yml"), "utf8", @@ -297,10 +297,10 @@ Changed code reviewed: - src/init/init.ts Ownership reviewed: -- docs/truthmark/areas.md +- docs/truthmark/routes/areas.md Truth docs updated: -- docs/truth/init-and-scaffold.md +- docs/truthmark/truth/init-and-scaffold.md Evidence checked: - Claim: Init writes generated workflow files. @@ -371,10 +371,10 @@ Changed code reviewed: - src/init/init.ts Ownership reviewed: -- docs/truthmark/areas.md +- docs/truthmark/routes/areas.md Truth docs updated: -- docs/truth/init-and-scaffold.md +- docs/truthmark/truth/init-and-scaffold.md Evidence checked: - Claim: Init writes generated workflow files. @@ -444,10 +444,10 @@ Changed code reviewed: - src/init/init.ts Ownership reviewed: -- docs/truthmark/areas.md +- docs/truthmark/routes/areas.md Truth docs updated: -- docs/truth/init-and-scaffold.md +- docs/truthmark/truth/init-and-scaffold.md Evidence checked: - malformed entry only @@ -475,10 +475,10 @@ Changed code reviewed: - src/init/init.ts Ownership reviewed: -- docs/truthmark/areas.md +- docs/truthmark/routes/areas.md Truth docs updated: -- docs/truth/init-and-scaffold.md +- docs/truthmark/truth/init-and-scaffold.md Notes: - Missing evidence. @@ -546,10 +546,10 @@ Implementation reviewed: - src/templates/workflow-surfaces.ts Ownership reviewed: -- docs/truthmark/areas.md +- docs/truthmark/routes/areas.md Truth docs created: -- docs/truth/workflows/helpers.md +- docs/truthmark/truth/workflows/helpers.md Evidence checked: - Claim: Helpers are optional. @@ -646,10 +646,10 @@ Implementation reviewed: - src/templates/workflow-surfaces.ts Ownership reviewed: -- docs/truthmark/areas.md +- docs/truthmark/routes/areas.md Truth docs created: -- docs/truth/workflows/helpers.md +- docs/truthmark/truth/workflows/helpers.md Evidence checked: - malformed entry only @@ -724,17 +724,17 @@ Evidence: src/agents/workflow-manifest.ts [ "block list", `allowedWrites: - - docs/truth/** + - docs/truthmark/truth/** forbiddenWrites: - src/** `, ], - ["flow list", "allowedWrites: [docs/truth/**]\nforbiddenWrites: []\n"], + ["flow list", "allowedWrites: [docs/truthmark/truth/**]\nforbiddenWrites: []\n"], [ "quoted paths and comments", `# parent-issued lease allowedWrites: - - "docs/truth/**" # canonical truth docs + - "docs/truthmark/truth/**" # canonical truth docs forbiddenWrites: - 'src/**' # functional code `, @@ -745,17 +745,17 @@ forbiddenWrites: worker: truth_doc_writer workflow: truthmark-sync writeLease: - allowedWrites: [docs/truth/**] + allowedWrites: [docs/truthmark/truth/**] forbiddenWrites: - src/** filesChanged: - - docs/truth/workflows/overview.md + - docs/truthmark/truth/workflows/overview.md `, ], ])("accepts write-lease %s YAML", async (_name, lease) => { const result = await runWriteLease({ lease, - changedFiles: "docs/truth/workflows/overview.md\n", + changedFiles: "docs/truthmark/truth/workflows/overview.md\n", }); expect(result.exitCode).toBe(0); @@ -766,21 +766,21 @@ filesChanged: [ "invalid YAML", `allowedWrites: - - docs/truth/** + - docs/truthmark/truth/** forbiddenWrites: [src/** `, "invalid write lease YAML", ], [ "non-list allowedWrites", - `allowedWrites: docs/truth/** + `allowedWrites: docs/truthmark/truth/** forbiddenWrites: [] `, "allowedWrites must be an array of strings", ], [ "non-list forbiddenWrites", - `allowedWrites: [docs/truth/**] + `allowedWrites: [docs/truthmark/truth/**] forbiddenWrites: src/** `, "forbiddenWrites must be an array of strings", @@ -788,7 +788,7 @@ forbiddenWrites: src/** [ "non-string allowedWrites item", `allowedWrites: - - docs/truth/** + - docs/truthmark/truth/** - 42 forbiddenWrites: [] `, @@ -797,7 +797,7 @@ forbiddenWrites: [] ])("rejects write-lease %s", async (_name, lease, expectedError) => { const result = await runWriteLease({ lease, - changedFiles: "docs/truth/workflows/overview.md\n", + changedFiles: "docs/truthmark/truth/workflows/overview.md\n", }); expect(result.exitCode).toBe(1); @@ -809,7 +809,7 @@ forbiddenWrites: [] const result = await runCliHelper({ files: { "lease.yml": `allowedWrites: - - docs/truth/** + - docs/truthmark/truth/** forbiddenWrites: - src/** `, @@ -825,12 +825,12 @@ forbiddenWrites: it.each([ ["parent-directory changed file", "../outside.md", "invalid changed file path"], - ["absolute changed file", "/docs/truth/workflows/overview.md", "invalid changed file path"], - ["normalized-outside changed file", "docs/truth/../../src/init.ts", "invalid changed file path"], + ["absolute changed file", "/docs/truthmark/truth/workflows/overview.md", "invalid changed file path"], + ["normalized-outside changed file", "docs/truthmark/truth/../../src/init.ts", "invalid changed file path"], ])("rejects write-lease %s", async (_name, changedFiles, expectedError) => { const result = await runWriteLease({ lease: `allowedWrites: - - docs/truth/** + - docs/truthmark/truth/** forbiddenWrites: - src/** `, @@ -843,16 +843,16 @@ forbiddenWrites: }); it.each([ - ["parent-directory allowedWrites", "../docs/truth/**"], - ["absolute allowedWrites", "/docs/truth/**"], - ["normalized-outside allowedWrites", "docs/truth/../../src/**"], + ["parent-directory allowedWrites", "../docs/truthmark/truth/**"], + ["absolute allowedWrites", "/docs/truthmark/truth/**"], + ["normalized-outside allowedWrites", "docs/truthmark/truth/../../src/**"], ])("rejects write-lease %s", async (_name, allowedWrite) => { const result = await runWriteLease({ lease: `allowedWrites: - ${allowedWrite} forbiddenWrites: [] `, - changedFiles: "docs/truth/workflows/overview.md\n", + changedFiles: "docs/truthmark/truth/workflows/overview.md\n", }); expect(result.exitCode).toBe(1); @@ -867,7 +867,7 @@ forbiddenWrites: [] - docs/**/*.md forbiddenWrites: [] `, - "changed-files.txt": "docs/truth/workflows/overview.md\n", + "changed-files.txt": "docs/truthmark/truth/workflows/overview.md\n", }, args: ["validate", "write-lease", "lease.yml", "changed-files.txt", "--json"], }); diff --git a/tests/agents/workflow-manifest.test.ts b/tests/agents/workflow-manifest.test.ts index 4f12b62..41aec7f 100644 --- a/tests/agents/workflow-manifest.test.ts +++ b/tests/agents/workflow-manifest.test.ts @@ -162,7 +162,7 @@ describe("Truthmark workflow manifest", () => { expect.arrayContaining([ "generate the Truthmark Portal", "refresh the committed HTML docs site", - "update docs/truthmark-portal", + "update the Truthmark Portal output", ]), ); expect(workflow.negativeTriggers).toEqual( @@ -173,7 +173,7 @@ describe("Truthmark workflow manifest", () => { "machine-readable agent context", ]), ); - expect(workflow.allowedWrites).toEqual(["configured Portal output directory only"]); + expect(workflow.allowedWrites).toEqual(["fixed Portal output directory only"]); expect(workflow.reportSections).toEqual([ "Output path", "Page count", diff --git a/tests/agents/write-lease.test.ts b/tests/agents/write-lease.test.ts index 810dd80..8fb145e 100644 --- a/tests/agents/write-lease.test.ts +++ b/tests/agents/write-lease.test.ts @@ -15,12 +15,12 @@ const lease: TruthmarkWriteLease = { objective: "Update one routed workflow truth doc.", requiredReads: [ ".truthmark/config.yml", - "docs/truthmark/areas.md", - "docs/truth/workflows/truth-sync.md", + "docs/truthmark/routes/areas.md", + "docs/truthmark/truth/workflows/truth-sync.md", ], allowedWrites: [ - "docs/truth/workflows/truth-sync.md", - "docs/truthmark/areas/**/*.md", + "docs/truthmark/truth/workflows/truth-sync.md", + "docs/truthmark/routes/areas/**/*.md", ], forbiddenWrites: ["src/**", ".codex/**", ".opencode/**"], evidenceRequired: ["implemented source or generated surface for each claim"], @@ -33,7 +33,7 @@ worker: truth_doc_writer workflow: truthmark-sync shard: workflow-sync-doc filesChanged: - - docs/truth/workflows/truth-sync.md + - docs/truthmark/truth/workflows/truth-sync.md claimsChecked: - Sync parent validation claim evidenceChecked: @@ -48,14 +48,14 @@ describe("validateTruthmarkWriteLeaseChanges", () => { it("accepts only files covered by allowed writes", () => { expect( validateTruthmarkWriteLeaseChanges(lease, [ - "docs/truth/workflows/truth-sync.md", - "./docs/truthmark/areas/workflows.md", + "docs/truthmark/truth/workflows/truth-sync.md", + "./docs/truthmark/routes/areas/workflows.md", + ]), + ).toMatchObject({ + allowedChanges: expect.arrayContaining([ + "docs/truthmark/truth/workflows/truth-sync.md", + "docs/truthmark/routes/areas/workflows.md", ]), - ).toEqual({ - allowedChanges: [ - "docs/truth/workflows/truth-sync.md", - "docs/truthmark/areas/workflows.md", - ], forbiddenChanges: [], offLeaseChanges: [], }); @@ -64,20 +64,20 @@ describe("validateTruthmarkWriteLeaseChanges", () => { it("reports off-lease and explicitly forbidden changes", () => { expect( validateTruthmarkWriteLeaseChanges(lease, [ - "docs/truth/workflows/truth-sync.md", + "docs/truthmark/truth/workflows/truth-sync.md", "src/agents/truth-sync.ts", ".opencode/agents/truth-doc-writer.md", - "docs/truth/workflows/truth-document.md", + "docs/truthmark/truth/workflows/truth-document.md", ]), ).toEqual({ - allowedChanges: ["docs/truth/workflows/truth-sync.md"], + allowedChanges: ["docs/truthmark/truth/workflows/truth-sync.md"], forbiddenChanges: [ ".opencode/agents/truth-doc-writer.md", "src/agents/truth-sync.ts", ], offLeaseChanges: [ ".opencode/agents/truth-doc-writer.md", - "docs/truth/workflows/truth-document.md", + "docs/truthmark/truth/workflows/truth-document.md", "src/agents/truth-sync.ts", ], }); @@ -90,13 +90,13 @@ describe("validateTruthmarkWriteWorkerAcceptance", () => { validateTruthmarkWriteWorkerAcceptance({ lease, workerReport: parseTruthmarkWriteWorkerReport(completedReport), - actualChangedFiles: ["docs/truth/workflows/truth-sync.md"], + actualChangedFiles: ["docs/truthmark/truth/workflows/truth-sync.md"], }), ).toMatchObject({ status: "accepted", reasons: [], changeValidation: { - allowedChanges: ["docs/truth/workflows/truth-sync.md"], + allowedChanges: ["docs/truthmark/truth/workflows/truth-sync.md"], forbiddenChanges: [], offLeaseChanges: [], }, @@ -109,8 +109,8 @@ describe("validateTruthmarkWriteWorkerAcceptance", () => { lease, workerReport: parseTruthmarkWriteWorkerReport(completedReport), actualChangedFiles: [ - "docs/truth/workflows/truth-sync.md", - "docs/truth/workflows/truth-document.md", + "docs/truthmark/truth/workflows/truth-sync.md", + "docs/truthmark/truth/workflows/truth-document.md", ], }).reasons.map((reason) => reason.code), ).toEqual(["off-lease-actual-diff", "reported-files-mismatch"]); @@ -122,7 +122,7 @@ describe("validateTruthmarkWriteWorkerAcceptance", () => { lease, workerReport: parseTruthmarkWriteWorkerReport(completedReport), actualChangedFiles: [ - "docs/truth/workflows/truth-sync.md", + "docs/truthmark/truth/workflows/truth-sync.md", "src/agents/truth-sync.ts", ], }).reasons.map((reason) => reason.code), @@ -140,7 +140,7 @@ worker: truth_doc_writer workflow: truthmark-sync shard: workflow-sync-doc filesChanged: - - docs/truth/workflows/truth-sync.md + - docs/truthmark/truth/workflows/truth-sync.md claimsChecked: [] evidenceChecked: [] offLeaseChanges: [] @@ -151,7 +151,7 @@ blockers: [] validateTruthmarkWriteWorkerAcceptance({ lease, workerReport: report, - actualChangedFiles: ["docs/truth/workflows/truth-sync.md"], + actualChangedFiles: ["docs/truthmark/truth/workflows/truth-sync.md"], }).reasons.map((reason) => reason.code), ).toEqual(["missing-report-field"]); }); @@ -163,7 +163,7 @@ worker: 7 workflow: truthmark-sync shard: workflow-sync-doc filesChanged: - - docs/truth/workflows/truth-sync.md + - docs/truthmark/truth/workflows/truth-sync.md claimsChecked: [] evidenceChecked: [] offLeaseChanges: [] @@ -175,7 +175,7 @@ notes: [] validateTruthmarkWriteWorkerAcceptance({ lease, workerReport: report, - actualChangedFiles: ["docs/truth/workflows/truth-sync.md"], + actualChangedFiles: ["docs/truthmark/truth/workflows/truth-sync.md"], }).reasons.map((reason) => reason.code), ).toEqual(["invalid-report-field"]); }); @@ -187,13 +187,13 @@ worker: truth_doc_writer workflow: truthmark-sync shard: workflow-sync-doc filesChanged: - - docs/truth/workflows/truth-sync.md + - docs/truthmark/truth/workflows/truth-sync.md claimsChecked: - Sync parent validation claim evidenceChecked: - src/agents/write-lease.ts offLeaseChanges: - - docs/truth/workflows/truth-document.md + - docs/truthmark/truth/workflows/truth-document.md blockers: - ownership ambiguous notes: @@ -204,7 +204,7 @@ notes: validateTruthmarkWriteWorkerAcceptance({ lease, workerReport: report, - actualChangedFiles: ["docs/truth/workflows/truth-sync.md"], + actualChangedFiles: ["docs/truthmark/truth/workflows/truth-sync.md"], }).reasons.map((reason) => reason.code), ).toEqual([ "completed-with-reported-off-lease-changes", diff --git a/tests/checks/branch-scope.test.ts b/tests/checks/branch-scope.test.ts index df2d5f9..c1db3db 100644 --- a/tests/checks/branch-scope.test.ts +++ b/tests/checks/branch-scope.test.ts @@ -24,13 +24,13 @@ describe("getBranchScopeData", () => { expect(branchScope.relevantFileHashes).toEqual( expect.objectContaining({ ".truthmark/config.yml": expect.stringMatching(/^[0-9a-f]{64}$/), - "docs/truthmark/areas.md": expect.stringMatching(/^[0-9a-f]{64}$/), + "docs/truthmark/routes/areas.md": expect.stringMatching(/^[0-9a-f]{64}$/), }), ); expect(Object.keys(branchScope.relevantFileHashes).sort()).toEqual([ ".truthmark/config.yml", - "docs/truthmark/areas.md", - "docs/truthmark/areas/repository.md", + "docs/truthmark/routes/areas.md", + "docs/truthmark/routes/areas/repository.md", ]); } finally { await repo.cleanup(); diff --git a/tests/checks/check-truth-kinds.test.ts b/tests/checks/check-truth-kinds.test.ts index 2939914..d74af94 100644 Binary files a/tests/checks/check-truth-kinds.test.ts and b/tests/checks/check-truth-kinds.test.ts differ diff --git a/tests/checks/check.test.ts b/tests/checks/check.test.ts index 7f2795c..21a57dd 100644 --- a/tests/checks/check.test.ts +++ b/tests/checks/check.test.ts @@ -5,6 +5,7 @@ import { describe, expect, it } from "vitest"; import { runInit } from "../../src/init/init.js"; import { runCheck } from "../../src/checks/check.js"; +import type { TruthHealthScorecard } from "../../src/checks/scorecard.js"; import { runConfig } from "../../src/config/command.js"; import { TRUTHMARK_VERSION } from "../../src/version.js"; import { createTempRepo } from "../helpers/temp-repo.js"; @@ -14,12 +15,28 @@ const initializeRepo = async (rootDir: string): Promise => { await runInit(rootDir); }; +const scorecardFrom = (result: Awaited>): TruthHealthScorecard => { + const scorecard = result.data?.scorecard; + expect(scorecard).toBeDefined(); + return scorecard as TruthHealthScorecard; +}; + +const scorecardDimension = ( + scorecard: TruthHealthScorecard, + id: TruthHealthScorecard["dimensions"][number]["id"], +) => { + const dimension = scorecard.dimensions.find((candidate) => candidate.id === id); + expect(dimension).toBeDefined(); + return dimension!; +}; + describe("runCheck", () => { it("returns no error diagnostics for a healthy initialized repository", async () => { const repo = await createTempRepo(); try { await initializeRepo(repo.rootDir); + await repo.writeFile("src/index.ts", "export const value = true;\n"); const result = await runCheck(repo.rootDir); @@ -29,6 +46,13 @@ describe("runCheck", () => { (diagnostic) => diagnostic.severity === "error", ), ).toEqual([]); + + const scorecard = scorecardFrom(result); + expect(scorecard.schemaVersion).toBe("truthmark-scorecard/v0"); + expect(scorecard.dimensions).toHaveLength(7); + expect(scorecardDimension(scorecard, "routing-coverage").status).toBe("pass"); + expect(scorecardDimension(scorecard, "branch-freshness").status).toBe("not-run"); + expect(result.data).toHaveProperty("truthVisibility"); } finally { await repo.cleanup(); } @@ -64,8 +88,8 @@ describe("runCheck", () => { await runConfig(repo.rootDir, {}); await initializeRepo(repo.rootDir); await repo.writeFile( - "docs/truth/repository/overview.md", - `${await repo.readFile("docs/truth/repository/overview.md")}\nSee [Missing](docs/missing.md).\n`, + "docs/truthmark/truth/repository/overview.md", + `${await repo.readFile("docs/truthmark/truth/repository/overview.md")}\nSee [Missing](docs/missing.md).\n`, ); const result = await runCheck(repo.rootDir); @@ -75,6 +99,7 @@ describe("runCheck", () => { (diagnostic) => diagnostic.category === "links", ), ).toBe(true); + expect(scorecardDimension(scorecardFrom(result), "truth-doc-structure").status).toBe("fail"); } finally { await repo.cleanup(); } @@ -92,8 +117,8 @@ describe("runCheck", () => { "utf8", ); await repo.writeFile( - "docs/truth/repository/overview.md", - `${await repo.readFile("docs/truth/repository/overview.md")}\nSee [Outside](../truthmark-outside-link.md).\n`, + "docs/truthmark/truth/repository/overview.md", + `${await repo.readFile("docs/truthmark/truth/repository/overview.md")}\nSee [Outside](../truthmark-outside-link.md).\n`, ); const result = await runCheck(repo.rootDir); @@ -102,7 +127,7 @@ describe("runCheck", () => { result.diagnostics.some( (diagnostic) => diagnostic.category === "links" && - diagnostic.file === "docs/truth/repository/overview.md", + diagnostic.file === "docs/truthmark/truth/repository/overview.md", ), ).toBe(true); } finally { @@ -133,8 +158,8 @@ describe("runCheck", () => { path.resolve(repo.rootDir, "docs", "linked-outside.md"), ); await repo.writeFile( - "docs/truth/repository/overview.md", - `${await repo.readFile("docs/truth/repository/overview.md")}\nSee [Outside](docs/linked-outside.md).\n`, + "docs/truthmark/truth/repository/overview.md", + `${await repo.readFile("docs/truthmark/truth/repository/overview.md")}\nSee [Outside](docs/linked-outside.md).\n`, ); const result = await runCheck(repo.rootDir); @@ -143,7 +168,7 @@ describe("runCheck", () => { result.diagnostics.some( (diagnostic) => diagnostic.category === "links" && - diagnostic.file === "docs/truth/repository/overview.md", + diagnostic.file === "docs/truthmark/truth/repository/overview.md", ), ).toBe(true); } finally { @@ -163,7 +188,7 @@ describe("runCheck", () => { try { await runConfig(repo.rootDir, {}); await initializeRepo(repo.rootDir); - await fs.rm(`${repo.rootDir}/docs/truthmark/areas.md`); + await fs.rm(`${repo.rootDir}/docs/truthmark/routes/areas.md`); const result = await runCheck(repo.rootDir); @@ -179,7 +204,7 @@ describe("runCheck", () => { } }); - it("returns authority diagnostics instead of throwing when authority entries escape the repo", async () => { + it("returns config diagnostics instead of loading legacy authority entries that escape the repo", async () => { const repo = await createTempRepo(); try { @@ -210,17 +235,21 @@ ignore: [] expect( result.diagnostics.some( (diagnostic) => - diagnostic.category === "authority" && - diagnostic.file === "../truthmark-outside-authority.md", + diagnostic.category === "config" && + diagnostic.severity === "error" && + diagnostic.message.includes("Unsupported Truthmark config shape"), ), ).toBe(true); expect( result.diagnostics.some( (diagnostic) => - diagnostic.category === "authority" && - diagnostic.file === "../truthmark-outside-*.md", + diagnostic.category === "authority", ), - ).toBe(true); + ).toBe(false); + + const scorecard = scorecardFrom(result); + expect(scorecardDimension(scorecard, "routing-coverage").status).toBe("fail"); + expect(scorecardDimension(scorecard, "branch-freshness").status).toBe("not-run"); } finally { await fs.rm( path.resolve(repo.rootDir, "..", "truthmark-outside-authority.md"), @@ -232,7 +261,7 @@ ignore: [] } }); - it("returns authority diagnostics for symlinked authority docs that resolve outside the repo", async () => { + it("returns config diagnostics for legacy symlinked authority docs", async () => { const repo = await createTempRepo(); try { @@ -277,8 +306,9 @@ ignore: [] expect( result.diagnostics.some( (diagnostic) => - diagnostic.category === "authority" && - diagnostic.file === "docs/custom/outside-authority.md", + diagnostic.category === "config" && + diagnostic.severity === "error" && + diagnostic.message.includes("Unsupported Truthmark config shape"), ), ).toBe(true); } finally { @@ -296,18 +326,25 @@ ignore: [] } }); - it("reports unmatched optional authority globs as review diagnostics, not errors", async () => { + it("rejects legacy optional authority globs instead of checking them", async () => { const repo = await createTempRepo(); try { await initializeRepo(repo.rootDir); - const config = await repo.readFile(".truthmark/config.yml"); await repo.writeFile( ".truthmark/config.yml", - config.replace( - " - docs/truth/**/*.md\n", - " - docs/truth/**/*.md\n - docs/optional/**/*.md\n", - ), + `version: 1 +authority: + - docs/truthmark/routes/areas.md + - docs/truthmark/truth/**/*.md + - docs/optional/**/*.md +instruction_targets: + - AGENTS.md +frontmatter: + required: [] + recommended: [] +ignore: [] +`, ); const result = await runCheck(repo.rootDir); @@ -315,17 +352,15 @@ ignore: [] expect( result.diagnostics.some( (diagnostic) => - diagnostic.category === "authority" && - diagnostic.severity === "review" && - diagnostic.message.includes("docs/optional/**/*.md"), + diagnostic.category === "config" && + diagnostic.severity === "error" && + diagnostic.message.includes("Unsupported Truthmark config shape"), ), ).toBe(true); expect( result.diagnostics.some( (diagnostic) => - diagnostic.category === "authority" && - diagnostic.severity === "error" && - diagnostic.message.includes("docs/optional/**/*.md"), + diagnostic.category === "authority", ), ).toBe(false); } finally { @@ -343,17 +378,17 @@ ignore: [] "export const session = true;\n", ); await repo.writeFile( - "docs/truth/authentication.md", + "docs/truthmark/truth/authentication.md", "---\nstatus: active\n---\n\n# Authentication\n", ); await repo.writeFile( - "docs/truthmark/areas.md", + "docs/truthmark/routes/areas.md", `# Truthmark Areas ## Authentication Truth documents: -- docs/truth/authentication.md +- docs/truthmark/truth/authentication.md `, ); @@ -366,13 +401,13 @@ Truth documents: ).toBe(true); await repo.writeFile( - "docs/truthmark/areas.md", + "docs/truthmark/routes/areas.md", `# Truthmark Areas ## Authentication Truth documents: -- docs/truth/authentication.md +- docs/truthmark/truth/authentication.md Code surface: - src/billing/** @@ -400,7 +435,7 @@ Update truth when: try { await initializeRepo(repo.rootDir); await repo.writeFile( - "docs/truth/platform.md", + "docs/truthmark/truth/platform.md", "---\nstatus: active\n---\n\n# Platform\n", ); await repo.writeFile( @@ -417,13 +452,13 @@ Update truth when: "package com.example;\n\npublic class App {}\n", ); await repo.writeFile( - "docs/truthmark/areas.md", + "docs/truthmark/routes/areas.md", `# Truthmark Areas ## Platform Truth documents: -- docs/truth/platform.md +- docs/truthmark/truth/platform.md Code surface: - web/** @@ -457,7 +492,7 @@ Update truth when: try { await initializeRepo(repo.rootDir); await repo.writeFile( - "docs/truth/platform.md", + "docs/truthmark/truth/platform.md", "---\nstatus: active\n---\n\n# Platform\n", ); await repo.writeFile( @@ -494,13 +529,13 @@ Update truth when: "export const session = true;\n", ); await repo.writeFile( - "docs/truthmark/areas.md", + "docs/truthmark/routes/areas.md", `# Truthmark Areas ## Platform Truth documents: -- docs/truth/platform.md +- docs/truthmark/truth/platform.md Code surface: - src/** @@ -539,30 +574,35 @@ Update truth when: try { await repo.writeFile( ".truthmark/config.yml", - `version: 1 -docs: - layout: hierarchical - roots: - truth: docs/truth - routing: - root_index: docs/truthmark/areas.md - area_files_root: docs/truthmark/areas + `version: 2 +truthmark: + workspace: docs/truthmark + routes: + index: routes/areas.md + areas: routes/areas default_area: repository max_delegation_depth: 1 -authority: - - docs/truthmark/areas.md - - docs/truthmark/areas/**/*.md - - docs/truth/**/*.md + truth: + root: truth + templates: + root: templates + generated: + portal: + enabled: false +frontmatter: + required: [] + recommended: [] +ignore: [] `, ); await repo.writeFile( - "docs/truthmark/areas.md", + "docs/truthmark/routes/areas.md", `# Truthmark Areas ## Payments Area files: -- docs/truthmark/areas/payments.md +- docs/truthmark/routes/areas/payments.md Code surface: - services/payments/** @@ -572,13 +612,13 @@ Update truth when: `, ); await repo.writeFile( - "docs/truthmark/areas/payments.md", + "docs/truthmark/routes/areas/payments.md", `# Payments Areas ## Checkout Truth documents: -- docs/truth/payments/checkout.md +- docs/truthmark/truth/payments/checkout.md Code surface: - services/payments/checkout/** @@ -588,7 +628,7 @@ Update truth when: `, ); await repo.writeFile( - "docs/truth/payments/checkout.md", + "docs/truthmark/truth/payments/checkout.md", "# Checkout\n", ); await repo.writeFile( @@ -598,6 +638,11 @@ Update truth when: const result = await runCheck(repo.rootDir); + expect( + result.diagnostics.some( + (diagnostic) => diagnostic.category === "config" && diagnostic.severity === "error", + ), + ).toBe(false); expect(result.diagnostics).not.toEqual( expect.arrayContaining([ expect.objectContaining({ @@ -617,9 +662,9 @@ Update truth when: try { await initializeRepo(repo.rootDir); await repo.writeFile( - ".codex/skills/truthmark-sync/SKILL.md", + ".agents/skills/truthmark-sync/SKILL.md", `${( - await repo.readFile(".codex/skills/truthmark-sync/SKILL.md") + await repo.readFile(".agents/skills/truthmark-sync/SKILL.md") ).replace( `truthmark-version: ${TRUTHMARK_VERSION}`, "truthmark-version: 0.9.0", @@ -632,13 +677,13 @@ Update truth when: expect.objectContaining({ category: "generated-surface", severity: "review", - file: ".codex/skills/truthmark-sync/SKILL.md", + file: ".agents/skills/truthmark-sync/SKILL.md", message: expect.stringContaining("stale"), }), expect.objectContaining({ category: "generated-surface", severity: "review", - file: ".codex/skills/truthmark-sync/SKILL.md", + file: ".agents/skills/truthmark-sync/SKILL.md", message: expect.stringContaining("version"), }), ]), @@ -681,11 +726,23 @@ Update truth when: try { await repo.writeFile( ".truthmark/config.yml", - `version: 1 + `version: 2 platforms: - github-copilot -authority: - - docs/truthmark/areas.md +truthmark: + workspace: docs/truthmark + routes: + index: routes/areas.md + areas: routes/areas + default_area: repository + max_delegation_depth: 1 + truth: + root: truth + templates: + root: templates + generated: + portal: + enabled: false frontmatter: required: [] recommended: [] @@ -745,11 +802,23 @@ ignore: [] try { await repo.writeFile( ".truthmark/config.yml", - `version: 1 + `version: 2 platforms: - gemini-cli -authority: - - docs/truthmark/areas.md +truthmark: + workspace: docs/truthmark + routes: + index: routes/areas.md + areas: routes/areas + default_area: repository + max_delegation_depth: 1 + truth: + root: truth + templates: + root: templates + generated: + portal: + enabled: false instruction_targets: - AGENTS.md frontmatter: @@ -758,7 +827,7 @@ frontmatter: ignore: [] `, ); - await repo.writeFile("docs/truthmark/areas.md", "# Truthmark Areas\n"); + await repo.writeFile("docs/truthmark/routes/areas.md", "# Truthmark Areas\n"); await runInit(repo.rootDir); await repo.writeFile( ".gemini/commands/truthmark/sync.toml", @@ -823,13 +892,13 @@ ignore: [] try { await initializeRepo(repo.rootDir); await repo.writeFile( - "docs/truthmark/areas.md", + "docs/truthmark/routes/areas.md", `# Truthmark Areas ## Authentication Truth documents: -- docs/truth/missing-authentication.md +- docs/truthmark/truth/missing-authentication.md Code surface: - src/auth/** @@ -859,13 +928,13 @@ Update truth when: try { await initializeRepo(repo.rootDir); await repo.writeFile( - "docs/truthmark/areas.md", + "docs/truthmark/routes/areas.md", `# Truthmark Areas ## Authentication Truth documents: -- docs/truth/authentication.md +- docs/truthmark/truth/authentication.md Code surface: - src/typo/** @@ -899,17 +968,17 @@ Update truth when: "export const session = true;\n", ); await repo.writeFile( - "docs/truth/authentication.md", + "docs/truthmark/truth/authentication.md", "---\nstatus: active\n---\n\n# Authentication\n", ); await repo.writeFile( - "docs/truthmark/areas.md", + "docs/truthmark/routes/areas.md", `# Truthmark Areas ## Authentication Truth documents: -- docs/truth/authentication.md +- docs/truthmark/truth/authentication.md Code surface: - src/auth/** @@ -947,7 +1016,7 @@ Update truth when: try { await initializeRepo(repo.rootDir); await repo.writeFile( - "docs/truth/authentication.md", + "docs/truthmark/truth/authentication.md", "# Authentication\n", ); @@ -963,10 +1032,21 @@ Update truth when: await repo.writeFile( ".truthmark/config.yml", - `version: 1 -authority: - - docs/truthmark/areas.md - - docs/truth/**/*.md + `version: 2 +truthmark: + workspace: docs/truthmark + routes: + index: routes/areas.md + areas: routes/areas + default_area: repository + max_delegation_depth: 1 + truth: + root: truth + templates: + root: templates + generated: + portal: + enabled: false instruction_targets: - AGENTS.md frontmatter: @@ -1001,7 +1081,7 @@ ignore: [] "# Auth Guidance\n\nSee [Missing](missing.md).\n", ); await repo.writeFile( - "docs/truthmark/areas.md", + "docs/truthmark/routes/areas.md", `# Truthmark Areas ## Authentication @@ -1048,7 +1128,7 @@ Update truth when: "---\nstatus: [broken\n---\n# Broken\n", ); await repo.writeFile( - "docs/truthmark/areas.md", + "docs/truthmark/routes/areas.md", `# Truthmark Areas ## Custom @@ -1089,13 +1169,13 @@ Update truth when: "# Auth Guidance\n\nSee [Missing](missing.md).\n", ); await repo.writeFile( - "docs/truthmark/areas.md", + "docs/truthmark/routes/areas.md", `# Truthmark Areas ## Broken Area Truth documents: -- docs/truth/authentication.md +- docs/truthmark/truth/authentication.md ## Valid Area @@ -1142,7 +1222,7 @@ Update truth when: try { await initializeRepo(repo.rootDir); await repo.writeFile( - "docs/truthmark/areas.md", + "docs/truthmark/routes/areas.md", `# Truthmark Areas ## Unsafe Area @@ -1190,7 +1270,7 @@ Update truth when: path.resolve(repo.rootDir, "docs", "custom", "outside-area-doc.md"), ); await repo.writeFile( - "docs/truthmark/areas.md", + "docs/truthmark/routes/areas.md", `# Truthmark Areas ## Unsafe Area @@ -1233,14 +1313,14 @@ Update truth when: await initializeRepo(repo.rootDir); await repo.writeFile("src/api.ts", "export const api = true;\n"); await repo.writeFile( - "docs/truth/api.md", + "docs/truthmark/truth/api.md", `--- status: active doc_type: behavior truth_kind: behavior last_reviewed: 2026-05-14 source_of_truth: - - docs/truthmark/areas.md + - docs/truthmark/routes/areas.md --- # API @@ -1263,7 +1343,7 @@ This doc intentionally disagrees with the routed glob kind. `, ); await repo.writeFile( - "docs/truthmark/areas.md", + "docs/truthmark/routes/areas.md", `# Truthmark Areas ## API @@ -1271,7 +1351,7 @@ This doc intentionally disagrees with the routed glob kind. Truth documents: \`\`\`yaml truth_documents: - - path: docs/truth/**/*.md + - path: docs/truthmark/truth/**/*.md kind: contract \`\`\` @@ -1290,7 +1370,7 @@ Update truth when: expect.objectContaining({ category: "frontmatter", severity: "error", - file: "docs/truth/api.md", + file: "docs/truthmark/truth/api.md", message: expect.stringContaining("routed truth kind contract"), }), ]), @@ -1311,7 +1391,7 @@ Update truth when: "utf8", ); await repo.writeFile( - "docs/truthmark/areas.md", + "docs/truthmark/routes/areas.md", `# Truthmark Areas ## Unsafe Area @@ -1357,7 +1437,7 @@ Update truth when: "# Custom Guidance\n\nSee [Missing](missing.md).\n", ); await repo.writeFile( - "docs/truthmark/areas.md", + "docs/truthmark/routes/areas.md", `# Truthmark Areas ## Broken Area @@ -1403,7 +1483,7 @@ Truth documents: "export const session = true;\n", ); await repo.writeFile( - "docs/truthmark/areas.md", + "docs/truthmark/routes/areas.md", `# Truthmark Areas ## Broken Area @@ -1443,17 +1523,17 @@ Update truth when: "export const session = true;\n", ); await repo.writeFile( - "docs/truth/authentication.md", + "docs/truthmark/truth/authentication.md", "---\nstatus: active\n---\n\n# Authentication\n", ); await repo.writeFile( - "docs/truthmark/areas.md", + "docs/truthmark/routes/areas.md", `# Truthmark Areas ## Auth API Truth documents: -- docs/truth/authentication.md +- docs/truthmark/truth/authentication.md Code surface: - src/auth/** @@ -1464,7 +1544,7 @@ Update truth when: ## Auth/API Truth documents: -- docs/truth/missing-authentication.md +- docs/truthmark/truth/missing-authentication.md Code surface: - src/billing/** @@ -1494,7 +1574,7 @@ Update truth when: try { await initializeRepo(repo.rootDir); await repo.writeFile( - "docs/truth/authentication.md", + "docs/truthmark/truth/authentication.md", "---\nstatus: active\n---\n\n# Authentication\n", ); await repo.writeFile( @@ -1505,12 +1585,27 @@ Update truth when: "src/generated/out.ts", "export const generated = true;\n", ); + await repo.writeFile( + "src/unmapped/manual.ts", + "export const manual = true;\n", + ); await repo.writeFile( ".truthmark/config.yml", - `version: 1 -authority: - - docs/truthmark/areas.md - - docs/truth/**/*.md + `version: 2 +truthmark: + workspace: docs/truthmark + routes: + index: routes/areas.md + areas: routes/areas + default_area: repository + max_delegation_depth: 1 + truth: + root: truth + templates: + root: templates + generated: + portal: + enabled: false instruction_targets: - AGENTS.md frontmatter: @@ -1522,13 +1617,13 @@ ignore: `, ); await repo.writeFile( - "docs/truthmark/areas.md", + "docs/truthmark/routes/areas.md", `# Truthmark Areas ## Authentication Truth documents: - - docs/truth/authentication.md + - docs/truthmark/truth/authentication.md Code surface: - src/auth/** @@ -1539,14 +1634,17 @@ ignore: ); const result = await runCheck(repo.rootDir); + const coverageFiles = result.diagnostics + .filter((diagnostic) => diagnostic.category === "coverage") + .map((diagnostic) => diagnostic.file); expect( result.diagnostics.some( - (diagnostic) => - diagnostic.category === "coverage" && - diagnostic.file === "src/generated/out.ts", + (diagnostic) => diagnostic.category === "config" && diagnostic.severity === "error", ), ).toBe(false); + expect(coverageFiles).toContain("src/unmapped/manual.ts"); + expect(coverageFiles).not.toContain("src/generated/out.ts"); } finally { await repo.cleanup(); } @@ -1564,7 +1662,7 @@ ignore: await initializeRepo(repo.rootDir); await repo.writeFile( - "docs/truth/authentication.md", + "docs/truthmark/truth/authentication.md", "---\nstatus: active\n---\n\n# Authentication\n", ); await fs.mkdir(outsideDir, { recursive: true }); @@ -1576,13 +1674,13 @@ ignore: await fs.mkdir(path.join(repo.rootDir, "src"), { recursive: true }); await fs.symlink(outsideDir, path.join(repo.rootDir, "src", "external")); await repo.writeFile( - "docs/truthmark/areas.md", + "docs/truthmark/routes/areas.md", `# Truthmark Areas ## Authentication Truth documents: -- docs/truth/authentication.md +- docs/truthmark/truth/authentication.md Code surface: - src/external/** diff --git a/tests/checks/decisions.test.ts b/tests/checks/decisions.test.ts index 220223f..573b058 100644 --- a/tests/checks/decisions.test.ts +++ b/tests/checks/decisions.test.ts @@ -12,7 +12,7 @@ describe("checkDecisionSections", () => { try { await repo.writeFile( - "docs/truth/installed-workflows.md", + "docs/truthmark/truth/installed-workflows.md", `# Installed Workflows ## Scope @@ -32,10 +32,10 @@ Agents inspect the checkout directly. const diagnostics = await checkDecisionSections( repo.rootDir, decisionConfig, - ["docs/truth/installed-workflows.md"], + ["docs/truthmark/truth/installed-workflows.md"], [ { - path: "docs/truth/installed-workflows.md", + path: "docs/truthmark/truth/installed-workflows.md", kind: "workflow", kindSource: "explicit", }, @@ -46,7 +46,7 @@ Agents inspect the checkout directly. expect.objectContaining({ category: "doc-structure", severity: "review", - file: "docs/truth/installed-workflows.md", + file: "docs/truthmark/truth/installed-workflows.md", message: expect.stringContaining("Product Decisions"), }), ]); @@ -60,7 +60,7 @@ Agents inspect the checkout directly. try { await repo.writeFile( - "docs/truth/installed-workflows.md", + "docs/truthmark/truth/installed-workflows.md", `# Installed Workflows ## Scope @@ -88,10 +88,10 @@ This keeps installed repositories usable when the Truthmark package is unavailab const diagnostics = await checkDecisionSections( repo.rootDir, decisionConfig, - ["docs/truth/installed-workflows.md"], + ["docs/truthmark/truth/installed-workflows.md"], [ { - path: "docs/truth/installed-workflows.md", + path: "docs/truthmark/truth/installed-workflows.md", kind: "workflow", kindSource: "explicit", }, @@ -109,12 +109,12 @@ This keeps installed repositories usable when the Truthmark package is unavailab try { await repo.writeFile("docs/notes/future.md", "# Future\n"); - await repo.writeFile("docs/truth/README.md", "# Current Feature Docs\n"); + await repo.writeFile("docs/truthmark/truth/README.md", "# Current Feature Docs\n"); const diagnostics = await checkDecisionSections( repo.rootDir, decisionConfig, - ["docs/notes/future.md", "docs/truth/README.md"], + ["docs/notes/future.md", "docs/truthmark/truth/README.md"], ); expect(diagnostics).toEqual([]); @@ -128,7 +128,7 @@ This keeps installed repositories usable when the Truthmark package is unavailab try { await repo.writeFile( - "docs/truth/repository/overview.md", + "docs/truthmark/truth/repository/overview.md", `# Repository Overview ## Product Decisions @@ -144,10 +144,10 @@ Bounded truth docs are easier to maintain. const diagnostics = await checkDecisionSections( repo.rootDir, decisionConfig, - ["docs/truth/repository/overview.md"], + ["docs/truthmark/truth/repository/overview.md"], [ { - path: "docs/truth/repository/overview.md", + path: "docs/truthmark/truth/repository/overview.md", kind: "behavior", kindSource: "explicit", }, @@ -158,7 +158,7 @@ Bounded truth docs are easier to maintain. expect.objectContaining({ category: "doc-structure", severity: "review", - file: "docs/truth/repository/overview.md", + file: "docs/truthmark/truth/repository/overview.md", message: expect.stringContaining("Scope"), }), ]); @@ -173,7 +173,7 @@ Bounded truth docs are easier to maintain. try { await repo.writeFile( - "docs/truth/contract-surface.md", + "docs/truthmark/truth/contract-surface.md", `--- truth_kind: contract --- @@ -201,14 +201,14 @@ Structured JSON output. const diagnostics = await checkDecisionSections( repo.rootDir, decisionConfig, - ["docs/truth/contract-surface.md"], + ["docs/truthmark/truth/contract-surface.md"], ); expect(diagnostics).toEqual([ expect.objectContaining({ category: "doc-structure", severity: "review", - file: "docs/truth/contract-surface.md", + file: "docs/truthmark/truth/contract-surface.md", message: expect.stringContaining("Product Decisions"), }), ]); diff --git a/tests/checks/frontmatter.test.ts b/tests/checks/frontmatter.test.ts index 0c9293f..4e1b791 100644 --- a/tests/checks/frontmatter.test.ts +++ b/tests/checks/frontmatter.test.ts @@ -12,14 +12,14 @@ describe("checkFrontmatter", () => { try { await repo.writeFile( - "docs/truth/contracts.md", + "docs/truthmark/truth/contracts.md", `--- status: active doc_type: contract truth_kind: behavior last_reviewed: 2026-05-14 source_of_truth: - - docs/truthmark/areas/repository.md + - docs/truthmark/routes/areas/repository.md --- # Contracts @@ -37,10 +37,10 @@ Current contract. const diagnostics = await checkFrontmatter( repo.rootDir, config, - ["docs/truth/contracts.md"], + ["docs/truthmark/truth/contracts.md"], [ { - path: "docs/truth/contracts.md", + path: "docs/truthmark/truth/contracts.md", kind: "contract", kindSource: "explicit", }, @@ -51,7 +51,7 @@ Current contract. expect.objectContaining({ category: "frontmatter", severity: "error", - file: "docs/truth/contracts.md", + file: "docs/truthmark/truth/contracts.md", message: expect.stringContaining("truth_kind"), }), ]); diff --git a/tests/checks/scorecard.test.ts b/tests/checks/scorecard.test.ts new file mode 100644 index 0000000..f99a615 --- /dev/null +++ b/tests/checks/scorecard.test.ts @@ -0,0 +1,104 @@ +import { describe, expect, it } from "vitest"; + +import { + buildTruthHealthScorecard, + TRUTH_HEALTH_DIMENSION_IDS, + type TruthHealthScorecardDimension, +} from "../../src/checks/scorecard.js"; +import type { Diagnostic } from "../../src/output/diagnostic.js"; + +const diagnostic = (partial: Partial & Pick): Diagnostic => ({ + severity: "review", + message: `${partial.category} diagnostic`, + ...partial, +}); + +const dimension = ( + dimensions: TruthHealthScorecardDimension[], + id: TruthHealthScorecardDimension["id"], +): TruthHealthScorecardDimension => { + const match = dimensions.find((candidate) => candidate.id === id); + expect(match).toBeDefined(); + return match!; +}; + +describe("buildTruthHealthScorecard", () => { + it("returns the compact truthmark-scorecard/v0 shape with the seven dimensions", () => { + const scorecard = buildTruthHealthScorecard([], { branchFreshnessRan: false }); + + expect(scorecard.schemaVersion).toBe("truthmark-scorecard/v0"); + expect(scorecard.dimensions.map((item) => item.id)).toEqual([...TRUTH_HEALTH_DIMENSION_IDS]); + for (const item of scorecard.dimensions) { + expect(Object.keys(item).sort()).toEqual(["diagnosticIndexes", "evidence", "id", "status"].filter((key) => key in item).sort()); + expect(item.diagnosticIndexes).toEqual([]); + } + expect(dimension(scorecard.dimensions, "branch-freshness").status).toBe("not-run"); + expect(dimension(scorecard.dimensions, "branch-freshness").evidence).toEqual([ + "base not supplied", + ]); + }); + + it("maps diagnostic severity to fail, warn, pass, and not-run statuses", () => { + const diagnostics: Diagnostic[] = [ + diagnostic({ category: "coverage", severity: "review", file: "src/unmapped.ts" }), + diagnostic({ category: "frontmatter", severity: "error", file: "docs/truth.md" }), + ]; + + const scorecard = buildTruthHealthScorecard(diagnostics, { branchFreshnessRan: false }); + + expect(dimension(scorecard.dimensions, "routing-coverage").status).toBe("warn"); + expect(dimension(scorecard.dimensions, "truth-doc-structure").status).toBe("fail"); + expect(dimension(scorecard.dimensions, "generated-surface-freshness").status).toBe("pass"); + expect(dimension(scorecard.dimensions, "branch-freshness").status).toBe("not-run"); + }); + + it("maps categories to the expected dimensions and caps compact evidence", () => { + const diagnostics: Diagnostic[] = [ + diagnostic({ category: "area-index", file: "docs/truthmark/routes/areas.md" }), + diagnostic({ category: "source-traceability", file: "docs/truthmark/truth/api.md" }), + diagnostic({ + category: "freshness", + message: "Changed file src/api.ts is not routed to truth ownership.", + file: "src/api.ts", + }), + diagnostic({ category: "generated-surface", file: "AGENTS.md" }), + diagnostic({ category: "doc-structure", message: "Missing Product Decisions section", file: "docs/architecture/overview.md" }), + diagnostic({ category: "doc-structure", message: "Missing Rationale section", file: "docs/architecture/overview.md" }), + diagnostic({ category: "doc-structure", message: "Missing Scope section", file: "docs/architecture/overview.md" }), + diagnostic({ + category: "doc-structure", + message: + "Canonical truth doc docs/truthmark/truth/check-diagnostics.md should include Current Behavior section(s). Decisions should live beside current behavior, not in timestamped planning logs.", + file: "docs/truthmark/truth/check-diagnostics.md", + }), + ]; + + const scorecard = buildTruthHealthScorecard(diagnostics, { branchFreshnessRan: true }); + + expect(dimension(scorecard.dimensions, "routing-coverage").diagnosticIndexes).toEqual([0]); + expect(dimension(scorecard.dimensions, "ownership-clarity").diagnosticIndexes).toEqual([0, 2]); + expect(dimension(scorecard.dimensions, "source-traceability").diagnosticIndexes).toEqual([1]); + expect(dimension(scorecard.dimensions, "branch-freshness").diagnosticIndexes).toEqual([2]); + expect(dimension(scorecard.dimensions, "generated-surface-freshness").diagnosticIndexes).toEqual([3]); + expect(dimension(scorecard.dimensions, "truth-doc-structure").diagnosticIndexes).toEqual([ + 4, 5, 6, 7, + ]); + expect(dimension(scorecard.dimensions, "truth-doc-structure").evidence).toHaveLength(2); + expect(dimension(scorecard.dimensions, "decision-rationale-preservation").diagnosticIndexes).toEqual([ + 4, 5, + ]); + }); + + it("keeps diagnostic indexes tied to the raw diagnostics array when one diagnostic maps to multiple dimensions", () => { + const diagnostics: Diagnostic[] = [ + diagnostic({ category: "generated-surface", file: "AGENTS.md" }), + diagnostic({ category: "coverage", file: "src/unmapped.ts" }), + ]; + + const scorecard = buildTruthHealthScorecard(diagnostics, { branchFreshnessRan: false }); + + expect(dimension(scorecard.dimensions, "routing-coverage").diagnosticIndexes).toEqual([1]); + expect(dimension(scorecard.dimensions, "ownership-clarity").diagnosticIndexes).toEqual([1]); + expect(dimension(scorecard.dimensions, "generated-surface-freshness").diagnosticIndexes).toEqual([0]); + }); +}); diff --git a/tests/cli/build-artifact.test.ts b/tests/cli/build-artifact.test.ts index 08c09e3..0a137be 100644 --- a/tests/cli/build-artifact.test.ts +++ b/tests/cli/build-artifact.test.ts @@ -5,6 +5,8 @@ import path from "node:path"; import { fileURLToPath } from "node:url"; import { describe, expect, it } from "vitest"; +import { runConfig } from "../../src/config/command.js"; +import { runInit } from "../../src/init/init.js"; import { createTempRepo } from "../helpers/temp-repo.js"; const workspaceRoot = path.resolve(fileURLToPath(new URL("../../", import.meta.url))); @@ -84,6 +86,8 @@ describe("built truthmark CLI", () => { const repo = await createTempRepo(); try { + await runConfig(repo.rootDir, { force: false, stdout: false }); + await runInit(repo.rootDir); const result = await execa( process.execPath, [builtCliEntrypoint, "check", "--json", "--workflow", "truth-sync"], @@ -100,4 +104,41 @@ describe("built truthmark CLI", () => { await repo.cleanup(); } }); + + it("runs workflow status from the built artifact outside the source repo cwd", async () => { + const buildResult = await execa("npm", ["run", "build"], { + cwd: workspaceRoot, + reject: false, + }); + + expect(buildResult.exitCode).toBe(0); + expect(path.isAbsolute(builtCliEntrypoint)).toBe(true); + + const repo = await createTempRepo(); + + try { + await runConfig(repo.rootDir, { force: false, stdout: false }); + await runInit(repo.rootDir); + const result = await execa( + process.execPath, + [builtCliEntrypoint, "workflow", "status", "--workflow", "truthmark-check", "--json"], + { + cwd: repo.rootDir, + reject: false, + }, + ); + const output = JSON.parse(result.stdout) as { + command: string; + data: { workflowState: { schemaVersion: string; workflow: string } }; + }; + + expect(result.exitCode).toBe(0); + expect(output.command).toBe("workflow status"); + expect(output.data.workflowState.schemaVersion).toBe("truthmark-workflow/v0"); + expect(output.data.workflowState.workflow).toBe("truthmark-check"); + } finally { + await repo.cleanup(); + } + }); + }); diff --git a/tests/cli/check-workflow.test.ts b/tests/cli/check-workflow.test.ts index d0faa93..87c59c7 100644 --- a/tests/cli/check-workflow.test.ts +++ b/tests/cli/check-workflow.test.ts @@ -18,3 +18,27 @@ describe("truthmark check workflow options", () => { expect(result.stderr.toLowerCase()).toContain("unknown option"); }); }); + +describe("truthmark workflow command surface", () => { + it("exposes workflow status without workflow instructions", async () => { + const help = await runCli(["workflow", "--help"]); + + expect(help.exitCode).toBe(0); + expect(help.stdout).toContain("status"); + expect(help.stdout).not.toContain("instructions"); + }); + + it("rejects removed workflow instructions invocations as unsupported", async () => { + const result = await runCli([ + "workflow", + "instructions", + "--workflow", + "truthmark-sync", + "--json", + ]); + + expect(result.exitCode).not.toBe(0); + expect(result.stdout).toBe(""); + expect(result.stderr.toLowerCase()).toContain("unknown command"); + }); +}); diff --git a/tests/cli/help.test.ts b/tests/cli/help.test.ts index 5585ddf..108ff2d 100644 --- a/tests/cli/help.test.ts +++ b/tests/cli/help.test.ts @@ -64,11 +64,17 @@ describe("truthmark CLI", () => { command: string; summary: string; diagnostics: unknown[]; + data?: { + scorecard?: { + schemaVersion?: string; + }; + }; }; expect(payload.command).toBe("check"); expect(typeof payload.summary).toBe("string"); expect(payload.summary.length).toBeGreaterThan(0); expect(Array.isArray(payload.diagnostics)).toBe(true); + expect(payload.data?.scorecard?.schemaVersion).toBe("truthmark-scorecard/v0"); }); }); diff --git a/tests/cli/index-impact-context.test.ts b/tests/cli/index-impact-context.test.ts index 296b841..c44491a 100644 --- a/tests/cli/index-impact-context.test.ts +++ b/tests/cli/index-impact-context.test.ts @@ -56,7 +56,7 @@ describe("repository intelligence CLI commands", () => { } }); - it("renders ContextPack from truthmark context --workflow truth-sync --base main --json", async () => { + it("renders markdown-only context data from truthmark context --workflow truth-sync --base main --json", async () => { const repo = await createTempRepo(); try { await repo.writeFile("src/index.ts", "export const value = 1;\n"); @@ -71,12 +71,88 @@ describe("repository intelligence CLI commands", () => { }); const output = JSON.parse(result.stdout) as { command: string; - data: { contextPack: { schemaVersion: string; workflow: string } }; + data: { + contextPack?: unknown; + markdown: string; + summary: string; + truthDocs?: Array<{ content?: string }>; + sourceFiles?: Array<{ content?: string }>; + }; + summary: string; }; expect(output.command).toBe("context"); - expect(output.data.contextPack.schemaVersion).toBe("context-pack/v0"); - expect(output.data.contextPack.workflow).toBe("truth-sync"); + expect(output.data.contextPack).toBeUndefined(); + expect(output.data.truthDocs).toBeUndefined(); + expect(output.data.sourceFiles).toBeUndefined(); + expect(output.data.markdown).toContain("# Truthmark ContextPack (truth-sync)"); + expect(output.data.summary).toBe(output.summary); + expect(JSON.stringify(output.data)).not.toContain('"truthDocs":[{'); + expect(JSON.stringify(output.data)).not.toContain('"sourceFiles":[{'); + expect(JSON.stringify(output.data)).not.toContain('"content":'); + } finally { + await repo.cleanup(); + } + }); + + it("keeps workflow status and context JSON free of ContextPack content", async () => { + const repo = await createTempRepo(); + try { + await repo.writeFile("src/index.ts", "export const value = 1;\n"); + await runConfig(repo.rootDir, { force: false, stdout: false }); + await runInit(repo.rootDir); + await repo.runGit(["add", "."]); + await repo.runGit(["commit", "-m", "initial"]); + await repo.writeFile("src/index.ts", "export const value = 2;\n"); + + const statusResult = await runCli( + ["workflow", "status", "--workflow", "truthmark-sync", "--base", "main", "--json"], + { cwd: repo.rootDir }, + ); + const statusOutput = JSON.parse(statusResult.stdout) as { + command: string; + data: { + workflowState: { + schemaVersion: string; + workflow: string; + contextPack?: unknown; + actionContext: { helperValidationCommands: unknown[] }; + checks: { helpers: unknown[] }; + }; + }; + }; + const statusJson = JSON.stringify(statusOutput.data.workflowState); + + expect(statusResult.exitCode).toBe(0); + expect(statusOutput.command).toBe("workflow status"); + expect(statusOutput.data.workflowState.schemaVersion).toBe("truthmark-workflow/v0"); + expect(statusOutput.data.workflowState.workflow).toBe("truthmark-sync"); + expect(statusOutput.data.workflowState.contextPack).toBeUndefined(); + expect(statusOutput.data.workflowState.actionContext.helperValidationCommands.length).toBeGreaterThan(0); + expect(statusOutput.data.workflowState.checks.helpers.length).toBeGreaterThan(0); + expect(statusJson).not.toContain('"routeMap"'); + expect(statusJson).not.toContain('"content"'); + + const contextResult = await runCli( + ["context", "--workflow", "truth-sync", "--base", "main", "--json"], + { cwd: repo.rootDir }, + ); + const contextOutput = JSON.parse(contextResult.stdout) as { + data: { + contextPack?: unknown; + markdown?: string; + truthDocs?: Array<{ content?: string }>; + sourceFiles?: Array<{ content?: string }>; + }; + }; + const contextJson = JSON.stringify(contextOutput.data); + + expect(contextResult.exitCode).toBe(0); + expect(contextOutput.data.contextPack).toBeUndefined(); + expect(contextOutput.data.truthDocs).toBeUndefined(); + expect(contextOutput.data.sourceFiles).toBeUndefined(); + expect(contextOutput.data.markdown).toContain("# Truthmark ContextPack (truth-sync)"); + expect(contextJson).not.toContain('"content":'); } finally { await repo.cleanup(); } @@ -95,6 +171,80 @@ describe("repository intelligence CLI commands", () => { expect(result.stdout).toContain("# Truthmark ContextPack (truth-document)"); expect(result.stdout).toContain("## Allowed Write Paths"); + expect(result.stdout.trim()).not.toContain('"contextPack"'); + } finally { + await repo.cleanup(); + } + }); + + it("renders ContextPack markdown by default", async () => { + const repo = await createTempRepo(); + try { + await repo.writeFile("src/index.ts", "export const value = 1;\n"); + await runConfig(repo.rootDir, { force: false, stdout: false }); + await runInit(repo.rootDir); + + const result = await runCli(["context", "--workflow", "truth-document"], { + cwd: repo.rootDir, + }); + + expect(result.stdout).toContain("# Truthmark ContextPack (truth-document)"); + expect(result.stdout).toContain("## Allowed Write Paths"); + expect(result.stdout.trim()).not.toContain('"contextPack"'); + } finally { + await repo.cleanup(); + } + }); + + it("renders markdown-only JSON data when --json and --format markdown are combined", async () => { + const repo = await createTempRepo(); + try { + await repo.writeFile("src/index.ts", "export const value = 1;\n"); + await runConfig(repo.rootDir, { force: false, stdout: false }); + await runInit(repo.rootDir); + + const result = await runCli( + ["context", "--workflow", "truth-document", "--format", "markdown", "--json"], + { cwd: repo.rootDir }, + ); + const output = JSON.parse(result.stdout) as { + command: string; + data: { contextPack?: unknown; markdown?: string; summary?: string }; + summary: string; + }; + + expect(output.command).toBe("context"); + expect(output.data.contextPack).toBeUndefined(); + expect(output.data.markdown).toContain("# Truthmark ContextPack (truth-document)"); + expect(output.data.markdown).toContain("## Allowed Write Paths"); + expect(output.data.summary).toBe(output.summary); + } finally { + await repo.cleanup(); + } + }); + + it("rejects JSON ContextPack format output", async () => { + const repo = await createTempRepo(); + try { + await repo.writeFile("src/index.ts", "export const value = 1;\n"); + await runConfig(repo.rootDir, { force: false, stdout: false }); + await runInit(repo.rootDir); + + const result = await runCli(["context", "--workflow", "truth-sync", "--format", "json", "--json"], { + cwd: repo.rootDir, + }); + const output = JSON.parse(result.stdout) as { + diagnostics: Array<{ category: string; severity: string; message: string }>; + }; + + expect(result.exitCode).toBe(1); + expect(output.diagnostics).toContainEqual( + expect.objectContaining({ + category: "context-pack", + severity: "error", + message: expect.stringContaining("JSON ContextPack output was removed in v2"), + }), + ); } finally { await repo.cleanup(); } @@ -119,7 +269,7 @@ describe("repository intelligence CLI commands", () => { expect.objectContaining({ category: "context-pack", severity: "error", - message: expect.stringContaining("--format json or markdown"), + message: expect.stringContaining("supports only --format markdown"), }), ); } finally { diff --git a/tests/cli/validate.test.ts b/tests/cli/validate.test.ts index 35e78a4..2a7610c 100644 --- a/tests/cli/validate.test.ts +++ b/tests/cli/validate.test.ts @@ -9,10 +9,10 @@ Changed code reviewed: - src/init/init.ts Ownership reviewed: -- docs/truthmark/areas.md +- docs/truthmark/routes/areas.md Truth docs updated: -- docs/truth/init-and-scaffold.md +- docs/truthmark/truth/init-and-scaffold.md Evidence checked: - Claim: Init writes generated workflow files. @@ -33,10 +33,10 @@ Implementation reviewed: - src/templates/workflow-surfaces.ts Ownership reviewed: -- docs/truthmark/areas.md +- docs/truthmark/routes/areas.md Truth docs created: -- docs/truth/workflows/helpers.md +- docs/truthmark/truth/workflows/helpers.md Evidence checked: - Claim: Helpers are optional. @@ -145,8 +145,8 @@ describe("truthmark validate CLI helpers", () => { it("rejects write-lease path traversal and Windows absolute changed paths", async () => { const repo = await createTempRepo(); try { - await repo.writeFile("lease.yml", "allowedWrites:\n - docs/truth/**\nforbiddenWrites:\n - src/**\n"); - await repo.writeFile("changed-files.txt", "C:/repo/docs/truth/secret.md\n"); + await repo.writeFile("lease.yml", "allowedWrites:\n - docs/truthmark/truth/**\nforbiddenWrites:\n - src/**\n"); + await repo.writeFile("changed-files.txt", "C:/repo/docs/truthmark/truth/secret.md\n"); const result = await runCli( ["validate", "write-lease", "lease.yml", "changed-files.txt", "--json"], diff --git a/tests/config/config-command.test.ts b/tests/config/config-command.test.ts index 3c5bec7..82b709b 100644 --- a/tests/config/config-command.test.ts +++ b/tests/config/config-command.test.ts @@ -15,32 +15,34 @@ describe("runConfig", () => { expect(result.command).toBe("config"); const configText = await repo.readFile(".truthmark/config.yml"); - const config = parse(configText) as { - platforms: string[]; - docs: { - layout: string; - roots: Record; - routing: { - area_files_root: string; - }; - }; - authority: string[]; - }; + const config = parse(configText) as Record; - expect(config.docs.layout).toBe("hierarchical"); - expect(config.docs.routing.area_files_root).toBe("docs/truthmark/areas"); - expect(config.platforms).toEqual( - expect.arrayContaining(["github-copilot", "gemini-cli"]), - ); - expect(config.docs.roots).toEqual({ - ai: "docs/ai", - standards: "docs/standards", - architecture: "docs/architecture", - truth: "docs/truth", + expect(config.version).toBe(2); + expect(config).not.toHaveProperty("docs"); + expect(config).not.toHaveProperty("authority"); + expect(config.truthmark).toEqual({ + workspace: "docs/truthmark", + routes: { + index: "routes/areas.md", + areas: "routes/areas", + default_area: "repository", + max_delegation_depth: 1, + }, + truth: { root: "truth" }, + templates: { root: "templates" }, + generated: { + portal: { + enabled: false, + }, + }, }); - expect(config.authority).toContain("docs/truth/**/*.md"); + expect(JSON.stringify(config)).not.toContain("docs/standards"); + expect(JSON.stringify(config)).not.toContain("docs/architecture"); + expect(JSON.stringify(config)).not.toContain("docs/ai"); + expect(JSON.stringify(config)).not.toContain("docs/truth\""); + expect(JSON.stringify(config)).not.toContain("docs/templates"); await expect(fs.stat(`${repo.rootDir}/AGENTS.md`)).rejects.toThrow(); - await expect(fs.stat(`${repo.rootDir}/docs/truthmark/areas.md`)).rejects.toThrow(); + await expect(fs.stat(`${repo.rootDir}/docs/truthmark/routes/areas.md`)).rejects.toThrow(); expect(result.diagnostics).toEqual( expect.arrayContaining([ expect.objectContaining({ @@ -65,15 +67,6 @@ describe("runConfig", () => { expect(await repo.readFile(".truthmark/config.yml")).toBe("version: 1\ncustom: true\n"); expect(result.summary).toContain("already exists"); - expect(result.diagnostics).toEqual( - expect.arrayContaining([ - expect.objectContaining({ - category: "config", - severity: "review", - file: ".truthmark/config.yml", - }), - ]), - ); } finally { await repo.cleanup(); } @@ -87,7 +80,7 @@ describe("runConfig", () => { const result = await runConfig(repo.rootDir, { force: true }); - expect(await repo.readFile(".truthmark/config.yml")).toContain("layout: hierarchical"); + expect(await repo.readFile(".truthmark/config.yml")).toContain("workspace: docs/truthmark"); expect(await repo.readFile(".truthmark/config.yml")).not.toContain("custom: true"); expect(result.summary).toContain("Wrote"); } finally { @@ -104,7 +97,7 @@ describe("runConfig", () => { expect(result.data).toMatchObject({ path: ".truthmark/config.yml", }); - expect(String(result.data?.content)).toContain("layout: hierarchical"); + expect(String(result.data?.content)).toContain("workspace: docs/truthmark"); await expect(fs.stat(`${repo.rootDir}/.truthmark/config.yml`)).rejects.toThrow(); } finally { await repo.cleanup(); diff --git a/tests/config/load.test.ts b/tests/config/load.test.ts index ef4cb3f..3c5b72f 100644 --- a/tests/config/load.test.ts +++ b/tests/config/load.test.ts @@ -1,258 +1,85 @@ import { describe, expect, it } from "vitest"; -import { createTempRepo } from "../helpers/temp-repo.js"; import { loadConfig } from "../../src/config/load.js"; +import { createTempRepo } from "../helpers/temp-repo.js"; -describe("loadConfig", () => { - const writeConfig = async ( - repo: Awaited>, - extraConfig = "", - ) => { - await repo.writeFile( - ".truthmark/config.yml", - `version: 1 -authority: - - docs/truthmark/areas.md -${extraConfig}`, - ); - }; - - it("loads a valid config and applies defaults for optional frontmatter and ignore fields", async () => { - const repo = await createTempRepo(); - - try { - await repo.writeFile( - ".truthmark/config.yml", - `version: 1 -authority: - - docs/truthmark/areas.md -`, - ); - - const result = await loadConfig(repo.rootDir); - - expect(result.status).toBe("loaded"); - expect(result.diagnostics).toEqual([]); - expect(result.config).toMatchObject({ - version: 1, - platforms: [ - "codex", - "opencode", - "claude-code", - "github-copilot", - "gemini-cli", - ], - authority: ["docs/truthmark/areas.md"], - docs: { - layout: "hierarchical", - roots: { - truth: "docs/truth", - }, - routing: { - rootIndex: "docs/truthmark/areas.md", - areaFilesRoot: "docs/truthmark/areas", - defaultArea: "repository", - maxDelegationDepth: 1, - }, - }, - instructionTargets: ["AGENTS.md"], - frontmatter: { - required: [], - recommended: [], - }, - ignore: [], - }); - } finally { - await repo.cleanup(); - } - }); - - it("accepts the V1 config fields only", async () => { - const repo = await createTempRepo(); - - try { - await repo.writeFile( - ".truthmark/config.yml", - `version: 1 -authority: - - docs/truthmark/areas.md -instruction_targets: - - AGENTS.md +const validConfig = (portalProperties = "") => `version: 2 platforms: - codex - - github-copilot +truthmark: + workspace: docs/truthmark + routes: + index: routes/areas.md + areas: routes/areas + default_area: repository + max_delegation_depth: 1 + truth: + root: truth + templates: + root: templates + generated: + portal: + enabled: true +${portalProperties}instruction_targets: + - AGENTS.md frontmatter: required: [] - recommended: - - status -ignore: - - dist/** -`, - ); + recommended: [] +ignore: [] +`; - const result = await loadConfig(repo.rootDir); - - expect(result.diagnostics).toEqual([]); - expect(result.config?.platforms).toEqual(["codex", "github-copilot"]); - expect(result.config?.instructionTargets).toEqual(["AGENTS.md"]); - expect(result.config?.frontmatter.recommended).toEqual(["status"]); - expect(result.config?.ignore).toEqual(["dist/**"]); - } finally { - await repo.cleanup(); - } - }); - - it("loads hierarchical docs config", async () => { +describe("loadConfig", () => { + it("rejects legacy config shape", async () => { const repo = await createTempRepo(); try { await repo.writeFile( ".truthmark/config.yml", - `version: 1 -docs: - layout: hierarchical - roots: - truth: docs/product - routing: - root_index: docs/truthmark/routes.md - area_files_root: docs/truthmark/routes - default_area: core - max_delegation_depth: 1 -authority: - - docs/truthmark/areas.md -`, - ); - - const result = await loadConfig(repo.rootDir); - - expect(result.diagnostics).toEqual([]); - expect(result.config?.docs).toMatchObject({ - layout: "hierarchical", - roots: { - truth: "docs/product", - }, - routing: { - rootIndex: "docs/truthmark/routes.md", - areaFilesRoot: "docs/truthmark/routes", - defaultArea: "core", - maxDelegationDepth: 1, - }, - }); - } finally { - await repo.cleanup(); - } - }); - - it("merges omitted docs roots from the current defaults", async () => { - const repo = await createTempRepo(); - - try { - await repo.writeFile( - ".truthmark/config.yml", - `version: 1 -docs: - layout: hierarchical - roots: - ai: docs/ai - routing: - root_index: docs/truthmark/areas.md - area_files_root: docs/truthmark/areas - default_area: repository - max_delegation_depth: 1 -authority: - - docs/truthmark/areas.md -`, - ); - - const result = await loadConfig(repo.rootDir); - - expect(result.diagnostics).toEqual([]); - expect(result.config?.docs.roots).toMatchObject({ - ai: "docs/ai", - standards: "docs/standards", - architecture: "docs/architecture", - truth: "docs/truth", - }); - } finally { - await repo.cleanup(); - } - }); - - it("rejects unsupported hierarchical routing depth", async () => { - const repo = await createTempRepo(); - - try { - await repo.writeFile( - ".truthmark/config.yml", - `version: 1 -docs: - layout: hierarchical - roots: - truth: docs/truth - routing: - root_index: docs/truthmark/areas.md - area_files_root: docs/truthmark/areas - default_area: repository - max_delegation_depth: 2 -authority: - - docs/truthmark/areas.md -`, - ); - - const result = await loadConfig(repo.rootDir); - - expect(result.config).toBeNull(); - expect(result.diagnostics).toEqual( - expect.arrayContaining([ - expect.objectContaining({ - category: "config", - severity: "error", - message: expect.stringContaining("max_delegation_depth"), - }), - ]), - ); - } finally { - await repo.cleanup(); - } - }); - - it("rejects unknown platform names", async () => { - const repo = await createTempRepo(); - - try { - await repo.writeFile( - ".truthmark/config.yml", - `version: 1 -platforms: - - codex - - unknown-agent -authority: - - docs/truthmark/areas.md -`, + "version: 1\ndocs:\n roots:\n - docs/truth\n", ); const result = await loadConfig(repo.rootDir); expect(result.status).toBe("invalid"); expect(result.config).toBeNull(); - expect(result.diagnostics.some((diagnostic) => diagnostic.message.includes("allowed"))).toBe( - true, + expect(result.diagnostics.map((diagnostic) => diagnostic.message).join("\n")).toContain( + "Unsupported Truthmark config shape", ); } finally { await repo.cleanup(); } }); - it("returns config diagnostics for invalid config data", async () => { + + it("rejects unsafe workspace and child paths", async () => { const repo = await createTempRepo(); try { await repo.writeFile( ".truthmark/config.yml", - `version: 2 -authority: invalid -automation: - enabled: true -`, + validConfig().replace("workspace: docs/truthmark", "workspace: ../truthmark"), + ); + + const result = await loadConfig(repo.rootDir); + + expect(result.status).toBe("invalid"); + expect(result.config).toBeNull(); + expect(result.diagnostics).toContainEqual( + expect.objectContaining({ + message: expect.stringContaining("truthmark.workspace must be a non-empty repo-relative directory"), + }), + ); + } finally { + await repo.cleanup(); + } + }); + + it("rejects custom Portal output and template properties", async () => { + const repo = await createTempRepo(); + + try { + await repo.writeFile( + ".truthmark/config.yml", + validConfig(" output: docs/custom-portal\n template: docs/custom-template.md\n"), ); const result = await loadConfig(repo.rootDir); @@ -262,8 +89,10 @@ automation: expect(result.diagnostics).toEqual( expect.arrayContaining([ expect.objectContaining({ - category: "config", - severity: "error", + message: expect.stringContaining("additional property output is not allowed"), + }), + expect.objectContaining({ + message: expect.stringContaining("additional property template is not allowed"), }), ]), ); @@ -272,188 +101,18 @@ automation: } }); - it("rejects retired config keys", async () => { + it("derives Portal paths from the Truthmark workspace defaults", async () => { const repo = await createTempRepo(); try { - await repo.writeFile( - ".truthmark/config.yml", - `version: 1 -authority: - - docs/truthmark/areas.md -alignment: - mode: packet -outputs: - directory: .truthmark/cache -`, - ); - - const result = await loadConfig(repo.rootDir); - - expect(result.config).toBeNull(); - expect(result.diagnostics.some((diagnostic) => diagnostic.message.includes("alignment"))).toBe( - true, - ); - expect( - result.diagnostics.some((diagnostic) => diagnostic.message.includes("outputs")), - ).toBe(true); - } finally { - await repo.cleanup(); - } - }); - - it("defaults omitted Portal config", async () => { - const repo = await createTempRepo(); - - try { - await writeConfig(repo); + await repo.writeFile(".truthmark/config.yml", validConfig()); const result = await loadConfig(repo.rootDir); expect(result.status).toBe("loaded"); - expect(result.diagnostics).toEqual([]); - expect(result.config?.truthmarkPortal).toEqual({ - enabled: false, - output: "docs/truthmark-portal", - template: "default", - }); - } finally { - await repo.cleanup(); - } - }); - - it("loads enabled Portal config", async () => { - const repo = await createTempRepo(); - - try { - await writeConfig( - repo, - `truthmark-portal: - enabled: true - output: docs/portal - template: docs/templates/portal.md -`, - ); - - const result = await loadConfig(repo.rootDir); - - expect(result.status).toBe("loaded"); - expect(result.diagnostics).toEqual([]); - expect(result.config?.truthmarkPortal).toEqual({ - enabled: true, - output: "docs/portal", - template: "docs/templates/portal.md", - }); - } finally { - await repo.cleanup(); - } - }); - - it("defaults omitted Portal enabled when nested Portal config is present", async () => { - const repo = await createTempRepo(); - - try { - await writeConfig( - repo, - `truthmark-portal: - output: docs/portal -`, - ); - - const result = await loadConfig(repo.rootDir); - - expect(result.status).toBe("loaded"); - expect(result.config?.truthmarkPortal).toEqual({ - enabled: false, - output: "docs/portal", - template: "default", - }); - } finally { - await repo.cleanup(); - } - }); - - it.each([ - ["/tmp/truthmark-portal", "absolute output path"], - ["../truthmark-portal", "parent output traversal"], - ["docs/truth", "canonical truth root overlap"], - ["docs/truthmark/areas", "routing files root overlap"], - ["AGENTS.md/portal", "instruction target overlap"], - ])("rejects unsafe Portal output for %s (%s)", async (output) => { - const repo = await createTempRepo(); - - try { - await writeConfig( - repo, - `truthmark-portal: - enabled: true - output: ${output} -`, - ); - - const result = await loadConfig(repo.rootDir); - - expect(result.status).toBe("invalid"); - expect(result.config).toBeNull(); - expect(result.diagnostics).toEqual([ - expect.objectContaining({ - category: "config", - severity: "error", - message: expect.stringContaining("truthmark-portal.output"), - }), - ]); - } finally { - await repo.cleanup(); - } - }); - - it.each([ - ["/tmp/portal-template.md", "absolute template path"], - ["docs/templates/../portal.md", "parent template traversal"], - ])("rejects unsafe Portal template for %s (%s)", async (template) => { - const repo = await createTempRepo(); - - try { - await writeConfig( - repo, - `truthmark-portal: - enabled: true - output: docs/portal - template: ${template} -`, - ); - - const result = await loadConfig(repo.rootDir); - - expect(result.status).toBe("invalid"); - expect(result.config).toBeNull(); - expect(result.diagnostics).toEqual([ - expect.objectContaining({ - category: "config", - severity: "error", - message: expect.stringContaining("truthmark-portal.template"), - }), - ]); - } finally { - await repo.cleanup(); - } - }); - - it("returns a typed missing status when config does not exist yet", async () => { - const repo = await createTempRepo(); - - try { - const result = await loadConfig(repo.rootDir); - - expect(result.status).toBe("missing"); - expect(result.config).toBeNull(); - expect(result.diagnostics).toEqual([ - expect.objectContaining({ - category: "config", - severity: "error", - file: ".truthmark/config.yml", - }), - ]); + expect(result.config?.truthmark.generated.portal).toEqual({ enabled: true }); + expect(result.config?.truthmark.paths.portalOutput).toBe("docs/truthmark/generated/portal"); + expect(result.config?.truthmark.paths.portalTemplate).toBe("docs/truthmark/templates/portal.html"); } finally { await repo.cleanup(); } diff --git a/tests/context-pack/build.test.ts b/tests/context-pack/build.test.ts index bf0ba8a..70edc06 100644 --- a/tests/context-pack/build.test.ts +++ b/tests/context-pack/build.test.ts @@ -5,6 +5,9 @@ import { runConfig } from "../../src/config/command.js"; import { runInit } from "../../src/init/init.js"; import { createTempRepo, type TempRepo } from "../helpers/temp-repo.js"; +const longDocument = (): string => + Array.from({ length: 241 }, (_, index) => `Line ${index + 1}`).join("\n"); + describe("buildContextPack", () => { const repos: TempRepo[] = []; @@ -12,128 +15,66 @@ describe("buildContextPack", () => { await Promise.all(repos.splice(0).map((repo) => repo.cleanup())); }); - it("builds a bounded Truth Sync context pack from an impact set", async () => { + it("does not grant default write paths when .truthmark/config.yml is invalid", async () => { const repo = await createTempRepo(); repos.push(repo); + + await repo.writeFile("package.json", JSON.stringify({ name: "sample" }, null, 2)); + await repo.writeFile("src/index.ts", "export const value = 1;\n"); + await repo.writeFile( + ".truthmark/config.yml", + "version: 2\ntruthmark:\n workspace: ../outside\n", + ); + + const contextPack = await buildContextPack(repo.rootDir, { workflow: "truth-sync" }); + + expect(contextPack.allowedWritePaths).toEqual([]); + expect(contextPack.warnings).toContainEqual( + expect.objectContaining({ + category: "config", + file: ".truthmark/config.yml", + }), + ); + expect(contextPack.allowedWritePaths).not.toContain("docs/truthmark/routes/areas.md"); + }); + + it("bounds selected truth docs in generated context", async () => { + const repo = await createTempRepo(); + repos.push(repo); + await repo.writeFile("package.json", JSON.stringify({ name: "sample" }, null, 2)); await repo.writeFile("src/index.ts", "export const value = 1;\n"); await runConfig(repo.rootDir, { force: false, stdout: false }); await runInit(repo.rootDir); + await repo.writeFile( + "docs/truthmark/routes/areas.md", + "# Truthmark Areas\n\n## Runtime\n\nTruth documents:\n- docs/truthmark/truth/runtime.md\n\nCode surface:\n- src/**\n\nUpdate truth when:\n- runtime code changes\n", + ); + await repo.writeFile("docs/truthmark/truth/runtime.md", longDocument()); await repo.runGit(["add", "."]); await repo.runGit(["commit", "-m", "initial"]); await repo.writeFile("src/index.ts", "export const value = 2;\n"); - const pack = await buildContextPack(repo.rootDir, { workflow: "truth-sync", base: "main" }); + const contextPack = await buildContextPack(repo.rootDir, { + workflow: "truth-sync", + base: "main", + }); - expect(pack.schemaVersion).toBe("context-pack/v0"); - expect(pack.workflow).toBe("truth-sync"); - expect(pack.allowedWritePaths).toContain("docs/truthmark/areas.md"); - expect(pack.truthDocs.length).toBeGreaterThan(0); - expect(pack.sourceFiles.map((file) => file.path)).toContain("src/index.ts"); - }); - - it("bounds Truth Realize writes to matched code surfaces", async () => { - const repo = await createTempRepo(); - repos.push(repo); - await repo.writeFile("src/index.ts", "export const value = 1;\n"); - await runConfig(repo.rootDir, { force: false, stdout: false }); - await runInit(repo.rootDir); - await repo.runGit(["add", "."]); - await repo.runGit(["commit", "-m", "initial"]); - await repo.writeFile("src/index.ts", "export const value = 2;\n"); - - const pack = await buildContextPack(repo.rootDir, { workflow: "truth-realize", base: "main" }); - - expect(pack.allowedWritePaths).toContain("src/**"); - }); - - it("does not widen no-base Truth Realize context packs to every code surface", async () => { - const repo = await createTempRepo(); - repos.push(repo); - await repo.writeFile("src/owned/index.ts", "export const owned = 1;\n"); - await repo.writeFile("src/other/index.ts", "export const other = 1;\n"); - await runConfig(repo.rootDir, { force: false, stdout: false }); - await runInit(repo.rootDir); - await repo.writeFile( - "docs/truthmark/areas.md", - `# Truthmark Areas - -## Owned - -Truth documents: -- docs/truth/owned.md - -Code surface: -- src/owned/** - -Update truth when: -- owned behavior changes - -## Other - -Truth documents: -- docs/truth/other.md - -Code surface: -- src/other/** - -Update truth when: -- other behavior changes -`, - ); - await repo.writeFile( - "docs/truth/owned.md", - `--- -source_of_truth: - - ../../src/owned/index.ts ---- -# Owned -`, - ); - await repo.writeFile( - "docs/truth/other.md", - `--- -source_of_truth: - - ../../src/other/index.ts ---- -# Other -`, - ); - - const pack = await buildContextPack(repo.rootDir, { workflow: "truth-realize" }); - - expect(pack.allowedWritePaths).toEqual([]); - expect(pack.truthDocs).toEqual([]); - expect(pack.sourceFiles).toEqual([]); - expect(pack.warnings).toContainEqual( + expect(contextPack.truthDocs).toEqual([ + expect.objectContaining({ + path: "docs/truthmark/truth/runtime.md", + truncated: true, + }), + ]); + expect(contextPack.truthDocs[0]?.content.split("\n")).toHaveLength(121); + expect(contextPack.truthDocs[0]?.content).toContain("\n...\n"); + expect(contextPack.truthDocs[0]?.content).not.toContain("Line 121\n"); + expect(contextPack.warnings).toContainEqual( expect.objectContaining({ category: "context-pack", - severity: "review", - message: expect.stringContaining("truth-realize requires --base"), + file: "docs/truthmark/truth/runtime.md", + message: + "Context truth doc docs/truthmark/truth/runtime.md was truncated to fit ContextPack v0 bounds.", }), ); }); - - it("includes source_of_truth files for Truth Document context without a base ref", async () => { - const repo = await createTempRepo(); - repos.push(repo); - await repo.writeFile("src/index.ts", "export const value = 1;\n"); - await runConfig(repo.rootDir, { force: false, stdout: false }); - await runInit(repo.rootDir); - await repo.writeFile( - "docs/truth/repository/overview.md", - `--- -status: active -doc_type: behavior -truth_kind: behavior -source_of_truth: - - ../../../src/index.ts ---- -# Repository Overview -`, - ); - - const pack = await buildContextPack(repo.rootDir, { workflow: "truth-document" }); - - expect(pack.sourceFiles.map((file) => file.path)).toContain("src/index.ts"); - }); }); diff --git a/tests/evals/no-cli-fallback-cases.ts b/tests/evals/no-cli-fallback-cases.ts new file mode 100644 index 0000000..8b7bfde --- /dev/null +++ b/tests/evals/no-cli-fallback-cases.ts @@ -0,0 +1,115 @@ +export type NoCliFallbackOutcomeAxis = + | "same target docs" + | "same block/apply decision" + | "same write boundary" + | "same evidence status"; + +export type NoCliFallbackEvalCase = { + id: string; + scenario: string; + changedSurface: readonly string[]; + expectedCliOutcome: { + targetDocs: readonly string[] | "none" | "structure-repair"; + decision: "apply" | "block" | "structure"; + writeBoundary: "truth-doc-write" | "route-write" | "none"; + evidenceStatus: "current" | "missing-or-stale" | "requires-preservation-check"; + }; + equivalenceAxes: readonly NoCliFallbackOutcomeAxis[]; +}; + +const ALL_EQUIVALENCE_AXES: readonly NoCliFallbackOutcomeAxis[] = [ + "same target docs", + "same block/apply decision", + "same write boundary", + "same evidence status", +]; + +export const NO_CLI_FALLBACK_EVAL_CASES: NoCliFallbackEvalCase[] = [ + { + id: "single-file-one-truth-doc", + scenario: "Single-file code change mapped to one truth doc.", + changedSurface: ["src/auth/session.ts"], + expectedCliOutcome: { + targetDocs: ["docs/truthmark/truth/authentication/session-timeout.md"], + decision: "apply", + writeBoundary: "truth-doc-write", + evidenceStatus: "current", + }, + equivalenceAxes: ALL_EQUIVALENCE_AXES, + }, + { + id: "multi-file-one-truth-doc", + scenario: "Multi-file change mapped to one truth doc.", + changedSurface: ["src/auth/session.ts", "src/auth/session-policy.ts"], + expectedCliOutcome: { + targetDocs: ["docs/truthmark/truth/authentication/session-timeout.md"], + decision: "apply", + writeBoundary: "truth-doc-write", + evidenceStatus: "current", + }, + equivalenceAxes: ALL_EQUIVALENCE_AXES, + }, + { + id: "multi-route-multiple-truth-docs", + scenario: "Multi-route change that legitimately needs multiple truth docs.", + changedSurface: ["src/auth/session.ts", "src/billing/invoices.ts"], + expectedCliOutcome: { + targetDocs: [ + "docs/truthmark/truth/authentication/session-timeout.md", + "docs/truthmark/truth/billing/invoices.md", + ], + decision: "apply", + writeBoundary: "truth-doc-write", + evidenceStatus: "current", + }, + equivalenceAxes: ALL_EQUIVALENCE_AXES, + }, + { + id: "ambiguous-unmapped-code-blocks", + scenario: "Ambiguous/unmapped code change that should block.", + changedSurface: ["src/unmapped/feature.ts"], + expectedCliOutcome: { + targetDocs: "none", + decision: "block", + writeBoundary: "none", + evidenceStatus: "current", + }, + equivalenceAxes: ALL_EQUIVALENCE_AXES, + }, + { + id: "broad-index-truth-doc-triggers-structure", + scenario: "Broad/index-like truth doc that should trigger Structure.", + changedSurface: ["docs/truthmark/truth/repository/overview.md"], + expectedCliOutcome: { + targetDocs: "structure-repair", + decision: "structure", + writeBoundary: "route-write", + evidenceStatus: "requires-preservation-check", + }, + equivalenceAxes: ALL_EQUIVALENCE_AXES, + }, + { + id: "evidence-reference-stale-or-missing", + scenario: "Evidence reference stale/missing.", + changedSurface: ["src/auth/session.ts", "docs/truthmark/truth/authentication/session-timeout.md"], + expectedCliOutcome: { + targetDocs: ["docs/truthmark/truth/authentication/session-timeout.md"], + decision: "block", + writeBoundary: "truth-doc-write", + evidenceStatus: "missing-or-stale", + }, + equivalenceAxes: ALL_EQUIVALENCE_AXES, + }, + { + id: "preserve-product-decisions-rationale", + scenario: "Product Decisions/Rationale preservation during split or update.", + changedSurface: ["docs/truthmark/routes/areas.md", "docs/truthmark/truth/authentication/session-timeout.md"], + expectedCliOutcome: { + targetDocs: "structure-repair", + decision: "structure", + writeBoundary: "route-write", + evidenceStatus: "requires-preservation-check", + }, + equivalenceAxes: ALL_EQUIVALENCE_AXES, + }, +]; diff --git a/tests/evals/workflow-routing-cases.ts b/tests/evals/workflow-routing-cases.ts index 26996cb..292c689 100644 --- a/tests/evals/workflow-routing-cases.ts +++ b/tests/evals/workflow-routing-cases.ts @@ -48,7 +48,7 @@ export const WORKFLOW_ROUTING_EVAL_CASES: WorkflowRoutingEvalCase[] = [ id: "sync-skip-docs-only", userPrompt: "I only edited documentation prose and no functional code changed; do not run finish-time Sync.", - changedFiles: ["docs/truth/repository/overview.md"], + changedFiles: ["docs/truthmark/truth/repository/overview.md"], expectedWorkflow: "none", expectedReason: "documentation-only change", expectedManifestSignals: [ @@ -62,7 +62,7 @@ export const WORKFLOW_ROUTING_EVAL_CASES: WorkflowRoutingEvalCase[] = [ id: "structure-broad-routing-repair", userPrompt: "The repository route is a broad src/** catch-all and needs to be split into bounded Truthmark areas.", - changedFiles: ["docs/truthmark/areas.md"], + changedFiles: ["docs/truthmark/routes/areas.md"], expectedWorkflow: "truthmark-structure", expectedReason: "split broad repository routing into bounded areas", expectedManifestSignals: [ @@ -103,8 +103,8 @@ export const WORKFLOW_ROUTING_EVAL_CASES: WorkflowRoutingEvalCase[] = [ { id: "realize-explicit-doc-first", userPrompt: - "Use $truthmark-realize to realize docs/truth/authentication/session-timeout.md into code.", - changedFiles: ["docs/truth/authentication/session-timeout.md"], + "Use $truthmark-realize to realize docs/truthmark/truth/authentication/session-timeout.md into code.", + changedFiles: ["docs/truthmark/truth/authentication/session-timeout.md"], expectedWorkflow: "truthmark-realize", expectedReason: "explicitly realize truth docs into functional code", expectedManifestSignals: [ @@ -144,12 +144,12 @@ export const WORKFLOW_ROUTING_EVAL_CASES: WorkflowRoutingEvalCase[] = [ { id: "portal-explicit-refresh", userPrompt: - "Refresh the committed Truthmark Portal static HTML docs site under docs/truthmark-portal.", + "Refresh the committed Truthmark Portal static HTML docs site under docs/truthmark/generated/portal.", expectedWorkflow: "truthmark-portal", expectedReason: "generate or refresh the committed static HTML Portal", expectedManifestSignals: [ "generate, refresh, or update the Truthmark Portal static HTML site", - "update docs/truthmark-portal", + "update the Truthmark Portal output", ], forbiddenWorkflows: ["truthmark-sync", "truthmark-check"], source: "manifest-positive", diff --git a/tests/evals/workflow-routing.test.ts b/tests/evals/workflow-routing.test.ts index c8b9024..8007b1b 100644 --- a/tests/evals/workflow-routing.test.ts +++ b/tests/evals/workflow-routing.test.ts @@ -7,6 +7,7 @@ import { getTruthmarkWorkflow, type TruthmarkWorkflowId, } from "../../src/agents/workflow-manifest.js"; +import { NO_CLI_FALLBACK_EVAL_CASES } from "./no-cli-fallback-cases.js"; import { WORKFLOW_ROUTING_EVAL_CASES } from "./workflow-routing-cases.js"; const WORKFLOW_COMMAND_PATHS: Record = { @@ -20,7 +21,7 @@ const WORKFLOW_COMMAND_PATHS: Record = { }; const WORKFLOW_SURFACE_PATHS = (id: TruthmarkWorkflowId): readonly string[] => [ - `.codex/skills/${id}/SKILL.md`, + `.agents/skills/${id}/SKILL.md`, `.opencode/skills/${id}/SKILL.md`, `.claude/skills/${id}/SKILL.md`, `.github/prompts/${id}.prompt.md`, @@ -28,7 +29,7 @@ const WORKFLOW_SURFACE_PATHS = (id: TruthmarkWorkflowId): readonly string[] => [ ]; const CODEX_METADATA_PATHS = (id: TruthmarkWorkflowId): string => - `.codex/skills/${id}/agents/openai.yaml`; + `.agents/skills/${id}/agents/openai.yaml`; const WORKFLOW_SKILL_PACKAGE_PATHS = ( hostSkillRoot: string, @@ -52,7 +53,7 @@ const WORKFLOW_SKILL_PACKAGE_PATHS = ( const WORKFLOW_CONTRACT_PATH_GROUPS = ( id: TruthmarkWorkflowId, ): readonly (readonly string[])[] => [ - WORKFLOW_SKILL_PACKAGE_PATHS(".codex/skills", id), + WORKFLOW_SKILL_PACKAGE_PATHS(".agents/skills", id), WORKFLOW_SKILL_PACKAGE_PATHS(".opencode/skills", id), WORKFLOW_SKILL_PACKAGE_PATHS(".claude/skills", id), [`.github/prompts/${id}.prompt.md`], @@ -111,7 +112,7 @@ const SURFACE_CONTRACT_TERMS: Record = { ], "truthmark-portal": [ "manual-only presentation workflow", - "configured Portal output directory only", + "fixed Portal output directory only", "Markdown remains canonical", "Truthmark Portal: completed", "Output path:", @@ -119,6 +120,23 @@ const SURFACE_CONTRACT_TERMS: Record = { ], }; +const NO_CLI_FALLBACK_SCENARIOS = [ + "single-file-one-truth-doc", + "multi-file-one-truth-doc", + "multi-route-multiple-truth-docs", + "ambiguous-unmapped-code-blocks", + "broad-index-truth-doc-triggers-structure", + "evidence-reference-stale-or-missing", + "preserve-product-decisions-rationale", +] as const; + +const NO_CLI_FALLBACK_EQUIVALENCE_AXES = [ + "same target docs", + "same block/apply decision", + "same write boundary", + "same evidence status", +] as const; + const manifestRoutingText = (id: TruthmarkWorkflowId): string => { const workflow = getTruthmarkWorkflow(id); @@ -145,7 +163,7 @@ const candidateManifestText = ( const buildGeneratedSurfaceMap = (): Map => { const config = createDefaultConfig(); - config.truthmarkPortal.enabled = true; + config.truthmark.generated.portal.enabled = true; return new Map( renderGeneratedSurfaces(config).map((surface) => [ surface.path, @@ -190,6 +208,31 @@ describe("workflow routing eval corpus", () => { ); }); +describe("no-CLI fallback eval corpus", () => { + it("covers route-first fallback outcomes before any hard budget policy is added", () => { + const caseIds = NO_CLI_FALLBACK_EVAL_CASES.map((testCase) => testCase.id); + + expect(caseIds).toEqual(expect.arrayContaining([...NO_CLI_FALLBACK_SCENARIOS])); + + for (const testCase of NO_CLI_FALLBACK_EVAL_CASES) { + expect(testCase.changedSurface.length).toBeGreaterThan(0); + expect(testCase.equivalenceAxes).toEqual([...NO_CLI_FALLBACK_EQUIVALENCE_AXES]); + expect(testCase.expectedCliOutcome).toEqual( + expect.objectContaining({ + decision: expect.stringMatching(/^(apply|block|structure)$/u), + evidenceStatus: expect.stringMatching( + /^(current|missing-or-stale|requires-preservation-check)$/u, + ), + }), + ); + } + + expect(NO_CLI_FALLBACK_EVAL_CASES.map((testCase) => testCase.scenario).join("\n")).not.toMatch( + /token budget|hard budget/iu, + ); + }); +}); + describe("generated workflow surface conformance", () => { const surfaces = buildGeneratedSurfaceMap(); @@ -243,4 +286,81 @@ describe("generated workflow surface conformance", () => { } } }); + + it("keeps write-workflow no-CLI fallback route-first and non-expansive", () => { + const writeWorkflowExpectations: Record< + | "truthmark-sync" + | "truthmark-structure" + | "truthmark-document" + | "truthmark-realize", + readonly string[] + > = { + "truthmark-sync": [ + "Inspect .truthmark/config.yml and configured route files", + "only when they exist; then inspect relevant canonical docs directly.", + "direct checkout inspection is the canonical path; do not require the truthmark binary.", + "May write canonical truth docs and truth routing files only; must not rewrite functional code.", + "Read support/procedure.md before editing truth docs.", + ], + "truthmark-structure": [ + "Inspect .truthmark/config.yml and configured route files", + "only when they exist; then inspect current docs and relevant code directly.", + "Define areas by product or behavior ownership, not by mechanical directory mirroring.", + "Do not edit functional code.", + "Read support/procedure.md before writing route or starter truth-doc changes.", + ], + "truthmark-document": [ + "Inspect .truthmark/config.yml and configured route files", + "only when they exist; then inspect existing canonical docs, implementation code, and tests directly.", + "Document current implemented behavior; do not invent future behavior.", + "May write canonical truth docs and truth routing files only; must not write functional code.", + "Read support/procedure.md before editing truth docs.", + ], + "truthmark-realize": [ + "Read the source truth docs, inspect .truthmark/config.yml and configured route files", + "only when they exist, then inspect tests and relevant functional code directly.", + "Truth docs lead; code follows.", + "may write functional code only; must not edit truth docs or truth routing while realizing those docs.", + "Read support/procedure.md before changing code.", + ], + }; + + for (const [id, expectedTerms] of Object.entries(writeWorkflowExpectations)) { + const content = surfaces.get(`.agents/skills/${id}/SKILL.md`); + + expect(content, `${id} Codex skill is generated`).toBeDefined(); + expect(content).toContain( + "Follow repository instruction files that exist in this checkout; do not assume any optional policy path exists.", + ); + expect(content).not.toContain("## Optional local CLI validation"); + expect(content).not.toContain( + "If the local Truthmark CLI is unavailable or too old", + ); + expect(content).not.toContain( + "use the checked-in workflow files as the contract", + ); + expect(content).not.toContain("Follow the route-first procedure"); + + for (const term of expectedTerms) { + expect(content).toContain(term); + } + } + }); + + it("labels non-main progressive-disclosure files as conditional", () => { + const syncSkill = surfaces.get(".agents/skills/truthmark-sync/SKILL.md"); + + expect(syncSkill).toContain( + "support/procedure.md — read before edits or detailed auditing; contains core quality gates", + ); + expect(syncSkill).toContain( + "support/subagents-and-leases.md — read only when using subagents, leases, or accepting worker output", + ); + expect(syncSkill).toContain( + "helper-manifest.yml — read only when invoking helper validators or validating helper registration", + ); + expect(syncSkill).toContain( + "support/helper-policy.md — read only when invoking helper validators or reporting helper status", + ); + }); }); diff --git a/tests/evidence/validate.test.ts b/tests/evidence/validate.test.ts index f2b6dd5..7f2ad8d 100644 --- a/tests/evidence/validate.test.ts +++ b/tests/evidence/validate.test.ts @@ -14,17 +14,17 @@ describe("validateEvidenceReferences", () => { const repo = await createTempRepo(); repos.push(repo); await repo.writeFile( - "docs/truth/sample.md", + "docs/truthmark/truth/sample.md", "---\nstatus: active\nsource_of_truth:\n - ../../src/missing.ts\n---\n# Sample\n", ); - const diagnostics = await validateEvidenceReferences(repo.rootDir, ["docs/truth/sample.md"]); + const diagnostics = await validateEvidenceReferences(repo.rootDir, ["docs/truthmark/truth/sample.md"]); expect(diagnostics).toContainEqual( expect.objectContaining({ - category: "freshness", + category: "source-traceability", severity: "error", - file: "docs/truth/sample.md", + file: "docs/truthmark/truth/sample.md", }), ); }); @@ -35,11 +35,11 @@ describe("validateEvidenceReferences", () => { await repo.writeFile("src/index.ts", "export const value = 1;\n"); await repo.writeFile( - "docs/truth/sample.md", - "---\nstatus: active\nsource_of_truth:\n - ../../src/**/*.ts\n---\n# Sample\n", + "docs/truthmark/truth/sample.md", + "---\nstatus: active\nsource_of_truth:\n - ../../../src/**/*.ts\n---\n# Sample\n", ); - const diagnostics = await validateEvidenceReferences(repo.rootDir, ["docs/truth/sample.md"]); + const diagnostics = await validateEvidenceReferences(repo.rootDir, ["docs/truthmark/truth/sample.md"]); expect(diagnostics).toEqual([]); }); @@ -48,13 +48,13 @@ describe("validateEvidenceReferences", () => { const repo = await createTempRepo(); repos.push(repo); - await repo.writeFile("docs/truth/overview.md", "# Overview\n"); + await repo.writeFile("docs/truthmark/truth/overview.md", "# Overview\n"); await repo.writeFile( - "docs/truth/sample.md", + "docs/truthmark/truth/sample.md", "---\nstatus: active\nsource_of_truth:\n - overview.md\n---\n# Sample\n", ); - const diagnostics = await validateEvidenceReferences(repo.rootDir, ["docs/truth/sample.md"]); + const diagnostics = await validateEvidenceReferences(repo.rootDir, ["docs/truthmark/truth/sample.md"]); expect(diagnostics).toEqual([]); }); @@ -65,7 +65,7 @@ describe("validateEvidenceReferences", () => { await repo.writeFile("src/index.ts", "export const value = 1;\n"); await repo.writeFile( - "docs/truth/sample.md", + "docs/truthmark/truth/sample.md", `--- status: active --- @@ -73,22 +73,82 @@ status: active \`\`\`yaml evidence: - - path: ../../src/index.ts + - path: ../../../src/index.ts start_line: 10 end_line: 12 \`\`\` `, ); - const diagnostics = await validateEvidenceReferences(repo.rootDir, ["docs/truth/sample.md"]); + const diagnostics = await validateEvidenceReferences(repo.rootDir, ["docs/truthmark/truth/sample.md"]); expect(diagnostics).toContainEqual( expect.objectContaining({ - category: "freshness", + category: "source-traceability", severity: "error", - file: "docs/truth/sample.md", + file: "docs/truthmark/truth/sample.md", message: expect.stringContaining("outside the file"), }), ); }); + + it("ignores malformed non-evidence YAML while reporting malformed evidence YAML", async () => { + const repo = await createTempRepo(); + repos.push(repo); + + await repo.writeFile("src/index.ts", "export const value = 1;\n"); + await repo.writeFile( + "docs/truthmark/truth/non-evidence.md", + `--- +status: active +source_of_truth: + - ../../../src/index.ts +--- +# Non-evidence YAML + +\`\`\`yaml +example: + - value: [ +\`\`\` +`, + ); + await repo.writeFile( + "docs/truthmark/truth/evidence.md", + `--- +status: active +source_of_truth: + - ../../../src/index.ts +--- +# Evidence YAML + +\`\`\`yaml +evidence: + - path: ../../../src/index.ts + start_line: [ +\`\`\` +`, + ); + + const diagnostics = await validateEvidenceReferences(repo.rootDir, [ + "docs/truthmark/truth/non-evidence.md", + "docs/truthmark/truth/evidence.md", + ]); + + expect(diagnostics).toContainEqual( + expect.objectContaining({ + category: "source-traceability", + severity: "error", + file: "docs/truthmark/truth/evidence.md", + message: expect.stringContaining("Malformed evidence YAML block"), + }), + ); + expect(diagnostics).not.toContainEqual( + expect.objectContaining({ + category: "source-traceability", + severity: "error", + file: "docs/truthmark/truth/non-evidence.md", + message: expect.stringContaining("Malformed evidence YAML block"), + }), + ); + }); }); diff --git a/tests/fs/paths.test.ts b/tests/fs/paths.test.ts index ed6c334..f0ae97c 100644 --- a/tests/fs/paths.test.ts +++ b/tests/fs/paths.test.ts @@ -54,11 +54,14 @@ describe("repo path writes", () => { const outsidePath = path.resolve(repo.rootDir, "..", "truthmark-paths-broken-link.md"); try { - await repo.writeFile("docs/templates/.keep", ""); - await fs.symlink(outsidePath, path.join(repo.rootDir, "docs", "templates", "behavior-doc.md")); + await repo.writeFile("docs/truthmark/templates/.keep", ""); + await fs.symlink( + outsidePath, + path.join(repo.rootDir, "docs", "truthmark", "templates", "behavior-doc.md"), + ); await expect( - ensureRepoFile(repo.rootDir, "docs/templates/behavior-doc.md", "# Template\n"), + ensureRepoFile(repo.rootDir, "docs/truthmark/templates/behavior-doc.md", "# Template\n"), ).rejects.toThrow("must stay inside the repository root"); await expect(fs.stat(outsidePath)).rejects.toThrow(); } finally { diff --git a/tests/generation/truth-doc-update.test.ts b/tests/generation/truth-doc-update.test.ts index dcf2dc3..3fccf7e 100644 --- a/tests/generation/truth-doc-update.test.ts +++ b/tests/generation/truth-doc-update.test.ts @@ -7,7 +7,7 @@ const contextPack = { task: "truth-sync", changedFiles: ["src/auth/session.ts"], owningAreas: ["Authentication"], - relevantDocs: ["docs/truth/authentication/session-timeout.md"], + relevantDocs: ["docs/truthmark/truth/authentication/session-timeout.md"], evidenceSnippets: [ { id: "E1", diff --git a/tests/generation/validate.test.ts b/tests/generation/validate.test.ts index 6e6379d..525bce8 100644 --- a/tests/generation/validate.test.ts +++ b/tests/generation/validate.test.ts @@ -7,7 +7,7 @@ const contextPack = { task: "truth-sync", changedFiles: ["src/auth/session.ts"], owningAreas: ["Authentication"], - relevantDocs: ["docs/truth/authentication/session-timeout.md"], + relevantDocs: ["docs/truthmark/truth/authentication/session-timeout.md"], evidenceSnippets: [ { id: "E1", @@ -23,7 +23,7 @@ const contextPack = { const validDraft = { status: "drafted", - targetDocs: ["docs/truth/authentication/session-timeout.md"], + targetDocs: ["docs/truthmark/truth/authentication/session-timeout.md"], claims: [ { text: "Session timeout is 15 minutes.", @@ -33,7 +33,7 @@ const validDraft = { ], patches: [ { - path: "docs/truth/authentication/session-timeout.md", + path: "docs/truthmark/truth/authentication/session-timeout.md", section: "Current Behavior", operation: "append", markdown: "- Sessions expire after 15 minutes of inactivity.", @@ -99,8 +99,8 @@ describe("parseTruthDocUpdateDraft", () => { parseTruthDocUpdateDraft( JSON.stringify({ ...validDraft, - targetDocs: ["docs/truth/other.md"], - patches: [{ ...validDraft.patches[0], path: "docs/truth/other.md" }], + targetDocs: ["docs/truthmark/truth/other.md"], + patches: [{ ...validDraft.patches[0], path: "docs/truthmark/truth/other.md" }], }), contextPack, ), @@ -125,7 +125,7 @@ describe("parseTruthDocUpdateDraft", () => { parseTruthDocUpdateDraft( JSON.stringify({ ...validDraft, - targetDocs: ["docs/truth/authentication/session-timeout.md"], + targetDocs: ["docs/truthmark/truth/authentication/session-timeout.md"], patches: [], }), contextPack, diff --git a/tests/git/changes.test.ts b/tests/git/changes.test.ts deleted file mode 100644 index 21195ad..0000000 --- a/tests/git/changes.test.ts +++ /dev/null @@ -1,138 +0,0 @@ -import fs from "node:fs/promises"; - -import { describe, expect, it } from "vitest"; - -import { getUncommittedChanges } from "../../src/git/changes.js"; -import { classifyPath } from "../../src/sync/classify.js"; -import { createTempRepo } from "../helpers/temp-repo.js"; - -describe("getUncommittedChanges", () => { - it("returns staged, unstaged, and untracked paths without duplicates", async () => { - const repo = await createTempRepo(); - - try { - await repo.writeFile("src/changed.ts", "export const changed = 1;\n"); - await repo.runGit(["add", "src/changed.ts"]); - await repo.runGit(["commit", "-m", "test: baseline tracked file"]); - - await repo.writeFile("src/staged.ts", "export const staged = true;\n"); - await repo.runGit(["add", "src/staged.ts"]); - - await repo.writeFile("src/changed.ts", "export const changed = 2;\n"); - await repo.runGit(["add", "src/changed.ts"]); - await repo.writeFile("src/changed.ts", "export const changed = 3;\n"); - - await repo.writeFile("src/untracked.ts", "export const untracked = true;\n"); - - const changes = await getUncommittedChanges(repo.rootDir); - - expect(changes).toEqual( - expect.arrayContaining([ - { - path: "src/changed.ts", - staged: true, - unstaged: true, - untracked: false, - deleted: false, - }, - { - path: "src/staged.ts", - staged: true, - unstaged: false, - untracked: false, - deleted: false, - }, - { - path: "src/untracked.ts", - staged: false, - unstaged: false, - untracked: true, - deleted: false, - }, - ]), - ); - expect(changes.filter((change) => change.path === "src/changed.ts")).toHaveLength(1); - } finally { - await repo.cleanup(); - } - }); - - it("includes deleted tracked files and marks them as deleted", async () => { - const repo = await createTempRepo(); - - try { - await repo.writeFile("src/deleted.ts", "export const deleted = true;\n"); - await repo.runGit(["add", "src/deleted.ts"]); - await repo.runGit(["commit", "-m", "test: baseline deleted source"]); - - await fs.rm(`${repo.rootDir}/src/deleted.ts`); - - const changes = await getUncommittedChanges(repo.rootDir); - - expect(changes).toEqual( - expect.arrayContaining([ - { - path: "src/deleted.ts", - staged: false, - unstaged: true, - untracked: false, - deleted: true, - }, - ]), - ); - } finally { - await repo.cleanup(); - } - }); -}); - -describe("classifyPath", () => { - it("treats markdown docs and config files as non-functional", () => { - expect(classifyPath("docs/guides/authentication.md", [])).toBe("markdown"); - expect(classifyPath(".truthmark/config.yml", [])).toBe("config"); - expect(classifyPath("package.json", [])).toBe("config"); - expect(classifyPath("src/auth/session.ts", [])).toBe("functional-code"); - }); - - it("respects ignore globs and treats generated Truthmark paths as derived", () => { - expect(classifyPath("dist/main.js", ["dist/**"])).toBe("ignored"); - expect(classifyPath("vendor/lib/index.rb", ["vendor/**"])).toBe("ignored"); - expect(classifyPath(".truthmark/cache/state.json", [])).toBe("derived"); - expect(classifyPath(".truthmark/sync/report.md", [])).toBe("derived"); - expect(classifyPath(".claude/skills/truthmark-sync/SKILL.md", [])).toBe( - "derived", - ); - expect(classifyPath(".codex/skills/truthmark-sync/SKILL.md", [])).toBe("derived"); - expect(classifyPath(".opencode/skills/truthmark-sync/SKILL.md", [])).toBe("derived"); - expect(classifyPath("skills/truthmark-sync/SKILL.md", [])).toBe("markdown"); - expect(classifyPath(".github/copilot-instructions.md", [])).toBe("derived"); - expect(classifyPath(".github/prompts/truthmark-sync.prompt.md", [])).toBe( - "derived", - ); - expect(classifyPath(".github/agents/truth-route-auditor.agent.md", [])).toBe( - "derived", - ); - expect(classifyPath("CLAUDE.md", [])).toBe("derived"); - expect(classifyPath("GEMINI.md", [])).toBe("derived"); - expect(classifyPath(".gemini/commands/truthmark/sync.toml", [])).toBe("derived"); - }); - - it("stays conservative for source-like paths in polyglot repos", () => { - expect(classifyPath("cmd/server.go", [])).toBe("functional-code"); - expect(classifyPath("lib/session.rs", [])).toBe("functional-code"); - expect(classifyPath("scripts/release.py", [])).toBe("functional-code"); - expect(classifyPath("notes/todo.txt", [])).toBe("other"); - }); - - it("classifies IaC, API schema, frontend, workflow, and monorepo surfaces as functional", () => { - expect(classifyPath("infra/main.tf", [])).toBe("functional-code"); - expect(classifyPath("k8s/deployment.yaml", [])).toBe("functional-code"); - expect(classifyPath("api/openapi.yaml", [])).toBe("functional-code"); - expect(classifyPath("schema/user.graphql", [])).toBe("functional-code"); - expect(classifyPath("proto/user.proto", [])).toBe("functional-code"); - expect(classifyPath("frontend/components/Login.tsx", [])).toBe("functional-code"); - expect(classifyPath(".github/workflows/ci.yml", [])).toBe("functional-code"); - expect(classifyPath("apps/web/src/App.tsx", [])).toBe("functional-code"); - expect(classifyPath("packages/auth/src/session.ts", [])).toBe("functional-code"); - }); -}); diff --git a/tests/git/repository.test.ts b/tests/git/repository.test.ts index e884d6b..037d33a 100644 --- a/tests/git/repository.test.ts +++ b/tests/git/repository.test.ts @@ -71,8 +71,8 @@ describe("resolveWorktreePath", () => { try { const repository = await getGitRepository(repo.rootDir); - expect(resolveWorktreePath(repository, "docs/truthmark/areas.md")).toBe( - path.join(repo.rootDir, "docs", "truthmark", "areas.md"), + expect(resolveWorktreePath(repository, "docs/truthmark/routes/areas.md")).toBe( + path.join(repo.rootDir, "docs", "truthmark", "routes", "areas.md"), ); expect(() => resolveWorktreePath(repository, "../outside.txt")).toThrow( "must stay inside the active worktree", diff --git a/tests/impact/build.test.ts b/tests/impact/build.test.ts index 69b9b53..045d512 100644 --- a/tests/impact/build.test.ts +++ b/tests/impact/build.test.ts @@ -44,7 +44,7 @@ describe("buildImpactSet", () => { await repo.runGit(["add", "."]); await repo.runGit(["commit", "-m", "initial"]); - const truthDocPath = "docs/truth/repository/overview.md"; + const truthDocPath = "docs/truthmark/truth/repository/overview.md"; await repo.writeFile( truthDocPath, `${await repo.readFile(truthDocPath)}\nUpdated direct truth-doc edit.\n`, @@ -156,13 +156,13 @@ describe("buildImpactSet", () => { await runConfig(repo.rootDir, { force: false, stdout: false }); await runInit(repo.rootDir); await repo.writeFile( - "docs/truthmark/areas.md", + "docs/truthmark/routes/areas.md", `# Truthmark Areas ## Old Truth documents: -- docs/truth/old.md +- docs/truthmark/truth/old.md Code surface: - src/old/** @@ -173,7 +173,7 @@ Update truth when: ## New Truth documents: -- docs/truth/new.md +- docs/truthmark/truth/new.md Code surface: - src/new/** @@ -182,8 +182,8 @@ Update truth when: - new behavior changes `, ); - await repo.writeFile("docs/truth/old.md", "# Old\n"); - await repo.writeFile("docs/truth/new.md", "# New\n"); + await repo.writeFile("docs/truthmark/truth/old.md", "# Old\n"); + await repo.writeFile("docs/truthmark/truth/new.md", "# New\n"); await repo.runGit(["add", "."]); await repo.runGit(["commit", "-m", "initial"]); await repo.runGit(["branch", "baseline"]); @@ -199,7 +199,7 @@ Update truth when: status: "renamed", }), ); - expect(impact.affectedTruthDocs).toEqual(["docs/truth/new.md", "docs/truth/old.md"]); + expect(impact.affectedTruthDocs).toEqual(["docs/truthmark/truth/new.md", "docs/truthmark/truth/old.md"]); expect(impact.changedPublicSymbols).toContainEqual({ path: "src/old/api.ts", name: "oldApi", diff --git a/tests/init/init-instructions.test.ts b/tests/init/init-instructions.test.ts index a4052fb..381e765 100644 --- a/tests/init/init-instructions.test.ts +++ b/tests/init/init-instructions.test.ts @@ -60,8 +60,8 @@ describe("runInit instruction integration", () => { ".truthmark/config.yml", `version: 1 authority: - - docs/truthmark/areas.md - - docs/truthmark/areas/**/*.md + - docs/truthmark/routes/areas.md + - docs/truthmark/routes/areas/**/*.md instruction_targets: - AGENTS.md frontmatter: diff --git a/tests/init/init.test.ts b/tests/init/init.test.ts index a9e46bd..99d3e27 100644 --- a/tests/init/init.test.ts +++ b/tests/init/init.test.ts @@ -34,7 +34,7 @@ describe("runInit", () => { ); await expect(fs.stat(`${repo.rootDir}/AGENTS.md`)).rejects.toThrow(); await expect( - fs.stat(`${repo.rootDir}/docs/truthmark/areas.md`), + fs.stat(`${repo.rootDir}/docs/truthmark/routes/areas.md`), ).rejects.toThrow(); } finally { await repo.cleanup(); @@ -50,167 +50,170 @@ describe("runInit", () => { const config = parse(await repo.readFile(".truthmark/config.yml")) as { version: number; platforms: string[]; - docs: { - roots: Record; - }; + truthmark: Record; }; expect(result.command).toBe("init"); - expect(config.version).toBe(1); + expect(config.version).toBe(2); expect(config.platforms.length).toBeGreaterThan(0); - expect(config.docs.roots).toEqual({ - ai: "docs/ai", - standards: "docs/standards", - architecture: "docs/architecture", - truth: "docs/truth", + expect(config.truthmark).toMatchObject({ + workspace: "docs/truthmark", + routes: { + index: "routes/areas.md", + areas: "routes/areas", + default_area: "repository", + max_delegation_depth: 1, + }, + truth: { root: "truth" }, + templates: { root: "templates" }, }); await expect( fs.stat(`${repo.rootDir}/.truthmark/local.example.yml`), ).rejects.toThrow(); - expect(await repo.readFile("docs/truthmark/areas.md")).toContain( + expect(await repo.readFile("docs/truthmark/routes/areas.md")).toContain( "# Truthmark Areas", ); - expect(await repo.readFile("docs/truthmark/areas.md")).toContain( + expect(await repo.readFile("docs/truthmark/routes/areas.md")).toContain( "Area files:", ); - expect(await repo.readFile("docs/truthmark/areas.md")).toContain( - "- docs/truthmark/areas/repository.md", + expect(await repo.readFile("docs/truthmark/routes/areas.md")).toContain( + "- docs/truthmark/routes/areas/repository.md", ); expect( - await repo.readFile("docs/truthmark/areas/repository.md"), + await repo.readFile("docs/truthmark/routes/areas/repository.md"), ).toContain("# Repository Areas"); expect( - await repo.readFile("docs/truthmark/areas/repository.md"), + await repo.readFile("docs/truthmark/routes/areas/repository.md"), ).toContain("Truth documents:"); expect( - await repo.readFile("docs/truthmark/areas/repository.md"), - ).toContain("path: docs/truth/repository/overview.md"); + await repo.readFile("docs/truthmark/routes/areas/repository.md"), + ).toContain("path: docs/truthmark/truth/repository/overview.md"); expect( - await repo.readFile("docs/truthmark/areas/repository.md"), + await repo.readFile("docs/truthmark/routes/areas/repository.md"), ).toContain("kind: behavior"); expect( - await repo.readFile("docs/truthmark/areas/repository.md"), - ).not.toContain("- docs/truth/repository/overview.md"); + await repo.readFile("docs/truthmark/routes/areas/repository.md"), + ).not.toContain("- docs/truthmark/truth/repository/overview.md"); expect( - await repo.readFile("docs/truthmark/areas/repository.md"), - ).not.toContain("- docs/truth/README.md"); - expect(await repo.readFile("docs/truth/README.md")).toContain( + await repo.readFile("docs/truthmark/routes/areas/repository.md"), + ).not.toContain("- docs/truthmark/truth/README.md"); + expect(await repo.readFile("docs/truthmark/truth/README.md")).toContain( "Truth Docs", ); - expect(await repo.readFile("docs/truth/README.md")).toContain("index"); - expect(await repo.readFile("docs/templates/behavior-doc.md")).toContain( + expect(await repo.readFile("docs/truthmark/truth/README.md")).toContain("index"); + expect(await repo.readFile("docs/truthmark/templates/behavior-doc.md")).toContain( "# {{title}}", ); - expect(await repo.readFile("docs/templates/behavior-doc.md")).toContain( + expect(await repo.readFile("docs/truthmark/templates/behavior-doc.md")).toContain( "## Current Behavior", ); - expect(await repo.readFile("docs/templates/behavior-doc.md")).toContain( + expect(await repo.readFile("docs/truthmark/templates/behavior-doc.md")).toContain( "## Scope", ); - expect(await repo.readFile("docs/templates/behavior-doc.md")).toContain( + expect(await repo.readFile("docs/truthmark/templates/behavior-doc.md")).toContain( "{{scope}}", ); - expect(await repo.readFile("docs/templates/behavior-doc.md")).toContain( + expect(await repo.readFile("docs/truthmark/templates/behavior-doc.md")).toContain( "## Core Rules", ); - expect(await repo.readFile("docs/templates/behavior-doc.md")).toContain( + expect(await repo.readFile("docs/truthmark/templates/behavior-doc.md")).toContain( "## Flows And States", ); - expect(await repo.readFile("docs/templates/behavior-doc.md")).toContain( + expect(await repo.readFile("docs/truthmark/templates/behavior-doc.md")).toContain( "Split into another leaf doc when content introduces", ); - expect(await repo.readFile("docs/truth/repository/README.md")).toContain( + expect(await repo.readFile("docs/truthmark/truth/repository/README.md")).toContain( "Repository Truth Docs", ); - expect(await repo.readFile("docs/truth/repository/README.md")).toContain( + expect(await repo.readFile("docs/truthmark/truth/repository/README.md")).toContain( "index", ); expect( - await repo.readFile("docs/truth/repository/overview.md"), + await repo.readFile("docs/truthmark/truth/repository/overview.md"), ).toContain("# Repository Overview"); expect( - await repo.readFile("docs/truth/repository/overview.md"), + await repo.readFile("docs/truthmark/truth/repository/overview.md"), ).toContain( - "This doc was created from the editable behavior-doc template at docs/templates/behavior-doc.md.", + "This doc was created from the editable behavior-doc template at docs/truthmark/templates/behavior-doc.md.", ); expect( - await repo.readFile("docs/truth/repository/overview.md"), + await repo.readFile("docs/truthmark/truth/repository/overview.md"), ).toContain("## Current Behavior"); expect( - await repo.readFile("docs/truth/repository/overview.md"), + await repo.readFile("docs/truthmark/truth/repository/overview.md"), ).toContain("## Purpose"); expect( - (await repo.readFile("docs/truth/repository/overview.md")).match( + (await repo.readFile("docs/truthmark/truth/repository/overview.md")).match( /## Scope/g, ), ).toHaveLength(1); expect( - await repo.readFile("docs/truth/repository/overview.md"), + await repo.readFile("docs/truthmark/truth/repository/overview.md"), ).toContain("## Non-Goals"); expect( - await repo.readFile("docs/truth/repository/overview.md"), + await repo.readFile("docs/truthmark/truth/repository/overview.md"), ).toContain("## Maintenance Notes"); expect( - await repo.readFile("docs/truth/repository/overview.md"), + await repo.readFile("docs/truthmark/truth/repository/overview.md"), ).not.toContain("{{"); expect( - await repo.readFile("docs/truth/repository/overview.md"), + await repo.readFile("docs/truthmark/truth/repository/overview.md"), ).toContain("## Product Decisions"); expect( - await repo.readFile("docs/truth/repository/overview.md"), + await repo.readFile("docs/truthmark/truth/repository/overview.md"), ).toContain("## Rationale"); const agents = await repo.readFile("AGENTS.md"); const structureSkill = await repo.readFile( - ".codex/skills/truthmark-structure/SKILL.md", + ".agents/skills/truthmark-structure/SKILL.md", ); const structureReportTemplate = await repo.readFile( - ".codex/skills/truthmark-structure/support/report-template.md", + ".agents/skills/truthmark-structure/support/report-template.md", ); const structureSkillMetadata = await repo.readFile( - ".codex/skills/truthmark-structure/agents/openai.yaml", + ".agents/skills/truthmark-structure/agents/openai.yaml", ); const structureOpenCodeSkill = await repo.readFile( ".opencode/skills/truthmark-structure/SKILL.md", ); const documentSkill = await repo.readFile( - ".codex/skills/truthmark-document/SKILL.md", + ".agents/skills/truthmark-document/SKILL.md", ); const documentSubagents = await repo.readFile( - ".codex/skills/truthmark-document/support/subagents-and-leases.md", + ".agents/skills/truthmark-document/support/subagents-and-leases.md", ); const documentReportTemplate = await repo.readFile( - ".codex/skills/truthmark-document/support/report-template.md", + ".agents/skills/truthmark-document/support/report-template.md", ); const documentSkillMetadata = await repo.readFile( - ".codex/skills/truthmark-document/agents/openai.yaml", + ".agents/skills/truthmark-document/agents/openai.yaml", ); const documentOpenCodeSkill = await repo.readFile( ".opencode/skills/truthmark-document/SKILL.md", ); const documentHelperManifest = await repo.readFile( - ".codex/skills/truthmark-document/helper-manifest.yml", + ".agents/skills/truthmark-document/helper-manifest.yml", ); const syncSkill = await repo.readFile( - ".codex/skills/truthmark-sync/SKILL.md", + ".agents/skills/truthmark-sync/SKILL.md", ); const syncHelperManifest = await repo.readFile( - ".codex/skills/truthmark-sync/helper-manifest.yml", + ".agents/skills/truthmark-sync/helper-manifest.yml", ); const syncHelperPolicy = await repo.readFile( - ".codex/skills/truthmark-sync/support/helper-policy.md", + ".agents/skills/truthmark-sync/support/helper-policy.md", ); const syncProcedure = await repo.readFile( - ".codex/skills/truthmark-sync/support/procedure.md", + ".agents/skills/truthmark-sync/support/procedure.md", ); const syncSubagents = await repo.readFile( - ".codex/skills/truthmark-sync/support/subagents-and-leases.md", + ".agents/skills/truthmark-sync/support/subagents-and-leases.md", ); const syncReportTemplate = await repo.readFile( - ".codex/skills/truthmark-sync/support/report-template.md", + ".agents/skills/truthmark-sync/support/report-template.md", ); const syncSkillMetadata = await repo.readFile( - ".codex/skills/truthmark-sync/agents/openai.yaml", + ".agents/skills/truthmark-sync/agents/openai.yaml", ); const syncOpenCodeSkill = await repo.readFile( ".opencode/skills/truthmark-sync/SKILL.md", @@ -222,25 +225,25 @@ describe("runInit", () => { ".github/prompts/truthmark-sync.prompt.md", ); const realizeSkill = await repo.readFile( - ".codex/skills/truthmark-realize/SKILL.md", + ".agents/skills/truthmark-realize/SKILL.md", ); const realizeSkillMetadata = await repo.readFile( - ".codex/skills/truthmark-realize/agents/openai.yaml", + ".agents/skills/truthmark-realize/agents/openai.yaml", ); const realizeOpenCodeSkill = await repo.readFile( ".opencode/skills/truthmark-realize/SKILL.md", ); const previewSkill = await repo.readFile( - ".codex/skills/truthmark-preview/SKILL.md", + ".agents/skills/truthmark-preview/SKILL.md", ); const previewSubagents = await repo.readFile( - ".codex/skills/truthmark-preview/support/subagents-and-leases.md", + ".agents/skills/truthmark-preview/support/subagents-and-leases.md", ); const previewReportTemplate = await repo.readFile( - ".codex/skills/truthmark-preview/support/report-template.md", + ".agents/skills/truthmark-preview/support/report-template.md", ); const previewSkillMetadata = await repo.readFile( - ".codex/skills/truthmark-preview/agents/openai.yaml", + ".agents/skills/truthmark-preview/agents/openai.yaml", ); const previewOpenCodeSkill = await repo.readFile( ".opencode/skills/truthmark-preview/SKILL.md", @@ -255,10 +258,10 @@ describe("runInit", () => { ".gemini/commands/truthmark/preview.toml", ); const checkSkill = await repo.readFile( - ".codex/skills/truthmark-check/SKILL.md", + ".agents/skills/truthmark-check/SKILL.md", ); const checkSkillMetadata = await repo.readFile( - ".codex/skills/truthmark-check/agents/openai.yaml", + ".agents/skills/truthmark-check/agents/openai.yaml", ); const checkOpenCodeSkill = await repo.readFile( ".opencode/skills/truthmark-check/SKILL.md", @@ -288,16 +291,16 @@ describe("runInit", () => { ".opencode/agents/truth-doc-writer.md", ); const copilotRouteAuditorAgent = await repo.readFile( - ".github/agents/truth-route-auditor.agent.md", + ".github/agents/truth-route-auditor.md", ); const copilotClaimVerifierAgent = await repo.readFile( - ".github/agents/truth-claim-verifier.agent.md", + ".github/agents/truth-claim-verifier.md", ); const copilotDocReviewerAgent = await repo.readFile( - ".github/agents/truth-doc-reviewer.agent.md", + ".github/agents/truth-doc-reviewer.md", ); const copilotDocWriterAgent = await repo.readFile( - ".github/agents/truth-doc-writer.agent.md", + ".github/agents/truth-doc-writer.md", ); const claudeRouteAuditorAgent = await repo.readFile( ".claude/agents/truth-route-auditor.md", @@ -335,9 +338,9 @@ describe("runInit", () => { ); expect(agents).toContain("load the installed skill for details"); expect(agents).toContain("Hierarchy hints: config .truthmark/config.yml"); - expect(agents).toContain("routes docs/truthmark/areas.md"); - expect(agents).toContain("docs/truthmark/areas/**/*.md"); - expect(agents).toContain("Truth docs: docs/truth/**/*.md"); + expect(agents).toContain("routes docs/truthmark/routes/areas.md"); + expect(agents).toContain("docs/truthmark/routes/areas/**/*.md"); + expect(agents).toContain("Truth docs: docs/truthmark/truth/**/*.md"); expect(agents).toContain( "Decisions live in the canonical doc they govern", ); @@ -418,14 +421,14 @@ describe("runInit", () => { expect(syncHelperManifest).toContain("- sync-report"); expect(syncHelperManifest).toContain("- "); expect(syncHelperManifest).toContain("- --json"); - expect(syncHelperManifest).not.toContain("cd .codex/skills/truthmark-sync"); + expect(syncHelperManifest).not.toContain("cd .agents/skills/truthmark-sync"); expect(syncHelperManifest).not.toContain("node scripts/"); expect(syncHelperManifest).toContain("writes: false"); expect(syncHelperPolicy).toContain("Optional helper CLI commands"); expect(syncHelperPolicy).toContain("manual fallback"); expect(syncHelperPolicy).toContain("Helper scripts:"); await expect( - repo.readFile(".codex/skills/truthmark-sync/scripts/validate-sync-report.mjs"), + repo.readFile(".agents/skills/truthmark-sync/scripts/validate-sync-report.mjs"), ).rejects.toThrow(); expect(syncProcedure).toContain("host supports subagent dispatch"); expect(syncSubagents).toContain("truth_doc_writer"); @@ -550,7 +553,7 @@ describe("runInit", () => { expect(openCodeDocReviewerAgent).toContain("edit: deny"); expect(openCodeDocReviewerAgent).toContain(READ_ONLY_CONTEXT_BOUNDARY); expect(openCodeDocWriterAgent).toContain("mode: subagent"); - expect(openCodeDocWriterAgent).toContain('"docs/truth/**": allow'); + expect(openCodeDocWriterAgent).toContain('"docs/truthmark/truth/**": allow'); expect(openCodeDocWriterAgent).toContain("@truth-doc-writer"); expect(openCodeDocWriterAgent).not.toContain(READ_ONLY_CONTEXT_BOUNDARY); expect(copilotRouteAuditorAgent).toContain("name: truth-route-auditor"); @@ -615,7 +618,7 @@ describe("runInit", () => { result.diagnostics.some( (diagnostic) => diagnostic.category === "truth-sync" && - diagnostic.file === ".codex/skills/truthmark-sync/SKILL.md", + diagnostic.file === ".agents/skills/truthmark-sync/SKILL.md", ), ).toBe(true); expect( @@ -636,21 +639,21 @@ describe("runInit", () => { result.diagnostics.some( (diagnostic) => diagnostic.category === "truth-sync" && - diagnostic.file === ".codex/skills/truthmark-structure/SKILL.md", + diagnostic.file === ".agents/skills/truthmark-structure/SKILL.md", ), ).toBe(true); expect( result.diagnostics.some( (diagnostic) => diagnostic.category === "truth-sync" && - diagnostic.file === ".codex/skills/truthmark-document/SKILL.md", + diagnostic.file === ".agents/skills/truthmark-document/SKILL.md", ), ).toBe(true); expect( result.diagnostics.some( (diagnostic) => diagnostic.category === "truth-sync" && - diagnostic.file === ".codex/skills/truthmark-check/SKILL.md", + diagnostic.file === ".agents/skills/truthmark-check/SKILL.md", ), ).toBe(true); expect( @@ -682,7 +685,7 @@ describe("runInit", () => { } }); - it("scaffolds typed truth-doc defaults under docs/truth", async () => { + it("scaffolds typed truth-doc defaults under the workspace truth root", async () => { const repo = await createTempRepo(); try { @@ -690,57 +693,56 @@ describe("runInit", () => { await runInit(repo.rootDir); const config = parse(await repo.readFile(".truthmark/config.yml")) as { - docs: { - roots: Record; - }; + truthmark: { workspace: string; truth: { root: string } }; }; - expect(config.docs.roots.truth).toBe("docs/truth"); - expect(await repo.readFile("docs/truth/README.md")).toContain( + expect(config.truthmark.workspace).toBe("docs/truthmark"); + expect(config.truthmark.truth.root).toBe("truth"); + expect(await repo.readFile("docs/truthmark/truth/README.md")).toContain( "Truth Docs", ); - expect(await repo.readFile("docs/truth/repository/README.md")).toContain( + expect(await repo.readFile("docs/truthmark/truth/repository/README.md")).toContain( "Repository Truth Docs", ); - expect(await repo.readFile("docs/templates/behavior-doc.md")).toContain( + expect(await repo.readFile("docs/truthmark/templates/behavior-doc.md")).toContain( "truth_kind: behavior", ); - expect(await repo.readFile("docs/templates/behavior-doc.md")).toContain( + expect(await repo.readFile("docs/truthmark/templates/behavior-doc.md")).toContain( "## Current Behavior", ); - expect(await repo.readFile("docs/templates/contract-doc.md")).toContain( + expect(await repo.readFile("docs/truthmark/templates/contract-doc.md")).toContain( "## Contract Surface", ); - expect(await repo.readFile("docs/templates/contract-doc.md")).toContain( + expect(await repo.readFile("docs/truthmark/templates/contract-doc.md")).toContain( "{{contract_surface}}", ); expect( - await repo.readFile("docs/templates/architecture-doc.md"), + await repo.readFile("docs/truthmark/templates/architecture-doc.md"), ).toContain("## Boundaries"); - expect(await repo.readFile("docs/templates/workflow-doc.md")).toContain( + expect(await repo.readFile("docs/truthmark/templates/workflow-doc.md")).toContain( "## Execution Model", ); - expect(await repo.readFile("docs/templates/operations-doc.md")).toContain( + expect(await repo.readFile("docs/truthmark/templates/operations-doc.md")).toContain( "## Runtime Topology", ); expect( - await repo.readFile("docs/templates/test-behavior-doc.md"), + await repo.readFile("docs/truthmark/templates/test-behavior-doc.md"), ).toContain("## Assertions And Invariants"); expect( - await repo.readFile("docs/truth/repository/overview.md"), + await repo.readFile("docs/truthmark/truth/repository/overview.md"), ).toContain("doc_type: behavior"); expect( - await repo.readFile("docs/truth/repository/overview.md"), + await repo.readFile("docs/truthmark/truth/repository/overview.md"), ).toContain("truth_kind: behavior"); expect( - await repo.readFile("docs/truth/repository/overview.md"), + await repo.readFile("docs/truthmark/truth/repository/overview.md"), ).toContain( "Truth README files are indexes; behavior truth belongs in bounded leaf docs.", ); expect( - await repo.readFile("docs/truth/repository/overview.md"), + await repo.readFile("docs/truthmark/truth/repository/overview.md"), ).toContain( - "This doc was created from the editable behavior-doc template at docs/templates/behavior-doc.md.", + "This doc was created from the editable behavior-doc template at docs/truthmark/templates/behavior-doc.md.", ); } finally { await repo.cleanup(); @@ -753,13 +755,25 @@ describe("runInit", () => { try { await repo.writeFile( ".truthmark/config.yml", - `version: 1 + `version: 2 platforms: - codex - github-copilot - gemini-cli -authority: - - docs/truthmark/areas.md +truthmark: + workspace: docs/truthmark + routes: + index: routes/areas.md + areas: routes/areas + default_area: repository + max_delegation_depth: 1 + truth: + root: truth + templates: + root: templates + generated: + portal: + enabled: false instruction_targets: - AGENTS.md frontmatter: @@ -768,22 +782,10 @@ frontmatter: ignore: [] `, ); - await repo.writeFile( - "GEMINI.md", - `Follow \`docs/ai/repo-rules.md\`. - -Use that file as the primary repository instruction source for this agent. - -Agent-specific: -- Read \`docs/README.md\` only when choosing or updating canonical docs. -- Use \`docs/ai/agent-onboarding.md\` only when task routing is unclear or cross-area. -`, - ); - await runInit(repo.rootDir); await expect( - fs.stat(`${repo.rootDir}/.codex/skills/truthmark-sync/SKILL.md`), + fs.stat(`${repo.rootDir}/.agents/skills/truthmark-sync/SKILL.md`), ).resolves.toBeTruthy(); await expect( fs.stat(`${repo.rootDir}/.github/copilot-instructions.md`), @@ -870,16 +872,7 @@ Agent-specific: ).resolves.toBeTruthy(); const geminiInstructions = await repo.readFile("GEMINI.md"); expect(geminiInstructions).not.toContain("/truthmark:sync"); - expect(geminiInstructions).toContain( - "Use explicitly configured repository policy docs only when they exist in this checkout.", - ); - expect(geminiInstructions).toContain("Agent-specific:"); - expect(geminiInstructions).toContain( - "Read the configured Truthmark routing files when choosing or updating canonical docs.", - ); - expect(geminiInstructions).toContain( - "Use repository onboarding or docs-map files only when present and needed for unclear or cross-area routing.", - ); + expect(geminiInstructions).toContain("Truthmark Workflow"); expect(geminiInstructions).not.toContain("for Codex"); expect(geminiInstructions).not.toContain("Codex-specific"); expect(await repo.readFile("AGENTS.md")).toContain("Truthmark Workflow"); @@ -901,11 +894,23 @@ Agent-specific: try { await repo.writeFile( ".truthmark/config.yml", - `version: 1 + `version: 2 platforms: - claude-code -authority: - - docs/truthmark/areas.md +truthmark: + workspace: docs/truthmark + routes: + index: routes/areas.md + areas: routes/areas + default_area: repository + max_delegation_depth: 1 + truth: + root: truth + templates: + root: templates + generated: + portal: + enabled: false instruction_targets: - AGENTS.md frontmatter: @@ -951,7 +956,7 @@ ignore: [] await repo.readFile(".claude/skills/truthmark-realize/SKILL.md"), ).toContain("Claude Code /truthmark-realize"); await expect( - fs.stat(`${repo.rootDir}/.codex/skills/truthmark-sync/SKILL.md`), + fs.stat(`${repo.rootDir}/.agents/skills/truthmark-sync/SKILL.md`), ).rejects.toThrow(); } finally { await repo.cleanup(); @@ -967,7 +972,7 @@ ignore: [] "# System Architecture\n", ); await repo.writeFile( - "docs/truth/authentication.md", + "docs/truthmark/truth/authentication.md", "# Authentication\n", ); await repo.writeFile( @@ -981,14 +986,14 @@ ignore: [] expect(await repo.readFile("docs/architecture/system.md")).toBe( "# System Architecture\n", ); - expect(await repo.readFile("docs/truth/authentication.md")).toBe( + expect(await repo.readFile("docs/truthmark/truth/authentication.md")).toBe( "# Authentication\n", ); - const areas = await repo.readFile("docs/truthmark/areas.md"); + const areas = await repo.readFile("docs/truthmark/routes/areas.md"); expect(areas).toContain("Area files:"); - expect(areas).toContain("docs/truthmark/areas/repository.md"); + expect(areas).toContain("docs/truthmark/routes/areas/repository.md"); const agents = await repo.readFile("AGENTS.md"); @@ -1006,7 +1011,7 @@ ignore: [] try { await runConfig(repo.rootDir, {}); await repo.writeFile( - "docs/templates/behavior-doc.md", + "docs/truthmark/templates/behavior-doc.md", `--- status: active doc_type: behavior @@ -1026,17 +1031,17 @@ Custom template for {{area}}. await runInit(repo.rootDir); - expect(await repo.readFile("docs/templates/behavior-doc.md")).toContain( + expect(await repo.readFile("docs/truthmark/templates/behavior-doc.md")).toContain( "## Local Standard", ); expect( - await repo.readFile("docs/truth/repository/overview.md"), + await repo.readFile("docs/truthmark/truth/repository/overview.md"), ).toContain("## Local Standard"); expect( - await repo.readFile("docs/truth/repository/overview.md"), + await repo.readFile("docs/truthmark/truth/repository/overview.md"), ).toContain("Custom template for repository."); expect( - await repo.readFile("docs/truth/repository/overview.md"), + await repo.readFile("docs/truthmark/truth/repository/overview.md"), ).not.toContain("{{"); } finally { await repo.cleanup(); @@ -1049,7 +1054,7 @@ Custom template for {{area}}. try { await runConfig(repo.rootDir, {}); await repo.writeFile( - "docs/templates/behavior-doc.md", + "docs/truthmark/templates/behavior-doc.md", `--- status: active doc_type: behavior @@ -1106,7 +1111,7 @@ Keep this project-specific trailing section. await runInit(repo.rootDir); - const updatedTemplate = await repo.readFile("docs/templates/behavior-doc.md"); + const updatedTemplate = await repo.readFile("docs/truthmark/templates/behavior-doc.md"); expect(updatedTemplate).toContain( "State the user/system outcome this behavior protects and why it exists.", @@ -1154,12 +1159,12 @@ Keep this project-specific trailing section. it("preserves custom preambles across every truth doc template on rerun", async () => { const repo = await createTempRepo(); const templatePaths = [ - "docs/templates/behavior-doc.md", - "docs/templates/contract-doc.md", - "docs/templates/architecture-doc.md", - "docs/templates/workflow-doc.md", - "docs/templates/operations-doc.md", - "docs/templates/test-behavior-doc.md", + "docs/truthmark/templates/behavior-doc.md", + "docs/truthmark/templates/contract-doc.md", + "docs/truthmark/templates/architecture-doc.md", + "docs/truthmark/templates/workflow-doc.md", + "docs/truthmark/templates/operations-doc.md", + "docs/truthmark/templates/test-behavior-doc.md", ]; try { @@ -1209,10 +1214,10 @@ Keep this project-specific trailing section. try { await runConfig(repo.rootDir, {}); - await repo.writeFile("docs/templates/.keep", ""); + await repo.writeFile("docs/truthmark/templates/.keep", ""); await fs.symlink( outsideTemplatePath, - path.join(repo.rootDir, "docs", "templates", "behavior-doc.md"), + path.join(repo.rootDir, "docs", "truthmark", "templates", "behavior-doc.md"), ); await expect(runInit(repo.rootDir)).rejects.toThrow( @@ -1251,28 +1256,28 @@ Keep this project-specific trailing section. expect( secondResult.diagnostics.some((diagnostic) => diagnostic.message.includes( - "Unchanged .codex/skills/truthmark-sync/SKILL.md", + "Unchanged .agents/skills/truthmark-sync/SKILL.md", ), ), ).toBe(true); expect( secondResult.diagnostics.some((diagnostic) => diagnostic.message.includes( - "Unchanged .codex/skills/truthmark-structure/SKILL.md", + "Unchanged .agents/skills/truthmark-structure/SKILL.md", ), ), ).toBe(true); expect( secondResult.diagnostics.some((diagnostic) => diagnostic.message.includes( - "Unchanged .codex/skills/truthmark-check/SKILL.md", + "Unchanged .agents/skills/truthmark-check/SKILL.md", ), ), ).toBe(true); expect( secondResult.diagnostics.some((diagnostic) => diagnostic.message.includes( - "Unchanged .codex/skills/truthmark-realize/SKILL.md", + "Unchanged .agents/skills/truthmark-realize/SKILL.md", ), ), ).toBe(true); @@ -1284,7 +1289,7 @@ Keep this project-specific trailing section. } }); - it("reports manual migration when configured truth root changes and old docs exist", async () => { + it("rejects legacy config shapes instead of migrating old docs roots", async () => { const repo = await createTempRepo(); try { @@ -1298,13 +1303,13 @@ docs: roots: truth: docs/product routing: - root_index: docs/truthmark/areas.md - area_files_root: docs/truthmark/areas + root_index: docs/truthmark/routes/areas.md + area_files_root: docs/truthmark/routes/areas default_area: repository max_delegation_depth: 1 authority: - - docs/truthmark/areas.md - - docs/truthmark/areas/**/*.md + - docs/truthmark/routes/areas.md + - docs/truthmark/routes/areas/**/*.md - docs/product/**/*.md `, ); @@ -1315,17 +1320,12 @@ authority: expect.arrayContaining([ expect.objectContaining({ category: "config", - severity: "review", - message: expect.stringContaining("manual migration"), + severity: "error", + message: expect.stringContaining("Unsupported Truthmark config shape"), }), ]), ); - expect( - await repo.readFile( - ".codex/skills/truthmark-realize/support/report-template.md", - ), - ).toContain("docs/product/authentication/session-timeout.md"); - expect(await repo.readFile("docs/truth/README.md")).toContain( + expect(await repo.readFile("docs/truthmark/truth/README.md")).toContain( "Truth Docs", ); } finally { @@ -1339,30 +1339,31 @@ authority: try { await repo.writeFile( ".truthmark/config.yml", - `version: 1 -docs: - layout: hierarchical - roots: - truth: docs/product - routing: - root_index: docs/truthmark/areas.md - area_files_root: docs/truthmark/areas + `version: 2 +truthmark: + workspace: docs/product + routes: + index: routes/areas.md + areas: routes/areas default_area: repository max_delegation_depth: 1 -authority: - - docs/truthmark/areas.md - - docs/truthmark/areas/**/*.md - - docs/product/**/*.md + truth: + root: truth + templates: + root: templates + generated: + portal: + enabled: false `, ); await runInit(repo.rootDir); const childRoute = await repo.readFile( - "docs/truthmark/areas/repository.md", + "docs/product/routes/areas/repository.md", ); expect(childRoute).toContain("```yaml"); - expect(childRoute).toContain("path: docs/product/repository/overview.md"); + expect(childRoute).toContain("path: docs/product/truth/repository/overview.md"); expect(childRoute).toContain("kind: behavior"); expect(childRoute).not.toContain("- docs/product/repository/overview.md"); @@ -1370,7 +1371,7 @@ authority: expect(result.diagnostics).not.toEqual( expect.arrayContaining([ expect.objectContaining({ - file: "docs/truthmark/areas/repository.md", + file: "docs/product/routes/areas/repository.md", message: expect.stringContaining("defaulting to behavior"), }), ]), @@ -1386,22 +1387,23 @@ authority: try { await repo.writeFile( ".truthmark/config.yml", - `version: 1 + `version: 2 platforms: - opencode -docs: - layout: hierarchical - roots: - truth: product/truth - routing: - root_index: product/routes/index.md - area_files_root: product/routes/areas +truthmark: + workspace: product + routes: + index: routes/index.md + areas: routes/areas default_area: repository max_delegation_depth: 1 -authority: - - product/routes/index.md - - product/routes/areas/**/*.md - - product/truth/**/*.md + truth: + root: truth + templates: + root: templates + generated: + portal: + enabled: false `, ); @@ -1417,9 +1419,9 @@ authority: expect(openCodeDocWriterAgent).toContain( '"product/routes/areas/**/*.md": allow', ); - expect(openCodeDocWriterAgent).not.toContain('"docs/truth/**": allow'); + expect(openCodeDocWriterAgent).not.toContain('"docs/truthmark/truth/**": allow'); expect(openCodeDocWriterAgent).not.toContain( - '"docs/truthmark/areas.md": allow', + '"docs/truthmark/routes/areas.md": allow', ); } finally { await repo.cleanup(); @@ -1437,8 +1439,8 @@ authority: `${await repo.readFile(".truthmark/config.yml")}\ncustom: true\n`, ); await repo.writeFile( - "docs/truthmark/areas.md", - `${await repo.readFile("docs/truthmark/areas.md")}\n## Local Area Notes\nKeep this routing note.\n`, + "docs/truthmark/routes/areas.md", + `${await repo.readFile("docs/truthmark/routes/areas.md")}\n## Local Area Notes\nKeep this routing note.\n`, ); await runInit(repo.rootDir); @@ -1446,7 +1448,7 @@ authority: expect(await repo.readFile(".truthmark/config.yml")).toContain( "custom: true", ); - expect(await repo.readFile("docs/truthmark/areas.md")).toContain( + expect(await repo.readFile("docs/truthmark/routes/areas.md")).toContain( "Keep this routing note.", ); } finally { @@ -1461,13 +1463,13 @@ authority: await runConfig(repo.rootDir, {}); await runInit(repo.rootDir); await repo.writeFile( - "docs/truthmark/areas.md", + "docs/truthmark/routes/areas.md", `# Truthmark Areas ## Local Area files: -- docs/truthmark/areas/local.md +- docs/truthmark/routes/areas/local.md Code surface: - src/local/** @@ -1477,23 +1479,23 @@ Update truth when: `, ); await fs.rm( - path.join(repo.rootDir, "docs/truthmark/areas/repository.md"), + path.join(repo.rootDir, "docs/truthmark/routes/areas/repository.md"), ); await runInit(repo.rootDir); await expect( - fs.stat(path.join(repo.rootDir, "docs/truthmark/areas/repository.md")), + fs.stat(path.join(repo.rootDir, "docs/truthmark/routes/areas/repository.md")), ).rejects.toThrow(); - expect(await repo.readFile("docs/truthmark/areas.md")).not.toContain( - "docs/truthmark/areas/repository.md", + expect(await repo.readFile("docs/truthmark/routes/areas.md")).not.toContain( + "docs/truthmark/routes/areas/repository.md", ); } finally { await repo.cleanup(); } }); - it("scaffolds under the default truth root when partial docs roots omit truth", async () => { + it("rejects partial legacy docs roots instead of applying defaults", async () => { const repo = await createTempRepo(); try { @@ -1505,23 +1507,28 @@ docs: roots: ai: docs/ai routing: - root_index: docs/truthmark/areas.md - area_files_root: docs/truthmark/areas + root_index: docs/truthmark/routes/areas.md + area_files_root: docs/truthmark/routes/areas default_area: repository max_delegation_depth: 1 authority: - - docs/truthmark/areas.md + - docs/truthmark/routes/areas.md `, ); - await runInit(repo.rootDir); + const result = await runInit(repo.rootDir); - expect(await repo.readFile("docs/truth/README.md")).toContain( - "Truth Docs", - ); - expect(await repo.readFile("AGENTS.md")).toContain( - "Truth docs: docs/truth/**/*.md", + expect(result.diagnostics).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + category: "config", + severity: "error", + message: expect.stringContaining("Unsupported Truthmark config shape"), + }), + ]), ); + await expect(fs.stat(`${repo.rootDir}/docs/truthmark/truth/README.md`)).rejects.toThrow(); + await expect(fs.stat(`${repo.rootDir}/AGENTS.md`)).rejects.toThrow(); } finally { await repo.cleanup(); } @@ -1550,29 +1557,6 @@ authority: } }); - it("removes orphaned managed block content before installing one clean block", async () => { - const repo = await createTempRepo(); - - try { - await runConfig(repo.rootDir, {}); - await repo.writeFile( - "AGENTS.md", - "# Notes\n\nKeep this note.\n\n\n## Truthmark Workflow\nManaged fragment marker\n- may write truth docs only\n- must not rewrite functional code\n", - ); - - await runInit(repo.rootDir); - - const agents = await repo.readFile("AGENTS.md"); - - expect(agents.match(//g)).toHaveLength(1); - expect(agents.match(//g)).toHaveLength(1); - expect(agents).toContain("Keep this note."); - expect(agents).not.toContain("Managed fragment marker"); - } finally { - await repo.cleanup(); - } - }); - it("preserves authored content above an orphaned end marker", async () => { const repo = await createTempRepo(); @@ -1641,27 +1625,6 @@ authority: } }); - it("removes a startless old managed workflow before an orphaned end marker", async () => { - const repo = await createTempRepo(); - - try { - await runConfig(repo.rootDir, {}); - await repo.writeFile( - "AGENTS.md", - "# Notes\n\n## Truthmark Workflow\n\n### Truth Sync\n- may read changed functional code files\n- may write truth docs only\n\n", - ); - - await runInit(repo.rootDir); - - const agents = await repo.readFile("AGENTS.md"); - - expect(agents.match(/## Truthmark Workflow/g)).toHaveLength(1); - expect(agents.match(/### Truth Sync/g)).toHaveLength(1); - } finally { - await repo.cleanup(); - } - }); - it("preserves authored Truthmark-shaped guidance above an orphaned end marker", async () => { const repo = await createTempRepo(); @@ -1715,10 +1678,10 @@ authority: await runConfig(repo.rootDir, {}); await runInit(repo.rootDir); - const firstAreas = await repo.readFile("docs/truthmark/areas.md"); + const firstAreas = await repo.readFile("docs/truthmark/routes/areas.md"); await runInit(repo.rootDir); - const secondAreas = await repo.readFile("docs/truthmark/areas.md"); + const secondAreas = await repo.readFile("docs/truthmark/routes/areas.md"); expect(secondAreas).toBe(firstAreas); } finally { diff --git a/tests/integration/agent-workflow-contract.test.ts b/tests/integration/agent-workflow-contract.test.ts index a55b423..7077aa5 100644 --- a/tests/integration/agent-workflow-contract.test.ts +++ b/tests/integration/agent-workflow-contract.test.ts @@ -21,13 +21,13 @@ describe("installed workflow contract", () => { const agents = await repo.readFile("AGENTS.md"); const structureSkill = await repo.readFile( - ".codex/skills/truthmark-structure/SKILL.md", + ".agents/skills/truthmark-structure/SKILL.md", ); const syncSkill = await repo.readFile( - ".codex/skills/truthmark-sync/SKILL.md", + ".agents/skills/truthmark-sync/SKILL.md", ); const documentSkill = await repo.readFile( - ".codex/skills/truthmark-document/SKILL.md", + ".agents/skills/truthmark-document/SKILL.md", ); const syncOpenCodeSkill = await repo.readFile( ".opencode/skills/truthmark-sync/SKILL.md", @@ -36,16 +36,16 @@ describe("installed workflow contract", () => { ".claude/skills/truthmark-sync/SKILL.md", ); const realizeSkill = await repo.readFile( - ".codex/skills/truthmark-realize/SKILL.md", + ".agents/skills/truthmark-realize/SKILL.md", ); const realizeOpenCodeSkill = await repo.readFile( ".opencode/skills/truthmark-realize/SKILL.md", ); const previewSkill = await repo.readFile( - ".codex/skills/truthmark-preview/SKILL.md", + ".agents/skills/truthmark-preview/SKILL.md", ); const checkSkill = await repo.readFile( - ".codex/skills/truthmark-check/SKILL.md", + ".agents/skills/truthmark-check/SKILL.md", ); const routeAuditorAgent = await repo.readFile( ".codex/agents/truth-route-auditor.toml", @@ -81,7 +81,7 @@ describe("installed workflow contract", () => { expect(structureSkill).toContain( "Follow repository instruction files that exist in this checkout", ); - expect(structureSkill).toContain("docs/truthmark/areas.md"); + expect(structureSkill).toContain("docs/truthmark/routes/areas.md"); expect(syncSkill).toContain("name: truthmark-sync"); expect(syncSkill).toContain( "Follow repository instruction files that exist in this checkout", diff --git a/tests/integration/branch-scope.test.ts b/tests/integration/branch-scope.test.ts index 37099ef..1f96b69 100644 --- a/tests/integration/branch-scope.test.ts +++ b/tests/integration/branch-scope.test.ts @@ -93,22 +93,22 @@ describe("branch-scoped truth integration", () => { const secondary = await repo.addWorktree("feature/docs"); await secondary.writeFile( - "docs/truthmark/areas.md", - `${await secondary.readFile("docs/truthmark/areas.md")}\n## Feature Branch Notes\nOnly here.\n`, + "docs/truthmark/routes/areas.md", + `${await secondary.readFile("docs/truthmark/routes/areas.md")}\n## Feature Branch Notes\nOnly here.\n`, ); const primaryResult = await runCheck(repo.rootDir); const secondaryResult = await runCheck(secondary.rootDir); const primaryHash = (primaryResult.data?.branchScope as { relevantFileHashes: Record }) - .relevantFileHashes["docs/truthmark/areas.md"]; + .relevantFileHashes["docs/truthmark/routes/areas.md"]; const secondaryHash = (secondaryResult.data?.branchScope as { relevantFileHashes: Record }) - .relevantFileHashes["docs/truthmark/areas.md"]; + .relevantFileHashes["docs/truthmark/routes/areas.md"]; expect(primaryHash).toBeTruthy(); expect(secondaryHash).toBeTruthy(); expect(primaryHash).not.toBe(secondaryHash); - expect(await repo.readFile("docs/truthmark/areas.md")).not.toContain("Feature Branch Notes"); - expect(await secondary.readFile("docs/truthmark/areas.md")).toContain("Feature Branch Notes"); + expect(await repo.readFile("docs/truthmark/routes/areas.md")).not.toContain("Feature Branch Notes"); + expect(await secondary.readFile("docs/truthmark/routes/areas.md")).toContain("Feature Branch Notes"); } finally { await repo.cleanup(); } diff --git a/tests/integration/init-check-workflow.test.ts b/tests/integration/init-check-workflow.test.ts index be3be7d..859fc98 100644 --- a/tests/integration/init-check-workflow.test.ts +++ b/tests/integration/init-check-workflow.test.ts @@ -24,19 +24,19 @@ describe("init and check workflow acceptance", () => { expect(initPayload.command).toBe("init"); await expect(fs.stat(`${repo.rootDir}/.truthmark/config.yml`)).resolves.toBeTruthy(); - await expect(fs.stat(`${repo.rootDir}/docs/truthmark/areas.md`)).resolves.toBeTruthy(); + await expect(fs.stat(`${repo.rootDir}/docs/truthmark/routes/areas.md`)).resolves.toBeTruthy(); await expect(fs.stat(`${repo.rootDir}/AGENTS.md`)).resolves.toBeTruthy(); await expect( - fs.stat(`${repo.rootDir}/.codex/skills/truthmark-structure/SKILL.md`), + fs.stat(`${repo.rootDir}/.agents/skills/truthmark-structure/SKILL.md`), ).resolves.toBeTruthy(); await expect( - fs.stat(`${repo.rootDir}/.codex/skills/truthmark-sync/SKILL.md`), + fs.stat(`${repo.rootDir}/.agents/skills/truthmark-sync/SKILL.md`), ).resolves.toBeTruthy(); await expect( - fs.stat(`${repo.rootDir}/.codex/skills/truthmark-realize/SKILL.md`), + fs.stat(`${repo.rootDir}/.agents/skills/truthmark-realize/SKILL.md`), ).resolves.toBeTruthy(); await expect( - fs.stat(`${repo.rootDir}/.codex/skills/truthmark-check/SKILL.md`), + fs.stat(`${repo.rootDir}/.agents/skills/truthmark-check/SKILL.md`), ).resolves.toBeTruthy(); await expect( fs.stat(`${repo.rootDir}/.claude/skills/truthmark-sync/SKILL.md`), @@ -80,17 +80,17 @@ describe("init and check workflow acceptance", () => { expect(initResult.exitCode).toBe(0); await repo.writeFile( - "docs/truth/authentication.md", + "docs/truthmark/truth/authentication.md", "---\nstatus: active\ndoc_type: behavior\ntruth_kind: behavior\nlast_reviewed: 2026-05-06\nsource_of_truth:\n - ../../../src/auth/session.ts\n---\n\n# Authentication\n", ); await repo.writeFile( - "docs/truthmark/areas.md", + "docs/truthmark/routes/areas.md", `# Truthmark Areas ## Authentication Truth documents: -- docs/truth/authentication.md +- docs/truthmark/truth/authentication.md Code surface: - src/auth/** diff --git a/tests/markdown/discovery.test.ts b/tests/markdown/discovery.test.ts index 49ea3b2..ce17504 100644 --- a/tests/markdown/discovery.test.ts +++ b/tests/markdown/discovery.test.ts @@ -7,7 +7,6 @@ import { renderConfigTemplate, renderAreasTemplate, } from "../../src/templates/init-files.js"; -import { renderDefaultStandards } from "../../src/templates/default-standards.js"; import { renderAgentsBlock } from "../../src/templates/agents-block.js"; describe("discoverMarkdownDocuments", () => { @@ -19,29 +18,26 @@ describe("discoverMarkdownDocuments", () => { "docs/architecture/system.md", "---\nstatus: active\n---\n# System Architecture\n", ); - await repo.writeFile( - "docs/truth/authentication.md", - "# Authentication\n", - ); + await repo.writeFile("docs/product/authentication.md", "# Authentication\n"); await repo.writeFile("README.md", "# Truthmark\n"); await repo.writeFile("node_modules/example/ignored.md", "# Ignore me\n"); await repo.writeFile("dist/generated.md", "# Ignore me\n"); await repo.writeFile("vendor/copied.md", "# Ignore me\n"); await repo.writeFile("build/output.md", "# Ignore me\n"); await repo.writeFile( - ".codex/skills/truthmark-sync/SKILL.md", + ".agents/skills/truthmark-sync/SKILL.md", "# Ignore me\n", ); await repo.writeFile( - ".codex/skills/truthmark-structure/SKILL.md", + ".agents/skills/truthmark-structure/SKILL.md", "# Ignore me\n", ); await repo.writeFile( - ".codex/skills/truthmark-realize/SKILL.md", + ".agents/skills/truthmark-realize/SKILL.md", "# Ignore me\n", ); await repo.writeFile( - ".codex/skills/truthmark-check/SKILL.md", + ".agents/skills/truthmark-check/SKILL.md", "# Ignore me\n", ); await repo.writeFile( @@ -58,7 +54,7 @@ describe("discoverMarkdownDocuments", () => { "# Ignore me\n", ); await repo.writeFile( - ".github/agents/truth-route-auditor.agent.md", + ".github/agents/truth-route-auditor.md", "# Ignore me\n", ); await repo.writeFile("CLAUDE.md", "# Ignore me\n"); @@ -82,7 +78,7 @@ describe("discoverMarkdownDocuments", () => { expect(documents.map((document) => document.path)).toEqual([ "README.md", "docs/architecture/system.md", - "docs/truth/authentication.md", + "docs/product/authentication.md", ]); expect(documents[1]).toMatchObject({ path: "docs/architecture/system.md", @@ -96,11 +92,9 @@ describe("discoverMarkdownDocuments", () => { }); describe("init templates", () => { - it("renders the V1 config template fields", () => { + it("renders the V2 workspace config template fields", () => { const config = parse(renderConfigTemplate()) as { - docs: { - roots: Record; - }; + truthmark: Record; frontmatter: { required: string[]; recommended: string[]; @@ -108,7 +102,7 @@ describe("init templates", () => { } & Record; expect(config).toMatchObject({ - version: 1, + version: 2, platforms: [ "codex", "opencode", @@ -116,7 +110,7 @@ describe("init templates", () => { "github-copilot", "gemini-cli", ], - authority: expect.any(Array), + truthmark: expect.any(Object), instruction_targets: expect.any(Array), frontmatter: expect.any(Object), ignore: expect.any(Array), @@ -125,18 +119,19 @@ describe("init templates", () => { required: [], recommended: ["status", "doc_type", "last_reviewed", "source_of_truth"], }); - expect(config.docs.roots).toEqual({ - ai: "docs/ai", - standards: "docs/standards", - architecture: "docs/architecture", - truth: "docs/truth", + expect(config).not.toHaveProperty("docs"); + expect(config).not.toHaveProperty("authority"); + expect(config.truthmark).toMatchObject({ + workspace: "docs/truthmark", + truth: { root: "truth" }, + templates: { root: "templates" }, }); }); - it("seeds docs/truthmark/areas.md from discovered docs without moving them", () => { + it("seeds docs/truthmark/routes/areas.md from discovered docs without moving them", () => { const areas = renderAreasTemplate([ { - path: "docs/truth/authentication.md", + path: "docs/truthmark/truth/authentication.md", title: "Authentication", hasFrontmatter: false, }, @@ -147,15 +142,15 @@ describe("init templates", () => { }, ]); - expect(areas).toContain("docs/truth/authentication.md"); + expect(areas).toContain("docs/truthmark/truth/authentication.md"); expect(areas).toContain("docs/api/authentication.md"); expect(areas).toContain("Truth documents:"); expect(areas).toContain("```yaml"); expect(areas).toContain("kind: behavior"); - expect(areas).toContain("kind: contract"); + expect(areas).not.toContain("kind: contract"); expect(areas).toContain("Code surface:"); expect(areas).toContain("Update truth when:"); - expect(areas).not.toContain("- docs/truth/authentication.md"); + expect(areas).not.toContain("- docs/truthmark/truth/authentication.md"); }); it("renders a managed AGENTS.md block with stable markers and workflow boundaries", () => { @@ -189,33 +184,4 @@ describe("init templates", () => { expect(agentsBlock).not.toContain("/skill truthmark-sync"); }); - it("renders default standards only when comparable standards are missing", () => { - const missingStandards = renderDefaultStandards([]); - - expect(missingStandards.map((template) => template.path)).toEqual([ - "docs/standards/default-principles.md", - "docs/standards/documentation-governance.md", - ]); - expect(missingStandards.map((template) => template.content).join("\n")).toContain( - "Architecture docs describe system structure, module boundaries, runtime topology, persistence boundaries, cross-cutting contracts, and generated-surface ownership.", - ); - expect(missingStandards.map((template) => template.content).join("\n")).toContain( - "Do not put ordinary feature behavior in architecture docs.", - ); - - const existingStandards = renderDefaultStandards([ - { - path: "docs/standards/default-principles.md", - title: "Default Principles", - hasFrontmatter: true, - }, - { - path: "docs/standards/documentation-governance.md", - title: "Documentation Governance", - hasFrontmatter: true, - }, - ]); - - expect(existingStandards).toEqual([]); - }); }); diff --git a/tests/markdown/parse.test.ts b/tests/markdown/parse.test.ts index 0ef4026..5ec1c77 100644 --- a/tests/markdown/parse.test.ts +++ b/tests/markdown/parse.test.ts @@ -35,20 +35,20 @@ describe("resolveAuthorityPaths", () => { const repo = await createTempRepo(); try { - await repo.writeFile("docs/truthmark/areas.md", "# Truthmark Areas\n"); + await repo.writeFile("docs/truthmark/routes/areas.md", "# Truthmark Areas\n"); await repo.writeFile("docs/guides/beta.md", "# Beta\n"); await repo.writeFile("docs/guides/alpha.md", "# Alpha\n"); await repo.writeFile("docs/api/authentication.md", "# Auth API\n"); const result = await resolveAuthorityPaths(repo.rootDir, [ - "docs/truthmark/areas.md", + "docs/truthmark/routes/areas.md", "docs/guides/*.md", "docs/api/*.md", ]); expect(result.diagnostics).toEqual([]); expect(result.paths).toEqual([ - "docs/truthmark/areas.md", + "docs/truthmark/routes/areas.md", "docs/guides/alpha.md", "docs/guides/beta.md", "docs/api/authentication.md", diff --git a/tests/output/render.test.ts b/tests/output/render.test.ts index 69d3a28..75c5c9a 100644 --- a/tests/output/render.test.ts +++ b/tests/output/render.test.ts @@ -78,7 +78,7 @@ describe("output rendering", () => { }, ], data: { - files: [".truthmark/config.yml", "docs/truthmark/areas.md"], + files: [".truthmark/config.yml", "docs/truthmark/routes/areas.md"], }, }; @@ -102,7 +102,9 @@ describe("output rendering", () => { "repo-index", "impact", "freshness", + "source-traceability", "context-pack", + "workflow-state", ]); }); }); diff --git a/tests/realize/report.test.ts b/tests/realize/report.test.ts index 6eda0a7..ceacc51 100644 --- a/tests/realize/report.test.ts +++ b/tests/realize/report.test.ts @@ -6,14 +6,14 @@ describe("renderTruthRealizeCompletedReport", () => { it("matches the README handoff-note shape", () => { expect( renderTruthRealizeCompletedReport({ - truthDocsUsed: ["docs/truth/authentication.md"], + truthDocsUsed: ["docs/truthmark/truth/authentication.md"], codeUpdated: ["src/auth/session.ts"], verification: ["npm test -- auth"], }), ).toBe(`Truth Realize: completed Truth docs used: -- docs/truth/authentication.md +- docs/truthmark/truth/authentication.md Code updated: - src/auth/session.ts diff --git a/tests/repo-index/build.test.ts b/tests/repo-index/build.test.ts index f48efb0..e2e62f4 100644 --- a/tests/repo-index/build.test.ts +++ b/tests/repo-index/build.test.ts @@ -37,7 +37,7 @@ describe("buildRepoIndex", () => { expect.objectContaining({ name: "sample", version: "1.0.0", manager: "npm" }), ); expect(result.files.map((file) => file.path)).toContain("src/math.ts"); - expect(result.docs.map((doc) => doc.path)).toContain("docs/truth/repository/overview.md"); + expect(result.docs.map((doc) => doc.path)).toContain("docs/truthmark/truth/repository/overview.md"); expect(result.files).toContainEqual( expect.objectContaining({ path: "AGENTS.md", kind: "generated" }), ); diff --git a/tests/routing/area-resolver.test.ts b/tests/routing/area-resolver.test.ts index f09714e..93b2f2e 100644 --- a/tests/routing/area-resolver.test.ts +++ b/tests/routing/area-resolver.test.ts @@ -4,8 +4,8 @@ import { resolveAreaRouting } from "../../src/routing/area-resolver.js"; import { createTempRepo } from "../helpers/temp-repo.js"; const config = { - rootIndex: "docs/truthmark/areas.md", - areaFilesRoot: "docs/truthmark/areas", + rootIndex: "docs/truthmark/routes/areas.md", + areaFilesRoot: "docs/truthmark/routes/areas", }; describe("resolveAreaRouting", () => { @@ -14,13 +14,13 @@ describe("resolveAreaRouting", () => { try { await repo.writeFile( - "docs/truthmark/areas.md", + "docs/truthmark/routes/areas.md", `# Truthmark Areas ## Payments Area files: -- docs/truthmark/areas/payments.md +- docs/truthmark/routes/areas/payments.md Code surface: - services/payments/** @@ -30,13 +30,13 @@ Update truth when: `, ); await repo.writeFile( - "docs/truthmark/areas/payments.md", + "docs/truthmark/routes/areas/payments.md", `# Payments Areas ## Checkout Truth documents: -- docs/truth/payments/checkout.md +- docs/truthmark/truth/payments/checkout.md Code surface: - services/payments/checkout/** @@ -50,14 +50,14 @@ Update truth when: expect(result.diagnostics).toEqual([]); expect(result.routeFiles).toEqual([ - "docs/truthmark/areas.md", - "docs/truthmark/areas/payments.md", + "docs/truthmark/routes/areas.md", + "docs/truthmark/routes/areas/payments.md", ]); expect(result.areas).toEqual([ expect.objectContaining({ name: "Checkout", - truthDocuments: ["docs/truth/payments/checkout.md"], - sourcePath: "docs/truthmark/areas/payments.md", + truthDocuments: ["docs/truthmark/truth/payments/checkout.md"], + sourcePath: "docs/truthmark/routes/areas/payments.md", parentName: "Payments", }), ]); @@ -71,7 +71,7 @@ Update truth when: try { await repo.writeFile( - "docs/truthmark/areas.md", + "docs/truthmark/routes/areas.md", `# Truthmark Areas ## Payments @@ -96,7 +96,7 @@ Update truth when: category: "area-index", severity: "error", file: "docs/payments.md", - message: expect.stringContaining("must live under docs/truthmark/areas"), + message: expect.stringContaining("must live under docs/truthmark/routes/areas"), }), ]), ); @@ -110,13 +110,13 @@ Update truth when: try { await repo.writeFile( - "docs/truthmark/areas.md", + "docs/truthmark/routes/areas.md", `# Truthmark Areas ## Payments Area files: -- docs/truthmark/areas/payments.md +- docs/truthmark/routes/areas/payments.md Code surface: - services/payments/** @@ -126,13 +126,13 @@ Update truth when: `, ); await repo.writeFile( - "docs/truthmark/areas/payments.md", + "docs/truthmark/routes/areas/payments.md", `# Payments Areas ## Checkout Area files: -- docs/truthmark/areas/payments/checkout.md +- docs/truthmark/routes/areas/payments/checkout.md Code surface: - services/payments/checkout/** @@ -150,7 +150,7 @@ Update truth when: expect.objectContaining({ category: "area-index", severity: "error", - file: "docs/truthmark/areas/payments.md", + file: "docs/truthmark/routes/areas/payments.md", message: expect.stringContaining("Child area files must contain leaf areas only"), }), ]), @@ -165,13 +165,13 @@ Update truth when: try { await repo.writeFile( - "docs/truthmark/areas.md", + "docs/truthmark/routes/areas.md", `# Truthmark Areas ## Payments Area files: -- docs/truthmark/areas/payments.md +- docs/truthmark/routes/areas/payments.md Code surface: - services/payments/** @@ -181,13 +181,13 @@ Update truth when: `, ); await repo.writeFile( - "docs/truthmark/areas/payments.md", + "docs/truthmark/routes/areas/payments.md", `# Payments Areas ## Checkout Truth documents: -- docs/truth/payments.md +- docs/truthmark/truth/payments.md Code surface: - services/payments/checkout/** @@ -198,7 +198,7 @@ Update truth when: ## Checkout Truth documents: -- docs/truth/payments-legacy.md +- docs/truthmark/truth/payments-legacy.md Code surface: - services/payments/legacy-checkout/** @@ -229,13 +229,13 @@ Update truth when: try { await repo.writeFile( - "docs/truthmark/areas.md", + "docs/truthmark/routes/areas.md", `# Truthmark Areas ## Payments Area files: -- docs/truthmark/areas/payments.md +- docs/truthmark/routes/areas/payments.md Code surface: - services/payments/** @@ -245,13 +245,13 @@ Update truth when: `, ); await repo.writeFile( - "docs/truthmark/areas/payments.md", + "docs/truthmark/routes/areas/payments.md", `# Payments Areas ## Checkout Truth documents: -- docs/truth/payments.md +- docs/truthmark/truth/payments.md Code surface: - services/orders/** @@ -268,7 +268,7 @@ Update truth when: expect.objectContaining({ category: "area-index", severity: "review", - file: "docs/truthmark/areas/payments.md", + file: "docs/truthmark/routes/areas/payments.md", message: expect.stringContaining("outside parent area Payments code surface"), }), ]), @@ -283,13 +283,13 @@ Update truth when: try { await repo.writeFile( - "docs/truthmark/areas.md", + "docs/truthmark/routes/areas.md", `# Truthmark Areas ## Apps Area files: -- docs/truthmark/areas/apps.md +- docs/truthmark/routes/areas/apps.md Code surface: - apps/*/src/** @@ -299,13 +299,13 @@ Update truth when: `, ); await repo.writeFile( - "docs/truthmark/areas/apps.md", + "docs/truthmark/routes/areas/apps.md", `# Apps Areas ## Admin Docs Truth documents: -- docs/truth/apps/admin-docs.md +- docs/truthmark/truth/apps/admin-docs.md Code surface: - apps/admin/docs/** @@ -322,7 +322,7 @@ Update truth when: expect.objectContaining({ category: "area-index", severity: "review", - file: "docs/truthmark/areas/apps.md", + file: "docs/truthmark/routes/areas/apps.md", message: expect.stringContaining("outside parent area Apps code surface"), }), ]), diff --git a/tests/routing/areas-markdown-globs.test.ts b/tests/routing/areas-markdown-globs.test.ts index b9e9350..5e3cb59 100644 --- a/tests/routing/areas-markdown-globs.test.ts +++ b/tests/routing/areas-markdown-globs.test.ts @@ -9,7 +9,7 @@ describe("parseAreasMarkdown Markdown glob handling", () => { ## Authentication Truth documents: -- docs/truth/authentication.md +- docs/truthmark/truth/authentication.md Code surface: - src/auth/\\*\\* diff --git a/tests/routing/areas.test.ts b/tests/routing/areas.test.ts index 3b36b19..064b229 100644 Binary files a/tests/routing/areas.test.ts and b/tests/routing/areas.test.ts differ diff --git a/tests/sync/policy.test.ts b/tests/sync/policy.test.ts index 0081379..544514e 100644 --- a/tests/sync/policy.test.ts +++ b/tests/sync/policy.test.ts @@ -23,12 +23,12 @@ describe("Truth Sync policy", () => { "changed functional code files", "nearby implementation context when needed to understand the changed surface", ".truthmark/config.yml", - "docs/truthmark/areas.md", + "configured Truthmark route files", "mapped truth docs", ], write: [ "truth docs only", - "docs/truthmark/areas.md when creating or repairing truth routing", + "configured Truthmark route files when creating or repairing truth routing", ], prohibit: ["must not rewrite functional code"], }); diff --git a/tests/sync/report.test.ts b/tests/sync/report.test.ts index 77778e5..75cd876 100644 --- a/tests/sync/report.test.ts +++ b/tests/sync/report.test.ts @@ -11,14 +11,14 @@ describe("Truth Sync reporting", () => { it("renders completed handoff notes in the README shape", () => { const report = renderTruthSyncCompletedReport({ changedCode: ["src/auth/session.ts"], - ownershipReviewed: ["docs/truthmark/areas/repository.md"], - truthDocsUpdated: ["docs/truth/authentication.md"], + ownershipReviewed: ["docs/truthmark/routes/areas/repository.md"], + truthDocsUpdated: ["docs/truthmark/truth/authentication.md"], evidenceChecked: [ { claim: "Session timeout behavior is documented in the authentication truth doc.", evidence: [ "src/auth/session.ts:12", - "docs/truthmark/areas/repository.md:18", + "docs/truthmark/routes/areas/repository.md:18", ], result: "supported", }, @@ -32,14 +32,14 @@ Changed code reviewed: - src/auth/session.ts Ownership reviewed: -- docs/truthmark/areas/repository.md +- docs/truthmark/routes/areas/repository.md Truth docs updated: -- docs/truth/authentication.md +- docs/truthmark/truth/authentication.md Evidence checked: - Claim: Session timeout behavior is documented in the authentication truth doc. - Evidence: src/auth/session.ts:12 / docs/truthmark/areas/repository.md:18 + Evidence: src/auth/session.ts:12 / docs/truthmark/routes/areas/repository.md:18 Result: supported Notes: @@ -47,14 +47,14 @@ Notes: expect(parseTruthSyncReport(report)).toEqual({ status: "completed", changedCode: ["src/auth/session.ts"], - ownershipReviewed: ["docs/truthmark/areas/repository.md"], - truthDocsUpdated: ["docs/truth/authentication.md"], + ownershipReviewed: ["docs/truthmark/routes/areas/repository.md"], + truthDocsUpdated: ["docs/truthmark/truth/authentication.md"], evidenceChecked: [ { claim: "Session timeout behavior is documented in the authentication truth doc.", evidence: [ "src/auth/session.ts:12", - "docs/truthmark/areas/repository.md:18", + "docs/truthmark/routes/areas/repository.md:18", ], result: "supported", }, @@ -66,8 +66,8 @@ Notes: it("round-trips optional helper script statuses", () => { const report = renderTruthSyncCompletedReport({ changedCode: ["src/auth/session.ts"], - ownershipReviewed: ["docs/truthmark/areas/repository.md"], - truthDocsUpdated: ["docs/truth/authentication.md"], + ownershipReviewed: ["docs/truthmark/routes/areas/repository.md"], + truthDocsUpdated: ["docs/truthmark/truth/authentication.md"], evidenceChecked: [ { claim: "Session timeout behavior is documented in the authentication truth doc.", @@ -103,7 +103,7 @@ Reason: expect( renderTruthSyncBlockedReport({ reason: "relevant tests failed before sync", - manualReviewFiles: ["docs/truth/authentication.md"], + manualReviewFiles: ["docs/truthmark/truth/authentication.md"], nextAction: "fix the failing tests, then rerun Truth Sync", }), ).toBe(`Truth Sync: blocked @@ -112,7 +112,7 @@ Reason: - relevant tests failed before sync Files requiring manual review: -- docs/truth/authentication.md +- docs/truthmark/truth/authentication.md Next action: - fix the failing tests, then rerun Truth Sync`); @@ -126,7 +126,7 @@ Changed code reviewed: - src/auth/session.ts Truth docs updated: -- docs/truth/authentication.md +- docs/truthmark/truth/authentication.md Evidence checked: - Session timeout behavior was reviewed. @@ -144,7 +144,7 @@ Changed code reviewed: - src/auth/session.ts Truth docs updated: -- docs/truth/authentication.md +- docs/truthmark/truth/authentication.md Evidence checked: - Claim:${" "} @@ -162,7 +162,7 @@ Changed code reviewed: - src/auth/session.ts Truth docs updated: -- docs/truth/authentication.md +- docs/truthmark/truth/authentication.md Evidence checked: - Claim: Session timeout behavior is documented. diff --git a/tests/templates/generated-surfaces.test.ts b/tests/templates/generated-surfaces.test.ts index 74fd756..aa162bc 100644 --- a/tests/templates/generated-surfaces.test.ts +++ b/tests/templates/generated-surfaces.test.ts @@ -5,8 +5,8 @@ import { renderAgentsBlock } from "../../src/templates/agents-block.js"; import { renderGeneratedSurfaces } from "../../src/templates/generated-surfaces.js"; const portalPaths = [ - ".codex/skills/truthmark-portal/SKILL.md", - ".codex/skills/truthmark-portal/agents/openai.yaml", + ".agents/skills/truthmark-portal/SKILL.md", + ".agents/skills/truthmark-portal/agents/openai.yaml", ".opencode/skills/truthmark-portal/SKILL.md", ".claude/skills/truthmark-portal/SKILL.md", ".github/skills/truthmark-portal/SKILL.md", @@ -16,11 +16,69 @@ const portalPaths = [ ]; describe("Truthmark Portal generated surfaces", () => { + it("omits generic optional CLI validation from generated user-facing workflow surfaces", () => { + const config = createDefaultConfig(); + const generatedSurfaces = renderGeneratedSurfaces(config); + const publicWorkflowSurfaces = generatedSurfaces.filter( + (surface) => + surface.path.endsWith("/SKILL.md") || + surface.path.startsWith(".github/prompts/") || + surface.path.startsWith(".gemini/commands/"), + ); + const forbiddenText = [ + "## Optional local CLI validation", + "truthmark workflow instructions --json", + ["truthmark", "workflow", "status", "--json"].join(" "), + "workflow instructions --json", + ["workflow", "status", "--json"].join(" "), + "live preflight", + ]; + + expect(publicWorkflowSurfaces.length).toBeGreaterThan(0); + for (const surface of publicWorkflowSurfaces) { + for (const text of forbiddenText) { + expect(surface.content, surface.path).not.toContain(text); + } + } + }); + + it("keeps compact workflow-specific validation and procedure guidance", () => { + const config = createDefaultConfig(); + const byPath = new Map( + renderGeneratedSurfaces(config).map((surface) => [ + surface.path, + surface.content, + ]), + ); + + const syncSkill = byPath.get(".agents/skills/truthmark-sync/SKILL.md") ?? ""; + const syncProcedure = + byPath.get(".agents/skills/truthmark-sync/support/procedure.md") ?? ""; + const syncHelperManifest = + byPath.get(".agents/skills/truthmark-sync/helper-manifest.yml") ?? ""; + const syncHelperPolicy = + byPath.get(".agents/skills/truthmark-sync/support/helper-policy.md") ?? ""; + const previewSkill = + byPath.get(".agents/skills/truthmark-preview/SKILL.md") ?? ""; + + expect(syncSkill).toContain("Quick procedure:"); + expect(syncSkill).toContain("direct checkout inspection is the canonical path"); + expect(syncSkill).toContain("Read support/procedure.md before editing truth docs."); + expect(syncProcedure).toContain("Code verification is parent-owned"); + expect(syncProcedure).toContain("Validate the report body before adding this validator's own success status"); + expect(syncHelperManifest).toContain("validate-sync-report"); + expect(syncHelperManifest).toContain("validate-write-lease"); + expect(syncHelperPolicy).toContain("Optional helper CLI commands may collect deterministic checkout facts"); + expect(syncHelperPolicy).toContain("truthmark validate ... --json"); + expect(previewSkill).toContain("Truth Preview is read-only"); + expect(previewSkill).not.toContain("CLI is unavailable"); + }); + it("omits Portal surfaces and AGENTS wording when disabled", () => { const config = createDefaultConfig(); const paths = renderGeneratedSurfaces(config).map((surface) => surface.path); - expect(config.truthmarkPortal.enabled).toBe(false); + expect(config.truthmark.generated.portal.enabled).toBe(false); for (const portalPath of portalPaths) { expect(paths).not.toContain(portalPath); } @@ -29,10 +87,8 @@ describe("Truthmark Portal generated surfaces", () => { it("renders Portal surfaces for all configured platforms when enabled", () => { const config = createDefaultConfig(); - config.truthmarkPortal = { + config.truthmark.generated.portal = { enabled: true, - output: "docs/project-map", - template: "docs/truthmark/portal-templates/product.md", }; const surfaces = renderGeneratedSurfaces(config); @@ -42,9 +98,9 @@ describe("Truthmark Portal generated surfaces", () => { expect(byPath.has(portalPath)).toBe(true); } - const portalSkill = byPath.get(".codex/skills/truthmark-portal/SKILL.md") ?? ""; + const portalSkill = byPath.get(".agents/skills/truthmark-portal/SKILL.md") ?? ""; const portalProcedure = - byPath.get(".codex/skills/truthmark-portal/support/procedure.md") ?? ""; + byPath.get(".agents/skills/truthmark-portal/support/procedure.md") ?? ""; const copilotPrompt = byPath.get(".github/prompts/truthmark-portal.prompt.md") ?? ""; const geminiCommand = byPath.get(".gemini/commands/truthmark/portal.toml") ?? ""; const agentsBlock = renderAgentsBlock(config); @@ -53,9 +109,8 @@ describe("Truthmark Portal generated surfaces", () => { expect(text).toContain("manual-only"); expect(text).toContain("Markdown remains canonical"); expect(text).toContain("does not require the truthmark CLI"); - expect(text).toContain("docs/truthmark-portal"); - expect(text).toContain("docs/project-map"); - expect(text).toContain("docs/truthmark/portal-templates/product.md"); + expect(text).toContain("docs/truthmark/generated/portal"); + expect(text).toContain("docs/truthmark/templates/portal.html"); expect(text).toContain("no remote dependencies"); expect(text).toContain("no .truthmark/index.json dependency"); expect(text).toContain("source provenance"); @@ -63,10 +118,10 @@ describe("Truthmark Portal generated surfaces", () => { } expect(portalProcedure).toContain("replace the entire output directory"); - expect(portalProcedure).toContain("configured Portal output directory only"); - expect(portalProcedure).toContain("explicit user or template request"); + expect(portalProcedure).toContain("fixed Portal output directory only"); + expect(portalProcedure).not.toContain("custom Portal output"); expect(agentsBlock).toContain("Truthmark Portal is a separate manual-only presentation workflow"); - expect(agentsBlock).toContain("default `docs/truthmark-portal/`"); + expect(agentsBlock).toContain("docs/truthmark/generated/portal/"); expect(agentsBlock).toContain("Markdown remains canonical"); }); }); diff --git a/tests/truth/docs.test.ts b/tests/truth/docs.test.ts index 79774c6..410b8b1 100644 --- a/tests/truth/docs.test.ts +++ b/tests/truth/docs.test.ts @@ -4,10 +4,9 @@ import { createDefaultConfig } from "../../src/config/defaults.js"; import { resolveTruthDocsRoot } from "../../src/truth/docs.js"; describe("resolveTruthDocsRoot", () => { - it("falls back to the default truth root when the truth root is omitted", () => { + it("returns the normalized configured truth root", () => { const config = createDefaultConfig(); - delete config.docs.roots.truth; - expect(resolveTruthDocsRoot(config)).toBe("docs/truth"); + expect(resolveTruthDocsRoot(config)).toBe("docs/truthmark/truth"); }); }); diff --git a/tests/workflow-state/build.test.ts b/tests/workflow-state/build.test.ts new file mode 100644 index 0000000..0b1664f --- /dev/null +++ b/tests/workflow-state/build.test.ts @@ -0,0 +1,336 @@ +import fs from "node:fs/promises"; +import path from "node:path"; + +import { afterEach, describe, expect, it } from "vitest"; + +import { TRUTHMARK_WORKFLOW_MANIFEST } from "../../src/agents/workflow-manifest.js"; +import { runConfig } from "../../src/config/command.js"; +import { runInit } from "../../src/init/init.js"; +import { buildWorkflowActionContext } from "../../src/workflow-state/action-context.js"; +import { buildWorkflowState } from "../../src/workflow-state/build.js"; +import type { WorkflowState } from "../../src/workflow-state/types.js"; +import { createTempRepo, type TempRepo } from "../helpers/temp-repo.js"; + +const readTree = async (rootDir: string, relativeRoot: string): Promise> => { + const absoluteRoot = path.join(rootDir, relativeRoot); + const snapshot: Record = {}; + + const visit = async (directory: string): Promise => { + let entries; + try { + entries = await fs.readdir(directory, { withFileTypes: true }); + } catch { + return; + } + + for (const entry of entries) { + const absolutePath = path.join(directory, entry.name); + if (entry.isDirectory()) { + await visit(absolutePath); + } else if (entry.isFile()) { + const relativePath = path.relative(rootDir, absolutePath).replace(/\\/gu, "/"); + snapshot[relativePath] = await fs.readFile(absolutePath, "utf8"); + } + } + }; + + await visit(absoluteRoot); + return snapshot; +}; + +const setupConfiguredRepo = async (): Promise => { + const repo = await createTempRepo(); + await repo.writeFile( + "package.json", + JSON.stringify({ name: "sample", scripts: { test: "vitest" } }, null, 2), + ); + await repo.writeFile( + "src/math.ts", + "export function add(left: number, right: number) { return left + right; }\n", + ); + await repo.writeFile("tests/math.test.ts", "import { add } from '../src/math.js';\nvoid add;\n"); + await runConfig(repo.rootDir, { force: false, stdout: false }); + await runInit(repo.rootDir); + await repo.runGit(["add", "."]); + await repo.runGit(["commit", "-m", "initial"]); + await repo.writeFile( + "src/math.ts", + "export function add(left: number, right: number) { return left + right + 0; }\n", + ); + return repo; +}; + +describe("workflow state contract", () => { + it("constructs minimal schema-versioned state with full manifest workflow id", () => { + const state: WorkflowState = { + schemaVersion: "truthmark-workflow/v0", + workflow: "truthmark-check", + applicability: { + state: "applicable", + reasons: [], + }, + actionContext: { + mode: "read-only", + allowedWritePaths: [], + forbiddenWritePaths: [], + stopConditions: [], + requiredEvidence: [], + helperValidationCommands: [], + writeLeaseRequired: false, + }, + changedFiles: [], + affectedRoutes: [], + targetTruthDocs: [], + diagnostics: [], + checks: { + required: [], + recommended: [], + helpers: [], + }, + nextSteps: [], + reportSections: [], + }; + + expect(state.schemaVersion).toBe("truthmark-workflow/v0"); + expect(state.workflow).toBe("truthmark-check"); + expect(state.workflow).not.toBe("truth-check"); + }); +}); + +describe("action context", () => { + it("maps read-only workflows to no allowed writes", () => { + for (const workflow of ["truthmark-preview", "truthmark-check"] as const) { + const context = buildWorkflowActionContext(TRUTHMARK_WORKFLOW_MANIFEST[workflow]); + + expect(context.mode).toBe("read-only"); + expect(context.allowedWritePaths).toEqual([]); + expect(context.writeLeaseRequired).toBe(false); + } + }); + + it("restricts sync and document to routed truth and route writes", () => { + for (const workflow of ["truthmark-sync", "truthmark-document"] as const) { + const context = buildWorkflowActionContext(TRUTHMARK_WORKFLOW_MANIFEST[workflow], { + routeIndexPath: "docs/truthmark/routes/areas.md", + routeFiles: ["docs/truthmark/routes/areas/repository.md"], + truthDocs: ["docs/truthmark/truth/repository/overview.md"], + }); + + expect(context.mode).toBe("truth-doc-write"); + expect(context.allowedWritePaths).toEqual([ + "docs/truthmark/routes/areas.md", + "docs/truthmark/routes/areas/repository.md", + "docs/truthmark/truth/repository/overview.md", + ]); + expect(context.allowedWritePaths).not.toContain("*"); + expect(context.writeLeaseRequired).toBe(true); + expect(context.helperValidationCommands.length).toBeGreaterThan(0); + } + }); + + it("restricts structure to route files and starter truth docs", () => { + const context = buildWorkflowActionContext(TRUTHMARK_WORKFLOW_MANIFEST["truthmark-structure"], { + routeIndexPath: "docs/truthmark/routes/areas.md", + routeFiles: ["docs/truthmark/routes/areas/new-area.md"], + starterTruthDocs: ["docs/truthmark/truth/new-area.md"], + }); + + expect(context.mode).toBe("route-write"); + expect(context.allowedWritePaths).toEqual([ + "docs/truthmark/routes/areas.md", + "docs/truthmark/routes/areas/new-area.md", + "docs/truthmark/truth/new-area.md", + ]); + expect(context.allowedWritePaths).not.toContain("*"); + }); + + it("forbids truth documentation writes for realize", () => { + const context = buildWorkflowActionContext(TRUTHMARK_WORKFLOW_MANIFEST["truthmark-realize"], { + routeIndexPath: "docs/truthmark/routes/areas.md", + routeFiles: ["docs/truthmark/routes/areas/repository.md"], + truthRoot: "docs/truthmark/truth", + truthDocs: ["docs/truthmark/truth/repository/overview.md"], + codeWritePaths: ["src/**/*.ts"], + }); + + expect(context.mode).toBe("code-write"); + expect(context.allowedWritePaths).toEqual(["src/**/*.ts"]); + expect(context.forbiddenWritePaths).toEqual([ + "docs/truthmark/routes/areas.md", + "docs/truthmark/routes/areas/repository.md", + "docs/truthmark/truth/**/*.md", + "docs/truthmark/truth/repository/overview.md", + ]); + }); + + it("restricts portal writes to configured output when enabled", () => { + const enabled = buildWorkflowActionContext(TRUTHMARK_WORKFLOW_MANIFEST["truthmark-portal"], { + portalEnabled: true, + portalOutputPath: "docs/truthmark/generated/portal", + }); + const disabled = buildWorkflowActionContext(TRUTHMARK_WORKFLOW_MANIFEST["truthmark-portal"], { + portalEnabled: false, + portalOutputPath: "docs/truthmark/generated/portal", + }); + + expect(enabled.mode).toBe("portal-write"); + expect(enabled.allowedWritePaths).toEqual(["docs/truthmark/generated/portal/**"]); + expect(disabled.allowedWritePaths).toEqual([]); + }); + + it("does not grant wildcard writes without config or route data", () => { + for (const workflow of [ + "truthmark-sync", + "truthmark-document", + "truthmark-structure", + "truthmark-portal", + ] as const) { + const context = buildWorkflowActionContext(TRUTHMARK_WORKFLOW_MANIFEST[workflow]); + + expect(context.allowedWritePaths).toEqual([]); + expect(context.allowedWritePaths).not.toContain("*"); + expect(context.allowedWritePaths).not.toContain("**/*"); + } + }); +}); + +describe("buildWorkflowState", () => { + const repos: TempRepo[] = []; + + afterEach(async () => { + await Promise.all(repos.splice(0).map((repo) => repo.cleanup())); + }); + + it("composes repo index, impact, checks, and manifest sections without ContextPack", async () => { + const repo = await setupConfiguredRepo(); + repos.push(repo); + + const state = await buildWorkflowState(repo.rootDir, { + workflow: "truthmark-sync", + base: "main", + }); + + expect(state.schemaVersion).toBe("truthmark-workflow/v0"); + expect(state.workflow).toBe("truthmark-sync"); + expect("base" in state).toBe(false); + expect(state.workflow).not.toBe("truth-sync"); + expect(state.changedFiles).toContainEqual(expect.objectContaining({ path: "src/math.ts" })); + expect(state.affectedRoutes.length).toBeGreaterThan(0); + expect(state.targetTruthDocs.length).toBeGreaterThan(0); + expect(state.actionContext.mode).toBe("truth-doc-write"); + expect(state.actionContext.allowedWritePaths).toEqual( + expect.arrayContaining(state.targetTruthDocs), + ); + expect(state.checks.required).toEqual( + expect.arrayContaining(TRUTHMARK_WORKFLOW_MANIFEST["truthmark-sync"].requiredGates), + ); + expect(state.checks.helpers.map((helper) => helper.id)).toContain("validate-sync-report"); + expect(state.reportSections).toEqual(TRUTHMARK_WORKFLOW_MANIFEST["truthmark-sync"].reportSections); + expect(Array.isArray(state.diagnostics)).toBe(true); + expect("base" in state).toBe(false); + expect("contextPack" in state).toBe(false); + }); + + it("does not expose a legacy ContextPack opt-in path", async () => { + const repo = await setupConfiguredRepo(); + repos.push(repo); + + const state = await buildWorkflowState(repo.rootDir, { + workflow: "truthmark-sync", + base: "main", + // Legacy callers may still pass this at runtime; WorkflowState must ignore it. + includeContextPack: true, + } as Parameters[1] & { includeContextPack: true }); + + expect("contextPack" in state).toBe(false); + expect(JSON.stringify(state)).not.toContain('"content":'); + }); + + it("selects a simple local comparison base for sync when none is supplied", async () => { + const repo = await setupConfiguredRepo(); + repos.push(repo); + + const state = await buildWorkflowState(repo.rootDir, { workflow: "truthmark-sync" }); + + expect(state.applicability.state).not.toBe("blocked"); + expect(state.changedFiles).toContainEqual(expect.objectContaining({ path: "src/math.ts" })); + expect(state.targetTruthDocs.length).toBeGreaterThan(0); + expect(state.nextSteps.join("\n")).not.toContain("--base"); + }); + + it("blocks sync without a supplied or discoverable comparison base", async () => { + const repo = await setupConfiguredRepo(); + repos.push(repo); + await repo.runGit(["branch", "-m", "feature/no-base"]); + + const state = await buildWorkflowState(repo.rootDir, { workflow: "truthmark-sync" }); + + expect(state.applicability.state).toBe("blocked"); + expect(state.applicability.reasons.join("\n")).toContain("truthmark-sync requires --base"); + expect(state.actionContext.allowedWritePaths).toEqual([]); + expect(state.changedFiles).toEqual([]); + expect(state.targetTruthDocs).toEqual([]); + expect(state.nextSteps.join("\n")).toContain("--base "); + }); + + it("blocks write-capable workflows when config is missing", async () => { + const repo = await createTempRepo(); + repos.push(repo); + await repo.writeFile("src/index.ts", "export const value = 1;\n"); + + const state = await buildWorkflowState(repo.rootDir, { workflow: "truthmark-sync" }); + + expect(["blocked", "not_applicable"]).toContain(state.applicability.state); + expect(state.applicability.reasons.join("\n")).toContain("Missing .truthmark/config.yml"); + expect(state.actionContext.allowedWritePaths).toEqual([]); + }); + + it("surfaces ambiguous routing for changed functional files without target guesses", async () => { + const repo = await createTempRepo(); + repos.push(repo); + await repo.writeFile("src/unmapped.ts", "export const value = 1;\n"); + await runConfig(repo.rootDir, { force: false, stdout: false }); + await runInit(repo.rootDir); + await repo.writeFile( + "docs/truthmark/routes/areas.md", + "# Truthmark Areas\n\n## Docs Only\n\nTruth documents:\n- docs/truthmark/truth/docs-only.md\n\nCode surface:\n- docs/**\n\nUpdate truth when:\n- docs change\n", + ); + await repo.writeFile("docs/truthmark/truth/docs-only.md", "# Docs Only\n"); + await repo.runGit(["add", "."]); + await repo.runGit(["commit", "-m", "initial"]); + await repo.writeFile("src/unmapped.ts", "export const value = 2;\n"); + + const state = await buildWorkflowState(repo.rootDir, { + workflow: "truthmark-sync", + base: "main", + }); + + expect(["ambiguous", "blocked"]).toContain(state.applicability.state); + expect(state.targetTruthDocs).toEqual([]); + expect(state.nextSteps.join("\n")).toMatch(/Truth Structure|route repair/u); + }); + + it("rejects invalid workflow ids without falling back", async () => { + const repo = await createTempRepo(); + repos.push(repo); + + await expect( + buildWorkflowState(repo.rootDir, { workflow: "truth-sync" as never }), + ).rejects.toThrow(/Unknown Truthmark workflow/u); + }); + + + it("does not mutate truth, route, or generated files", async () => { + const repo = await setupConfiguredRepo(); + repos.push(repo); + const before = await readTree(repo.rootDir, "docs/truthmark"); + + await buildWorkflowState(repo.rootDir, { + workflow: "truthmark-sync", + base: "main", + }); + + const after = await readTree(repo.rootDir, "docs/truthmark"); + expect(after).toEqual(before); + }); +});