From 2dc0da40ff817ace46b2b0f64af1748a80ee704a Mon Sep 17 00:00:00 2001 From: Merlin's Cat Date: Tue, 16 Jun 2026 00:54:46 +1000 Subject: [PATCH] chore: refresh Truthmark to 2.2.0 (#15) * Split Truthmark product and engineering truth lanes * chore: align truthmark docs and runtime with lane updates * chore: bump package version to 2.2.0 * chore: refresh truthmark surfaces for 2.2.0 and document release * chore: migrate legacy truth docs to engineering legacy path * chore: remove legacy docs/truth legacy docs from repository * chore: trim document command prompts to adapter stubs * chore: customize truth root README guidance per lane * chore: make doc reviewer guidance lane-specific and helper-rendered * fix: remove duplicate check lane-classification render in evidence gate * fix: make realize doc example lane-agnostic to product and engineering * feat: separate product and engineering truth lanes * test: restore workflow surface coverage * Fix workflow lane prompt boundaries * test: guard read-only generated surface wording * Fix manual Realize lane guidance * fix: harden route relationship diagnostics Validate reciprocal product and engineering route links, gate missing product-link review diagnostics on product evidence, and reject duplicate route entries with divergent relationship metadata. * fix: merge duplicate route relationships Allow repeated route entries for the same truth document, kind, and lane to contribute additive relationship metadata. Keep hard validation errors for kind and lane conflicts and emit merged relationships in RouteMap output. * fix: make route relationships local Treat realized_by and realizes metadata as route-local navigation edges. Validate target existence and lane compatibility without requiring reciprocal declarations, and document the chosen semantics. --------- Co-authored-by: MerlinH --- .agents/skills/truthmark-check/SKILL.md | 2 +- .../skills/truthmark-check/agents/openai.yaml | 2 +- .../truthmark-check/support/procedure.md | 31 +- .../support/report-template.md | 2 +- .../support/subagents-and-leases.md | 2 +- .agents/skills/truthmark-document/SKILL.md | 2 +- .../truthmark-document/agents/openai.yaml | 2 +- .../truthmark-document/helper-manifest.yml | 6 +- .../support/helper-policy.md | 6 +- .../truthmark-document/support/procedure.md | 38 +- .../support/report-template.md | 8 +- .../support/subagents-and-leases.md | 2 +- .agents/skills/truthmark-preview/SKILL.md | 4 +- .../truthmark-preview/agents/openai.yaml | 2 +- .../truthmark-preview/support/procedure.md | 22 +- .../support/report-template.md | 8 +- .../support/subagents-and-leases.md | 2 +- .agents/skills/truthmark-realize/SKILL.md | 2 +- .../truthmark-realize/agents/openai.yaml | 2 +- .../truthmark-realize/support/procedure.md | 5 +- .../support/report-template.md | 5 +- .agents/skills/truthmark-structure/SKILL.md | 2 +- .../truthmark-structure/agents/openai.yaml | 2 +- .../truthmark-structure/support/procedure.md | 55 +- .../support/report-template.md | 13 +- .../support/subagents-and-leases.md | 2 +- .agents/skills/truthmark-sync/SKILL.md | 2 +- .../skills/truthmark-sync/agents/openai.yaml | 2 +- .../skills/truthmark-sync/helper-manifest.yml | 6 +- .../truthmark-sync/support/helper-policy.md | 6 +- .../truthmark-sync/support/procedure.md | 41 +- .../truthmark-sync/support/report-template.md | 4 +- .../support/subagents-and-leases.md | 2 +- .claude/agents/truth-claim-verifier.md | 2 +- .claude/agents/truth-doc-reviewer.md | 4 +- .claude/agents/truth-doc-writer.md | 2 +- .claude/agents/truth-route-auditor.md | 9 +- .claude/skills/truthmark-check/SKILL.md | 2 +- .../truthmark-check/support/procedure.md | 31 +- .../support/report-template.md | 2 +- .../support/subagents-and-leases.md | 2 +- .claude/skills/truthmark-document/SKILL.md | 2 +- .../truthmark-document/helper-manifest.yml | 6 +- .../support/helper-policy.md | 6 +- .../truthmark-document/support/procedure.md | 38 +- .../support/report-template.md | 8 +- .../support/subagents-and-leases.md | 2 +- .claude/skills/truthmark-preview/SKILL.md | 4 +- .../truthmark-preview/support/procedure.md | 22 +- .../support/report-template.md | 8 +- .../support/subagents-and-leases.md | 2 +- .claude/skills/truthmark-realize/SKILL.md | 2 +- .../truthmark-realize/support/procedure.md | 5 +- .../support/report-template.md | 5 +- .claude/skills/truthmark-structure/SKILL.md | 2 +- .../truthmark-structure/support/procedure.md | 55 +- .../support/report-template.md | 13 +- .../support/subagents-and-leases.md | 2 +- .claude/skills/truthmark-sync/SKILL.md | 2 +- .../skills/truthmark-sync/helper-manifest.yml | 6 +- .../truthmark-sync/support/helper-policy.md | 6 +- .../truthmark-sync/support/procedure.md | 41 +- .../truthmark-sync/support/report-template.md | 4 +- .../support/subagents-and-leases.md | 2 +- .codex/agents/truth-claim-verifier.toml | 2 +- .codex/agents/truth-doc-reviewer.toml | 4 +- .codex/agents/truth-doc-writer.toml | 2 +- .codex/agents/truth-route-auditor.toml | 9 +- .gemini/agents/truth-claim-verifier.md | 2 +- .gemini/agents/truth-doc-reviewer.md | 4 +- .gemini/agents/truth-doc-writer.md | 2 +- .gemini/agents/truth-route-auditor.md | 9 +- .gemini/commands/truthmark/check.toml | 70 +-- .gemini/commands/truthmark/document.toml | 125 +---- .gemini/commands/truthmark/preview.toml | 90 +-- .gemini/commands/truthmark/realize.toml | 65 +-- .gemini/commands/truthmark/structure.toml | 152 +---- .gemini/commands/truthmark/sync.toml | 137 +---- .gemini/skills/truthmark-check/SKILL.md | 2 +- .../truthmark-check/support/procedure.md | 31 +- .../support/report-template.md | 2 +- .../support/subagents-and-leases.md | 2 +- .gemini/skills/truthmark-document/SKILL.md | 2 +- .../truthmark-document/helper-manifest.yml | 6 +- .../support/helper-policy.md | 6 +- .../truthmark-document/support/procedure.md | 38 +- .../support/report-template.md | 8 +- .../support/subagents-and-leases.md | 2 +- .gemini/skills/truthmark-preview/SKILL.md | 4 +- .../truthmark-preview/support/procedure.md | 22 +- .../support/report-template.md | 8 +- .../support/subagents-and-leases.md | 2 +- .gemini/skills/truthmark-realize/SKILL.md | 2 +- .../truthmark-realize/support/procedure.md | 5 +- .../support/report-template.md | 5 +- .gemini/skills/truthmark-structure/SKILL.md | 2 +- .../truthmark-structure/support/procedure.md | 55 +- .../support/report-template.md | 13 +- .../support/subagents-and-leases.md | 2 +- .gemini/skills/truthmark-sync/SKILL.md | 2 +- .../skills/truthmark-sync/helper-manifest.yml | 6 +- .../truthmark-sync/support/helper-policy.md | 6 +- .../truthmark-sync/support/procedure.md | 41 +- .../truthmark-sync/support/report-template.md | 4 +- .../support/subagents-and-leases.md | 2 +- .github/ISSUE_TEMPLATE/bug_report.yml | 52 ++ .github/ISSUE_TEMPLATE/config.yml | 8 + .github/ISSUE_TEMPLATE/feature_request.yml | 40 ++ .github/PULL_REQUEST_TEMPLATE.md | 30 + .github/agents/truth-claim-verifier.md | 2 +- .github/agents/truth-doc-reviewer.md | 4 +- .github/agents/truth-doc-writer.md | 2 +- .github/agents/truth-route-auditor.md | 9 +- .github/copilot-instructions.md | 4 +- .github/prompts/truthmark-check.prompt.md | 77 +-- .github/prompts/truthmark-document.prompt.md | 135 +---- .github/prompts/truthmark-preview.prompt.md | 90 +-- .github/prompts/truthmark-realize.prompt.md | 66 +-- .github/prompts/truthmark-structure.prompt.md | 158 +----- .github/prompts/truthmark-sync.prompt.md | 147 +---- .github/skills/truthmark-check/SKILL.md | 2 +- .../truthmark-check/support/procedure.md | 31 +- .../support/report-template.md | 2 +- .../support/subagents-and-leases.md | 2 +- .github/skills/truthmark-document/SKILL.md | 2 +- .../truthmark-document/helper-manifest.yml | 6 +- .../support/helper-policy.md | 6 +- .../truthmark-document/support/procedure.md | 38 +- .../support/report-template.md | 8 +- .../support/subagents-and-leases.md | 2 +- .github/skills/truthmark-preview/SKILL.md | 4 +- .../truthmark-preview/support/procedure.md | 22 +- .../support/report-template.md | 8 +- .../support/subagents-and-leases.md | 2 +- .github/skills/truthmark-realize/SKILL.md | 2 +- .../truthmark-realize/support/procedure.md | 5 +- .../support/report-template.md | 5 +- .github/skills/truthmark-structure/SKILL.md | 2 +- .../truthmark-structure/support/procedure.md | 55 +- .../support/report-template.md | 13 +- .../support/subagents-and-leases.md | 2 +- .github/skills/truthmark-sync/SKILL.md | 2 +- .../skills/truthmark-sync/helper-manifest.yml | 6 +- .../truthmark-sync/support/helper-policy.md | 6 +- .../truthmark-sync/support/procedure.md | 41 +- .../truthmark-sync/support/report-template.md | 4 +- .../support/subagents-and-leases.md | 2 +- .opencode/agents/truth-claim-verifier.md | 2 +- .opencode/agents/truth-doc-reviewer.md | 4 +- .opencode/agents/truth-doc-writer.md | 5 +- .opencode/agents/truth-route-auditor.md | 9 +- .opencode/skills/truthmark-check/SKILL.md | 2 +- .../truthmark-check/support/procedure.md | 31 +- .../support/report-template.md | 2 +- .../support/subagents-and-leases.md | 2 +- .opencode/skills/truthmark-document/SKILL.md | 2 +- .../truthmark-document/helper-manifest.yml | 6 +- .../support/helper-policy.md | 6 +- .../truthmark-document/support/procedure.md | 38 +- .../support/report-template.md | 8 +- .../support/subagents-and-leases.md | 2 +- .opencode/skills/truthmark-preview/SKILL.md | 4 +- .../truthmark-preview/support/procedure.md | 22 +- .../support/report-template.md | 8 +- .../support/subagents-and-leases.md | 2 +- .opencode/skills/truthmark-realize/SKILL.md | 2 +- .../truthmark-realize/support/procedure.md | 5 +- .../support/report-template.md | 5 +- .opencode/skills/truthmark-structure/SKILL.md | 2 +- .../truthmark-structure/support/procedure.md | 55 +- .../support/report-template.md | 13 +- .../support/subagents-and-leases.md | 2 +- .opencode/skills/truthmark-sync/SKILL.md | 2 +- .../skills/truthmark-sync/helper-manifest.yml | 6 +- .../truthmark-sync/support/helper-policy.md | 6 +- .../truthmark-sync/support/procedure.md | 41 +- .../truthmark-sync/support/report-template.md | 4 +- .../support/subagents-and-leases.md | 2 +- .truthmark/config.yml | 11 - AGENTS.md | 4 +- CLAUDE.md | 4 +- CONTRIBUTORS.md => CONTRIBUTING.md | 2 +- GEMINI.md | 4 +- README.de.md | 11 +- README.es.md | 11 +- README.md | 11 +- README.ru.md | 11 +- README.zh.md | 11 +- SECURITY.md | 27 + SUPPORT.md | 27 + changes/2026-06-14-version-2-2-0.md | 20 + docs/truthmark/engineering/README.md | 17 + .../engineering/architecture/overview.md | 59 ++ .../behaviors/check-diagnostics.md | 62 +++ .../behaviors/init-and-scaffold.md | 44 ++ .../config-route-and-check-contracts.md | 70 +++ .../contracts/generated-host-surfaces.md | 59 ++ .../operations/release-automation.md | 47 ++ .../engineering/repository/README.md | 18 + .../engineering/repository/overview.md | 120 ++++ .../repository/repository-intelligence.md | 46 ++ .../workflows/installed-workflow-runtime.md | 52 ++ docs/truthmark/product/README.md | 17 + .../agent-native-workflow-injection.md | 48 ++ .../capabilities/lane-separated-truth.md | 55 ++ docs/truthmark/routes/areas.md | 76 ++- .../routes/areas/check-and-routing.md | 57 +- .../routes/areas/contracts-and-commands.md | 24 +- .../routes/areas/init-and-scaffold.md | 46 +- .../routes/areas/installed-workflows.md | 54 +- .../routes/areas/release-automation.md | 20 +- .../routes/areas/repository-intelligence.md | 47 +- ...ure-doc.md => engineering-architecture.md} | 25 +- ...ehavior-doc.md => engineering-behavior.md} | 38 +- ...ontract-doc.md => engineering-contract.md} | 25 +- ...tions-doc.md => engineering-operations.md} | 25 +- ...or-doc.md => engineering-test-behavior.md} | 25 +- ...orkflow-doc.md => engineering-workflow.md} | 25 +- .../truthmark/templates/product-capability.md | 94 ++++ docs/truthmark/truth/README.md | 13 - docs/truthmark/truth/architecture/README.md | 19 - .../truth/architecture/module-map.md | 73 --- docs/truthmark/truth/architecture/overview.md | 142 ----- docs/truthmark/truth/check-diagnostics.md | 275 --------- docs/truthmark/truth/contracts.md | 390 ------------- docs/truthmark/truth/init-and-scaffold.md | 287 ---------- docs/truthmark/truth/release/README.md | 17 - docs/truthmark/truth/release/automation.md | 88 --- docs/truthmark/truth/repository/README.md | 21 - .../truth/repository/context-pack.md | 74 --- docs/truthmark/truth/repository/impact-set.md | 75 --- docs/truthmark/truth/repository/overview.md | 60 -- docs/truthmark/truth/repository/repo-index.md | 75 --- .../truth/repository/workflow-state.md | 83 --- docs/truthmark/truth/routing-examples.md | 82 --- .../truth/workflows/content-generation.md | 73 --- docs/truthmark/truth/workflows/overview.md | 142 ----- .../truthmark/truth/workflows/shared-gates.md | 121 ---- docs/truthmark/truth/workflows/truth-check.md | 86 --- .../truth/workflows/truth-document.md | 101 ---- .../truth/workflows/truth-preview.md | 88 --- .../truth/workflows/truth-realize.md | 81 --- .../truth/workflows/truth-structure.md | 98 ---- docs/truthmark/truth/workflows/truth-sync.md | 116 ---- .../truth/workflows/truthmark-portal.md | 103 ---- package-lock.json | 4 +- package.json | 2 +- src/agents/instructions.ts | 11 +- src/agents/prompts.ts | 36 +- src/agents/shared.ts | 122 +++- src/agents/truth-check.ts | 71 ++- src/agents/truth-document.ts | 60 +- src/agents/truth-preview.ts | 54 +- src/agents/truth-structure.ts | 100 ++-- src/agents/truth-sync.ts | 61 +- src/agents/truthmark-portal.ts | 31 +- src/agents/workflow-manifest.ts | 16 +- src/checks/areas.ts | 230 +++++++- src/checks/decisions.ts | 150 ++++- src/checks/frontmatter.ts | 57 +- src/config/defaults.ts | 52 +- src/config/load.ts | 76 +-- src/config/schema.ts | 48 +- src/evidence/parse.ts | 56 +- src/evidence/types.ts | 2 +- src/init/hierarchy.ts | 88 ++- src/output/diagnostic.ts | 3 + src/repo-index/file-tree.ts | 93 +++- src/repo-index/route-map.ts | 48 +- src/repo-index/types.ts | 6 + src/routing/area-resolver.ts | 6 + src/routing/areas.ts | 176 +++++- src/templates/agents-block.ts | 15 +- src/templates/init-files.ts | 354 +++++++++--- src/templates/workflow-surfaces.ts | 422 +++++++++----- src/truth/docs.ts | 29 +- src/truth/source-references.ts | 105 ++++ tests/agents/instructions.test.ts | 2 +- tests/agents/prompts.test.ts | 20 +- tests/agents/truth-check.test.ts | 42 +- tests/agents/truth-document.test.ts | 31 +- tests/agents/truth-preview.test.ts | 26 + tests/agents/truth-structure.test.ts | 46 +- tests/agents/truth-sync.test.ts | 135 ++++- tests/checks/check-truth-kinds.test.ts | 10 +- tests/checks/check.test.ts | 522 ++++++++++++++---- tests/checks/decisions.test.ts | 116 ++-- tests/checks/frontmatter.test.ts | 196 ++++++- tests/config/config-command.test.ts | 15 +- tests/config/load.test.ts | 113 +++- tests/evals/workflow-routing.test.ts | 187 ++++++- tests/evidence/validate.test.ts | 79 ++- tests/fs/paths.test.ts | 66 ++- tests/impact/build.test.ts | 2 +- tests/init/init.test.ts | 501 ++++++++++------- tests/integration/init-check-workflow.test.ts | 102 +++- tests/markdown/discovery.test.ts | 187 ------- tests/output/render.test.ts | 3 + tests/realize/report.test.ts | 4 +- tests/repo-index/build.test.ts | 120 +++- tests/repo-index/route-map.test.ts | 63 +++ tests/routing/area-resolver.test.ts | 4 +- tests/routing/areas-markdown-globs.test.ts | 2 +- tests/routing/areas.test.ts | 99 ++-- tests/sync/report.test.ts | 18 +- tests/templates/generated-surfaces.test.ts | 86 ++- tests/templates/init-files.test.ts | 53 ++ tests/truth/docs.test.ts | 2 +- tests/workflow-state/build.test.ts | 20 +- 309 files changed, 6483 insertions(+), 6151 deletions(-) create mode 100644 .github/ISSUE_TEMPLATE/bug_report.yml create mode 100644 .github/ISSUE_TEMPLATE/config.yml create mode 100644 .github/ISSUE_TEMPLATE/feature_request.yml create mode 100644 .github/PULL_REQUEST_TEMPLATE.md rename CONTRIBUTORS.md => CONTRIBUTING.md (98%) create mode 100644 SECURITY.md create mode 100644 SUPPORT.md create mode 100644 changes/2026-06-14-version-2-2-0.md create mode 100644 docs/truthmark/engineering/README.md create mode 100644 docs/truthmark/engineering/architecture/overview.md create mode 100644 docs/truthmark/engineering/behaviors/check-diagnostics.md create mode 100644 docs/truthmark/engineering/behaviors/init-and-scaffold.md create mode 100644 docs/truthmark/engineering/contracts/config-route-and-check-contracts.md create mode 100644 docs/truthmark/engineering/contracts/generated-host-surfaces.md create mode 100644 docs/truthmark/engineering/operations/release-automation.md create mode 100644 docs/truthmark/engineering/repository/README.md create mode 100644 docs/truthmark/engineering/repository/overview.md create mode 100644 docs/truthmark/engineering/repository/repository-intelligence.md create mode 100644 docs/truthmark/engineering/workflows/installed-workflow-runtime.md create mode 100644 docs/truthmark/product/README.md create mode 100644 docs/truthmark/product/capabilities/agent-native-workflow-injection.md create mode 100644 docs/truthmark/product/capabilities/lane-separated-truth.md rename docs/truthmark/templates/{architecture-doc.md => engineering-architecture.md} (83%) rename docs/truthmark/templates/{behavior-doc.md => engineering-behavior.md} (76%) rename docs/truthmark/templates/{contract-doc.md => engineering-contract.md} (83%) rename docs/truthmark/templates/{operations-doc.md => engineering-operations.md} (83%) rename docs/truthmark/templates/{test-behavior-doc.md => engineering-test-behavior.md} (83%) rename docs/truthmark/templates/{workflow-doc.md => engineering-workflow.md} (82%) create mode 100644 docs/truthmark/templates/product-capability.md delete mode 100644 docs/truthmark/truth/README.md delete mode 100644 docs/truthmark/truth/architecture/README.md delete mode 100644 docs/truthmark/truth/architecture/module-map.md delete mode 100644 docs/truthmark/truth/architecture/overview.md delete mode 100644 docs/truthmark/truth/check-diagnostics.md delete mode 100644 docs/truthmark/truth/contracts.md delete mode 100644 docs/truthmark/truth/init-and-scaffold.md delete mode 100644 docs/truthmark/truth/release/README.md delete mode 100644 docs/truthmark/truth/release/automation.md delete mode 100644 docs/truthmark/truth/repository/README.md delete mode 100644 docs/truthmark/truth/repository/context-pack.md delete mode 100644 docs/truthmark/truth/repository/impact-set.md delete mode 100644 docs/truthmark/truth/repository/overview.md delete mode 100644 docs/truthmark/truth/repository/repo-index.md delete mode 100644 docs/truthmark/truth/repository/workflow-state.md delete mode 100644 docs/truthmark/truth/routing-examples.md delete mode 100644 docs/truthmark/truth/workflows/content-generation.md delete mode 100644 docs/truthmark/truth/workflows/overview.md delete mode 100644 docs/truthmark/truth/workflows/shared-gates.md delete mode 100644 docs/truthmark/truth/workflows/truth-check.md delete mode 100644 docs/truthmark/truth/workflows/truth-document.md delete mode 100644 docs/truthmark/truth/workflows/truth-preview.md delete mode 100644 docs/truthmark/truth/workflows/truth-realize.md delete mode 100644 docs/truthmark/truth/workflows/truth-structure.md delete mode 100644 docs/truthmark/truth/workflows/truth-sync.md delete mode 100644 docs/truthmark/truth/workflows/truthmark-portal.md create mode 100644 src/truth/source-references.ts delete mode 100644 tests/markdown/discovery.test.ts create mode 100644 tests/templates/init-files.test.ts diff --git a/.agents/skills/truthmark-check/SKILL.md b/.agents/skills/truthmark-check/SKILL.md index b8b5902..4f52656 100644 --- a/.agents/skills/truthmark-check/SKILL.md +++ b/.agents/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: 2.1.0 +truthmark-version: 2.2.0 --- # Truthmark Check diff --git a/.agents/skills/truthmark-check/agents/openai.yaml b/.agents/skills/truthmark-check/agents/openai.yaml index 7156cc6..37db946 100644 --- a/.agents/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: "2.1.0" + version: "2.2.0" refresh_command: "truthmark init" diff --git a/.agents/skills/truthmark-check/support/procedure.md b/.agents/skills/truthmark-check/support/procedure.md index 6132ff9..c8c76bd 100644 --- a/.agents/skills/truthmark-check/support/procedure.md +++ b/.agents/skills/truthmark-check/support/procedure.md @@ -1,6 +1,6 @@ # Truthmark Check Procedure -Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.0. Rerun truthmark init after upgrades. # Truthmark Check @@ -11,13 +11,31 @@ Invocations: OpenCode /skill truthmark-check; Codex /truthmark-check or $truthma 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/routes/areas.md and relevant child route files under docs/truthmark/routes/areas/ when they exist +- Evidence authority: + - 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. +- Lane classification: + - classify the request or changed surface as product-lane, engineering-lane, both-lane, or ambiguous for reporting only + - product-lane ownership belongs under docs/truthmark/product and describes product promises, boundaries, rationale, decisions, and success criteria + - engineering-lane ownership belongs under docs/truthmark/engineering and describes source-backed current realization, contracts, architecture, workflows, operations, or tests + - both-lane ownership uses separate product and engineering docs cross-linked in route YAML with realized_by and realizes, not in doc frontmatter + - ambiguous lane ownership should be reported as blocked or routed to Truth Structure + - Do not make product docs a summary of engineering docs. Do not make engineering docs a detailed version of product docs. Product truth says what must be true and why. Engineering truth says how the repository currently realizes it. - check that current docs describe current code rather than historical plans +- keep lane and cross-lane checks route-first and bounded: + - for a narrow audit, inspect only the routed area and directly linked counterpart docs + - for root-wide truth health, first build a cheap route-map/index from route files, then inspect only mismatches and linked leaves + - inspect product counterparts for engineering docs only when route YAML claims a product relationship, or when the user explicitly asks for user-visible product coverage +- check lane root/kind alignment for product truth under docs/truthmark/product and engineering truth under docs/truthmark/engineering +- check route YAML cross-lane realized_by and realizes links for existence and lane compatibility +- report missing product links for user-visible engineering docs only as a second-pass review diagnostic, not as default full-document reads or hard errors +- check product docs do not contain engineering execution flow, generated file inventories, or CLI envelope mechanics +- check engineering docs do not contain product promises, product rationale, or Product Decisions sections +- never judge whether a product decision is commercially correct, valuable, prioritized, or desirable - 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 -- check that canonical behavior docs keep active Product Decisions and Rationale sections +- check that canonical docs keep lane-appropriate decisions and rationale sections - optionally run truthmark check when local tooling is available - must not require the truthmark binary; direct inspection is always valid - report issues and suggested fixes without silently rewriting unrelated files @@ -31,7 +49,8 @@ Truthmark hierarchy hints: - Config, when present: .truthmark/config.yml - 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 +- Product truth docs, when present: docs/truthmark/product/**/*.md +- Engineering truth docs, when present: docs/truthmark/engineering/**/*.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. +Product decisions belong in product truth; engineering, architecture, contract, workflow, and operational decisions belong in engineering truth. diff --git a/.agents/skills/truthmark-check/support/report-template.md b/.agents/skills/truthmark-check/support/report-template.md index 00a3453..435fdfa 100644 --- a/.agents/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 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.0. Rerun truthmark init after upgrades. Report completion in this shape: diff --git a/.agents/skills/truthmark-check/support/subagents-and-leases.md b/.agents/skills/truthmark-check/support/subagents-and-leases.md index b55697f..158823a 100644 --- a/.agents/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 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.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/.agents/skills/truthmark-document/SKILL.md b/.agents/skills/truthmark-document/SKILL.md index 241a841..d238539 100644 --- a/.agents/skills/truthmark-document/SKILL.md +++ b/.agents/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: 2.1.0 +truthmark-version: 2.2.0 --- # Truthmark Document diff --git a/.agents/skills/truthmark-document/agents/openai.yaml b/.agents/skills/truthmark-document/agents/openai.yaml index 1ed710a..2eeb8ec 100644 --- a/.agents/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: "2.1.0" + version: "2.2.0" refresh_command: "truthmark init" diff --git a/.agents/skills/truthmark-document/helper-manifest.yml b/.agents/skills/truthmark-document/helper-manifest.yml index 175e1a0..1763234 100644 --- a/.agents/skills/truthmark-document/helper-manifest.yml +++ b/.agents/skills/truthmark-document/helper-manifest.yml @@ -1,8 +1,8 @@ -# Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. +# Generated by Truthmark 2.2.0. Rerun truthmark init after upgrades. helpers: validate-document-report: optional: true - runner: truthmark>=2.1.0 + runner: truthmark>=2.2.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>=2.1.0 + runner: truthmark>=2.2.0 command: argv: - truthmark diff --git a/.agents/skills/truthmark-document/support/helper-policy.md b/.agents/skills/truthmark-document/support/helper-policy.md index 2cb7bd6..58bcb56 100644 --- a/.agents/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 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.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>=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 +- validate-document-report: optional truthmark>=2.2.0; manual fallback: manually validate support/report-template.md required sections and structured Evidence checked entries +- validate-write-lease: optional truthmark>=2.2.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/.agents/skills/truthmark-document/support/procedure.md b/.agents/skills/truthmark-document/support/procedure.md index be8590f..b787061 100644 --- a/.agents/skills/truthmark-document/support/procedure.md +++ b/.agents/skills/truthmark-document/support/procedure.md @@ -1,6 +1,6 @@ # Truthmark Document Procedure -Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.0. Rerun truthmark init after upgrades. # Truthmark Document @@ -11,8 +11,16 @@ Truth Document is manual and implementation-first: - run only when the user explicitly asks to generate or update truth docs for existing behavior, or when Truth Sync, Truth Check, or Truth Structure reports implemented behavior that lacks canonical truth docs - inspect .truthmark/config.yml and configured route files only when they exist; then inspect existing canonical docs, implementation code, and tests 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. +- Evidence authority: + - 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. +- Lane classification: + - before writing canonical truth docs, classify the request or change as product-lane, engineering-lane, both-lane, or ambiguous + - product-lane writes belong under docs/truthmark/product and state product promises, boundaries, rationale, decisions, and success criteria + - engineering-lane writes belong under docs/truthmark/engineering and state source-backed current realization, contracts, architecture, workflows, operations, or tests + - both-lane work must write separate product and engineering docs and cross-link them in route YAML with realized_by and realizes, not in doc frontmatter + - ambiguous lane ownership must block or invoke Truth Structure instead of writing a mixed document + - Do not make product docs a summary of engineering docs. Do not make engineering docs a detailed version of product docs. Product truth says what must be true and why. Engineering truth says how the repository currently realizes it. - document current implemented behavior; do not invent future behavior or planned endpoints - may write canonical truth docs and docs/truthmark/routes/areas.md or relevant child route files only - must not write functional code @@ -20,7 +28,10 @@ Implementation code and canonical truth docs are inspected evidence for current - block and recommend Truth Structure when routing repair is unsafe, ambiguous, or outside the task boundary - keep feature README.md files as indexes rather than truth-document targets - create or update bounded leaf truth docs when behavior does not fit an existing leaf doc -- keep behavior truth docs behavior-oriented, not endpoint-oriented, unless the endpoint itself is the behavior boundary +- write product capability/boundary truth under docs/truthmark/product when documenting product promise, boundary, rationale, or user/stakeholder value +- write engineering truth under docs/truthmark/engineering when documenting implementation behavior, contracts, architecture, workflows, operations, or tests +- for both-lane documentation requests, write separate product and engineering docs and cross-link them in route YAML with realized_by and realizes, not in doc frontmatter +- keep engineering behavior truth behavior-oriented, not endpoint-oriented, unless the endpoint itself is the behavior boundary - keep API endpoint details in the nearest contract truth doc when such a doc owns the API contract - preserve unrelated authored content Truth-doc ownership gate: @@ -28,15 +39,15 @@ Truth-doc ownership gate: - if a target/source doc mixes independent owners, spans unrelated behaviors, acts as an index, or needs cross-owner edits, do not patch or in-place repair it - if the target doc is broad, mixed-owner, index-like, or the documented behavior spans independent owners, run Truth Structure first when safe and in scope; otherwise block and recommend Truth Structure - report Ownership reviewed, Structure required, Truth docs split, Truth docs restructured, or Blocked reason as applicable -Product Decisions/Rationale preservation gate: -- before any truth-doc split, restructure, or shape repair, inventory existing Product Decisions and Rationale sections in every source or touched truth doc -- preserve each current decision and rationale in the bounded owner doc it governs; when splitting, move it to the new owner doc rather than deleting it or leaving it in an index +Decision/Rationale preservation gate: +- before any truth-doc split, restructure, or shape repair, inventory existing Product Decisions, Engineering Decisions, and Rationale sections in every source or touched truth doc +- preserve each current decision and rationale in the correct product or engineering lane owner; when splitting, move it to the new owner doc rather than deleting it or leaving it in an index - 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 +- after the edit, verify every touched truth doc keeps lane-appropriate decision/rationale sections and every pre-existing entry is preserved, moved, narrowed, removed with evidence, or blocked Evidence Gate: - route-first: map the documented behavior to bounded route owners and primary canonical docs -- review new or changed behavior-bearing claims only in touched docs, route ownership, Product Decisions, and Rationale +- review new or changed behavior-bearing claims only in touched docs, route ownership, lane-specific decisions, and rationale - support claims with primary checkout evidence: implementation, config, routing, generated templates, schemas, or contract definitions - tests/examples/canonical docs corroborate; they are not sole proof when implementation conflicts - remove, narrow, or block unsupported claims @@ -45,10 +56,10 @@ Repository intelligence artifacts are optional derived context: RepoIndex, Route 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 template under the configured Truthmark templates root. -Supported kinds: behavior, contract, architecture, workflow, operations, and test-behavior. +Supported kinds: product-capability, engineering-behavior, engineering-contract, engineering-architecture, engineering-workflow, engineering-operations, and engineering-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. +If the template is missing, use lane-specific sections: product truth says what must be true and why; engineering truth says how the repository currently realizes it. 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. @@ -63,10 +74,11 @@ Truthmark hierarchy hints: - Config, when present: .truthmark/config.yml - 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 +- Product truth docs, when present: docs/truthmark/product/**/*.md +- Engineering truth docs, when present: docs/truthmark/engineering/**/*.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. +Product decisions belong in product truth; engineering, architecture, contract, workflow, and operational decisions belong in engineering truth. Helper status reporting: - Validate the report body before adding this validator's own success status; the body may omit `validate-document-report` while validation is pending. - After `truthmark validate document-report --json` returns `data.validation.ok: true`, append or update `validate-document-report: ran, passed` in the final report. diff --git a/.agents/skills/truthmark-document/support/report-template.md b/.agents/skills/truthmark-document/support/report-template.md index 5e38b92..6673f6a 100644 --- a/.agents/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 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.0. Rerun truthmark init after upgrades. Report completion in this shape: ```md @@ -13,13 +13,13 @@ Ownership reviewed: - docs/truthmark/routes/areas.md Truth docs created: -- docs/truthmark/truth/contracts.md +- docs/truthmark/engineering/contracts/routing.md Truth docs updated: -- docs/truthmark/truth/check-diagnostics.md +- docs/truthmark/engineering/behaviors/check-diagnostics.md Truth docs restructured: -- docs/truthmark/truth/check-diagnostics.md +- docs/truthmark/engineering/behaviors/check-diagnostics.md Routing updated: - docs/truthmark/routes/areas.md diff --git a/.agents/skills/truthmark-document/support/subagents-and-leases.md b/.agents/skills/truthmark-document/support/subagents-and-leases.md index b15fea1..a806a25 100644 --- a/.agents/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 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.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/.agents/skills/truthmark-preview/SKILL.md b/.agents/skills/truthmark-preview/SKILL.md index 7db8d92..ae61cf9 100644 --- a/.agents/skills/truthmark-preview/SKILL.md +++ b/.agents/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: 2.1.0 +truthmark-version: 2.2.0 --- # Truthmark Preview @@ -14,7 +14,7 @@ Invocations: OpenCode /skill truthmark-preview; Codex /truthmark-preview or $tru 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/routes/areas.md; docs/truthmark/routes/areas/) only when they exist; then inspect only the truth docs or implementation files needed to preview ownership. +- Inspect .truthmark/config.yml and the root route index (docs/truthmark/routes/areas.md) first when present; then inspect only child route files under docs/truthmark/routes/areas/ that are relevant to the selected scope or changed paths, plus 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. diff --git a/.agents/skills/truthmark-preview/agents/openai.yaml b/.agents/skills/truthmark-preview/agents/openai.yaml index fc75934..7b71480 100644 --- a/.agents/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: "2.1.0" + version: "2.2.0" refresh_command: "truthmark init" diff --git a/.agents/skills/truthmark-preview/support/procedure.md b/.agents/skills/truthmark-preview/support/procedure.md index 276926b..9579a10 100644 --- a/.agents/skills/truthmark-preview/support/procedure.md +++ b/.agents/skills/truthmark-preview/support/procedure.md @@ -1,6 +1,6 @@ # Truthmark Preview Procedure -Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.0. Rerun truthmark init after upgrades. Use this skill only when the user explicitly asks to preview Truthmark routing or workflow choice before edits. @@ -10,16 +10,25 @@ Truth Preview is read-only. Its report is intended, not authorized. Purpose: - preview the likely Truthmark workflow, route owner, target files, expected write classes, suggested subagent use, and blocking ambiguity before edits happen +- report likely product lane impact, engineering lane impact, target docs, and ambiguity before edits - hand off to the selected workflow after user approval - keep the selector thin so agents can avoid loading or acting through heavier workflows prematurely Read: - .truthmark/config.yml, only when present -- docs/truthmark/routes/areas.md, only when present -- relevant child route files under docs/truthmark/routes/areas/, only when present +- docs/truthmark/routes/areas.md, first, only when present +- relevant child route files under docs/truthmark/routes/areas/ for the selected scope or changed paths, 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. +- Evidence authority: + - 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. +- Lane classification: + - classify the request or changed surface as product-lane, engineering-lane, both-lane, or ambiguous for reporting only + - product-lane ownership belongs under docs/truthmark/product and describes product promises, boundaries, rationale, decisions, and success criteria + - engineering-lane ownership belongs under docs/truthmark/engineering and describes source-backed current realization, contracts, architecture, workflows, operations, or tests + - both-lane ownership uses separate product and engineering docs cross-linked in route YAML with realized_by and realizes, not in doc frontmatter + - ambiguous lane ownership should be reported as blocked or routed to Truth Structure + - Do not make product docs a summary of engineering docs. Do not make engineering docs a detailed version of product docs. Product truth says what must be true and why. Engineering truth says how the repository currently realizes it. Do not: - must not edit files @@ -40,4 +49,5 @@ Truthmark hierarchy hints: - Config, when present: .truthmark/config.yml - 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 +- Product truth docs, when present: docs/truthmark/product/**/*.md +- Engineering truth docs, when present: docs/truthmark/engineering/**/*.md diff --git a/.agents/skills/truthmark-preview/support/report-template.md b/.agents/skills/truthmark-preview/support/report-template.md index bff96a9..f529f70 100644 --- a/.agents/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 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.0. Rerun truthmark init after upgrades. Report completion in this shape: ```md @@ -19,14 +19,16 @@ Why this workflow: Likely route owner: - route file: docs/truthmark/routes/areas.md -- truth doc: docs/truthmark/truth/example.md +- likely lane impact: engineering-lane +- product target docs: none identified +- engineering target docs: docs/truthmark/engineering/behaviors/example.md - confidence: medium Expected write classes: - truth docs Expected target files: -- docs/truthmark/truth/example.md +- docs/truthmark/engineering/behaviors/example.md Suggested subagent use: - read-only verifiers: truth_route_auditor diff --git a/.agents/skills/truthmark-preview/support/subagents-and-leases.md b/.agents/skills/truthmark-preview/support/subagents-and-leases.md index 0b91ede..e624bbb 100644 --- a/.agents/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 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.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/.agents/skills/truthmark-realize/SKILL.md b/.agents/skills/truthmark-realize/SKILL.md index 8256b8e..2c479a7 100644 --- a/.agents/skills/truthmark-realize/SKILL.md +++ b/.agents/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: 2.1.0 +truthmark-version: 2.2.0 --- # Truthmark Realize diff --git a/.agents/skills/truthmark-realize/agents/openai.yaml b/.agents/skills/truthmark-realize/agents/openai.yaml index b5bbffa..6b9d61b 100644 --- a/.agents/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: "2.1.0" + version: "2.2.0" refresh_command: "truthmark init" diff --git a/.agents/skills/truthmark-realize/support/procedure.md b/.agents/skills/truthmark-realize/support/procedure.md index c419a77..5b3ba33 100644 --- a/.agents/skills/truthmark-realize/support/procedure.md +++ b/.agents/skills/truthmark-realize/support/procedure.md @@ -1,6 +1,6 @@ # Truthmark Realize Procedure -Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.0. Rerun truthmark init after upgrades. # Truthmark Realize @@ -33,7 +33,8 @@ Truthmark hierarchy hints: - Config, when present: .truthmark/config.yml - 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 +- Product truth docs, when present: docs/truthmark/product/**/*.md +- Engineering truth docs, when present: docs/truthmark/engineering/**/*.md Read and write boundaries: diff --git a/.agents/skills/truthmark-realize/support/report-template.md b/.agents/skills/truthmark-realize/support/report-template.md index b540f61..246d9cf 100644 --- a/.agents/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 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.0. Rerun truthmark init after upgrades. Report completion in this shape: @@ -8,7 +8,8 @@ Report completion in this shape: Truth Realize: completed Truth docs used: -- docs/truthmark/truth/authentication/session-timeout.md +- docs/truthmark/product/capabilities/authentication-session.md +- docs/truthmark/engineering/behaviors/authentication-session.md Code updated: - src/auth/session.ts diff --git a/.agents/skills/truthmark-structure/SKILL.md b/.agents/skills/truthmark-structure/SKILL.md index 4e0d2ab..7c88c52 100644 --- a/.agents/skills/truthmark-structure/SKILL.md +++ b/.agents/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: 2.1.0 +truthmark-version: 2.2.0 --- # Truthmark Structure diff --git a/.agents/skills/truthmark-structure/agents/openai.yaml b/.agents/skills/truthmark-structure/agents/openai.yaml index 3e5ec08..afa75d5 100644 --- a/.agents/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: "2.1.0" + version: "2.2.0" refresh_command: "truthmark init" diff --git a/.agents/skills/truthmark-structure/support/procedure.md b/.agents/skills/truthmark-structure/support/procedure.md index 5112d6e..34f4e41 100644 --- a/.agents/skills/truthmark-structure/support/procedure.md +++ b/.agents/skills/truthmark-structure/support/procedure.md @@ -1,29 +1,38 @@ # Truthmark Structure Procedure -Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.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. 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. +- Evidence authority: + - 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. +- Lane classification: + - before writing canonical truth docs, classify the request or change as product-lane, engineering-lane, both-lane, or ambiguous + - product-lane writes belong under docs/truthmark/product and state product promises, boundaries, rationale, decisions, and success criteria + - engineering-lane writes belong under docs/truthmark/engineering and state source-backed current realization, contracts, architecture, workflows, operations, or tests + - both-lane work must write separate product and engineering docs and cross-link them in route YAML with realized_by and realizes, not in doc frontmatter + - ambiguous lane ownership must block or invoke Truth Structure instead of writing a mixed document + - Do not make product docs a summary of engineering docs. Do not make engineering docs a detailed version of product docs. Product truth says what must be true and why. Engineering truth says how the repository currently realizes it. - 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/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. +- Starter truth docs must use closed YAML frontmatter bounded by opening and closing --- lines; include status, truth_kind, and last_reviewed inside that frontmatter. Put source references in the final ## Source References section, not in frontmatter. +- Starter truth docs must use lane-specific templates and keep product and engineering truth in separate files. 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. +Supported kinds: product-capability, engineering-behavior, engineering-contract, engineering-architecture, engineering-workflow, engineering-operations, and engineering-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. +If the template is missing, use lane-specific sections: product truth says what must be true and why; engineering truth says how the repository currently realizes it. 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 docs/truthmark/product/** for product truth destinations +- use docs/truthmark/engineering/** for engineering 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 +- keep active Product Decisions in product truth and Engineering Decisions in engineering truth - preserve unrelated authored content ## New area setup Use when a user asks to onboard a new code area into Truthmark, a new package, controller, domain, or product area lacks bounded truth ownership, or a new product area needs routing and starter truth docs. @@ -41,7 +50,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/truthmark/truth. Treat the configured truth root as a managed semantic root. +Truth Structure owns documentation topology, lane splits, decision relocation, and relationship repair. Do not depend on humans to manually organize docs/truthmark/product or docs/truthmark/engineering. Treat both configured lane roots as managed semantic roots. 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: @@ -49,17 +58,17 @@ Truth-doc ownership gate: - if a target/source doc mixes independent owners, spans unrelated behaviors, acts as an index, or needs cross-owner edits, do not patch or in-place repair it - if a truth doc mixes independent owners, route ownership is broad, or a split is required for bounded ownership, split and reroute into bounded truth docs when safe; otherwise block with manual-review files - report Ownership reviewed, Structure required, Truth docs split, Truth docs restructured, or Blocked reason as applicable -Product Decisions/Rationale preservation gate: -- before any truth-doc split, restructure, or shape repair, inventory existing Product Decisions and Rationale sections in every source or touched truth doc -- preserve each current decision and rationale in the bounded owner doc it governs; when splitting, move it to the new owner doc rather than deleting it or leaving it in an index +Decision/Rationale preservation gate: +- before any truth-doc split, restructure, or shape repair, inventory existing Product Decisions, Engineering Decisions, and Rationale sections in every source or touched truth doc +- preserve each current decision and rationale in the correct product or engineering lane owner; when splitting, move it to the new owner doc rather than deleting it or leaving it in an index - 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 +- after the edit, verify every touched truth doc keeps lane-appropriate decision/rationale sections and every pre-existing entry is preserved, moved, narrowed, removed with evidence, or blocked Topology pressure signals: - one area maps broad code such as src/**, app/**, server/**, services/**, or packages/** - one area maps multiple unrelated controllers, route groups, services, or bounded contexts - one truth doc owns unrelated behaviors or unrelated endpoint families -- the configured truth root has many direct non-index docs +- either configured lane 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/routes/areas/** @@ -72,9 +81,10 @@ 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/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 +- create engineering behavior truth docs under docs/truthmark/engineering only when behavior lacks a current doc +- create product truth docs under docs/truthmark/product only when product promise, boundary, rationale, or user-visible capability truth is in scope - README.md files are indexes, not Truth Sync targets -- prefer bounded leaf truth docs at //.md +- prefer bounded product docs under product/capabilities or product/decisions and engineering docs under engineering//.md - keep behavior truth docs behavior-oriented, not endpoint-oriented - keep API endpoint details in the nearest contract truth doc when such a doc exists - update routing so future Truth Sync can target small docs @@ -88,13 +98,13 @@ Truth-doc shape repair gate: - preserve supported claims; remove, narrow, or block unsupported or stale claims - report docs restructured and why a narrow edit was not sufficient Evidence Gate: -- apply the Evidence Gate before finishing when Truth Structure writes routed docs, ownership claims, Product Decisions, or Rationale +- apply the Evidence Gate before finishing when Truth Structure writes routed docs, ownership claims, lane-specific decisions, or rationale - support ownership/behavior claims with topology or primary checkout evidence from layout, implementation boundaries, docs, config, route files, tests, templates, schemas, or contracts - tests/examples/canonical docs corroborate; remove, narrow, or block unsupported claims Maintain architecture docs only for structure-level changes: system structure, module boundaries, runtime topology, persistence boundaries, cross-cutting contracts, or generated-surface ownership. Keep ordinary behavior, endpoints, UI copy, validation rules, and bug fixes in behavior or contract docs unless they change those boundaries. -- Do not finish topology repair with routed canonical current-truth docs missing Product Decisions or Rationale sections. -- If an existing canonical doc lacks either section, add the missing heading beside Current Behavior with a concise current-state placeholder or active decision. +- Do not finish topology repair with mixed product/engineering authority in a single canonical truth doc. +- If an existing canonical doc has wrong-lane sections, split or move them into the correct product or engineering lane. Portable fallback: - If this skill surface is unavailable, perform the same workflow directly from committed repository files. - Do not require the truthmark CLI. @@ -104,7 +114,8 @@ Truthmark hierarchy hints: - Config, when present: .truthmark/config.yml - 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 +- Product truth docs, when present: docs/truthmark/product/**/*.md +- Engineering truth docs, when present: docs/truthmark/engineering/**/*.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. +Product decisions belong in product truth; engineering, architecture, contract, workflow, and operational decisions belong in engineering truth. diff --git a/.agents/skills/truthmark-structure/support/report-template.md b/.agents/skills/truthmark-structure/support/report-template.md index 1be260b..7d1ae37 100644 --- a/.agents/skills/truthmark-structure/support/report-template.md +++ b/.agents/skills/truthmark-structure/support/report-template.md @@ -1,13 +1,14 @@ # Truthmark Structure Report Template -Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.0. Rerun truthmark init after upgrades. Report completion in this shape: ```md Truth Structure: completed Topology reviewed: - controllers: src/auth/** -- docs root: docs/truthmark/truth +- product docs root: docs/truthmark/product +- engineering docs root: docs/truthmark/engineering - route files: docs/truthmark/routes/areas.md Areas reviewed: - src/auth/** @@ -16,12 +17,14 @@ Routing updated: Initial truth boundary: - Area: Authentication - Code: src/auth/** -- Truth owner: docs/truthmark/truth/authentication/session.md +- Product owner: docs/truthmark/product/capabilities/authentication-session.md +- Engineering owner: docs/truthmark/engineering/behaviors/authentication-session.md - Scope: session behavior only Truth docs created: -- docs/truthmark/truth/authentication/session.md +- docs/truthmark/product/capabilities/authentication-session.md +- docs/truthmark/engineering/behaviors/authentication-session.md Truth docs split: -- docs/truthmark/truth/authentication/README.md -> docs/truthmark/truth/authentication/session.md +- docs/truthmark/truth/authentication/README.md -> docs/truthmark/product/capabilities/authentication-session.md and docs/truthmark/engineering/behaviors/authentication-session.md Truth docs restructured: - docs/truthmark/truth/authentication/README.md Evidence checked: diff --git a/.agents/skills/truthmark-structure/support/subagents-and-leases.md b/.agents/skills/truthmark-structure/support/subagents-and-leases.md index a5b4f52..02b827d 100644 --- a/.agents/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 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.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/.agents/skills/truthmark-sync/SKILL.md b/.agents/skills/truthmark-sync/SKILL.md index ff1d4eb..bc5514e 100644 --- a/.agents/skills/truthmark-sync/SKILL.md +++ b/.agents/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: 2.1.0 +truthmark-version: 2.2.0 --- # Truthmark Sync diff --git a/.agents/skills/truthmark-sync/agents/openai.yaml b/.agents/skills/truthmark-sync/agents/openai.yaml index acb82ec..7985171 100644 --- a/.agents/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: "2.1.0" + version: "2.2.0" refresh_command: "truthmark init" diff --git a/.agents/skills/truthmark-sync/helper-manifest.yml b/.agents/skills/truthmark-sync/helper-manifest.yml index dd0153a..1f9a1f1 100644 --- a/.agents/skills/truthmark-sync/helper-manifest.yml +++ b/.agents/skills/truthmark-sync/helper-manifest.yml @@ -1,8 +1,8 @@ -# Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. +# Generated by Truthmark 2.2.0. Rerun truthmark init after upgrades. helpers: validate-sync-report: optional: true - runner: truthmark>=2.1.0 + runner: truthmark>=2.2.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>=2.1.0 + runner: truthmark>=2.2.0 command: argv: - truthmark diff --git a/.agents/skills/truthmark-sync/support/helper-policy.md b/.agents/skills/truthmark-sync/support/helper-policy.md index 6c44128..885d6a1 100644 --- a/.agents/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 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.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>=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 +- validate-sync-report: optional truthmark>=2.2.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.2.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/.agents/skills/truthmark-sync/support/procedure.md b/.agents/skills/truthmark-sync/support/procedure.md index ff0f6f7..3026dce 100644 --- a/.agents/skills/truthmark-sync/support/procedure.md +++ b/.agents/skills/truthmark-sync/support/procedure.md @@ -1,6 +1,6 @@ # Truthmark Sync Procedure -Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.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. @@ -10,10 +10,19 @@ Parent workflow: 1. Inspect git status, staged changes, unstaged changes, and untracked files directly. 2. Inspect .truthmark/config.yml and configured route files only when they exist; then inspect relevant canonical docs. 3. Identify functional-code changes and the nearest truth docs or routing repairs. -4. 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. -5. Code verification is parent-owned: follow repository instructions and task context, and report what ran or why it did not run. -6. Dispatch bounded Truth Sync workers only when the host supports subagent dispatch and the acting agent chooses that path; otherwise execute the same sync task inline. +4. Evidence authority: + - 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. +5. Lane classification gate: + - before writing canonical truth docs, classify the request or change as product-lane, engineering-lane, both-lane, or ambiguous + - product-lane writes belong under docs/truthmark/product and state product promises, boundaries, rationale, decisions, and success criteria + - engineering-lane writes belong under docs/truthmark/engineering and state source-backed current realization, contracts, architecture, workflows, operations, or tests + - both-lane work must write separate product and engineering docs and cross-link them in route YAML with realized_by and realizes, not in doc frontmatter + - ambiguous lane ownership must block or invoke Truth Structure instead of writing a mixed document + - Do not make product docs a summary of engineering docs. Do not make engineering docs a detailed version of product docs. Product truth says what must be true and why. Engineering truth says how the repository currently realizes it. +6. Update engineering truth first after code changes. Update product truth only when implemented user-visible product promise or capability boundary changed and explicit source/user evidence supports it; otherwise report product-lane review needed. +7. Code verification is parent-owned: follow repository instructions and task context, and report what ran or why it did not run. +8. Dispatch bounded Truth Sync workers only when the host supports subagent dispatch and the acting agent chooses that path; otherwise execute the same sync task inline. Topology quality gate: - before updating truth docs, verify the changed code resolves to a specific behavior-owned area and bounded truth owner - if routing is missing, stale, broad, overloaded, catch-all route only, or cannot map changed code to a bounded truth owner, do not create another generic truth doc @@ -23,22 +32,23 @@ Topology quality gate: - README.md files are indexes, not Truth Sync targets - must not append behavior details to a README.md index - create or update a bounded leaf truth doc when behavior changes do not fit an existing leaf doc +- write engineering truth under docs/truthmark/engineering; product truth updates under docs/truthmark/product are allowed only for explicit current product behavior changes Truth-doc ownership gate: - before editing or relying on changed functional files and impacted truth docs, verify each target/source truth doc is a bounded owner for the behavior - if a target/source doc mixes independent owners, spans unrelated behaviors, acts as an index, or needs cross-owner edits, do not patch or in-place repair it - if an impacted doc is broad, mixed-owner, index-like, or the update spans independent behavior owners, run Truth Structure before syncing when safe and in scope; otherwise block and recommend Truth Structure - report Ownership reviewed, Structure required, Truth docs split, Truth docs restructured, or Blocked reason as applicable -Product Decisions/Rationale preservation gate: -- before any truth-doc split, restructure, or shape repair, inventory existing Product Decisions and Rationale sections in every source or touched truth doc -- preserve each current decision and rationale in the bounded owner doc it governs; when splitting, move it to the new owner doc rather than deleting it or leaving it in an index +Decision/Rationale preservation gate: +- before any truth-doc split, restructure, or shape repair, inventory existing Product Decisions, Engineering Decisions, and Rationale sections in every source or touched truth doc +- preserve each current decision and rationale in the correct product or engineering lane owner; when splitting, move it to the new owner doc rather than deleting it or leaving it in an index - 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 +- after the edit, verify every touched truth doc keeps lane-appropriate decision/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 template under the configured Truthmark templates root. -Supported kinds: behavior, contract, architecture, workflow, operations, and test-behavior. +Supported kinds: product-capability, engineering-behavior, engineering-contract, engineering-architecture, engineering-workflow, engineering-operations, and engineering-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. +If the template is missing, use lane-specific sections: product truth says what must be true and why; engineering truth says how the repository currently realizes it. 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. @@ -51,7 +61,7 @@ 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. Evidence Gate: - route-first: map changed functional files to bounded route owners and primary canonical docs -- review new or changed behavior-bearing claims only in touched docs, route ownership, Product Decisions, and Rationale +- review new or changed behavior-bearing claims only in touched docs, route ownership, lane-specific decisions, and rationale - support claims with primary checkout evidence: implementation, config, routing, generated templates, schemas, or contract definitions - tests/examples/canonical docs corroborate; they are not sole proof when implementation conflicts - remove, narrow, or block unsupported claims @@ -63,7 +73,7 @@ Optional validation tooling: - you may run truthmark check when local tooling is available - do not require the truthmark binary; direct checkout inspection is the canonical path - optional validation must not replace agent judgment about docs and routing -- update Product Decisions and Rationale when a behavior change comes from a decision change +- update Product Decisions only in product truth and Engineering Decisions only in engineering truth when evidence supports the lane-specific decision change Helper status reporting: - Validate the report body before adding this validator's own success status; the body may omit `validate-sync-report` while validation is pending. - After `truthmark validate sync-report --json` returns `data.validation.ok: true`, append or update `validate-sync-report: ran, passed` in the final report. @@ -74,10 +84,11 @@ Truthmark hierarchy hints: - Config, when present: .truthmark/config.yml - 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 +- Product truth docs, when present: docs/truthmark/product/**/*.md +- Engineering truth docs, when present: docs/truthmark/engineering/**/*.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. +Product decisions belong in product truth; engineering, architecture, contract, workflow, and operational decisions belong in engineering truth. Parent post-sync verification: - verify only truth docs and leased truth routing files changed during sync - block on any unrelated diff caused by the sync step diff --git a/.agents/skills/truthmark-sync/support/report-template.md b/.agents/skills/truthmark-sync/support/report-template.md index 4dfa42d..5331249 100644 --- a/.agents/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 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.0. Rerun truthmark init after upgrades. Report completion in this shape: ```md @@ -13,7 +13,7 @@ Ownership reviewed: - docs/truthmark/routes/areas.md Truth docs updated: -- docs/truthmark/truth/repository/overview.md +- docs/truthmark/engineering/repository/overview.md Evidence checked: - Claim: Session timeout behavior is documented in the mapped repository truth doc. diff --git a/.agents/skills/truthmark-sync/support/subagents-and-leases.md b/.agents/skills/truthmark-sync/support/subagents-and-leases.md index d29ded4..e7dfac8 100644 --- a/.agents/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 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.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 8b64222..58d4c25 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 2.1.0. Rerun truthmark init after upgrades. +# Generated by Truthmark 2.2.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 c841e51..8322689 100644 --- a/.claude/agents/truth-doc-reviewer.md +++ b/.claude/agents/truth-doc-reviewer.md @@ -4,12 +4,12 @@ description: Read-only Truthmark doc reviewer for shape, decision, rationale, an tools: Read, Grep, Glob, LS --- -# Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. +# Generated by Truthmark 2.2.0. Rerun truthmark init after upgrades. Manual invocation: use the truth-doc-reviewer subagent. Stay read-only. -Review assigned canonical truth docs for frontmatter, source_of_truth, required template sections, Evidence checked entries, Product Decisions, and Rationale. +Review assigned canonical truth docs for compact frontmatter, required template sections, final Source References entries, Evidence checked entries, and lane-appropriate decision sections (Product Decisions in product truth, Engineering Decisions in engineering truth). Flag README.md files used as behavior truth targets, mixed-owner docs, and shape repairs that should move to Truth Structure. Do not edit files, stage changes, or rewrite docs. Return JSON only with keys: scope, filesReviewed, findings, evidence, confidence, recommendedWorkflow, notes. diff --git a/.claude/agents/truth-doc-writer.md b/.claude/agents/truth-doc-writer.md index 6cd79d5..2742768 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 2.1.0. Rerun truthmark init after upgrades. +# Generated by Truthmark 2.2.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 9a194b6..a697676 100644 --- a/.claude/agents/truth-route-auditor.md +++ b/.claude/agents/truth-route-auditor.md @@ -4,14 +4,21 @@ description: Read-only Truthmark route auditor for bounded routing and ownership tools: Read, Grep, Glob, LS --- -# Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. +# Generated by Truthmark 2.2.0. Rerun truthmark init after upgrades. Manual invocation: use the truth-route-auditor subagent. Stay read-only. Audit one bounded Truthmark route, area, or doc shard assigned by the parent. Inspect .truthmark/config.yml and route files only when they exist; then inspect mapped truth docs and relevant implementation files directly. +Use a route-first bounded strategy: narrow audits inspect only the routed area and directly linked counterpart docs; root-wide health first builds a cheap route-map/index from route files, then inspects only mismatches and linked leaves. Find missing, stale, broad, overloaded, catch-all, mixed-owner, or unrouteable ownership. +Validate route ownership against lane-specific roots and route kind: +- confirm mapped truth docs resolve to the correct lane root (product or engineering) for their kind +- flag mismatch between assigned route kind and resolved doc kind (for example, product-capability routed to engineering paths) +- verify route-doc linkage for lane pairings via realized_by and realizes before recommending edits +- inspect product counterparts for engineering docs only when route YAML claims a product relationship, or when the parent explicitly asks for user-visible product coverage +- treat missing product links for user-visible engineering docs as a second-pass diagnostic, not a default full-document read. Do not edit files, stage changes, or propose broad rewrites. Return JSON only with keys: scope, filesReviewed, findings, evidence, confidence, recommendedWorkflow, notes. recommendedWorkflow must be one of: none, truthmark-document, truthmark-structure. diff --git a/.claude/skills/truthmark-check/SKILL.md b/.claude/skills/truthmark-check/SKILL.md index b8b5902..4f52656 100644 --- a/.claude/skills/truthmark-check/SKILL.md +++ b/.claude/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: 2.1.0 +truthmark-version: 2.2.0 --- # Truthmark Check diff --git a/.claude/skills/truthmark-check/support/procedure.md b/.claude/skills/truthmark-check/support/procedure.md index 6132ff9..c8c76bd 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 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.0. Rerun truthmark init after upgrades. # Truthmark Check @@ -11,13 +11,31 @@ Invocations: OpenCode /skill truthmark-check; Codex /truthmark-check or $truthma 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/routes/areas.md and relevant child route files under docs/truthmark/routes/areas/ when they exist +- Evidence authority: + - 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. +- Lane classification: + - classify the request or changed surface as product-lane, engineering-lane, both-lane, or ambiguous for reporting only + - product-lane ownership belongs under docs/truthmark/product and describes product promises, boundaries, rationale, decisions, and success criteria + - engineering-lane ownership belongs under docs/truthmark/engineering and describes source-backed current realization, contracts, architecture, workflows, operations, or tests + - both-lane ownership uses separate product and engineering docs cross-linked in route YAML with realized_by and realizes, not in doc frontmatter + - ambiguous lane ownership should be reported as blocked or routed to Truth Structure + - Do not make product docs a summary of engineering docs. Do not make engineering docs a detailed version of product docs. Product truth says what must be true and why. Engineering truth says how the repository currently realizes it. - check that current docs describe current code rather than historical plans +- keep lane and cross-lane checks route-first and bounded: + - for a narrow audit, inspect only the routed area and directly linked counterpart docs + - for root-wide truth health, first build a cheap route-map/index from route files, then inspect only mismatches and linked leaves + - inspect product counterparts for engineering docs only when route YAML claims a product relationship, or when the user explicitly asks for user-visible product coverage +- check lane root/kind alignment for product truth under docs/truthmark/product and engineering truth under docs/truthmark/engineering +- check route YAML cross-lane realized_by and realizes links for existence and lane compatibility +- report missing product links for user-visible engineering docs only as a second-pass review diagnostic, not as default full-document reads or hard errors +- check product docs do not contain engineering execution flow, generated file inventories, or CLI envelope mechanics +- check engineering docs do not contain product promises, product rationale, or Product Decisions sections +- never judge whether a product decision is commercially correct, valuable, prioritized, or desirable - 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 -- check that canonical behavior docs keep active Product Decisions and Rationale sections +- check that canonical docs keep lane-appropriate decisions and rationale sections - optionally run truthmark check when local tooling is available - must not require the truthmark binary; direct inspection is always valid - report issues and suggested fixes without silently rewriting unrelated files @@ -31,7 +49,8 @@ Truthmark hierarchy hints: - Config, when present: .truthmark/config.yml - 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 +- Product truth docs, when present: docs/truthmark/product/**/*.md +- Engineering truth docs, when present: docs/truthmark/engineering/**/*.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. +Product decisions belong in product truth; engineering, architecture, contract, workflow, and operational decisions belong in engineering truth. diff --git a/.claude/skills/truthmark-check/support/report-template.md b/.claude/skills/truthmark-check/support/report-template.md index 00a3453..435fdfa 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 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.0. Rerun truthmark init after upgrades. Report completion in this shape: diff --git a/.claude/skills/truthmark-check/support/subagents-and-leases.md b/.claude/skills/truthmark-check/support/subagents-and-leases.md index 29ad47b..f7b7bcd 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 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.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 241a841..d238539 100644 --- a/.claude/skills/truthmark-document/SKILL.md +++ b/.claude/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: 2.1.0 +truthmark-version: 2.2.0 --- # Truthmark Document diff --git a/.claude/skills/truthmark-document/helper-manifest.yml b/.claude/skills/truthmark-document/helper-manifest.yml index 175e1a0..1763234 100644 --- a/.claude/skills/truthmark-document/helper-manifest.yml +++ b/.claude/skills/truthmark-document/helper-manifest.yml @@ -1,8 +1,8 @@ -# Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. +# Generated by Truthmark 2.2.0. Rerun truthmark init after upgrades. helpers: validate-document-report: optional: true - runner: truthmark>=2.1.0 + runner: truthmark>=2.2.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>=2.1.0 + runner: truthmark>=2.2.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 2cb7bd6..58bcb56 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 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.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>=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 +- validate-document-report: optional truthmark>=2.2.0; manual fallback: manually validate support/report-template.md required sections and structured Evidence checked entries +- validate-write-lease: optional truthmark>=2.2.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 be8590f..b787061 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 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.0. Rerun truthmark init after upgrades. # Truthmark Document @@ -11,8 +11,16 @@ Truth Document is manual and implementation-first: - run only when the user explicitly asks to generate or update truth docs for existing behavior, or when Truth Sync, Truth Check, or Truth Structure reports implemented behavior that lacks canonical truth docs - inspect .truthmark/config.yml and configured route files only when they exist; then inspect existing canonical docs, implementation code, and tests 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. +- Evidence authority: + - 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. +- Lane classification: + - before writing canonical truth docs, classify the request or change as product-lane, engineering-lane, both-lane, or ambiguous + - product-lane writes belong under docs/truthmark/product and state product promises, boundaries, rationale, decisions, and success criteria + - engineering-lane writes belong under docs/truthmark/engineering and state source-backed current realization, contracts, architecture, workflows, operations, or tests + - both-lane work must write separate product and engineering docs and cross-link them in route YAML with realized_by and realizes, not in doc frontmatter + - ambiguous lane ownership must block or invoke Truth Structure instead of writing a mixed document + - Do not make product docs a summary of engineering docs. Do not make engineering docs a detailed version of product docs. Product truth says what must be true and why. Engineering truth says how the repository currently realizes it. - document current implemented behavior; do not invent future behavior or planned endpoints - may write canonical truth docs and docs/truthmark/routes/areas.md or relevant child route files only - must not write functional code @@ -20,7 +28,10 @@ Implementation code and canonical truth docs are inspected evidence for current - block and recommend Truth Structure when routing repair is unsafe, ambiguous, or outside the task boundary - keep feature README.md files as indexes rather than truth-document targets - create or update bounded leaf truth docs when behavior does not fit an existing leaf doc -- keep behavior truth docs behavior-oriented, not endpoint-oriented, unless the endpoint itself is the behavior boundary +- write product capability/boundary truth under docs/truthmark/product when documenting product promise, boundary, rationale, or user/stakeholder value +- write engineering truth under docs/truthmark/engineering when documenting implementation behavior, contracts, architecture, workflows, operations, or tests +- for both-lane documentation requests, write separate product and engineering docs and cross-link them in route YAML with realized_by and realizes, not in doc frontmatter +- keep engineering behavior truth behavior-oriented, not endpoint-oriented, unless the endpoint itself is the behavior boundary - keep API endpoint details in the nearest contract truth doc when such a doc owns the API contract - preserve unrelated authored content Truth-doc ownership gate: @@ -28,15 +39,15 @@ Truth-doc ownership gate: - if a target/source doc mixes independent owners, spans unrelated behaviors, acts as an index, or needs cross-owner edits, do not patch or in-place repair it - if the target doc is broad, mixed-owner, index-like, or the documented behavior spans independent owners, run Truth Structure first when safe and in scope; otherwise block and recommend Truth Structure - report Ownership reviewed, Structure required, Truth docs split, Truth docs restructured, or Blocked reason as applicable -Product Decisions/Rationale preservation gate: -- before any truth-doc split, restructure, or shape repair, inventory existing Product Decisions and Rationale sections in every source or touched truth doc -- preserve each current decision and rationale in the bounded owner doc it governs; when splitting, move it to the new owner doc rather than deleting it or leaving it in an index +Decision/Rationale preservation gate: +- before any truth-doc split, restructure, or shape repair, inventory existing Product Decisions, Engineering Decisions, and Rationale sections in every source or touched truth doc +- preserve each current decision and rationale in the correct product or engineering lane owner; when splitting, move it to the new owner doc rather than deleting it or leaving it in an index - 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 +- after the edit, verify every touched truth doc keeps lane-appropriate decision/rationale sections and every pre-existing entry is preserved, moved, narrowed, removed with evidence, or blocked Evidence Gate: - route-first: map the documented behavior to bounded route owners and primary canonical docs -- review new or changed behavior-bearing claims only in touched docs, route ownership, Product Decisions, and Rationale +- review new or changed behavior-bearing claims only in touched docs, route ownership, lane-specific decisions, and rationale - support claims with primary checkout evidence: implementation, config, routing, generated templates, schemas, or contract definitions - tests/examples/canonical docs corroborate; they are not sole proof when implementation conflicts - remove, narrow, or block unsupported claims @@ -45,10 +56,10 @@ Repository intelligence artifacts are optional derived context: RepoIndex, Route 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 template under the configured Truthmark templates root. -Supported kinds: behavior, contract, architecture, workflow, operations, and test-behavior. +Supported kinds: product-capability, engineering-behavior, engineering-contract, engineering-architecture, engineering-workflow, engineering-operations, and engineering-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. +If the template is missing, use lane-specific sections: product truth says what must be true and why; engineering truth says how the repository currently realizes it. 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. @@ -63,10 +74,11 @@ Truthmark hierarchy hints: - Config, when present: .truthmark/config.yml - 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 +- Product truth docs, when present: docs/truthmark/product/**/*.md +- Engineering truth docs, when present: docs/truthmark/engineering/**/*.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. +Product decisions belong in product truth; engineering, architecture, contract, workflow, and operational decisions belong in engineering truth. Helper status reporting: - Validate the report body before adding this validator's own success status; the body may omit `validate-document-report` while validation is pending. - After `truthmark validate document-report --json` returns `data.validation.ok: true`, append or update `validate-document-report: ran, passed` in the final report. diff --git a/.claude/skills/truthmark-document/support/report-template.md b/.claude/skills/truthmark-document/support/report-template.md index 5e38b92..6673f6a 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 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.0. Rerun truthmark init after upgrades. Report completion in this shape: ```md @@ -13,13 +13,13 @@ Ownership reviewed: - docs/truthmark/routes/areas.md Truth docs created: -- docs/truthmark/truth/contracts.md +- docs/truthmark/engineering/contracts/routing.md Truth docs updated: -- docs/truthmark/truth/check-diagnostics.md +- docs/truthmark/engineering/behaviors/check-diagnostics.md Truth docs restructured: -- docs/truthmark/truth/check-diagnostics.md +- docs/truthmark/engineering/behaviors/check-diagnostics.md Routing updated: - docs/truthmark/routes/areas.md diff --git a/.claude/skills/truthmark-document/support/subagents-and-leases.md b/.claude/skills/truthmark-document/support/subagents-and-leases.md index 08313b3..7e679d0 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 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.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 7db8d92..ae61cf9 100644 --- a/.claude/skills/truthmark-preview/SKILL.md +++ b/.claude/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: 2.1.0 +truthmark-version: 2.2.0 --- # Truthmark Preview @@ -14,7 +14,7 @@ Invocations: OpenCode /skill truthmark-preview; Codex /truthmark-preview or $tru 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/routes/areas.md; docs/truthmark/routes/areas/) only when they exist; then inspect only the truth docs or implementation files needed to preview ownership. +- Inspect .truthmark/config.yml and the root route index (docs/truthmark/routes/areas.md) first when present; then inspect only child route files under docs/truthmark/routes/areas/ that are relevant to the selected scope or changed paths, plus 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. diff --git a/.claude/skills/truthmark-preview/support/procedure.md b/.claude/skills/truthmark-preview/support/procedure.md index 276926b..9579a10 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 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.0. Rerun truthmark init after upgrades. Use this skill only when the user explicitly asks to preview Truthmark routing or workflow choice before edits. @@ -10,16 +10,25 @@ Truth Preview is read-only. Its report is intended, not authorized. Purpose: - preview the likely Truthmark workflow, route owner, target files, expected write classes, suggested subagent use, and blocking ambiguity before edits happen +- report likely product lane impact, engineering lane impact, target docs, and ambiguity before edits - hand off to the selected workflow after user approval - keep the selector thin so agents can avoid loading or acting through heavier workflows prematurely Read: - .truthmark/config.yml, only when present -- docs/truthmark/routes/areas.md, only when present -- relevant child route files under docs/truthmark/routes/areas/, only when present +- docs/truthmark/routes/areas.md, first, only when present +- relevant child route files under docs/truthmark/routes/areas/ for the selected scope or changed paths, 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. +- Evidence authority: + - 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. +- Lane classification: + - classify the request or changed surface as product-lane, engineering-lane, both-lane, or ambiguous for reporting only + - product-lane ownership belongs under docs/truthmark/product and describes product promises, boundaries, rationale, decisions, and success criteria + - engineering-lane ownership belongs under docs/truthmark/engineering and describes source-backed current realization, contracts, architecture, workflows, operations, or tests + - both-lane ownership uses separate product and engineering docs cross-linked in route YAML with realized_by and realizes, not in doc frontmatter + - ambiguous lane ownership should be reported as blocked or routed to Truth Structure + - Do not make product docs a summary of engineering docs. Do not make engineering docs a detailed version of product docs. Product truth says what must be true and why. Engineering truth says how the repository currently realizes it. Do not: - must not edit files @@ -40,4 +49,5 @@ Truthmark hierarchy hints: - Config, when present: .truthmark/config.yml - 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 +- Product truth docs, when present: docs/truthmark/product/**/*.md +- Engineering truth docs, when present: docs/truthmark/engineering/**/*.md diff --git a/.claude/skills/truthmark-preview/support/report-template.md b/.claude/skills/truthmark-preview/support/report-template.md index bff96a9..f529f70 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 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.0. Rerun truthmark init after upgrades. Report completion in this shape: ```md @@ -19,14 +19,16 @@ Why this workflow: Likely route owner: - route file: docs/truthmark/routes/areas.md -- truth doc: docs/truthmark/truth/example.md +- likely lane impact: engineering-lane +- product target docs: none identified +- engineering target docs: docs/truthmark/engineering/behaviors/example.md - confidence: medium Expected write classes: - truth docs Expected target files: -- docs/truthmark/truth/example.md +- docs/truthmark/engineering/behaviors/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 cfbffe3..cf9028f 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 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.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 8256b8e..2c479a7 100644 --- a/.claude/skills/truthmark-realize/SKILL.md +++ b/.claude/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: 2.1.0 +truthmark-version: 2.2.0 --- # Truthmark Realize diff --git a/.claude/skills/truthmark-realize/support/procedure.md b/.claude/skills/truthmark-realize/support/procedure.md index c419a77..5b3ba33 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 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.0. Rerun truthmark init after upgrades. # Truthmark Realize @@ -33,7 +33,8 @@ Truthmark hierarchy hints: - Config, when present: .truthmark/config.yml - 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 +- Product truth docs, when present: docs/truthmark/product/**/*.md +- Engineering truth docs, when present: docs/truthmark/engineering/**/*.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 b540f61..246d9cf 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 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.0. Rerun truthmark init after upgrades. Report completion in this shape: @@ -8,7 +8,8 @@ Report completion in this shape: Truth Realize: completed Truth docs used: -- docs/truthmark/truth/authentication/session-timeout.md +- docs/truthmark/product/capabilities/authentication-session.md +- docs/truthmark/engineering/behaviors/authentication-session.md Code updated: - src/auth/session.ts diff --git a/.claude/skills/truthmark-structure/SKILL.md b/.claude/skills/truthmark-structure/SKILL.md index 4e0d2ab..7c88c52 100644 --- a/.claude/skills/truthmark-structure/SKILL.md +++ b/.claude/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: 2.1.0 +truthmark-version: 2.2.0 --- # Truthmark Structure diff --git a/.claude/skills/truthmark-structure/support/procedure.md b/.claude/skills/truthmark-structure/support/procedure.md index 5112d6e..34f4e41 100644 --- a/.claude/skills/truthmark-structure/support/procedure.md +++ b/.claude/skills/truthmark-structure/support/procedure.md @@ -1,29 +1,38 @@ # Truthmark Structure Procedure -Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.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. 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. +- Evidence authority: + - 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. +- Lane classification: + - before writing canonical truth docs, classify the request or change as product-lane, engineering-lane, both-lane, or ambiguous + - product-lane writes belong under docs/truthmark/product and state product promises, boundaries, rationale, decisions, and success criteria + - engineering-lane writes belong under docs/truthmark/engineering and state source-backed current realization, contracts, architecture, workflows, operations, or tests + - both-lane work must write separate product and engineering docs and cross-link them in route YAML with realized_by and realizes, not in doc frontmatter + - ambiguous lane ownership must block or invoke Truth Structure instead of writing a mixed document + - Do not make product docs a summary of engineering docs. Do not make engineering docs a detailed version of product docs. Product truth says what must be true and why. Engineering truth says how the repository currently realizes it. - 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/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. +- Starter truth docs must use closed YAML frontmatter bounded by opening and closing --- lines; include status, truth_kind, and last_reviewed inside that frontmatter. Put source references in the final ## Source References section, not in frontmatter. +- Starter truth docs must use lane-specific templates and keep product and engineering truth in separate files. 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. +Supported kinds: product-capability, engineering-behavior, engineering-contract, engineering-architecture, engineering-workflow, engineering-operations, and engineering-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. +If the template is missing, use lane-specific sections: product truth says what must be true and why; engineering truth says how the repository currently realizes it. 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 docs/truthmark/product/** for product truth destinations +- use docs/truthmark/engineering/** for engineering 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 +- keep active Product Decisions in product truth and Engineering Decisions in engineering truth - preserve unrelated authored content ## New area setup Use when a user asks to onboard a new code area into Truthmark, a new package, controller, domain, or product area lacks bounded truth ownership, or a new product area needs routing and starter truth docs. @@ -41,7 +50,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/truthmark/truth. Treat the configured truth root as a managed semantic root. +Truth Structure owns documentation topology, lane splits, decision relocation, and relationship repair. Do not depend on humans to manually organize docs/truthmark/product or docs/truthmark/engineering. Treat both configured lane roots as managed semantic roots. 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: @@ -49,17 +58,17 @@ Truth-doc ownership gate: - if a target/source doc mixes independent owners, spans unrelated behaviors, acts as an index, or needs cross-owner edits, do not patch or in-place repair it - if a truth doc mixes independent owners, route ownership is broad, or a split is required for bounded ownership, split and reroute into bounded truth docs when safe; otherwise block with manual-review files - report Ownership reviewed, Structure required, Truth docs split, Truth docs restructured, or Blocked reason as applicable -Product Decisions/Rationale preservation gate: -- before any truth-doc split, restructure, or shape repair, inventory existing Product Decisions and Rationale sections in every source or touched truth doc -- preserve each current decision and rationale in the bounded owner doc it governs; when splitting, move it to the new owner doc rather than deleting it or leaving it in an index +Decision/Rationale preservation gate: +- before any truth-doc split, restructure, or shape repair, inventory existing Product Decisions, Engineering Decisions, and Rationale sections in every source or touched truth doc +- preserve each current decision and rationale in the correct product or engineering lane owner; when splitting, move it to the new owner doc rather than deleting it or leaving it in an index - 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 +- after the edit, verify every touched truth doc keeps lane-appropriate decision/rationale sections and every pre-existing entry is preserved, moved, narrowed, removed with evidence, or blocked Topology pressure signals: - one area maps broad code such as src/**, app/**, server/**, services/**, or packages/** - one area maps multiple unrelated controllers, route groups, services, or bounded contexts - one truth doc owns unrelated behaviors or unrelated endpoint families -- the configured truth root has many direct non-index docs +- either configured lane 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/routes/areas/** @@ -72,9 +81,10 @@ 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/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 +- create engineering behavior truth docs under docs/truthmark/engineering only when behavior lacks a current doc +- create product truth docs under docs/truthmark/product only when product promise, boundary, rationale, or user-visible capability truth is in scope - README.md files are indexes, not Truth Sync targets -- prefer bounded leaf truth docs at //.md +- prefer bounded product docs under product/capabilities or product/decisions and engineering docs under engineering//.md - keep behavior truth docs behavior-oriented, not endpoint-oriented - keep API endpoint details in the nearest contract truth doc when such a doc exists - update routing so future Truth Sync can target small docs @@ -88,13 +98,13 @@ Truth-doc shape repair gate: - preserve supported claims; remove, narrow, or block unsupported or stale claims - report docs restructured and why a narrow edit was not sufficient Evidence Gate: -- apply the Evidence Gate before finishing when Truth Structure writes routed docs, ownership claims, Product Decisions, or Rationale +- apply the Evidence Gate before finishing when Truth Structure writes routed docs, ownership claims, lane-specific decisions, or rationale - support ownership/behavior claims with topology or primary checkout evidence from layout, implementation boundaries, docs, config, route files, tests, templates, schemas, or contracts - tests/examples/canonical docs corroborate; remove, narrow, or block unsupported claims Maintain architecture docs only for structure-level changes: system structure, module boundaries, runtime topology, persistence boundaries, cross-cutting contracts, or generated-surface ownership. Keep ordinary behavior, endpoints, UI copy, validation rules, and bug fixes in behavior or contract docs unless they change those boundaries. -- Do not finish topology repair with routed canonical current-truth docs missing Product Decisions or Rationale sections. -- If an existing canonical doc lacks either section, add the missing heading beside Current Behavior with a concise current-state placeholder or active decision. +- Do not finish topology repair with mixed product/engineering authority in a single canonical truth doc. +- If an existing canonical doc has wrong-lane sections, split or move them into the correct product or engineering lane. Portable fallback: - If this skill surface is unavailable, perform the same workflow directly from committed repository files. - Do not require the truthmark CLI. @@ -104,7 +114,8 @@ Truthmark hierarchy hints: - Config, when present: .truthmark/config.yml - 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 +- Product truth docs, when present: docs/truthmark/product/**/*.md +- Engineering truth docs, when present: docs/truthmark/engineering/**/*.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. +Product decisions belong in product truth; engineering, architecture, contract, workflow, and operational decisions belong in engineering truth. diff --git a/.claude/skills/truthmark-structure/support/report-template.md b/.claude/skills/truthmark-structure/support/report-template.md index 1be260b..7d1ae37 100644 --- a/.claude/skills/truthmark-structure/support/report-template.md +++ b/.claude/skills/truthmark-structure/support/report-template.md @@ -1,13 +1,14 @@ # Truthmark Structure Report Template -Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.0. Rerun truthmark init after upgrades. Report completion in this shape: ```md Truth Structure: completed Topology reviewed: - controllers: src/auth/** -- docs root: docs/truthmark/truth +- product docs root: docs/truthmark/product +- engineering docs root: docs/truthmark/engineering - route files: docs/truthmark/routes/areas.md Areas reviewed: - src/auth/** @@ -16,12 +17,14 @@ Routing updated: Initial truth boundary: - Area: Authentication - Code: src/auth/** -- Truth owner: docs/truthmark/truth/authentication/session.md +- Product owner: docs/truthmark/product/capabilities/authentication-session.md +- Engineering owner: docs/truthmark/engineering/behaviors/authentication-session.md - Scope: session behavior only Truth docs created: -- docs/truthmark/truth/authentication/session.md +- docs/truthmark/product/capabilities/authentication-session.md +- docs/truthmark/engineering/behaviors/authentication-session.md Truth docs split: -- docs/truthmark/truth/authentication/README.md -> docs/truthmark/truth/authentication/session.md +- docs/truthmark/truth/authentication/README.md -> docs/truthmark/product/capabilities/authentication-session.md and docs/truthmark/engineering/behaviors/authentication-session.md Truth docs restructured: - docs/truthmark/truth/authentication/README.md Evidence checked: diff --git a/.claude/skills/truthmark-structure/support/subagents-and-leases.md b/.claude/skills/truthmark-structure/support/subagents-and-leases.md index b7af6fd..fa8f5bd 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 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.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 ff1d4eb..bc5514e 100644 --- a/.claude/skills/truthmark-sync/SKILL.md +++ b/.claude/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: 2.1.0 +truthmark-version: 2.2.0 --- # Truthmark Sync diff --git a/.claude/skills/truthmark-sync/helper-manifest.yml b/.claude/skills/truthmark-sync/helper-manifest.yml index dd0153a..1f9a1f1 100644 --- a/.claude/skills/truthmark-sync/helper-manifest.yml +++ b/.claude/skills/truthmark-sync/helper-manifest.yml @@ -1,8 +1,8 @@ -# Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. +# Generated by Truthmark 2.2.0. Rerun truthmark init after upgrades. helpers: validate-sync-report: optional: true - runner: truthmark>=2.1.0 + runner: truthmark>=2.2.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>=2.1.0 + runner: truthmark>=2.2.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 6c44128..885d6a1 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 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.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>=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 +- validate-sync-report: optional truthmark>=2.2.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.2.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 ff0f6f7..3026dce 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 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.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. @@ -10,10 +10,19 @@ Parent workflow: 1. Inspect git status, staged changes, unstaged changes, and untracked files directly. 2. Inspect .truthmark/config.yml and configured route files only when they exist; then inspect relevant canonical docs. 3. Identify functional-code changes and the nearest truth docs or routing repairs. -4. 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. -5. Code verification is parent-owned: follow repository instructions and task context, and report what ran or why it did not run. -6. Dispatch bounded Truth Sync workers only when the host supports subagent dispatch and the acting agent chooses that path; otherwise execute the same sync task inline. +4. Evidence authority: + - 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. +5. Lane classification gate: + - before writing canonical truth docs, classify the request or change as product-lane, engineering-lane, both-lane, or ambiguous + - product-lane writes belong under docs/truthmark/product and state product promises, boundaries, rationale, decisions, and success criteria + - engineering-lane writes belong under docs/truthmark/engineering and state source-backed current realization, contracts, architecture, workflows, operations, or tests + - both-lane work must write separate product and engineering docs and cross-link them in route YAML with realized_by and realizes, not in doc frontmatter + - ambiguous lane ownership must block or invoke Truth Structure instead of writing a mixed document + - Do not make product docs a summary of engineering docs. Do not make engineering docs a detailed version of product docs. Product truth says what must be true and why. Engineering truth says how the repository currently realizes it. +6. Update engineering truth first after code changes. Update product truth only when implemented user-visible product promise or capability boundary changed and explicit source/user evidence supports it; otherwise report product-lane review needed. +7. Code verification is parent-owned: follow repository instructions and task context, and report what ran or why it did not run. +8. Dispatch bounded Truth Sync workers only when the host supports subagent dispatch and the acting agent chooses that path; otherwise execute the same sync task inline. Topology quality gate: - before updating truth docs, verify the changed code resolves to a specific behavior-owned area and bounded truth owner - if routing is missing, stale, broad, overloaded, catch-all route only, or cannot map changed code to a bounded truth owner, do not create another generic truth doc @@ -23,22 +32,23 @@ Topology quality gate: - README.md files are indexes, not Truth Sync targets - must not append behavior details to a README.md index - create or update a bounded leaf truth doc when behavior changes do not fit an existing leaf doc +- write engineering truth under docs/truthmark/engineering; product truth updates under docs/truthmark/product are allowed only for explicit current product behavior changes Truth-doc ownership gate: - before editing or relying on changed functional files and impacted truth docs, verify each target/source truth doc is a bounded owner for the behavior - if a target/source doc mixes independent owners, spans unrelated behaviors, acts as an index, or needs cross-owner edits, do not patch or in-place repair it - if an impacted doc is broad, mixed-owner, index-like, or the update spans independent behavior owners, run Truth Structure before syncing when safe and in scope; otherwise block and recommend Truth Structure - report Ownership reviewed, Structure required, Truth docs split, Truth docs restructured, or Blocked reason as applicable -Product Decisions/Rationale preservation gate: -- before any truth-doc split, restructure, or shape repair, inventory existing Product Decisions and Rationale sections in every source or touched truth doc -- preserve each current decision and rationale in the bounded owner doc it governs; when splitting, move it to the new owner doc rather than deleting it or leaving it in an index +Decision/Rationale preservation gate: +- before any truth-doc split, restructure, or shape repair, inventory existing Product Decisions, Engineering Decisions, and Rationale sections in every source or touched truth doc +- preserve each current decision and rationale in the correct product or engineering lane owner; when splitting, move it to the new owner doc rather than deleting it or leaving it in an index - 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 +- after the edit, verify every touched truth doc keeps lane-appropriate decision/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 template under the configured Truthmark templates root. -Supported kinds: behavior, contract, architecture, workflow, operations, and test-behavior. +Supported kinds: product-capability, engineering-behavior, engineering-contract, engineering-architecture, engineering-workflow, engineering-operations, and engineering-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. +If the template is missing, use lane-specific sections: product truth says what must be true and why; engineering truth says how the repository currently realizes it. 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. @@ -51,7 +61,7 @@ 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. Evidence Gate: - route-first: map changed functional files to bounded route owners and primary canonical docs -- review new or changed behavior-bearing claims only in touched docs, route ownership, Product Decisions, and Rationale +- review new or changed behavior-bearing claims only in touched docs, route ownership, lane-specific decisions, and rationale - support claims with primary checkout evidence: implementation, config, routing, generated templates, schemas, or contract definitions - tests/examples/canonical docs corroborate; they are not sole proof when implementation conflicts - remove, narrow, or block unsupported claims @@ -63,7 +73,7 @@ Optional validation tooling: - you may run truthmark check when local tooling is available - do not require the truthmark binary; direct checkout inspection is the canonical path - optional validation must not replace agent judgment about docs and routing -- update Product Decisions and Rationale when a behavior change comes from a decision change +- update Product Decisions only in product truth and Engineering Decisions only in engineering truth when evidence supports the lane-specific decision change Helper status reporting: - Validate the report body before adding this validator's own success status; the body may omit `validate-sync-report` while validation is pending. - After `truthmark validate sync-report --json` returns `data.validation.ok: true`, append or update `validate-sync-report: ran, passed` in the final report. @@ -74,10 +84,11 @@ Truthmark hierarchy hints: - Config, when present: .truthmark/config.yml - 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 +- Product truth docs, when present: docs/truthmark/product/**/*.md +- Engineering truth docs, when present: docs/truthmark/engineering/**/*.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. +Product decisions belong in product truth; engineering, architecture, contract, workflow, and operational decisions belong in engineering truth. Parent post-sync verification: - verify only truth docs and leased truth routing files changed during sync - block on any unrelated diff caused by the sync step diff --git a/.claude/skills/truthmark-sync/support/report-template.md b/.claude/skills/truthmark-sync/support/report-template.md index 4dfa42d..5331249 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 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.0. Rerun truthmark init after upgrades. Report completion in this shape: ```md @@ -13,7 +13,7 @@ Ownership reviewed: - docs/truthmark/routes/areas.md Truth docs updated: -- docs/truthmark/truth/repository/overview.md +- docs/truthmark/engineering/repository/overview.md Evidence checked: - Claim: Session timeout behavior is documented in the mapped repository truth doc. diff --git a/.claude/skills/truthmark-sync/support/subagents-and-leases.md b/.claude/skills/truthmark-sync/support/subagents-and-leases.md index 12ac2c7..9cae7c4 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 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.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 3ca3986..26ea9e2 100644 --- a/.codex/agents/truth-claim-verifier.toml +++ b/.codex/agents/truth-claim-verifier.toml @@ -1,4 +1,4 @@ -# Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. +# Generated by Truthmark 2.2.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 189d62b..16ed5e4 100644 --- a/.codex/agents/truth-doc-reviewer.toml +++ b/.codex/agents/truth-doc-reviewer.toml @@ -1,11 +1,11 @@ -# Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. +# Generated by Truthmark 2.2.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" nickname_candidates = ["Doc Audit", "Doc Shape", "Doc Check"] developer_instructions = """ Stay read-only. -Review assigned canonical truth docs for frontmatter, source_of_truth, required template sections, Evidence checked entries, Product Decisions, and Rationale. +Review assigned canonical truth docs for compact frontmatter, required template sections, final Source References entries, Evidence checked entries, and lane-appropriate decision sections (Product Decisions in product truth, Engineering Decisions in engineering truth). Flag README.md files used as behavior truth targets, mixed-owner docs, and shape repairs that should move to Truth Structure. Do not edit files, stage changes, or rewrite docs. Return JSON only with keys: scope, filesReviewed, findings, evidence, confidence, recommendedWorkflow, notes. diff --git a/.codex/agents/truth-doc-writer.toml b/.codex/agents/truth-doc-writer.toml index a6a9607..3d37ad4 100644 --- a/.codex/agents/truth-doc-writer.toml +++ b/.codex/agents/truth-doc-writer.toml @@ -1,4 +1,4 @@ -# Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. +# Generated by Truthmark 2.2.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 54edecd..ffc2dca 100644 --- a/.codex/agents/truth-route-auditor.toml +++ b/.codex/agents/truth-route-auditor.toml @@ -1,4 +1,4 @@ -# Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. +# Generated by Truthmark 2.2.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" @@ -7,7 +7,14 @@ developer_instructions = """ Stay read-only. Audit one bounded Truthmark route, area, or doc shard assigned by the parent. Inspect .truthmark/config.yml and route files only when they exist; then inspect mapped truth docs and relevant implementation files directly. +Use a route-first bounded strategy: narrow audits inspect only the routed area and directly linked counterpart docs; root-wide health first builds a cheap route-map/index from route files, then inspects only mismatches and linked leaves. Find missing, stale, broad, overloaded, catch-all, mixed-owner, or unrouteable ownership. +Validate route ownership against lane-specific roots and route kind: +- confirm mapped truth docs resolve to the correct lane root (product or engineering) for their kind +- flag mismatch between assigned route kind and resolved doc kind (for example, product-capability routed to engineering paths) +- verify route-doc linkage for lane pairings via realized_by and realizes before recommending edits +- inspect product counterparts for engineering docs only when route YAML claims a product relationship, or when the parent explicitly asks for user-visible product coverage +- treat missing product links for user-visible engineering docs as a second-pass diagnostic, not a default full-document read. Do not edit files, stage changes, or propose broad rewrites. Return JSON only with keys: scope, filesReviewed, findings, evidence, confidence, recommendedWorkflow, notes. recommendedWorkflow must be one of: none, truthmark-document, truthmark-structure. diff --git a/.gemini/agents/truth-claim-verifier.md b/.gemini/agents/truth-claim-verifier.md index 4fd99b5..3d28b16 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 2.1.0. Rerun truthmark init after upgrades. +# Generated by Truthmark 2.2.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 ca21e31..5a045ae 100644 --- a/.gemini/agents/truth-doc-reviewer.md +++ b/.gemini/agents/truth-doc-reviewer.md @@ -5,12 +5,12 @@ kind: local tools: [read_file, grep_search] --- -# Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. +# Generated by Truthmark 2.2.0. Rerun truthmark init after upgrades. Manual invocation: @truth-doc-reviewer Stay read-only. -Review assigned canonical truth docs for frontmatter, source_of_truth, required template sections, Evidence checked entries, Product Decisions, and Rationale. +Review assigned canonical truth docs for compact frontmatter, required template sections, final Source References entries, Evidence checked entries, and lane-appropriate decision sections (Product Decisions in product truth, Engineering Decisions in engineering truth). Flag README.md files used as behavior truth targets, mixed-owner docs, and shape repairs that should move to Truth Structure. Do not edit files, stage changes, or rewrite docs. Return JSON only with keys: scope, filesReviewed, findings, evidence, confidence, recommendedWorkflow, notes. diff --git a/.gemini/agents/truth-doc-writer.md b/.gemini/agents/truth-doc-writer.md index b41d60d..3c849ba 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 2.1.0. Rerun truthmark init after upgrades. +# Generated by Truthmark 2.2.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 fcda8b2..5ef9972 100644 --- a/.gemini/agents/truth-route-auditor.md +++ b/.gemini/agents/truth-route-auditor.md @@ -5,14 +5,21 @@ kind: local tools: [read_file, grep_search] --- -# Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. +# Generated by Truthmark 2.2.0. Rerun truthmark init after upgrades. Manual invocation: @truth-route-auditor Stay read-only. Audit one bounded Truthmark route, area, or doc shard assigned by the parent. Inspect .truthmark/config.yml and route files only when they exist; then inspect mapped truth docs and relevant implementation files directly. +Use a route-first bounded strategy: narrow audits inspect only the routed area and directly linked counterpart docs; root-wide health first builds a cheap route-map/index from route files, then inspects only mismatches and linked leaves. Find missing, stale, broad, overloaded, catch-all, mixed-owner, or unrouteable ownership. +Validate route ownership against lane-specific roots and route kind: +- confirm mapped truth docs resolve to the correct lane root (product or engineering) for their kind +- flag mismatch between assigned route kind and resolved doc kind (for example, product-capability routed to engineering paths) +- verify route-doc linkage for lane pairings via realized_by and realizes before recommending edits +- inspect product counterparts for engineering docs only when route YAML claims a product relationship, or when the parent explicitly asks for user-visible product coverage +- treat missing product links for user-visible engineering docs as a second-pass diagnostic, not a default full-document read. Do not edit files, stage changes, or propose broad rewrites. Return JSON only with keys: scope, filesReviewed, findings, evidence, confidence, recommendedWorkflow, notes. recommendedWorkflow must be one of: none, truthmark-document, truthmark-structure. diff --git a/.gemini/commands/truthmark/check.toml b/.gemini/commands/truthmark/check.toml index 33cd2d6..27ed0bc 100644 --- a/.gemini/commands/truthmark/check.toml +++ b/.gemini/commands/truthmark/check.toml @@ -1,69 +1,15 @@ 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." prompt = ''' ---- -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: 2.1.0 ---- +This command is the Gemini CLI entrypoint for Truthmark Check. -# Truthmark Check +Do not invoke another Truthmark command from here. -Use this skill to audit repository truth health. +Read these host-local files in order only as needed: +- .gemini/skills/truthmark-check/SKILL.md +- .gemini/skills/truthmark-check/support/procedure.md +- .gemini/skills/truthmark-check/support/report-template.md +- .gemini/skills/truthmark-check/support/subagents-and-leases.md -Invocations: OpenCode /skill truthmark-check; Codex /truthmark-check or $truthmark-check; Claude Code /truthmark-check; GitHub Copilot /truthmark-check; Gemini CLI /truthmark:check. - -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/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 -- check that canonical behavior docs keep active Product Decisions and Rationale sections -- optionally run truthmark check when local tooling is available -- must not require the truthmark binary; direct inspection is always valid -- report issues and suggested fixes without silently rewriting unrelated files -- if follow-up docs edits are needed for mixed-owner docs, run or recommend Truth Structure before editing -Evidence Gate: -- support each finding and suggested fix with evidence from config, route files, canonical docs, implementation, templates, or tests -- canonical docs are context, not sole proof when implementation conflicts -- remove unsupported findings or mark open questions; validate changed claims if you edit docs - -Truthmark hierarchy hints: -- Config, when present: .truthmark/config.yml -- 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. - -Report completion in this shape: - -```md -Truth Check: completed - -Files reviewed: -- docs/truthmark/routes/areas.md - -Issues found: -- none - -Fixes suggested: -- none - -Evidence checked: -- Finding: The root route index is present and maps repository truth owners. - Evidence: docs/truthmark/routes/areas.md:1 - Suggested fix: none - Confidence: high - -Validation: -- truthmark check -``` +If skill entrypoints are unavailable, use the host's direct evidence-first manual fallback procedure. User focus or arguments: {{args}} ''' diff --git a/.gemini/commands/truthmark/document.toml b/.gemini/commands/truthmark/document.toml index 15fb447..b67e299 100644 --- a/.gemini/commands/truthmark/document.toml +++ b/.gemini/commands/truthmark/document.toml @@ -1,122 +1,17 @@ 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." prompt = ''' ---- -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: 2.1.0 ---- +This command is the Gemini CLI entrypoint for Truthmark Document. -# Truthmark Document +Do not invoke another Truthmark command from here. -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. +Read these host-local files in order only as needed: +- .gemini/skills/truthmark-document/SKILL.md +- .gemini/skills/truthmark-document/support/procedure.md +- .gemini/skills/truthmark-document/support/report-template.md +- .gemini/skills/truthmark-document/support/subagents-and-leases.md +- .gemini/skills/truthmark-document/helper-manifest.yml +- .gemini/skills/truthmark-document/support/helper-policy.md -Truth Document is manual and implementation-first: - -- run only when the user explicitly asks to generate or update truth docs for existing behavior, or when Truth Sync, Truth Check, or Truth Structure reports implemented behavior that lacks canonical truth docs -- inspect .truthmark/config.yml and configured route files only when they exist; then inspect existing canonical docs, implementation code, and tests 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. -- document current implemented behavior; do not invent future behavior or planned endpoints -- 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 -- keep feature README.md files as indexes rather than truth-document targets -- create or update bounded leaf truth docs when behavior does not fit an existing leaf doc -- keep behavior truth docs behavior-oriented, not endpoint-oriented, unless the endpoint itself is the behavior boundary -- keep API endpoint details in the nearest contract truth doc when such a doc owns the API contract -- preserve unrelated authored content -Truth-doc ownership gate: -- before editing or relying on the implemented behavior and candidate truth docs, verify each target/source truth doc is a bounded owner for the behavior -- if a target/source doc mixes independent owners, spans unrelated behaviors, acts as an index, or needs cross-owner edits, do not patch or in-place repair it -- if the target doc is broad, mixed-owner, index-like, or the documented behavior spans independent owners, run Truth Structure first when safe and in scope; otherwise block and recommend Truth Structure -- report Ownership reviewed, Structure required, Truth docs split, Truth docs restructured, or Blocked reason as applicable -Product Decisions/Rationale preservation gate: -- before any truth-doc split, restructure, or shape repair, inventory existing Product Decisions and Rationale sections in every source or touched truth doc -- preserve each current decision and rationale in the bounded owner doc it governs; when splitting, move it to the new owner doc rather than deleting it or leaving it in an index -- 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 -Evidence Gate: -- route-first: map the documented behavior to bounded route owners and primary canonical docs -- review new or changed behavior-bearing claims only in touched docs, route ownership, Product Decisions, and Rationale -- support claims with primary checkout evidence: implementation, config, routing, generated templates, schemas, or contract definitions -- tests/examples/canonical docs corroborate; they are not sole proof when implementation conflicts -- remove, narrow, or block unsupported claims -- if no truth doc changed, report why current truth was already sufficient or why documentation was blocked -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 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 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 -- use Truth Structure for ownership splits; do not treat broad or mixed-owner docs as in-place repair work -- repair shape when a narrow edit would make truth worse: missing template sections, stale evidence conflicts, cross-section updates within one owner, or wrong frontmatter/source/headings -- preserve supported claims; remove, narrow, or block unsupported or stale claims -- report docs restructured and why a narrow edit was not sufficient -Maintain architecture docs only for structure-level changes: system structure, module boundaries, runtime topology, persistence boundaries, cross-cutting contracts, or generated-surface ownership. -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/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. -Helper status reporting: -- Validate the report body before adding this validator's own success status; the body may omit `validate-document-report` while validation is pending. -- After `truthmark validate document-report --json` returns `data.validation.ok: true`, append or update `validate-document-report: ran, passed` in the final report. -- If the installed Truthmark CLI is unavailable or the helper is skipped, record `validate-document-report: skipped, ` and manually validate the report shape. -- Record `validate-write-lease: ran, passed` only after validating a concrete write lease; otherwise use a truthful skipped status such as `skipped, no write lease used`. -- Helper output is derived evidence and never replaces direct checkout inspection, evidence review, or parent acceptance. -Parent post-document verification: -- verify only truth docs and leased truth routing files changed during document work -- block on functional code, generated host surfaces, or unrelated diffs caused by document work -- for each write lease, validate the worker report against the actual worker diff, allowedWrites, forbiddenWrites, identity fields, filesChanged, offLeaseChanges, blockers, and required report fields before accepting it -- verify the final report records ownership review, structure requirement, restructure, routing update, or blocked reason when applicable - -Report completion in this shape: -```md -Truth Document: completed - -Implementation reviewed: -- src/routing/area-resolver.ts - -Ownership reviewed: -- docs/truthmark/routes/areas.md - -Truth docs created: -- docs/truthmark/truth/contracts.md - -Truth docs updated: -- docs/truthmark/truth/check-diagnostics.md - -Truth docs restructured: -- docs/truthmark/truth/check-diagnostics.md - -Routing updated: -- 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/routes/areas.md:9 - Result: supported - -Helper scripts: -- validate-write-lease: skipped, no write lease used - -Notes: -- Documented routing and behavior from route handlers and tests. -``` +If skill entrypoints are unavailable, use the host's direct evidence-first manual fallback procedure. User focus or arguments: {{args}} ''' diff --git a/.gemini/commands/truthmark/preview.toml b/.gemini/commands/truthmark/preview.toml index f1f6322..99e1fc0 100644 --- a/.gemini/commands/truthmark/preview.toml +++ b/.gemini/commands/truthmark/preview.toml @@ -1,89 +1,15 @@ 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." prompt = ''' ---- -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: 2.1.0 ---- +This command is the Gemini CLI entrypoint for Truthmark Preview. -Use this skill only when the user explicitly asks to preview Truthmark routing or workflow choice before edits. +Do not invoke another Truthmark command from here. -Invocations: OpenCode /skill truthmark-preview; Codex /truthmark-preview or $truthmark-preview; Claude Code /truthmark-preview; GitHub Copilot /truthmark-preview; Gemini CLI /truthmark:preview. +Read these host-local files in order only as needed: +- .gemini/skills/truthmark-preview/SKILL.md +- .gemini/skills/truthmark-preview/support/procedure.md +- .gemini/skills/truthmark-preview/support/report-template.md +- .gemini/skills/truthmark-preview/support/subagents-and-leases.md -Truth Preview is read-only. Its report is intended, not authorized. - -Purpose: -- preview the likely Truthmark workflow, route owner, target files, expected write classes, suggested subagent use, and blocking ambiguity before edits happen -- hand off to the selected workflow after user approval -- keep the selector thin so agents can avoid loading or acting through heavier workflows prematurely - -Read: -- .truthmark/config.yml, 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. - -Do not: -- must not edit files -- must not create truth docs -- must not update routing -- must not run Truth Sync automatically -- must not replace Truth Check -- must not claim final correctness -- must not issue write leases -- must not mutate code - -Suggested subagent use: -- optional read-only verifier: truth_route_auditor -- write workers: none -- leases needed: none - -Truthmark hierarchy hints: -- Config, when present: .truthmark/config.yml -- 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 -Truth Preview: completed - -Requested outcome: -- preview likely Truthmark workflow routing before edits - -Likely workflow: -- truthmark-document - -Why this workflow: -- positive trigger: document existing implemented behavior -- negative triggers considered: functional-code change, doc-first implementation, topology repair, truth audit -- forbidden adjacency considered: must not edit functional code - -Likely route owner: -- 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/truthmark/truth/example.md - -Suggested subagent use: -- read-only verifiers: truth_route_auditor -- write workers: none in Preview -- leases needed: none in Preview - -Blocking ambiguity: -- none identified in preview - -Handoff: -- Run the selected Truthmark workflow after user approval. -``` +If skill entrypoints are unavailable, use the host's direct evidence-first manual fallback procedure. User focus or arguments: {{args}} ''' diff --git a/.gemini/commands/truthmark/realize.toml b/.gemini/commands/truthmark/realize.toml index 40c00f7..6288a1c 100644 --- a/.gemini/commands/truthmark/realize.toml +++ b/.gemini/commands/truthmark/realize.toml @@ -1,65 +1,14 @@ 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." prompt = ''' ---- -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: 2.1.0 ---- +This command is the Gemini CLI entrypoint for Truthmark Realize. -# Truthmark Realize +Do not invoke another Truthmark command from here. -Use this skill only when the user explicitly asks to realize truth docs into code. +Read these host-local files in order only as needed: +- .gemini/skills/truthmark-realize/SKILL.md +- .gemini/skills/truthmark-realize/support/procedure.md +- .gemini/skills/truthmark-realize/support/report-template.md -Invocations: OpenCode /skill truthmark-realize; Codex /truthmark-realize or $truthmark-realize; Claude Code /truthmark-realize; GitHub Copilot /truthmark-realize; Gemini CLI /truthmark:realize. - -Truth Realize is doc-first: - -- truth docs lead -- code follows -- Truth Realize never edits the truth docs it is realizing - -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/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: -- before editing or relying on source truth docs before writing code, verify each target/source truth doc is a bounded owner for the behavior -- if a target/source doc mixes independent owners, spans unrelated behaviors, acts as an index, or needs cross-owner edits, do not patch or in-place repair it -- if a source truth doc is broad, mixed-owner, index-like, unrouteable, stale, or conflicts with implementation evidence, block before writing code and recommend Truth Structure or Truth Document -- report Ownership reviewed, Structure required, Truth docs split, Truth docs restructured, or Blocked reason as applicable -4. Update functional code only so implementation matches bounded, current truth claims from the source docs. -5. Do not edit truth docs or truth routing while realizing those docs. -6. Run relevant tests for the changed code. -7. Report changed code files and verification steps. -Truthmark hierarchy hints: -- Config, when present: .truthmark/config.yml -- 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: - -- may read truth docs, routing docs, and relevant functional code -- may write functional code only -- must not edit truth docs or truth routing while realizing those docs - -Report completion in this shape: - -```md -Truth Realize: completed - -Truth docs used: -- docs/truthmark/truth/authentication/session-timeout.md - -Code updated: -- src/auth/session.ts - -Verification: -- npm test -- auth -``` +If skill entrypoints are unavailable, use the host's direct evidence-first manual fallback procedure. User focus or arguments: {{args}} ''' diff --git a/.gemini/commands/truthmark/structure.toml b/.gemini/commands/truthmark/structure.toml index af13bf4..bc46820 100644 --- a/.gemini/commands/truthmark/structure.toml +++ b/.gemini/commands/truthmark/structure.toml @@ -1,149 +1,15 @@ 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." prompt = ''' ---- -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: 2.1.0 ---- +This command is the Gemini CLI entrypoint for 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. -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/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/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. +Do not invoke another Truthmark command from here. -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 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 -## New area setup -Use when a user asks to onboard a new code area into Truthmark, a new package, controller, domain, or product area lacks bounded truth ownership, or a new product area needs routing and starter truth docs. -Do: -- inspect the named code area -- infer bounded product or behavior ownership -- choose the owning route when ownership is clear; otherwise propose the route and block for review -- create or update the child route entry or file -- create starter truth docs only where current truth is missing -- report the initial truth boundary -Do not: -- do not edit functional code -- do not perform full behavior documentation unless evidence is inspected and the task explicitly asks for it -- do not patch broad or mixed-owner docs in place -- 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/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: -- before editing or relying on candidate route owners and current truth docs, verify each target/source truth doc is a bounded owner for the behavior -- if a target/source doc mixes independent owners, spans unrelated behaviors, acts as an index, or needs cross-owner edits, do not patch or in-place repair it -- if a truth doc mixes independent owners, route ownership is broad, or a split is required for bounded ownership, split and reroute into bounded truth docs when safe; otherwise block with manual-review files -- report Ownership reviewed, Structure required, Truth docs split, Truth docs restructured, or Blocked reason as applicable -Product Decisions/Rationale preservation gate: -- before any truth-doc split, restructure, or shape repair, inventory existing Product Decisions and Rationale sections in every source or touched truth doc -- preserve each current decision and rationale in the bounded owner doc it governs; when splitting, move it to the new owner doc rather than deleting it or leaving it in an index -- 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 -Topology pressure signals: -- one area maps broad code such as src/**, app/**, server/**, services/**, or packages/** -- one area maps multiple unrelated controllers, route groups, services, or bounded contexts -- one truth doc owns unrelated behaviors or unrelated endpoint families -- 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/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 -- more than 8 truth docs mapped to one area -- more than 5 controllers mapped through one catch-all area -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/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 -- keep behavior truth docs behavior-oriented, not endpoint-oriented -- keep API endpoint details in the nearest contract truth doc when such a doc exists -- update routing so future Truth Sync can target small docs -- preserve existing authored docs; move or rewrite only when needed to remove ambiguity -- report Truth docs split when one broad or mixed-owner truth doc becomes multiple bounded docs -Truth-doc shape repair gate: -- Truth Structure may restructure broader routed docs when topology, ownership, or doc-shape repair is already in scope. -- repair shape in place only after the ownership gate confirms the doc is the right bounded owner -- use Truth Structure for ownership splits; do not treat broad or mixed-owner docs as in-place repair work -- repair shape when a narrow edit would make truth worse: missing template sections, stale evidence conflicts, cross-section updates within one owner, or wrong frontmatter/source/headings -- preserve supported claims; remove, narrow, or block unsupported or stale claims -- report docs restructured and why a narrow edit was not sufficient -Evidence Gate: -- apply the Evidence Gate before finishing when Truth Structure writes routed docs, ownership claims, Product Decisions, or Rationale -- support ownership/behavior claims with topology or primary checkout evidence from layout, implementation boundaries, docs, config, route files, tests, templates, schemas, or contracts -- tests/examples/canonical docs corroborate; remove, narrow, or block unsupported claims -Maintain architecture docs only for structure-level changes: system structure, module boundaries, runtime topology, persistence boundaries, cross-cutting contracts, or generated-surface ownership. -Keep ordinary behavior, endpoints, UI copy, validation rules, and bug fixes in behavior or contract docs unless they change those boundaries. -- Do not finish topology repair with routed canonical current-truth docs missing Product Decisions or Rationale sections. -- If an existing canonical doc lacks either section, add the missing heading beside Current Behavior with a concise current-state placeholder or active decision. -Portable fallback: -- If this skill surface is unavailable, perform the same workflow directly from committed repository files. -- Do not require the truthmark CLI. -- Inspect .truthmark/config.yml and configured route files only when they exist; then inspect canonical docs and representative implementation code. -- 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/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. -Report completion in this shape: -```md -Truth Structure: completed -Topology reviewed: -- controllers: src/auth/** -- docs root: docs/truthmark/truth -- route files: docs/truthmark/routes/areas.md -Areas reviewed: -- src/auth/** -Routing updated: -- docs/truthmark/routes/areas.md -Initial truth boundary: -- Area: Authentication -- Code: src/auth/** -- Truth owner: docs/truthmark/truth/authentication/session.md -- Scope: session behavior only -Truth docs created: -- docs/truthmark/truth/authentication/session.md -Truth docs split: -- docs/truthmark/truth/authentication/README.md -> docs/truthmark/truth/authentication/session.md -Truth docs restructured: -- docs/truthmark/truth/authentication/README.md -Evidence checked: -- Claim: Session behavior belongs to a dedicated Authentication truth owner. - 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. -Notes: -- Added an Authentication area for session behavior. -``` +Read these host-local files in order only as needed: +- .gemini/skills/truthmark-structure/SKILL.md +- .gemini/skills/truthmark-structure/support/procedure.md +- .gemini/skills/truthmark-structure/support/report-template.md +- .gemini/skills/truthmark-structure/support/subagents-and-leases.md + +If skill entrypoints are unavailable, use the host's direct evidence-first manual fallback procedure. User focus or arguments: {{args}} ''' diff --git a/.gemini/commands/truthmark/sync.toml b/.gemini/commands/truthmark/sync.toml index 59c1a34..5d983d6 100644 --- a/.gemini/commands/truthmark/sync.toml +++ b/.gemini/commands/truthmark/sync.toml @@ -1,134 +1,17 @@ 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." prompt = ''' ---- -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: 2.1.0 ---- +This command is the Gemini CLI entrypoint for 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. -Explicit invocation runs immediately. Later functional-code changes reopen the finish-time requirement, and an earlier explicit run satisfies the finish gate only if no later functional-code changes occur. -Skip when changes are documentation-only, formatting-only, clearly behavior-preserving renames with no truth impact, when no Truthmark config exists yet, or when there are no functional code changes. -Parent workflow: -1. Inspect git status, staged changes, unstaged changes, and untracked files directly. -2. Inspect .truthmark/config.yml and configured route files only when they exist; then inspect relevant canonical docs. -3. Identify functional-code changes and the nearest truth docs or routing repairs. -4. 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. -5. Code verification is parent-owned: follow repository instructions and task context, and report what ran or why it did not run. -6. Dispatch bounded Truth Sync workers only when the host supports subagent dispatch and the acting agent chooses that path; otherwise execute the same sync task inline. -Topology quality gate: -- before updating truth docs, verify the changed code resolves to a specific behavior-owned area and bounded truth owner -- if routing is missing, stale, broad, overloaded, catch-all route only, or cannot map changed code to a bounded truth owner, do not create another generic truth doc -- run Truth Structure before syncing when topology repair is safe and in scope -- block and recommend Truth Structure when topology repair is unsafe, ambiguous, or outside the current task boundary -- report the route files and changed code paths that require structure repair -- README.md files are indexes, not Truth Sync targets -- must not append behavior details to a README.md index -- create or update a bounded leaf truth doc when behavior changes do not fit an existing leaf doc -Truth-doc ownership gate: -- before editing or relying on changed functional files and impacted truth docs, verify each target/source truth doc is a bounded owner for the behavior -- if a target/source doc mixes independent owners, spans unrelated behaviors, acts as an index, or needs cross-owner edits, do not patch or in-place repair it -- if an impacted doc is broad, mixed-owner, index-like, or the update spans independent behavior owners, run Truth Structure before syncing when safe and in scope; otherwise block and recommend Truth Structure -- report Ownership reviewed, Structure required, Truth docs split, Truth docs restructured, or Blocked reason as applicable -Product Decisions/Rationale preservation gate: -- before any truth-doc split, restructure, or shape repair, inventory existing Product Decisions and Rationale sections in every source or touched truth doc -- preserve each current decision and rationale in the bounded owner doc it governs; when splitting, move it to the new owner doc rather than deleting it or leaving it in an index -- 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 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 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 -- use Truth Structure for ownership splits; do not treat broad or mixed-owner docs as in-place repair work -- repair shape when a narrow edit would make truth worse: missing template sections, stale evidence conflicts, cross-section updates within one owner, or wrong frontmatter/source/headings -- preserve supported claims; remove, narrow, or block unsupported or stale claims -- report docs restructured and why a narrow edit was not sufficient -Maintain architecture docs only for structure-level changes: system structure, module boundaries, runtime topology, persistence boundaries, cross-cutting contracts, or generated-surface ownership. -Keep ordinary behavior, endpoints, UI copy, validation rules, and bug fixes in behavior or contract docs unless they change those boundaries. -Evidence Gate: -- route-first: map changed functional files to bounded route owners and primary canonical docs -- review new or changed behavior-bearing claims only in touched docs, route ownership, Product Decisions, and Rationale -- support claims with primary checkout evidence: implementation, config, routing, generated templates, schemas, or contract definitions -- tests/examples/canonical docs corroborate; they are not sole proof when implementation conflicts -- remove, narrow, or block unsupported claims -- if no impacted doc changed, report why truth was already current or why sync was skipped -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. -Optional validation tooling: -- you may run truthmark check when local tooling is available -- do not require the truthmark binary; direct checkout inspection is the canonical path -- optional validation must not replace agent judgment about docs and routing -- update Product Decisions and Rationale when a behavior change comes from a decision change -Helper status reporting: -- Validate the report body before adding this validator's own success status; the body may omit `validate-sync-report` while validation is pending. -- After `truthmark validate sync-report --json` returns `data.validation.ok: true`, append or update `validate-sync-report: ran, passed` in the final report. -- If the installed Truthmark CLI is unavailable or the helper is skipped, record `validate-sync-report: skipped, ` and manually validate the report shape. -- Record `validate-write-lease: ran, passed` only after validating a concrete write lease; otherwise use a truthful skipped status such as `skipped, no write lease used`. -- 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/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. -Parent post-sync verification: -- verify only truth docs and leased truth routing files changed during sync -- block on any unrelated diff caused by the sync step -- block if functional code changed during sync -- for each write lease, validate the worker report against the actual worker diff, allowedWrites, forbiddenWrites, identity fields, filesChanged, offLeaseChanges, blockers, and required report fields before accepting it -- validate the final report against the structured Truth Sync report contract, including Claim, indented Evidence, and Result values supported, narrowed, removed, or blocked under Evidence checked -- verify the updated docs correspond to the reviewed changed-code surface -- verify the final report records ownership review, structure requirement, split, restructure, or blocked reason when the ownership gate fired -- blocked outcomes must preserve the working tree as-is: no rollback, no post-block cleanup edits, and manual-review reporting of any remaining files -Report completion in this shape: -```md -Truth Sync: completed +Do not invoke another Truthmark command from here. -Changed code reviewed: -- src/auth/session.ts +Read these host-local files in order only as needed: +- .gemini/skills/truthmark-sync/SKILL.md +- .gemini/skills/truthmark-sync/support/procedure.md +- .gemini/skills/truthmark-sync/support/report-template.md +- .gemini/skills/truthmark-sync/support/subagents-and-leases.md +- .gemini/skills/truthmark-sync/helper-manifest.yml +- .gemini/skills/truthmark-sync/support/helper-policy.md -Ownership reviewed: -- docs/truthmark/routes/areas.md - -Truth docs updated: -- 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/routes/areas.md:11 - Result: supported - -Helper scripts: -- validate-write-lease: skipped, no write lease used - -Notes: -- Updated session timeout behavior. -``` -Blocked report example: -```md -Truth Sync: blocked - -Reason: -- routing repair is not allowed - -Files requiring manual review: -- docs/truthmark/routes/areas.md - -Next action: -- update routing metadata and rerun Truth Sync -``` +If skill entrypoints are unavailable, use the host's direct evidence-first manual fallback procedure. User focus or arguments: {{args}} ''' diff --git a/.gemini/skills/truthmark-check/SKILL.md b/.gemini/skills/truthmark-check/SKILL.md index b15383b..7dff7d6 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: 2.1.0 +truthmark-version: 2.2.0 --- # Truthmark Check diff --git a/.gemini/skills/truthmark-check/support/procedure.md b/.gemini/skills/truthmark-check/support/procedure.md index 6132ff9..c8c76bd 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 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.0. Rerun truthmark init after upgrades. # Truthmark Check @@ -11,13 +11,31 @@ Invocations: OpenCode /skill truthmark-check; Codex /truthmark-check or $truthma 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/routes/areas.md and relevant child route files under docs/truthmark/routes/areas/ when they exist +- Evidence authority: + - 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. +- Lane classification: + - classify the request or changed surface as product-lane, engineering-lane, both-lane, or ambiguous for reporting only + - product-lane ownership belongs under docs/truthmark/product and describes product promises, boundaries, rationale, decisions, and success criteria + - engineering-lane ownership belongs under docs/truthmark/engineering and describes source-backed current realization, contracts, architecture, workflows, operations, or tests + - both-lane ownership uses separate product and engineering docs cross-linked in route YAML with realized_by and realizes, not in doc frontmatter + - ambiguous lane ownership should be reported as blocked or routed to Truth Structure + - Do not make product docs a summary of engineering docs. Do not make engineering docs a detailed version of product docs. Product truth says what must be true and why. Engineering truth says how the repository currently realizes it. - check that current docs describe current code rather than historical plans +- keep lane and cross-lane checks route-first and bounded: + - for a narrow audit, inspect only the routed area and directly linked counterpart docs + - for root-wide truth health, first build a cheap route-map/index from route files, then inspect only mismatches and linked leaves + - inspect product counterparts for engineering docs only when route YAML claims a product relationship, or when the user explicitly asks for user-visible product coverage +- check lane root/kind alignment for product truth under docs/truthmark/product and engineering truth under docs/truthmark/engineering +- check route YAML cross-lane realized_by and realizes links for existence and lane compatibility +- report missing product links for user-visible engineering docs only as a second-pass review diagnostic, not as default full-document reads or hard errors +- check product docs do not contain engineering execution flow, generated file inventories, or CLI envelope mechanics +- check engineering docs do not contain product promises, product rationale, or Product Decisions sections +- never judge whether a product decision is commercially correct, valuable, prioritized, or desirable - 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 -- check that canonical behavior docs keep active Product Decisions and Rationale sections +- check that canonical docs keep lane-appropriate decisions and rationale sections - optionally run truthmark check when local tooling is available - must not require the truthmark binary; direct inspection is always valid - report issues and suggested fixes without silently rewriting unrelated files @@ -31,7 +49,8 @@ Truthmark hierarchy hints: - Config, when present: .truthmark/config.yml - 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 +- Product truth docs, when present: docs/truthmark/product/**/*.md +- Engineering truth docs, when present: docs/truthmark/engineering/**/*.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. +Product decisions belong in product truth; engineering, architecture, contract, workflow, and operational decisions belong in engineering truth. diff --git a/.gemini/skills/truthmark-check/support/report-template.md b/.gemini/skills/truthmark-check/support/report-template.md index 00a3453..435fdfa 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 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.0. Rerun truthmark init after upgrades. Report completion in this shape: diff --git a/.gemini/skills/truthmark-check/support/subagents-and-leases.md b/.gemini/skills/truthmark-check/support/subagents-and-leases.md index e38dc16..be5da14 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 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.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 dfe6d2b..b2e81ee 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: 2.1.0 +truthmark-version: 2.2.0 --- # Truthmark Document diff --git a/.gemini/skills/truthmark-document/helper-manifest.yml b/.gemini/skills/truthmark-document/helper-manifest.yml index 175e1a0..1763234 100644 --- a/.gemini/skills/truthmark-document/helper-manifest.yml +++ b/.gemini/skills/truthmark-document/helper-manifest.yml @@ -1,8 +1,8 @@ -# Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. +# Generated by Truthmark 2.2.0. Rerun truthmark init after upgrades. helpers: validate-document-report: optional: true - runner: truthmark>=2.1.0 + runner: truthmark>=2.2.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>=2.1.0 + runner: truthmark>=2.2.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 2cb7bd6..58bcb56 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 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.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>=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 +- validate-document-report: optional truthmark>=2.2.0; manual fallback: manually validate support/report-template.md required sections and structured Evidence checked entries +- validate-write-lease: optional truthmark>=2.2.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 be8590f..b787061 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 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.0. Rerun truthmark init after upgrades. # Truthmark Document @@ -11,8 +11,16 @@ Truth Document is manual and implementation-first: - run only when the user explicitly asks to generate or update truth docs for existing behavior, or when Truth Sync, Truth Check, or Truth Structure reports implemented behavior that lacks canonical truth docs - inspect .truthmark/config.yml and configured route files only when they exist; then inspect existing canonical docs, implementation code, and tests 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. +- Evidence authority: + - 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. +- Lane classification: + - before writing canonical truth docs, classify the request or change as product-lane, engineering-lane, both-lane, or ambiguous + - product-lane writes belong under docs/truthmark/product and state product promises, boundaries, rationale, decisions, and success criteria + - engineering-lane writes belong under docs/truthmark/engineering and state source-backed current realization, contracts, architecture, workflows, operations, or tests + - both-lane work must write separate product and engineering docs and cross-link them in route YAML with realized_by and realizes, not in doc frontmatter + - ambiguous lane ownership must block or invoke Truth Structure instead of writing a mixed document + - Do not make product docs a summary of engineering docs. Do not make engineering docs a detailed version of product docs. Product truth says what must be true and why. Engineering truth says how the repository currently realizes it. - document current implemented behavior; do not invent future behavior or planned endpoints - may write canonical truth docs and docs/truthmark/routes/areas.md or relevant child route files only - must not write functional code @@ -20,7 +28,10 @@ Implementation code and canonical truth docs are inspected evidence for current - block and recommend Truth Structure when routing repair is unsafe, ambiguous, or outside the task boundary - keep feature README.md files as indexes rather than truth-document targets - create or update bounded leaf truth docs when behavior does not fit an existing leaf doc -- keep behavior truth docs behavior-oriented, not endpoint-oriented, unless the endpoint itself is the behavior boundary +- write product capability/boundary truth under docs/truthmark/product when documenting product promise, boundary, rationale, or user/stakeholder value +- write engineering truth under docs/truthmark/engineering when documenting implementation behavior, contracts, architecture, workflows, operations, or tests +- for both-lane documentation requests, write separate product and engineering docs and cross-link them in route YAML with realized_by and realizes, not in doc frontmatter +- keep engineering behavior truth behavior-oriented, not endpoint-oriented, unless the endpoint itself is the behavior boundary - keep API endpoint details in the nearest contract truth doc when such a doc owns the API contract - preserve unrelated authored content Truth-doc ownership gate: @@ -28,15 +39,15 @@ Truth-doc ownership gate: - if a target/source doc mixes independent owners, spans unrelated behaviors, acts as an index, or needs cross-owner edits, do not patch or in-place repair it - if the target doc is broad, mixed-owner, index-like, or the documented behavior spans independent owners, run Truth Structure first when safe and in scope; otherwise block and recommend Truth Structure - report Ownership reviewed, Structure required, Truth docs split, Truth docs restructured, or Blocked reason as applicable -Product Decisions/Rationale preservation gate: -- before any truth-doc split, restructure, or shape repair, inventory existing Product Decisions and Rationale sections in every source or touched truth doc -- preserve each current decision and rationale in the bounded owner doc it governs; when splitting, move it to the new owner doc rather than deleting it or leaving it in an index +Decision/Rationale preservation gate: +- before any truth-doc split, restructure, or shape repair, inventory existing Product Decisions, Engineering Decisions, and Rationale sections in every source or touched truth doc +- preserve each current decision and rationale in the correct product or engineering lane owner; when splitting, move it to the new owner doc rather than deleting it or leaving it in an index - 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 +- after the edit, verify every touched truth doc keeps lane-appropriate decision/rationale sections and every pre-existing entry is preserved, moved, narrowed, removed with evidence, or blocked Evidence Gate: - route-first: map the documented behavior to bounded route owners and primary canonical docs -- review new or changed behavior-bearing claims only in touched docs, route ownership, Product Decisions, and Rationale +- review new or changed behavior-bearing claims only in touched docs, route ownership, lane-specific decisions, and rationale - support claims with primary checkout evidence: implementation, config, routing, generated templates, schemas, or contract definitions - tests/examples/canonical docs corroborate; they are not sole proof when implementation conflicts - remove, narrow, or block unsupported claims @@ -45,10 +56,10 @@ Repository intelligence artifacts are optional derived context: RepoIndex, Route 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 template under the configured Truthmark templates root. -Supported kinds: behavior, contract, architecture, workflow, operations, and test-behavior. +Supported kinds: product-capability, engineering-behavior, engineering-contract, engineering-architecture, engineering-workflow, engineering-operations, and engineering-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. +If the template is missing, use lane-specific sections: product truth says what must be true and why; engineering truth says how the repository currently realizes it. 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. @@ -63,10 +74,11 @@ Truthmark hierarchy hints: - Config, when present: .truthmark/config.yml - 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 +- Product truth docs, when present: docs/truthmark/product/**/*.md +- Engineering truth docs, when present: docs/truthmark/engineering/**/*.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. +Product decisions belong in product truth; engineering, architecture, contract, workflow, and operational decisions belong in engineering truth. Helper status reporting: - Validate the report body before adding this validator's own success status; the body may omit `validate-document-report` while validation is pending. - After `truthmark validate document-report --json` returns `data.validation.ok: true`, append or update `validate-document-report: ran, passed` in the final report. diff --git a/.gemini/skills/truthmark-document/support/report-template.md b/.gemini/skills/truthmark-document/support/report-template.md index 5e38b92..6673f6a 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 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.0. Rerun truthmark init after upgrades. Report completion in this shape: ```md @@ -13,13 +13,13 @@ Ownership reviewed: - docs/truthmark/routes/areas.md Truth docs created: -- docs/truthmark/truth/contracts.md +- docs/truthmark/engineering/contracts/routing.md Truth docs updated: -- docs/truthmark/truth/check-diagnostics.md +- docs/truthmark/engineering/behaviors/check-diagnostics.md Truth docs restructured: -- docs/truthmark/truth/check-diagnostics.md +- docs/truthmark/engineering/behaviors/check-diagnostics.md Routing updated: - docs/truthmark/routes/areas.md diff --git a/.gemini/skills/truthmark-document/support/subagents-and-leases.md b/.gemini/skills/truthmark-document/support/subagents-and-leases.md index 05cf06a..4e78de7 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 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.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 78dff00..d7d1bf4 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: 2.1.0 +truthmark-version: 2.2.0 --- # Truthmark Preview @@ -16,7 +16,7 @@ Invocations: OpenCode /skill truthmark-preview; Codex /truthmark-preview or $tru 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/routes/areas.md; docs/truthmark/routes/areas/) only when they exist; then inspect only the truth docs or implementation files needed to preview ownership. +- Inspect .truthmark/config.yml and the root route index (docs/truthmark/routes/areas.md) first when present; then inspect only child route files under docs/truthmark/routes/areas/ that are relevant to the selected scope or changed paths, plus 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. diff --git a/.gemini/skills/truthmark-preview/support/procedure.md b/.gemini/skills/truthmark-preview/support/procedure.md index 276926b..9579a10 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 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.0. Rerun truthmark init after upgrades. Use this skill only when the user explicitly asks to preview Truthmark routing or workflow choice before edits. @@ -10,16 +10,25 @@ Truth Preview is read-only. Its report is intended, not authorized. Purpose: - preview the likely Truthmark workflow, route owner, target files, expected write classes, suggested subagent use, and blocking ambiguity before edits happen +- report likely product lane impact, engineering lane impact, target docs, and ambiguity before edits - hand off to the selected workflow after user approval - keep the selector thin so agents can avoid loading or acting through heavier workflows prematurely Read: - .truthmark/config.yml, only when present -- docs/truthmark/routes/areas.md, only when present -- relevant child route files under docs/truthmark/routes/areas/, only when present +- docs/truthmark/routes/areas.md, first, only when present +- relevant child route files under docs/truthmark/routes/areas/ for the selected scope or changed paths, 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. +- Evidence authority: + - 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. +- Lane classification: + - classify the request or changed surface as product-lane, engineering-lane, both-lane, or ambiguous for reporting only + - product-lane ownership belongs under docs/truthmark/product and describes product promises, boundaries, rationale, decisions, and success criteria + - engineering-lane ownership belongs under docs/truthmark/engineering and describes source-backed current realization, contracts, architecture, workflows, operations, or tests + - both-lane ownership uses separate product and engineering docs cross-linked in route YAML with realized_by and realizes, not in doc frontmatter + - ambiguous lane ownership should be reported as blocked or routed to Truth Structure + - Do not make product docs a summary of engineering docs. Do not make engineering docs a detailed version of product docs. Product truth says what must be true and why. Engineering truth says how the repository currently realizes it. Do not: - must not edit files @@ -40,4 +49,5 @@ Truthmark hierarchy hints: - Config, when present: .truthmark/config.yml - 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 +- Product truth docs, when present: docs/truthmark/product/**/*.md +- Engineering truth docs, when present: docs/truthmark/engineering/**/*.md diff --git a/.gemini/skills/truthmark-preview/support/report-template.md b/.gemini/skills/truthmark-preview/support/report-template.md index bff96a9..f529f70 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 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.0. Rerun truthmark init after upgrades. Report completion in this shape: ```md @@ -19,14 +19,16 @@ Why this workflow: Likely route owner: - route file: docs/truthmark/routes/areas.md -- truth doc: docs/truthmark/truth/example.md +- likely lane impact: engineering-lane +- product target docs: none identified +- engineering target docs: docs/truthmark/engineering/behaviors/example.md - confidence: medium Expected write classes: - truth docs Expected target files: -- docs/truthmark/truth/example.md +- docs/truthmark/engineering/behaviors/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 08ff8c8..6984540 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 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.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 116788d..d475dbe 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: 2.1.0 +truthmark-version: 2.2.0 --- # Truthmark Realize diff --git a/.gemini/skills/truthmark-realize/support/procedure.md b/.gemini/skills/truthmark-realize/support/procedure.md index c419a77..5b3ba33 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 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.0. Rerun truthmark init after upgrades. # Truthmark Realize @@ -33,7 +33,8 @@ Truthmark hierarchy hints: - Config, when present: .truthmark/config.yml - 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 +- Product truth docs, when present: docs/truthmark/product/**/*.md +- Engineering truth docs, when present: docs/truthmark/engineering/**/*.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 b540f61..246d9cf 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 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.0. Rerun truthmark init after upgrades. Report completion in this shape: @@ -8,7 +8,8 @@ Report completion in this shape: Truth Realize: completed Truth docs used: -- docs/truthmark/truth/authentication/session-timeout.md +- docs/truthmark/product/capabilities/authentication-session.md +- docs/truthmark/engineering/behaviors/authentication-session.md Code updated: - src/auth/session.ts diff --git a/.gemini/skills/truthmark-structure/SKILL.md b/.gemini/skills/truthmark-structure/SKILL.md index ad9ca04..1d90e20 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: 2.1.0 +truthmark-version: 2.2.0 --- # Truthmark Structure diff --git a/.gemini/skills/truthmark-structure/support/procedure.md b/.gemini/skills/truthmark-structure/support/procedure.md index 5112d6e..34f4e41 100644 --- a/.gemini/skills/truthmark-structure/support/procedure.md +++ b/.gemini/skills/truthmark-structure/support/procedure.md @@ -1,29 +1,38 @@ # Truthmark Structure Procedure -Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.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. 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. +- Evidence authority: + - 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. +- Lane classification: + - before writing canonical truth docs, classify the request or change as product-lane, engineering-lane, both-lane, or ambiguous + - product-lane writes belong under docs/truthmark/product and state product promises, boundaries, rationale, decisions, and success criteria + - engineering-lane writes belong under docs/truthmark/engineering and state source-backed current realization, contracts, architecture, workflows, operations, or tests + - both-lane work must write separate product and engineering docs and cross-link them in route YAML with realized_by and realizes, not in doc frontmatter + - ambiguous lane ownership must block or invoke Truth Structure instead of writing a mixed document + - Do not make product docs a summary of engineering docs. Do not make engineering docs a detailed version of product docs. Product truth says what must be true and why. Engineering truth says how the repository currently realizes it. - 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/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. +- Starter truth docs must use closed YAML frontmatter bounded by opening and closing --- lines; include status, truth_kind, and last_reviewed inside that frontmatter. Put source references in the final ## Source References section, not in frontmatter. +- Starter truth docs must use lane-specific templates and keep product and engineering truth in separate files. 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. +Supported kinds: product-capability, engineering-behavior, engineering-contract, engineering-architecture, engineering-workflow, engineering-operations, and engineering-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. +If the template is missing, use lane-specific sections: product truth says what must be true and why; engineering truth says how the repository currently realizes it. 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 docs/truthmark/product/** for product truth destinations +- use docs/truthmark/engineering/** for engineering 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 +- keep active Product Decisions in product truth and Engineering Decisions in engineering truth - preserve unrelated authored content ## New area setup Use when a user asks to onboard a new code area into Truthmark, a new package, controller, domain, or product area lacks bounded truth ownership, or a new product area needs routing and starter truth docs. @@ -41,7 +50,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/truthmark/truth. Treat the configured truth root as a managed semantic root. +Truth Structure owns documentation topology, lane splits, decision relocation, and relationship repair. Do not depend on humans to manually organize docs/truthmark/product or docs/truthmark/engineering. Treat both configured lane roots as managed semantic roots. 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: @@ -49,17 +58,17 @@ Truth-doc ownership gate: - if a target/source doc mixes independent owners, spans unrelated behaviors, acts as an index, or needs cross-owner edits, do not patch or in-place repair it - if a truth doc mixes independent owners, route ownership is broad, or a split is required for bounded ownership, split and reroute into bounded truth docs when safe; otherwise block with manual-review files - report Ownership reviewed, Structure required, Truth docs split, Truth docs restructured, or Blocked reason as applicable -Product Decisions/Rationale preservation gate: -- before any truth-doc split, restructure, or shape repair, inventory existing Product Decisions and Rationale sections in every source or touched truth doc -- preserve each current decision and rationale in the bounded owner doc it governs; when splitting, move it to the new owner doc rather than deleting it or leaving it in an index +Decision/Rationale preservation gate: +- before any truth-doc split, restructure, or shape repair, inventory existing Product Decisions, Engineering Decisions, and Rationale sections in every source or touched truth doc +- preserve each current decision and rationale in the correct product or engineering lane owner; when splitting, move it to the new owner doc rather than deleting it or leaving it in an index - 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 +- after the edit, verify every touched truth doc keeps lane-appropriate decision/rationale sections and every pre-existing entry is preserved, moved, narrowed, removed with evidence, or blocked Topology pressure signals: - one area maps broad code such as src/**, app/**, server/**, services/**, or packages/** - one area maps multiple unrelated controllers, route groups, services, or bounded contexts - one truth doc owns unrelated behaviors or unrelated endpoint families -- the configured truth root has many direct non-index docs +- either configured lane 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/routes/areas/** @@ -72,9 +81,10 @@ 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/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 +- create engineering behavior truth docs under docs/truthmark/engineering only when behavior lacks a current doc +- create product truth docs under docs/truthmark/product only when product promise, boundary, rationale, or user-visible capability truth is in scope - README.md files are indexes, not Truth Sync targets -- prefer bounded leaf truth docs at //.md +- prefer bounded product docs under product/capabilities or product/decisions and engineering docs under engineering//.md - keep behavior truth docs behavior-oriented, not endpoint-oriented - keep API endpoint details in the nearest contract truth doc when such a doc exists - update routing so future Truth Sync can target small docs @@ -88,13 +98,13 @@ Truth-doc shape repair gate: - preserve supported claims; remove, narrow, or block unsupported or stale claims - report docs restructured and why a narrow edit was not sufficient Evidence Gate: -- apply the Evidence Gate before finishing when Truth Structure writes routed docs, ownership claims, Product Decisions, or Rationale +- apply the Evidence Gate before finishing when Truth Structure writes routed docs, ownership claims, lane-specific decisions, or rationale - support ownership/behavior claims with topology or primary checkout evidence from layout, implementation boundaries, docs, config, route files, tests, templates, schemas, or contracts - tests/examples/canonical docs corroborate; remove, narrow, or block unsupported claims Maintain architecture docs only for structure-level changes: system structure, module boundaries, runtime topology, persistence boundaries, cross-cutting contracts, or generated-surface ownership. Keep ordinary behavior, endpoints, UI copy, validation rules, and bug fixes in behavior or contract docs unless they change those boundaries. -- Do not finish topology repair with routed canonical current-truth docs missing Product Decisions or Rationale sections. -- If an existing canonical doc lacks either section, add the missing heading beside Current Behavior with a concise current-state placeholder or active decision. +- Do not finish topology repair with mixed product/engineering authority in a single canonical truth doc. +- If an existing canonical doc has wrong-lane sections, split or move them into the correct product or engineering lane. Portable fallback: - If this skill surface is unavailable, perform the same workflow directly from committed repository files. - Do not require the truthmark CLI. @@ -104,7 +114,8 @@ Truthmark hierarchy hints: - Config, when present: .truthmark/config.yml - 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 +- Product truth docs, when present: docs/truthmark/product/**/*.md +- Engineering truth docs, when present: docs/truthmark/engineering/**/*.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. +Product decisions belong in product truth; engineering, architecture, contract, workflow, and operational decisions belong in engineering truth. diff --git a/.gemini/skills/truthmark-structure/support/report-template.md b/.gemini/skills/truthmark-structure/support/report-template.md index 1be260b..7d1ae37 100644 --- a/.gemini/skills/truthmark-structure/support/report-template.md +++ b/.gemini/skills/truthmark-structure/support/report-template.md @@ -1,13 +1,14 @@ # Truthmark Structure Report Template -Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.0. Rerun truthmark init after upgrades. Report completion in this shape: ```md Truth Structure: completed Topology reviewed: - controllers: src/auth/** -- docs root: docs/truthmark/truth +- product docs root: docs/truthmark/product +- engineering docs root: docs/truthmark/engineering - route files: docs/truthmark/routes/areas.md Areas reviewed: - src/auth/** @@ -16,12 +17,14 @@ Routing updated: Initial truth boundary: - Area: Authentication - Code: src/auth/** -- Truth owner: docs/truthmark/truth/authentication/session.md +- Product owner: docs/truthmark/product/capabilities/authentication-session.md +- Engineering owner: docs/truthmark/engineering/behaviors/authentication-session.md - Scope: session behavior only Truth docs created: -- docs/truthmark/truth/authentication/session.md +- docs/truthmark/product/capabilities/authentication-session.md +- docs/truthmark/engineering/behaviors/authentication-session.md Truth docs split: -- docs/truthmark/truth/authentication/README.md -> docs/truthmark/truth/authentication/session.md +- docs/truthmark/truth/authentication/README.md -> docs/truthmark/product/capabilities/authentication-session.md and docs/truthmark/engineering/behaviors/authentication-session.md Truth docs restructured: - docs/truthmark/truth/authentication/README.md Evidence checked: diff --git a/.gemini/skills/truthmark-structure/support/subagents-and-leases.md b/.gemini/skills/truthmark-structure/support/subagents-and-leases.md index bd8594e..19aa831 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 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.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 6a6fbd4..586f907 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: 2.1.0 +truthmark-version: 2.2.0 --- # Truthmark Sync diff --git a/.gemini/skills/truthmark-sync/helper-manifest.yml b/.gemini/skills/truthmark-sync/helper-manifest.yml index dd0153a..1f9a1f1 100644 --- a/.gemini/skills/truthmark-sync/helper-manifest.yml +++ b/.gemini/skills/truthmark-sync/helper-manifest.yml @@ -1,8 +1,8 @@ -# Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. +# Generated by Truthmark 2.2.0. Rerun truthmark init after upgrades. helpers: validate-sync-report: optional: true - runner: truthmark>=2.1.0 + runner: truthmark>=2.2.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>=2.1.0 + runner: truthmark>=2.2.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 6c44128..885d6a1 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 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.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>=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 +- validate-sync-report: optional truthmark>=2.2.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.2.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 ff0f6f7..3026dce 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 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.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. @@ -10,10 +10,19 @@ Parent workflow: 1. Inspect git status, staged changes, unstaged changes, and untracked files directly. 2. Inspect .truthmark/config.yml and configured route files only when they exist; then inspect relevant canonical docs. 3. Identify functional-code changes and the nearest truth docs or routing repairs. -4. 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. -5. Code verification is parent-owned: follow repository instructions and task context, and report what ran or why it did not run. -6. Dispatch bounded Truth Sync workers only when the host supports subagent dispatch and the acting agent chooses that path; otherwise execute the same sync task inline. +4. Evidence authority: + - 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. +5. Lane classification gate: + - before writing canonical truth docs, classify the request or change as product-lane, engineering-lane, both-lane, or ambiguous + - product-lane writes belong under docs/truthmark/product and state product promises, boundaries, rationale, decisions, and success criteria + - engineering-lane writes belong under docs/truthmark/engineering and state source-backed current realization, contracts, architecture, workflows, operations, or tests + - both-lane work must write separate product and engineering docs and cross-link them in route YAML with realized_by and realizes, not in doc frontmatter + - ambiguous lane ownership must block or invoke Truth Structure instead of writing a mixed document + - Do not make product docs a summary of engineering docs. Do not make engineering docs a detailed version of product docs. Product truth says what must be true and why. Engineering truth says how the repository currently realizes it. +6. Update engineering truth first after code changes. Update product truth only when implemented user-visible product promise or capability boundary changed and explicit source/user evidence supports it; otherwise report product-lane review needed. +7. Code verification is parent-owned: follow repository instructions and task context, and report what ran or why it did not run. +8. Dispatch bounded Truth Sync workers only when the host supports subagent dispatch and the acting agent chooses that path; otherwise execute the same sync task inline. Topology quality gate: - before updating truth docs, verify the changed code resolves to a specific behavior-owned area and bounded truth owner - if routing is missing, stale, broad, overloaded, catch-all route only, or cannot map changed code to a bounded truth owner, do not create another generic truth doc @@ -23,22 +32,23 @@ Topology quality gate: - README.md files are indexes, not Truth Sync targets - must not append behavior details to a README.md index - create or update a bounded leaf truth doc when behavior changes do not fit an existing leaf doc +- write engineering truth under docs/truthmark/engineering; product truth updates under docs/truthmark/product are allowed only for explicit current product behavior changes Truth-doc ownership gate: - before editing or relying on changed functional files and impacted truth docs, verify each target/source truth doc is a bounded owner for the behavior - if a target/source doc mixes independent owners, spans unrelated behaviors, acts as an index, or needs cross-owner edits, do not patch or in-place repair it - if an impacted doc is broad, mixed-owner, index-like, or the update spans independent behavior owners, run Truth Structure before syncing when safe and in scope; otherwise block and recommend Truth Structure - report Ownership reviewed, Structure required, Truth docs split, Truth docs restructured, or Blocked reason as applicable -Product Decisions/Rationale preservation gate: -- before any truth-doc split, restructure, or shape repair, inventory existing Product Decisions and Rationale sections in every source or touched truth doc -- preserve each current decision and rationale in the bounded owner doc it governs; when splitting, move it to the new owner doc rather than deleting it or leaving it in an index +Decision/Rationale preservation gate: +- before any truth-doc split, restructure, or shape repair, inventory existing Product Decisions, Engineering Decisions, and Rationale sections in every source or touched truth doc +- preserve each current decision and rationale in the correct product or engineering lane owner; when splitting, move it to the new owner doc rather than deleting it or leaving it in an index - 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 +- after the edit, verify every touched truth doc keeps lane-appropriate decision/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 template under the configured Truthmark templates root. -Supported kinds: behavior, contract, architecture, workflow, operations, and test-behavior. +Supported kinds: product-capability, engineering-behavior, engineering-contract, engineering-architecture, engineering-workflow, engineering-operations, and engineering-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. +If the template is missing, use lane-specific sections: product truth says what must be true and why; engineering truth says how the repository currently realizes it. 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. @@ -51,7 +61,7 @@ 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. Evidence Gate: - route-first: map changed functional files to bounded route owners and primary canonical docs -- review new or changed behavior-bearing claims only in touched docs, route ownership, Product Decisions, and Rationale +- review new or changed behavior-bearing claims only in touched docs, route ownership, lane-specific decisions, and rationale - support claims with primary checkout evidence: implementation, config, routing, generated templates, schemas, or contract definitions - tests/examples/canonical docs corroborate; they are not sole proof when implementation conflicts - remove, narrow, or block unsupported claims @@ -63,7 +73,7 @@ Optional validation tooling: - you may run truthmark check when local tooling is available - do not require the truthmark binary; direct checkout inspection is the canonical path - optional validation must not replace agent judgment about docs and routing -- update Product Decisions and Rationale when a behavior change comes from a decision change +- update Product Decisions only in product truth and Engineering Decisions only in engineering truth when evidence supports the lane-specific decision change Helper status reporting: - Validate the report body before adding this validator's own success status; the body may omit `validate-sync-report` while validation is pending. - After `truthmark validate sync-report --json` returns `data.validation.ok: true`, append or update `validate-sync-report: ran, passed` in the final report. @@ -74,10 +84,11 @@ Truthmark hierarchy hints: - Config, when present: .truthmark/config.yml - 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 +- Product truth docs, when present: docs/truthmark/product/**/*.md +- Engineering truth docs, when present: docs/truthmark/engineering/**/*.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. +Product decisions belong in product truth; engineering, architecture, contract, workflow, and operational decisions belong in engineering truth. Parent post-sync verification: - verify only truth docs and leased truth routing files changed during sync - block on any unrelated diff caused by the sync step diff --git a/.gemini/skills/truthmark-sync/support/report-template.md b/.gemini/skills/truthmark-sync/support/report-template.md index 4dfa42d..5331249 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 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.0. Rerun truthmark init after upgrades. Report completion in this shape: ```md @@ -13,7 +13,7 @@ Ownership reviewed: - docs/truthmark/routes/areas.md Truth docs updated: -- docs/truthmark/truth/repository/overview.md +- docs/truthmark/engineering/repository/overview.md Evidence checked: - Claim: Session timeout behavior is documented in the mapped repository truth doc. diff --git a/.gemini/skills/truthmark-sync/support/subagents-and-leases.md b/.gemini/skills/truthmark-sync/support/subagents-and-leases.md index 6c5c65f..2173a12 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 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.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/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000..7364ebf --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,52 @@ +name: Bug report +description: Report a reproducible Truthmark bug +title: "bug: " +labels: [bug] +body: + - type: markdown + attributes: + value: | + Thanks for helping improve Truthmark. Please remove secrets and private repository content before submitting. + - type: input + id: version + attributes: + label: Truthmark version or commit + description: Paste the package version, commit, or branch you tested. + validations: + required: true + - type: input + id: environment + attributes: + label: Environment + description: OS, Node.js version, npm version, and package manager. + placeholder: "macOS 15, Node 22, npm 10" + validations: + required: true + - type: textarea + id: steps + attributes: + label: Reproduction steps + description: Include the command or workflow, relevant config/routes/truth-doc snippets, and minimal steps. + placeholder: | + 1. Run `truthmark ...` + 2. Observe ... + validations: + required: true + - type: textarea + id: expected + attributes: + label: Expected behavior + validations: + required: true + - type: textarea + id: actual + attributes: + label: Actual behavior + description: Include command output or diagnostics when useful. + validations: + required: true + - type: textarea + id: notes + attributes: + label: Additional context + description: Link related PRs, docs, generated surfaces, or screenshots if helpful. diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..8dea006 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,8 @@ +blank_issues_enabled: false +contact_links: + - name: Security vulnerability + url: https://github.com/merlinhu1/truthmark/security/advisories/new + about: Please report exploitable security issues privately when GitHub private reporting is available. + - name: Contribution guide + url: https://github.com/merlinhu1/truthmark/blob/main/CONTRIBUTING.md + about: Read setup and verification notes before opening a contribution PR. diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 0000000..76b5aa8 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,40 @@ +name: Feature request +description: Propose a Truthmark behavior, workflow, or documentation improvement +title: "feat: " +labels: [enhancement] +body: + - type: markdown + attributes: + value: | + Please keep proposals aligned with Truthmark's local-first, Git-reviewable repository-truth boundary. + - type: textarea + id: problem + attributes: + label: Problem + description: What user, maintainer, reviewer, or agent workflow problem would this solve? + validations: + required: true + - type: textarea + id: proposal + attributes: + label: Proposed change + description: Describe the smallest useful change. + validations: + required: true + - type: textarea + id: boundary + attributes: + label: Product-boundary check + description: Explain how this stays local-first, host-native, branch-scoped, and Git-reviewable. + validations: + required: true + - type: textarea + id: alternatives + attributes: + label: Alternatives considered + description: Optional; include workarounds or rejected designs. + - type: textarea + id: verification + attributes: + label: Verification idea + description: What test, fixture, generated diff, or validation command would prove this works? diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..228af65 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,30 @@ +## Summary + +- + +## Type of Change + +- [ ] Bug fix +- [ ] Feature or behavior change +- [ ] Documentation-only change +- [ ] Generated workflow surface update +- [ ] Release/package change + +## Truthmark Impact + +- [ ] Functional code changed and relevant tests were run +- [ ] Truth docs or routing were updated when behavior changed +- [ ] Generated surfaces were refreshed/reviewed when templates or renderers changed +- [ ] Not applicable; explain why: + +## Verification + +List the commands you ran and the result: + +```text + +``` + +## Review Notes + +Call out any intentional skipped checks, unresolved follow-ups, or areas where reviewer attention is needed. diff --git a/.github/agents/truth-claim-verifier.md b/.github/agents/truth-claim-verifier.md index 0502791..0f51a78 100644 --- a/.github/agents/truth-claim-verifier.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 2.1.0. Rerun truthmark init after upgrades. +# Generated by Truthmark 2.2.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.md b/.github/agents/truth-doc-reviewer.md index 62db034..c709941 100644 --- a/.github/agents/truth-doc-reviewer.md +++ b/.github/agents/truth-doc-reviewer.md @@ -4,10 +4,10 @@ description: Read-only Truthmark doc reviewer for shape, decision, rationale, an tools: [read, search] --- -# Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. +# Generated by Truthmark 2.2.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. +Review assigned canonical truth docs for compact frontmatter, required template sections, final Source References entries, Evidence checked entries, and lane-appropriate decision sections (Product Decisions in product truth, Engineering Decisions in engineering truth). Flag README.md files used as behavior truth targets, mixed-owner docs, and shape repairs that should move to Truth Structure. Do not edit files, stage changes, or rewrite docs. Return JSON only with keys: scope, filesReviewed, findings, evidence, confidence, recommendedWorkflow, notes. diff --git a/.github/agents/truth-doc-writer.md b/.github/agents/truth-doc-writer.md index 118ecdf..91e6f2e 100644 --- a/.github/agents/truth-doc-writer.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 2.1.0. Rerun truthmark init after upgrades. +# Generated by Truthmark 2.2.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.md b/.github/agents/truth-route-auditor.md index ffdd0f4..8c45d89 100644 --- a/.github/agents/truth-route-auditor.md +++ b/.github/agents/truth-route-auditor.md @@ -4,12 +4,19 @@ description: Read-only Truthmark route auditor for bounded routing and ownership tools: [read, search] --- -# Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. +# Generated by Truthmark 2.2.0. Rerun truthmark init after upgrades. Stay read-only. Audit one bounded Truthmark route, area, or doc shard assigned by the parent. Inspect .truthmark/config.yml and route files only when they exist; then inspect mapped truth docs and relevant implementation files directly. +Use a route-first bounded strategy: narrow audits inspect only the routed area and directly linked counterpart docs; root-wide health first builds a cheap route-map/index from route files, then inspects only mismatches and linked leaves. Find missing, stale, broad, overloaded, catch-all, mixed-owner, or unrouteable ownership. +Validate route ownership against lane-specific roots and route kind: +- confirm mapped truth docs resolve to the correct lane root (product or engineering) for their kind +- flag mismatch between assigned route kind and resolved doc kind (for example, product-capability routed to engineering paths) +- verify route-doc linkage for lane pairings via realized_by and realizes before recommending edits +- inspect product counterparts for engineering docs only when route YAML claims a product relationship, or when the parent explicitly asks for user-visible product coverage +- treat missing product links for user-visible engineering docs as a second-pass diagnostic, not a default full-document read. Do not edit files, stage changes, or propose broad rewrites. Return JSON only with keys: scope, filesReviewed, findings, evidence, confidence, recommendedWorkflow, notes. recommendedWorkflow must be one of: none, truthmark-document, truthmark-structure. diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 5202bc3..9bfa8a8 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -9,8 +9,8 @@ Agent-specific: ## Truthmark Workflow -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. +Generated by Truthmark 2.2.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/product/**/*.md and docs/truthmark/engineering/**/*.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 e1f326b..001703c 100644 --- a/.github/prompts/truthmark-check.prompt.md +++ b/.github/prompts/truthmark-check.prompt.md @@ -3,75 +3,14 @@ agent: 'agent' 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.' --- ---- -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: 2.1.0 ---- +This prompt is the GitHub Copilot entrypoint for Truthmark Check. -# Truthmark Check +Do not invoke another Truthmark command from here. -Use this skill to audit repository truth health. +Read these host-local files in order only as needed: +- .github/skills/truthmark-check/SKILL.md +- .github/skills/truthmark-check/support/procedure.md +- .github/skills/truthmark-check/support/report-template.md +- .github/skills/truthmark-check/support/subagents-and-leases.md -Invocations: OpenCode /skill truthmark-check; Codex /truthmark-check or $truthmark-check; Claude Code /truthmark-check; GitHub Copilot /truthmark-check; Gemini CLI /truthmark:check. - -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/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 -- check that canonical behavior docs keep active Product Decisions and Rationale sections -- optionally run truthmark check when local tooling is available -- must not require the truthmark binary; direct inspection is always valid -- report issues and suggested fixes without silently rewriting unrelated files -- if follow-up docs edits are needed for mixed-owner docs, run or recommend Truth Structure before editing -Evidence Gate: -- support each finding and suggested fix with evidence from config, route files, canonical docs, implementation, templates, or tests -- canonical docs are context, not sole proof when implementation conflicts -- remove unsupported findings or mark open questions; validate changed claims if you edit docs - -Copilot custom-agent mode: -- use automatically when this workflow runs in Copilot and the parent agent chooses bounded custom-agent fan-out -- dispatch read-only project custom agents only: @truth-route-auditor, @truth-claim-verifier, @truth-doc-reviewer -- custom agents inspect checkout evidence directly, return structured findings, and must not edit files -- 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 the final Truth Check report - -Truthmark hierarchy hints: -- Config, when present: .truthmark/config.yml -- 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. - -Report completion in this shape: - -```md -Truth Check: completed - -Files reviewed: -- docs/truthmark/routes/areas.md - -Issues found: -- none - -Fixes suggested: -- none - -Evidence checked: -- Finding: The root route index is present and maps repository truth owners. - Evidence: docs/truthmark/routes/areas.md:1 - Suggested fix: none - Confidence: high - -Validation: -- truthmark check -``` +If skill entrypoints are unavailable, use the host's direct evidence-first manual fallback procedure. diff --git a/.github/prompts/truthmark-document.prompt.md b/.github/prompts/truthmark-document.prompt.md index c88472a..d7f903d 100644 --- a/.github/prompts/truthmark-document.prompt.md +++ b/.github/prompts/truthmark-document.prompt.md @@ -3,131 +3,16 @@ agent: 'agent' 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.' --- ---- -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: 2.1.0 ---- +This prompt is the GitHub Copilot entrypoint for Truthmark Document. -# Truthmark Document +Do not invoke another Truthmark command from here. -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. +Read these host-local files in order only as needed: +- .github/skills/truthmark-document/SKILL.md +- .github/skills/truthmark-document/support/procedure.md +- .github/skills/truthmark-document/support/report-template.md +- .github/skills/truthmark-document/support/subagents-and-leases.md +- .github/skills/truthmark-document/helper-manifest.yml +- .github/skills/truthmark-document/support/helper-policy.md -Truth Document is manual and implementation-first: - -- run only when the user explicitly asks to generate or update truth docs for existing behavior, or when Truth Sync, Truth Check, or Truth Structure reports implemented behavior that lacks canonical truth docs -- inspect .truthmark/config.yml and configured route files only when they exist; then inspect existing canonical docs, implementation code, and tests 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. -- document current implemented behavior; do not invent future behavior or planned endpoints -- 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 -- keep feature README.md files as indexes rather than truth-document targets -- create or update bounded leaf truth docs when behavior does not fit an existing leaf doc -- keep behavior truth docs behavior-oriented, not endpoint-oriented, unless the endpoint itself is the behavior boundary -- keep API endpoint details in the nearest contract truth doc when such a doc owns the API contract -- preserve unrelated authored content -Truth-doc ownership gate: -- before editing or relying on the implemented behavior and candidate truth docs, verify each target/source truth doc is a bounded owner for the behavior -- if a target/source doc mixes independent owners, spans unrelated behaviors, acts as an index, or needs cross-owner edits, do not patch or in-place repair it -- if the target doc is broad, mixed-owner, index-like, or the documented behavior spans independent owners, run Truth Structure first when safe and in scope; otherwise block and recommend Truth Structure -- report Ownership reviewed, Structure required, Truth docs split, Truth docs restructured, or Blocked reason as applicable -Product Decisions/Rationale preservation gate: -- before any truth-doc split, restructure, or shape repair, inventory existing Product Decisions and Rationale sections in every source or touched truth doc -- preserve each current decision and rationale in the bounded owner doc it governs; when splitting, move it to the new owner doc rather than deleting it or leaving it in an index -- 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 -Evidence Gate: -- route-first: map the documented behavior to bounded route owners and primary canonical docs -- review new or changed behavior-bearing claims only in touched docs, route ownership, Product Decisions, and Rationale -- support claims with primary checkout evidence: implementation, config, routing, generated templates, schemas, or contract definitions -- tests/examples/canonical docs corroborate; they are not sole proof when implementation conflicts -- remove, narrow, or block unsupported claims -- if no truth doc changed, report why current truth was already sufficient or why documentation was blocked -Copilot custom-agent mode: -- use automatically when this workflow runs in Copilot and the parent agent chooses bounded custom-agent fan-out -- dispatch read-only project custom agents for verification: @truth-route-auditor, @truth-claim-verifier -- read-only custom agents inspect checkout evidence directly, return structured findings, and must not edit files -- parent supplies bounded evidence shards; read-only custom agents must not preload host instruction files or repo-wide policy docs unless assigned as evidence -- dispatch write-capable project custom agents only with explicit write leases: @truth-doc-writer -- each write lease must name objective, required reads, allowed writes, forbidden writes, evidence, verification, and report fields -- write workers must stop when a required edit is off-lease and report status, filesChanged, evidence, offLeaseChanges, blockers, and notes -- parent must inspect the actual checkout diff against each lease before accepting a worker report -- Parent agent owns Truth Document acceptance, lease validation, and final report -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 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 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 -- use Truth Structure for ownership splits; do not treat broad or mixed-owner docs as in-place repair work -- repair shape when a narrow edit would make truth worse: missing template sections, stale evidence conflicts, cross-section updates within one owner, or wrong frontmatter/source/headings -- preserve supported claims; remove, narrow, or block unsupported or stale claims -- report docs restructured and why a narrow edit was not sufficient -Maintain architecture docs only for structure-level changes: system structure, module boundaries, runtime topology, persistence boundaries, cross-cutting contracts, or generated-surface ownership. -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/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. -Helper status reporting: -- Validate the report body before adding this validator's own success status; the body may omit `validate-document-report` while validation is pending. -- After `truthmark validate document-report --json` returns `data.validation.ok: true`, append or update `validate-document-report: ran, passed` in the final report. -- If the installed Truthmark CLI is unavailable or the helper is skipped, record `validate-document-report: skipped, ` and manually validate the report shape. -- Record `validate-write-lease: ran, passed` only after validating a concrete write lease; otherwise use a truthful skipped status such as `skipped, no write lease used`. -- Helper output is derived evidence and never replaces direct checkout inspection, evidence review, or parent acceptance. -Parent post-document verification: -- verify only truth docs and leased truth routing files changed during document work -- block on functional code, generated host surfaces, or unrelated diffs caused by document work -- for each write lease, validate the worker report against the actual worker diff, allowedWrites, forbiddenWrites, identity fields, filesChanged, offLeaseChanges, blockers, and required report fields before accepting it -- verify the final report records ownership review, structure requirement, restructure, routing update, or blocked reason when applicable - -Report completion in this shape: -```md -Truth Document: completed - -Implementation reviewed: -- src/routing/area-resolver.ts - -Ownership reviewed: -- docs/truthmark/routes/areas.md - -Truth docs created: -- docs/truthmark/truth/contracts.md - -Truth docs updated: -- docs/truthmark/truth/check-diagnostics.md - -Truth docs restructured: -- docs/truthmark/truth/check-diagnostics.md - -Routing updated: -- 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/routes/areas.md:9 - Result: supported - -Helper scripts: -- validate-write-lease: skipped, no write lease used - -Notes: -- Documented routing and behavior from route handlers and tests. -``` +If skill entrypoints are unavailable, use the host's direct evidence-first manual fallback procedure. diff --git a/.github/prompts/truthmark-preview.prompt.md b/.github/prompts/truthmark-preview.prompt.md index a3bdc50..34b8a9a 100644 --- a/.github/prompts/truthmark-preview.prompt.md +++ b/.github/prompts/truthmark-preview.prompt.md @@ -3,88 +3,14 @@ agent: 'agent' 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.' --- ---- -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: 2.1.0 ---- +This prompt is the GitHub Copilot entrypoint for Truthmark Preview. -Use this skill only when the user explicitly asks to preview Truthmark routing or workflow choice before edits. +Do not invoke another Truthmark command from here. -Invocations: OpenCode /skill truthmark-preview; Codex /truthmark-preview or $truthmark-preview; Claude Code /truthmark-preview; GitHub Copilot /truthmark-preview; Gemini CLI /truthmark:preview. +Read these host-local files in order only as needed: +- .github/skills/truthmark-preview/SKILL.md +- .github/skills/truthmark-preview/support/procedure.md +- .github/skills/truthmark-preview/support/report-template.md +- .github/skills/truthmark-preview/support/subagents-and-leases.md -Truth Preview is read-only. Its report is intended, not authorized. - -Purpose: -- preview the likely Truthmark workflow, route owner, target files, expected write classes, suggested subagent use, and blocking ambiguity before edits happen -- hand off to the selected workflow after user approval -- keep the selector thin so agents can avoid loading or acting through heavier workflows prematurely - -Read: -- .truthmark/config.yml, 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. - -Do not: -- must not edit files -- must not create truth docs -- must not update routing -- must not run Truth Sync automatically -- must not replace Truth Check -- must not claim final correctness -- must not issue write leases -- must not mutate code - -Suggested subagent use: -- optional read-only verifier: truth_route_auditor -- write workers: none -- leases needed: none - -Truthmark hierarchy hints: -- Config, when present: .truthmark/config.yml -- 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 -Truth Preview: completed - -Requested outcome: -- preview likely Truthmark workflow routing before edits - -Likely workflow: -- truthmark-document - -Why this workflow: -- positive trigger: document existing implemented behavior -- negative triggers considered: functional-code change, doc-first implementation, topology repair, truth audit -- forbidden adjacency considered: must not edit functional code - -Likely route owner: -- 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/truthmark/truth/example.md - -Suggested subagent use: -- read-only verifiers: truth_route_auditor -- write workers: none in Preview -- leases needed: none in Preview - -Blocking ambiguity: -- none identified in preview - -Handoff: -- Run the selected Truthmark workflow after user approval. -``` +If skill entrypoints are unavailable, use the host's direct evidence-first manual fallback procedure. diff --git a/.github/prompts/truthmark-realize.prompt.md b/.github/prompts/truthmark-realize.prompt.md index cc20366..4f694dd 100644 --- a/.github/prompts/truthmark-realize.prompt.md +++ b/.github/prompts/truthmark-realize.prompt.md @@ -3,65 +3,13 @@ agent: 'agent' 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.' --- ---- -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: 2.1.0 ---- +This prompt is the GitHub Copilot entrypoint for Truthmark Realize. -# Truthmark Realize +Do not invoke another Truthmark command from here. -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. - -Truth Realize is doc-first: - -- truth docs lead -- code follows -- Truth Realize never edits the truth docs it is realizing - -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/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: -- before editing or relying on source truth docs before writing code, verify each target/source truth doc is a bounded owner for the behavior -- if a target/source doc mixes independent owners, spans unrelated behaviors, acts as an index, or needs cross-owner edits, do not patch or in-place repair it -- if a source truth doc is broad, mixed-owner, index-like, unrouteable, stale, or conflicts with implementation evidence, block before writing code and recommend Truth Structure or Truth Document -- report Ownership reviewed, Structure required, Truth docs split, Truth docs restructured, or Blocked reason as applicable -4. Update functional code only so implementation matches bounded, current truth claims from the source docs. -5. Do not edit truth docs or truth routing while realizing those docs. -6. Run relevant tests for the changed code. -7. Report changed code files and verification steps. -Truthmark hierarchy hints: -- Config, when present: .truthmark/config.yml -- 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: - -- may read truth docs, routing docs, and relevant functional code -- may write functional code only -- must not edit truth docs or truth routing while realizing those docs - -Report completion in this shape: - -```md -Truth Realize: completed - -Truth docs used: -- docs/truthmark/truth/authentication/session-timeout.md - -Code updated: -- src/auth/session.ts - -Verification: -- npm test -- auth -``` +Read these host-local files in order only as needed: +- .github/skills/truthmark-realize/SKILL.md +- .github/skills/truthmark-realize/support/procedure.md +- .github/skills/truthmark-realize/support/report-template.md +If skill entrypoints are unavailable, use the host's direct evidence-first manual fallback procedure. diff --git a/.github/prompts/truthmark-structure.prompt.md b/.github/prompts/truthmark-structure.prompt.md index 2d5e5de..22a3578 100644 --- a/.github/prompts/truthmark-structure.prompt.md +++ b/.github/prompts/truthmark-structure.prompt.md @@ -3,154 +3,14 @@ agent: 'agent' 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.' --- ---- -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: 2.1.0 ---- +This prompt is the GitHub Copilot entrypoint for 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. -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/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/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. -Copilot custom-agent mode: -- use automatically when this workflow runs in Copilot and the parent agent chooses bounded custom-agent fan-out -- dispatch read-only project custom agents only: @truth-route-auditor -- custom agents inspect checkout evidence directly, return structured findings, and must not edit files -- 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 +Do not invoke another Truthmark command from here. -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 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 -## New area setup -Use when a user asks to onboard a new code area into Truthmark, a new package, controller, domain, or product area lacks bounded truth ownership, or a new product area needs routing and starter truth docs. -Do: -- inspect the named code area -- infer bounded product or behavior ownership -- choose the owning route when ownership is clear; otherwise propose the route and block for review -- create or update the child route entry or file -- create starter truth docs only where current truth is missing -- report the initial truth boundary -Do not: -- do not edit functional code -- do not perform full behavior documentation unless evidence is inspected and the task explicitly asks for it -- do not patch broad or mixed-owner docs in place -- 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/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: -- before editing or relying on candidate route owners and current truth docs, verify each target/source truth doc is a bounded owner for the behavior -- if a target/source doc mixes independent owners, spans unrelated behaviors, acts as an index, or needs cross-owner edits, do not patch or in-place repair it -- if a truth doc mixes independent owners, route ownership is broad, or a split is required for bounded ownership, split and reroute into bounded truth docs when safe; otherwise block with manual-review files -- report Ownership reviewed, Structure required, Truth docs split, Truth docs restructured, or Blocked reason as applicable -Product Decisions/Rationale preservation gate: -- before any truth-doc split, restructure, or shape repair, inventory existing Product Decisions and Rationale sections in every source or touched truth doc -- preserve each current decision and rationale in the bounded owner doc it governs; when splitting, move it to the new owner doc rather than deleting it or leaving it in an index -- 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 -Topology pressure signals: -- one area maps broad code such as src/**, app/**, server/**, services/**, or packages/** -- one area maps multiple unrelated controllers, route groups, services, or bounded contexts -- one truth doc owns unrelated behaviors or unrelated endpoint families -- 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/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 -- more than 8 truth docs mapped to one area -- more than 5 controllers mapped through one catch-all area -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/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 -- keep behavior truth docs behavior-oriented, not endpoint-oriented -- keep API endpoint details in the nearest contract truth doc when such a doc exists -- update routing so future Truth Sync can target small docs -- preserve existing authored docs; move or rewrite only when needed to remove ambiguity -- report Truth docs split when one broad or mixed-owner truth doc becomes multiple bounded docs -Truth-doc shape repair gate: -- Truth Structure may restructure broader routed docs when topology, ownership, or doc-shape repair is already in scope. -- repair shape in place only after the ownership gate confirms the doc is the right bounded owner -- use Truth Structure for ownership splits; do not treat broad or mixed-owner docs as in-place repair work -- repair shape when a narrow edit would make truth worse: missing template sections, stale evidence conflicts, cross-section updates within one owner, or wrong frontmatter/source/headings -- preserve supported claims; remove, narrow, or block unsupported or stale claims -- report docs restructured and why a narrow edit was not sufficient -Evidence Gate: -- apply the Evidence Gate before finishing when Truth Structure writes routed docs, ownership claims, Product Decisions, or Rationale -- support ownership/behavior claims with topology or primary checkout evidence from layout, implementation boundaries, docs, config, route files, tests, templates, schemas, or contracts -- tests/examples/canonical docs corroborate; remove, narrow, or block unsupported claims -Maintain architecture docs only for structure-level changes: system structure, module boundaries, runtime topology, persistence boundaries, cross-cutting contracts, or generated-surface ownership. -Keep ordinary behavior, endpoints, UI copy, validation rules, and bug fixes in behavior or contract docs unless they change those boundaries. -- Do not finish topology repair with routed canonical current-truth docs missing Product Decisions or Rationale sections. -- If an existing canonical doc lacks either section, add the missing heading beside Current Behavior with a concise current-state placeholder or active decision. -Portable fallback: -- If this skill surface is unavailable, perform the same workflow directly from committed repository files. -- Do not require the truthmark CLI. -- Inspect .truthmark/config.yml and configured route files only when they exist; then inspect canonical docs and representative implementation code. -- 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/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. -Report completion in this shape: -```md -Truth Structure: completed -Topology reviewed: -- controllers: src/auth/** -- docs root: docs/truthmark/truth -- route files: docs/truthmark/routes/areas.md -Areas reviewed: -- src/auth/** -Routing updated: -- docs/truthmark/routes/areas.md -Initial truth boundary: -- Area: Authentication -- Code: src/auth/** -- Truth owner: docs/truthmark/truth/authentication/session.md -- Scope: session behavior only -Truth docs created: -- docs/truthmark/truth/authentication/session.md -Truth docs split: -- docs/truthmark/truth/authentication/README.md -> docs/truthmark/truth/authentication/session.md -Truth docs restructured: -- docs/truthmark/truth/authentication/README.md -Evidence checked: -- Claim: Session behavior belongs to a dedicated Authentication truth owner. - 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. -Notes: -- Added an Authentication area for session behavior. -``` +Read these host-local files in order only as needed: +- .github/skills/truthmark-structure/SKILL.md +- .github/skills/truthmark-structure/support/procedure.md +- .github/skills/truthmark-structure/support/report-template.md +- .github/skills/truthmark-structure/support/subagents-and-leases.md + +If skill entrypoints are unavailable, use the host's direct evidence-first manual fallback procedure. diff --git a/.github/prompts/truthmark-sync.prompt.md b/.github/prompts/truthmark-sync.prompt.md index 26b5352..6c64f0e 100644 --- a/.github/prompts/truthmark-sync.prompt.md +++ b/.github/prompts/truthmark-sync.prompt.md @@ -3,143 +3,16 @@ agent: 'agent' 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.' --- ---- -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: 2.1.0 ---- +This prompt is the GitHub Copilot entrypoint for 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. -Explicit invocation runs immediately. Later functional-code changes reopen the finish-time requirement, and an earlier explicit run satisfies the finish gate only if no later functional-code changes occur. -Skip when changes are documentation-only, formatting-only, clearly behavior-preserving renames with no truth impact, when no Truthmark config exists yet, or when there are no functional code changes. -Parent workflow: -1. Inspect git status, staged changes, unstaged changes, and untracked files directly. -2. Inspect .truthmark/config.yml and configured route files only when they exist; then inspect relevant canonical docs. -3. Identify functional-code changes and the nearest truth docs or routing repairs. -4. 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. -5. Code verification is parent-owned: follow repository instructions and task context, and report what ran or why it did not run. -6. Dispatch bounded Truth Sync workers only when the host supports subagent dispatch and the acting agent chooses that path; otherwise execute the same sync task inline. -Copilot custom-agent mode: -- use automatically when this workflow runs in Copilot and the parent agent chooses bounded custom-agent fan-out -- dispatch read-only project custom agents for verification: @truth-route-auditor, @truth-claim-verifier -- read-only custom agents inspect checkout evidence directly, return structured findings, and must not edit files -- parent supplies bounded evidence shards; read-only custom agents must not preload host instruction files or repo-wide policy docs unless assigned as evidence -- dispatch write-capable project custom agents only with explicit write leases: @truth-doc-writer -- each write lease must name objective, required reads, allowed writes, forbidden writes, evidence, verification, and report fields -- write workers must stop when a required edit is off-lease and report status, filesChanged, evidence, offLeaseChanges, blockers, and notes -- parent must inspect the actual checkout diff against each lease before accepting a worker report -- Parent agent owns Truth Sync acceptance, lease validation, and final report -Topology quality gate: -- before updating truth docs, verify the changed code resolves to a specific behavior-owned area and bounded truth owner -- if routing is missing, stale, broad, overloaded, catch-all route only, or cannot map changed code to a bounded truth owner, do not create another generic truth doc -- run Truth Structure before syncing when topology repair is safe and in scope -- block and recommend Truth Structure when topology repair is unsafe, ambiguous, or outside the current task boundary -- report the route files and changed code paths that require structure repair -- README.md files are indexes, not Truth Sync targets -- must not append behavior details to a README.md index -- create or update a bounded leaf truth doc when behavior changes do not fit an existing leaf doc -Truth-doc ownership gate: -- before editing or relying on changed functional files and impacted truth docs, verify each target/source truth doc is a bounded owner for the behavior -- if a target/source doc mixes independent owners, spans unrelated behaviors, acts as an index, or needs cross-owner edits, do not patch or in-place repair it -- if an impacted doc is broad, mixed-owner, index-like, or the update spans independent behavior owners, run Truth Structure before syncing when safe and in scope; otherwise block and recommend Truth Structure -- report Ownership reviewed, Structure required, Truth docs split, Truth docs restructured, or Blocked reason as applicable -Product Decisions/Rationale preservation gate: -- before any truth-doc split, restructure, or shape repair, inventory existing Product Decisions and Rationale sections in every source or touched truth doc -- preserve each current decision and rationale in the bounded owner doc it governs; when splitting, move it to the new owner doc rather than deleting it or leaving it in an index -- 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 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 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 -- use Truth Structure for ownership splits; do not treat broad or mixed-owner docs as in-place repair work -- repair shape when a narrow edit would make truth worse: missing template sections, stale evidence conflicts, cross-section updates within one owner, or wrong frontmatter/source/headings -- preserve supported claims; remove, narrow, or block unsupported or stale claims -- report docs restructured and why a narrow edit was not sufficient -Maintain architecture docs only for structure-level changes: system structure, module boundaries, runtime topology, persistence boundaries, cross-cutting contracts, or generated-surface ownership. -Keep ordinary behavior, endpoints, UI copy, validation rules, and bug fixes in behavior or contract docs unless they change those boundaries. -Evidence Gate: -- route-first: map changed functional files to bounded route owners and primary canonical docs -- review new or changed behavior-bearing claims only in touched docs, route ownership, Product Decisions, and Rationale -- support claims with primary checkout evidence: implementation, config, routing, generated templates, schemas, or contract definitions -- tests/examples/canonical docs corroborate; they are not sole proof when implementation conflicts -- remove, narrow, or block unsupported claims -- if no impacted doc changed, report why truth was already current or why sync was skipped -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. -Optional validation tooling: -- you may run truthmark check when local tooling is available -- do not require the truthmark binary; direct checkout inspection is the canonical path -- optional validation must not replace agent judgment about docs and routing -- update Product Decisions and Rationale when a behavior change comes from a decision change -Helper status reporting: -- Validate the report body before adding this validator's own success status; the body may omit `validate-sync-report` while validation is pending. -- After `truthmark validate sync-report --json` returns `data.validation.ok: true`, append or update `validate-sync-report: ran, passed` in the final report. -- If the installed Truthmark CLI is unavailable or the helper is skipped, record `validate-sync-report: skipped, ` and manually validate the report shape. -- Record `validate-write-lease: ran, passed` only after validating a concrete write lease; otherwise use a truthful skipped status such as `skipped, no write lease used`. -- 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/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. -Parent post-sync verification: -- verify only truth docs and leased truth routing files changed during sync -- block on any unrelated diff caused by the sync step -- block if functional code changed during sync -- for each write lease, validate the worker report against the actual worker diff, allowedWrites, forbiddenWrites, identity fields, filesChanged, offLeaseChanges, blockers, and required report fields before accepting it -- validate the final report against the structured Truth Sync report contract, including Claim, indented Evidence, and Result values supported, narrowed, removed, or blocked under Evidence checked -- verify the updated docs correspond to the reviewed changed-code surface -- verify the final report records ownership review, structure requirement, split, restructure, or blocked reason when the ownership gate fired -- blocked outcomes must preserve the working tree as-is: no rollback, no post-block cleanup edits, and manual-review reporting of any remaining files -Report completion in this shape: -```md -Truth Sync: completed +Do not invoke another Truthmark command from here. -Changed code reviewed: -- src/auth/session.ts +Read these host-local files in order only as needed: +- .github/skills/truthmark-sync/SKILL.md +- .github/skills/truthmark-sync/support/procedure.md +- .github/skills/truthmark-sync/support/report-template.md +- .github/skills/truthmark-sync/support/subagents-and-leases.md +- .github/skills/truthmark-sync/helper-manifest.yml +- .github/skills/truthmark-sync/support/helper-policy.md -Ownership reviewed: -- docs/truthmark/routes/areas.md - -Truth docs updated: -- 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/routes/areas.md:11 - Result: supported - -Helper scripts: -- validate-write-lease: skipped, no write lease used - -Notes: -- Updated session timeout behavior. -``` -Blocked report example: -```md -Truth Sync: blocked - -Reason: -- routing repair is not allowed - -Files requiring manual review: -- docs/truthmark/routes/areas.md - -Next action: -- update routing metadata and rerun Truth Sync -``` +If skill entrypoints are unavailable, use the host's direct evidence-first manual fallback procedure. diff --git a/.github/skills/truthmark-check/SKILL.md b/.github/skills/truthmark-check/SKILL.md index 1ffbf63..5507e4a 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: 2.1.0 +truthmark-version: 2.2.0 --- # Truthmark Check diff --git a/.github/skills/truthmark-check/support/procedure.md b/.github/skills/truthmark-check/support/procedure.md index 6132ff9..c8c76bd 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 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.0. Rerun truthmark init after upgrades. # Truthmark Check @@ -11,13 +11,31 @@ Invocations: OpenCode /skill truthmark-check; Codex /truthmark-check or $truthma 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/routes/areas.md and relevant child route files under docs/truthmark/routes/areas/ when they exist +- Evidence authority: + - 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. +- Lane classification: + - classify the request or changed surface as product-lane, engineering-lane, both-lane, or ambiguous for reporting only + - product-lane ownership belongs under docs/truthmark/product and describes product promises, boundaries, rationale, decisions, and success criteria + - engineering-lane ownership belongs under docs/truthmark/engineering and describes source-backed current realization, contracts, architecture, workflows, operations, or tests + - both-lane ownership uses separate product and engineering docs cross-linked in route YAML with realized_by and realizes, not in doc frontmatter + - ambiguous lane ownership should be reported as blocked or routed to Truth Structure + - Do not make product docs a summary of engineering docs. Do not make engineering docs a detailed version of product docs. Product truth says what must be true and why. Engineering truth says how the repository currently realizes it. - check that current docs describe current code rather than historical plans +- keep lane and cross-lane checks route-first and bounded: + - for a narrow audit, inspect only the routed area and directly linked counterpart docs + - for root-wide truth health, first build a cheap route-map/index from route files, then inspect only mismatches and linked leaves + - inspect product counterparts for engineering docs only when route YAML claims a product relationship, or when the user explicitly asks for user-visible product coverage +- check lane root/kind alignment for product truth under docs/truthmark/product and engineering truth under docs/truthmark/engineering +- check route YAML cross-lane realized_by and realizes links for existence and lane compatibility +- report missing product links for user-visible engineering docs only as a second-pass review diagnostic, not as default full-document reads or hard errors +- check product docs do not contain engineering execution flow, generated file inventories, or CLI envelope mechanics +- check engineering docs do not contain product promises, product rationale, or Product Decisions sections +- never judge whether a product decision is commercially correct, valuable, prioritized, or desirable - 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 -- check that canonical behavior docs keep active Product Decisions and Rationale sections +- check that canonical docs keep lane-appropriate decisions and rationale sections - optionally run truthmark check when local tooling is available - must not require the truthmark binary; direct inspection is always valid - report issues and suggested fixes without silently rewriting unrelated files @@ -31,7 +49,8 @@ Truthmark hierarchy hints: - Config, when present: .truthmark/config.yml - 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 +- Product truth docs, when present: docs/truthmark/product/**/*.md +- Engineering truth docs, when present: docs/truthmark/engineering/**/*.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. +Product decisions belong in product truth; engineering, architecture, contract, workflow, and operational decisions belong in engineering truth. diff --git a/.github/skills/truthmark-check/support/report-template.md b/.github/skills/truthmark-check/support/report-template.md index 00a3453..435fdfa 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 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.0. Rerun truthmark init after upgrades. Report completion in this shape: diff --git a/.github/skills/truthmark-check/support/subagents-and-leases.md b/.github/skills/truthmark-check/support/subagents-and-leases.md index f588254..0f2a7fa 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 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.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 7309fe0..a24ba93 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: 2.1.0 +truthmark-version: 2.2.0 --- # Truthmark Document diff --git a/.github/skills/truthmark-document/helper-manifest.yml b/.github/skills/truthmark-document/helper-manifest.yml index 175e1a0..1763234 100644 --- a/.github/skills/truthmark-document/helper-manifest.yml +++ b/.github/skills/truthmark-document/helper-manifest.yml @@ -1,8 +1,8 @@ -# Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. +# Generated by Truthmark 2.2.0. Rerun truthmark init after upgrades. helpers: validate-document-report: optional: true - runner: truthmark>=2.1.0 + runner: truthmark>=2.2.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>=2.1.0 + runner: truthmark>=2.2.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 2cb7bd6..58bcb56 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 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.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>=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 +- validate-document-report: optional truthmark>=2.2.0; manual fallback: manually validate support/report-template.md required sections and structured Evidence checked entries +- validate-write-lease: optional truthmark>=2.2.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 be8590f..b787061 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 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.0. Rerun truthmark init after upgrades. # Truthmark Document @@ -11,8 +11,16 @@ Truth Document is manual and implementation-first: - run only when the user explicitly asks to generate or update truth docs for existing behavior, or when Truth Sync, Truth Check, or Truth Structure reports implemented behavior that lacks canonical truth docs - inspect .truthmark/config.yml and configured route files only when they exist; then inspect existing canonical docs, implementation code, and tests 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. +- Evidence authority: + - 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. +- Lane classification: + - before writing canonical truth docs, classify the request or change as product-lane, engineering-lane, both-lane, or ambiguous + - product-lane writes belong under docs/truthmark/product and state product promises, boundaries, rationale, decisions, and success criteria + - engineering-lane writes belong under docs/truthmark/engineering and state source-backed current realization, contracts, architecture, workflows, operations, or tests + - both-lane work must write separate product and engineering docs and cross-link them in route YAML with realized_by and realizes, not in doc frontmatter + - ambiguous lane ownership must block or invoke Truth Structure instead of writing a mixed document + - Do not make product docs a summary of engineering docs. Do not make engineering docs a detailed version of product docs. Product truth says what must be true and why. Engineering truth says how the repository currently realizes it. - document current implemented behavior; do not invent future behavior or planned endpoints - may write canonical truth docs and docs/truthmark/routes/areas.md or relevant child route files only - must not write functional code @@ -20,7 +28,10 @@ Implementation code and canonical truth docs are inspected evidence for current - block and recommend Truth Structure when routing repair is unsafe, ambiguous, or outside the task boundary - keep feature README.md files as indexes rather than truth-document targets - create or update bounded leaf truth docs when behavior does not fit an existing leaf doc -- keep behavior truth docs behavior-oriented, not endpoint-oriented, unless the endpoint itself is the behavior boundary +- write product capability/boundary truth under docs/truthmark/product when documenting product promise, boundary, rationale, or user/stakeholder value +- write engineering truth under docs/truthmark/engineering when documenting implementation behavior, contracts, architecture, workflows, operations, or tests +- for both-lane documentation requests, write separate product and engineering docs and cross-link them in route YAML with realized_by and realizes, not in doc frontmatter +- keep engineering behavior truth behavior-oriented, not endpoint-oriented, unless the endpoint itself is the behavior boundary - keep API endpoint details in the nearest contract truth doc when such a doc owns the API contract - preserve unrelated authored content Truth-doc ownership gate: @@ -28,15 +39,15 @@ Truth-doc ownership gate: - if a target/source doc mixes independent owners, spans unrelated behaviors, acts as an index, or needs cross-owner edits, do not patch or in-place repair it - if the target doc is broad, mixed-owner, index-like, or the documented behavior spans independent owners, run Truth Structure first when safe and in scope; otherwise block and recommend Truth Structure - report Ownership reviewed, Structure required, Truth docs split, Truth docs restructured, or Blocked reason as applicable -Product Decisions/Rationale preservation gate: -- before any truth-doc split, restructure, or shape repair, inventory existing Product Decisions and Rationale sections in every source or touched truth doc -- preserve each current decision and rationale in the bounded owner doc it governs; when splitting, move it to the new owner doc rather than deleting it or leaving it in an index +Decision/Rationale preservation gate: +- before any truth-doc split, restructure, or shape repair, inventory existing Product Decisions, Engineering Decisions, and Rationale sections in every source or touched truth doc +- preserve each current decision and rationale in the correct product or engineering lane owner; when splitting, move it to the new owner doc rather than deleting it or leaving it in an index - 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 +- after the edit, verify every touched truth doc keeps lane-appropriate decision/rationale sections and every pre-existing entry is preserved, moved, narrowed, removed with evidence, or blocked Evidence Gate: - route-first: map the documented behavior to bounded route owners and primary canonical docs -- review new or changed behavior-bearing claims only in touched docs, route ownership, Product Decisions, and Rationale +- review new or changed behavior-bearing claims only in touched docs, route ownership, lane-specific decisions, and rationale - support claims with primary checkout evidence: implementation, config, routing, generated templates, schemas, or contract definitions - tests/examples/canonical docs corroborate; they are not sole proof when implementation conflicts - remove, narrow, or block unsupported claims @@ -45,10 +56,10 @@ Repository intelligence artifacts are optional derived context: RepoIndex, Route 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 template under the configured Truthmark templates root. -Supported kinds: behavior, contract, architecture, workflow, operations, and test-behavior. +Supported kinds: product-capability, engineering-behavior, engineering-contract, engineering-architecture, engineering-workflow, engineering-operations, and engineering-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. +If the template is missing, use lane-specific sections: product truth says what must be true and why; engineering truth says how the repository currently realizes it. 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. @@ -63,10 +74,11 @@ Truthmark hierarchy hints: - Config, when present: .truthmark/config.yml - 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 +- Product truth docs, when present: docs/truthmark/product/**/*.md +- Engineering truth docs, when present: docs/truthmark/engineering/**/*.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. +Product decisions belong in product truth; engineering, architecture, contract, workflow, and operational decisions belong in engineering truth. Helper status reporting: - Validate the report body before adding this validator's own success status; the body may omit `validate-document-report` while validation is pending. - After `truthmark validate document-report --json` returns `data.validation.ok: true`, append or update `validate-document-report: ran, passed` in the final report. diff --git a/.github/skills/truthmark-document/support/report-template.md b/.github/skills/truthmark-document/support/report-template.md index 5e38b92..6673f6a 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 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.0. Rerun truthmark init after upgrades. Report completion in this shape: ```md @@ -13,13 +13,13 @@ Ownership reviewed: - docs/truthmark/routes/areas.md Truth docs created: -- docs/truthmark/truth/contracts.md +- docs/truthmark/engineering/contracts/routing.md Truth docs updated: -- docs/truthmark/truth/check-diagnostics.md +- docs/truthmark/engineering/behaviors/check-diagnostics.md Truth docs restructured: -- docs/truthmark/truth/check-diagnostics.md +- docs/truthmark/engineering/behaviors/check-diagnostics.md Routing updated: - docs/truthmark/routes/areas.md diff --git a/.github/skills/truthmark-document/support/subagents-and-leases.md b/.github/skills/truthmark-document/support/subagents-and-leases.md index 19f3dc3..434baa6 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 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.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 48820f0..61aabe7 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: 2.1.0 +truthmark-version: 2.2.0 --- # Truthmark Preview @@ -16,7 +16,7 @@ Invocations: OpenCode /skill truthmark-preview; Codex /truthmark-preview or $tru 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/routes/areas.md; docs/truthmark/routes/areas/) only when they exist; then inspect only the truth docs or implementation files needed to preview ownership. +- Inspect .truthmark/config.yml and the root route index (docs/truthmark/routes/areas.md) first when present; then inspect only child route files under docs/truthmark/routes/areas/ that are relevant to the selected scope or changed paths, plus 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. diff --git a/.github/skills/truthmark-preview/support/procedure.md b/.github/skills/truthmark-preview/support/procedure.md index 276926b..9579a10 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 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.0. Rerun truthmark init after upgrades. Use this skill only when the user explicitly asks to preview Truthmark routing or workflow choice before edits. @@ -10,16 +10,25 @@ Truth Preview is read-only. Its report is intended, not authorized. Purpose: - preview the likely Truthmark workflow, route owner, target files, expected write classes, suggested subagent use, and blocking ambiguity before edits happen +- report likely product lane impact, engineering lane impact, target docs, and ambiguity before edits - hand off to the selected workflow after user approval - keep the selector thin so agents can avoid loading or acting through heavier workflows prematurely Read: - .truthmark/config.yml, only when present -- docs/truthmark/routes/areas.md, only when present -- relevant child route files under docs/truthmark/routes/areas/, only when present +- docs/truthmark/routes/areas.md, first, only when present +- relevant child route files under docs/truthmark/routes/areas/ for the selected scope or changed paths, 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. +- Evidence authority: + - 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. +- Lane classification: + - classify the request or changed surface as product-lane, engineering-lane, both-lane, or ambiguous for reporting only + - product-lane ownership belongs under docs/truthmark/product and describes product promises, boundaries, rationale, decisions, and success criteria + - engineering-lane ownership belongs under docs/truthmark/engineering and describes source-backed current realization, contracts, architecture, workflows, operations, or tests + - both-lane ownership uses separate product and engineering docs cross-linked in route YAML with realized_by and realizes, not in doc frontmatter + - ambiguous lane ownership should be reported as blocked or routed to Truth Structure + - Do not make product docs a summary of engineering docs. Do not make engineering docs a detailed version of product docs. Product truth says what must be true and why. Engineering truth says how the repository currently realizes it. Do not: - must not edit files @@ -40,4 +49,5 @@ Truthmark hierarchy hints: - Config, when present: .truthmark/config.yml - 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 +- Product truth docs, when present: docs/truthmark/product/**/*.md +- Engineering truth docs, when present: docs/truthmark/engineering/**/*.md diff --git a/.github/skills/truthmark-preview/support/report-template.md b/.github/skills/truthmark-preview/support/report-template.md index bff96a9..f529f70 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 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.0. Rerun truthmark init after upgrades. Report completion in this shape: ```md @@ -19,14 +19,16 @@ Why this workflow: Likely route owner: - route file: docs/truthmark/routes/areas.md -- truth doc: docs/truthmark/truth/example.md +- likely lane impact: engineering-lane +- product target docs: none identified +- engineering target docs: docs/truthmark/engineering/behaviors/example.md - confidence: medium Expected write classes: - truth docs Expected target files: -- docs/truthmark/truth/example.md +- docs/truthmark/engineering/behaviors/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 9f41bbc..6d860ad 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 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.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 138b9e3..23ee176 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: 2.1.0 +truthmark-version: 2.2.0 --- # Truthmark Realize diff --git a/.github/skills/truthmark-realize/support/procedure.md b/.github/skills/truthmark-realize/support/procedure.md index c419a77..5b3ba33 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 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.0. Rerun truthmark init after upgrades. # Truthmark Realize @@ -33,7 +33,8 @@ Truthmark hierarchy hints: - Config, when present: .truthmark/config.yml - 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 +- Product truth docs, when present: docs/truthmark/product/**/*.md +- Engineering truth docs, when present: docs/truthmark/engineering/**/*.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 b540f61..246d9cf 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 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.0. Rerun truthmark init after upgrades. Report completion in this shape: @@ -8,7 +8,8 @@ Report completion in this shape: Truth Realize: completed Truth docs used: -- docs/truthmark/truth/authentication/session-timeout.md +- docs/truthmark/product/capabilities/authentication-session.md +- docs/truthmark/engineering/behaviors/authentication-session.md Code updated: - src/auth/session.ts diff --git a/.github/skills/truthmark-structure/SKILL.md b/.github/skills/truthmark-structure/SKILL.md index 8bbe8b6..c203286 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: 2.1.0 +truthmark-version: 2.2.0 --- # Truthmark Structure diff --git a/.github/skills/truthmark-structure/support/procedure.md b/.github/skills/truthmark-structure/support/procedure.md index 5112d6e..34f4e41 100644 --- a/.github/skills/truthmark-structure/support/procedure.md +++ b/.github/skills/truthmark-structure/support/procedure.md @@ -1,29 +1,38 @@ # Truthmark Structure Procedure -Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.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. 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. +- Evidence authority: + - 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. +- Lane classification: + - before writing canonical truth docs, classify the request or change as product-lane, engineering-lane, both-lane, or ambiguous + - product-lane writes belong under docs/truthmark/product and state product promises, boundaries, rationale, decisions, and success criteria + - engineering-lane writes belong under docs/truthmark/engineering and state source-backed current realization, contracts, architecture, workflows, operations, or tests + - both-lane work must write separate product and engineering docs and cross-link them in route YAML with realized_by and realizes, not in doc frontmatter + - ambiguous lane ownership must block or invoke Truth Structure instead of writing a mixed document + - Do not make product docs a summary of engineering docs. Do not make engineering docs a detailed version of product docs. Product truth says what must be true and why. Engineering truth says how the repository currently realizes it. - 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/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. +- Starter truth docs must use closed YAML frontmatter bounded by opening and closing --- lines; include status, truth_kind, and last_reviewed inside that frontmatter. Put source references in the final ## Source References section, not in frontmatter. +- Starter truth docs must use lane-specific templates and keep product and engineering truth in separate files. 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. +Supported kinds: product-capability, engineering-behavior, engineering-contract, engineering-architecture, engineering-workflow, engineering-operations, and engineering-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. +If the template is missing, use lane-specific sections: product truth says what must be true and why; engineering truth says how the repository currently realizes it. 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 docs/truthmark/product/** for product truth destinations +- use docs/truthmark/engineering/** for engineering 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 +- keep active Product Decisions in product truth and Engineering Decisions in engineering truth - preserve unrelated authored content ## New area setup Use when a user asks to onboard a new code area into Truthmark, a new package, controller, domain, or product area lacks bounded truth ownership, or a new product area needs routing and starter truth docs. @@ -41,7 +50,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/truthmark/truth. Treat the configured truth root as a managed semantic root. +Truth Structure owns documentation topology, lane splits, decision relocation, and relationship repair. Do not depend on humans to manually organize docs/truthmark/product or docs/truthmark/engineering. Treat both configured lane roots as managed semantic roots. 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: @@ -49,17 +58,17 @@ Truth-doc ownership gate: - if a target/source doc mixes independent owners, spans unrelated behaviors, acts as an index, or needs cross-owner edits, do not patch or in-place repair it - if a truth doc mixes independent owners, route ownership is broad, or a split is required for bounded ownership, split and reroute into bounded truth docs when safe; otherwise block with manual-review files - report Ownership reviewed, Structure required, Truth docs split, Truth docs restructured, or Blocked reason as applicable -Product Decisions/Rationale preservation gate: -- before any truth-doc split, restructure, or shape repair, inventory existing Product Decisions and Rationale sections in every source or touched truth doc -- preserve each current decision and rationale in the bounded owner doc it governs; when splitting, move it to the new owner doc rather than deleting it or leaving it in an index +Decision/Rationale preservation gate: +- before any truth-doc split, restructure, or shape repair, inventory existing Product Decisions, Engineering Decisions, and Rationale sections in every source or touched truth doc +- preserve each current decision and rationale in the correct product or engineering lane owner; when splitting, move it to the new owner doc rather than deleting it or leaving it in an index - 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 +- after the edit, verify every touched truth doc keeps lane-appropriate decision/rationale sections and every pre-existing entry is preserved, moved, narrowed, removed with evidence, or blocked Topology pressure signals: - one area maps broad code such as src/**, app/**, server/**, services/**, or packages/** - one area maps multiple unrelated controllers, route groups, services, or bounded contexts - one truth doc owns unrelated behaviors or unrelated endpoint families -- the configured truth root has many direct non-index docs +- either configured lane 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/routes/areas/** @@ -72,9 +81,10 @@ 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/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 +- create engineering behavior truth docs under docs/truthmark/engineering only when behavior lacks a current doc +- create product truth docs under docs/truthmark/product only when product promise, boundary, rationale, or user-visible capability truth is in scope - README.md files are indexes, not Truth Sync targets -- prefer bounded leaf truth docs at //.md +- prefer bounded product docs under product/capabilities or product/decisions and engineering docs under engineering//.md - keep behavior truth docs behavior-oriented, not endpoint-oriented - keep API endpoint details in the nearest contract truth doc when such a doc exists - update routing so future Truth Sync can target small docs @@ -88,13 +98,13 @@ Truth-doc shape repair gate: - preserve supported claims; remove, narrow, or block unsupported or stale claims - report docs restructured and why a narrow edit was not sufficient Evidence Gate: -- apply the Evidence Gate before finishing when Truth Structure writes routed docs, ownership claims, Product Decisions, or Rationale +- apply the Evidence Gate before finishing when Truth Structure writes routed docs, ownership claims, lane-specific decisions, or rationale - support ownership/behavior claims with topology or primary checkout evidence from layout, implementation boundaries, docs, config, route files, tests, templates, schemas, or contracts - tests/examples/canonical docs corroborate; remove, narrow, or block unsupported claims Maintain architecture docs only for structure-level changes: system structure, module boundaries, runtime topology, persistence boundaries, cross-cutting contracts, or generated-surface ownership. Keep ordinary behavior, endpoints, UI copy, validation rules, and bug fixes in behavior or contract docs unless they change those boundaries. -- Do not finish topology repair with routed canonical current-truth docs missing Product Decisions or Rationale sections. -- If an existing canonical doc lacks either section, add the missing heading beside Current Behavior with a concise current-state placeholder or active decision. +- Do not finish topology repair with mixed product/engineering authority in a single canonical truth doc. +- If an existing canonical doc has wrong-lane sections, split or move them into the correct product or engineering lane. Portable fallback: - If this skill surface is unavailable, perform the same workflow directly from committed repository files. - Do not require the truthmark CLI. @@ -104,7 +114,8 @@ Truthmark hierarchy hints: - Config, when present: .truthmark/config.yml - 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 +- Product truth docs, when present: docs/truthmark/product/**/*.md +- Engineering truth docs, when present: docs/truthmark/engineering/**/*.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. +Product decisions belong in product truth; engineering, architecture, contract, workflow, and operational decisions belong in engineering truth. diff --git a/.github/skills/truthmark-structure/support/report-template.md b/.github/skills/truthmark-structure/support/report-template.md index 1be260b..7d1ae37 100644 --- a/.github/skills/truthmark-structure/support/report-template.md +++ b/.github/skills/truthmark-structure/support/report-template.md @@ -1,13 +1,14 @@ # Truthmark Structure Report Template -Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.0. Rerun truthmark init after upgrades. Report completion in this shape: ```md Truth Structure: completed Topology reviewed: - controllers: src/auth/** -- docs root: docs/truthmark/truth +- product docs root: docs/truthmark/product +- engineering docs root: docs/truthmark/engineering - route files: docs/truthmark/routes/areas.md Areas reviewed: - src/auth/** @@ -16,12 +17,14 @@ Routing updated: Initial truth boundary: - Area: Authentication - Code: src/auth/** -- Truth owner: docs/truthmark/truth/authentication/session.md +- Product owner: docs/truthmark/product/capabilities/authentication-session.md +- Engineering owner: docs/truthmark/engineering/behaviors/authentication-session.md - Scope: session behavior only Truth docs created: -- docs/truthmark/truth/authentication/session.md +- docs/truthmark/product/capabilities/authentication-session.md +- docs/truthmark/engineering/behaviors/authentication-session.md Truth docs split: -- docs/truthmark/truth/authentication/README.md -> docs/truthmark/truth/authentication/session.md +- docs/truthmark/truth/authentication/README.md -> docs/truthmark/product/capabilities/authentication-session.md and docs/truthmark/engineering/behaviors/authentication-session.md Truth docs restructured: - docs/truthmark/truth/authentication/README.md Evidence checked: diff --git a/.github/skills/truthmark-structure/support/subagents-and-leases.md b/.github/skills/truthmark-structure/support/subagents-and-leases.md index 23d8abc..7791bf7 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 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.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 0e7e53e..b728261 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: 2.1.0 +truthmark-version: 2.2.0 --- # Truthmark Sync diff --git a/.github/skills/truthmark-sync/helper-manifest.yml b/.github/skills/truthmark-sync/helper-manifest.yml index dd0153a..1f9a1f1 100644 --- a/.github/skills/truthmark-sync/helper-manifest.yml +++ b/.github/skills/truthmark-sync/helper-manifest.yml @@ -1,8 +1,8 @@ -# Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. +# Generated by Truthmark 2.2.0. Rerun truthmark init after upgrades. helpers: validate-sync-report: optional: true - runner: truthmark>=2.1.0 + runner: truthmark>=2.2.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>=2.1.0 + runner: truthmark>=2.2.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 6c44128..885d6a1 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 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.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>=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 +- validate-sync-report: optional truthmark>=2.2.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.2.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 ff0f6f7..3026dce 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 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.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. @@ -10,10 +10,19 @@ Parent workflow: 1. Inspect git status, staged changes, unstaged changes, and untracked files directly. 2. Inspect .truthmark/config.yml and configured route files only when they exist; then inspect relevant canonical docs. 3. Identify functional-code changes and the nearest truth docs or routing repairs. -4. 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. -5. Code verification is parent-owned: follow repository instructions and task context, and report what ran or why it did not run. -6. Dispatch bounded Truth Sync workers only when the host supports subagent dispatch and the acting agent chooses that path; otherwise execute the same sync task inline. +4. Evidence authority: + - 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. +5. Lane classification gate: + - before writing canonical truth docs, classify the request or change as product-lane, engineering-lane, both-lane, or ambiguous + - product-lane writes belong under docs/truthmark/product and state product promises, boundaries, rationale, decisions, and success criteria + - engineering-lane writes belong under docs/truthmark/engineering and state source-backed current realization, contracts, architecture, workflows, operations, or tests + - both-lane work must write separate product and engineering docs and cross-link them in route YAML with realized_by and realizes, not in doc frontmatter + - ambiguous lane ownership must block or invoke Truth Structure instead of writing a mixed document + - Do not make product docs a summary of engineering docs. Do not make engineering docs a detailed version of product docs. Product truth says what must be true and why. Engineering truth says how the repository currently realizes it. +6. Update engineering truth first after code changes. Update product truth only when implemented user-visible product promise or capability boundary changed and explicit source/user evidence supports it; otherwise report product-lane review needed. +7. Code verification is parent-owned: follow repository instructions and task context, and report what ran or why it did not run. +8. Dispatch bounded Truth Sync workers only when the host supports subagent dispatch and the acting agent chooses that path; otherwise execute the same sync task inline. Topology quality gate: - before updating truth docs, verify the changed code resolves to a specific behavior-owned area and bounded truth owner - if routing is missing, stale, broad, overloaded, catch-all route only, or cannot map changed code to a bounded truth owner, do not create another generic truth doc @@ -23,22 +32,23 @@ Topology quality gate: - README.md files are indexes, not Truth Sync targets - must not append behavior details to a README.md index - create or update a bounded leaf truth doc when behavior changes do not fit an existing leaf doc +- write engineering truth under docs/truthmark/engineering; product truth updates under docs/truthmark/product are allowed only for explicit current product behavior changes Truth-doc ownership gate: - before editing or relying on changed functional files and impacted truth docs, verify each target/source truth doc is a bounded owner for the behavior - if a target/source doc mixes independent owners, spans unrelated behaviors, acts as an index, or needs cross-owner edits, do not patch or in-place repair it - if an impacted doc is broad, mixed-owner, index-like, or the update spans independent behavior owners, run Truth Structure before syncing when safe and in scope; otherwise block and recommend Truth Structure - report Ownership reviewed, Structure required, Truth docs split, Truth docs restructured, or Blocked reason as applicable -Product Decisions/Rationale preservation gate: -- before any truth-doc split, restructure, or shape repair, inventory existing Product Decisions and Rationale sections in every source or touched truth doc -- preserve each current decision and rationale in the bounded owner doc it governs; when splitting, move it to the new owner doc rather than deleting it or leaving it in an index +Decision/Rationale preservation gate: +- before any truth-doc split, restructure, or shape repair, inventory existing Product Decisions, Engineering Decisions, and Rationale sections in every source or touched truth doc +- preserve each current decision and rationale in the correct product or engineering lane owner; when splitting, move it to the new owner doc rather than deleting it or leaving it in an index - 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 +- after the edit, verify every touched truth doc keeps lane-appropriate decision/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 template under the configured Truthmark templates root. -Supported kinds: behavior, contract, architecture, workflow, operations, and test-behavior. +Supported kinds: product-capability, engineering-behavior, engineering-contract, engineering-architecture, engineering-workflow, engineering-operations, and engineering-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. +If the template is missing, use lane-specific sections: product truth says what must be true and why; engineering truth says how the repository currently realizes it. 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. @@ -51,7 +61,7 @@ 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. Evidence Gate: - route-first: map changed functional files to bounded route owners and primary canonical docs -- review new or changed behavior-bearing claims only in touched docs, route ownership, Product Decisions, and Rationale +- review new or changed behavior-bearing claims only in touched docs, route ownership, lane-specific decisions, and rationale - support claims with primary checkout evidence: implementation, config, routing, generated templates, schemas, or contract definitions - tests/examples/canonical docs corroborate; they are not sole proof when implementation conflicts - remove, narrow, or block unsupported claims @@ -63,7 +73,7 @@ Optional validation tooling: - you may run truthmark check when local tooling is available - do not require the truthmark binary; direct checkout inspection is the canonical path - optional validation must not replace agent judgment about docs and routing -- update Product Decisions and Rationale when a behavior change comes from a decision change +- update Product Decisions only in product truth and Engineering Decisions only in engineering truth when evidence supports the lane-specific decision change Helper status reporting: - Validate the report body before adding this validator's own success status; the body may omit `validate-sync-report` while validation is pending. - After `truthmark validate sync-report --json` returns `data.validation.ok: true`, append or update `validate-sync-report: ran, passed` in the final report. @@ -74,10 +84,11 @@ Truthmark hierarchy hints: - Config, when present: .truthmark/config.yml - 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 +- Product truth docs, when present: docs/truthmark/product/**/*.md +- Engineering truth docs, when present: docs/truthmark/engineering/**/*.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. +Product decisions belong in product truth; engineering, architecture, contract, workflow, and operational decisions belong in engineering truth. Parent post-sync verification: - verify only truth docs and leased truth routing files changed during sync - block on any unrelated diff caused by the sync step diff --git a/.github/skills/truthmark-sync/support/report-template.md b/.github/skills/truthmark-sync/support/report-template.md index 4dfa42d..5331249 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 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.0. Rerun truthmark init after upgrades. Report completion in this shape: ```md @@ -13,7 +13,7 @@ Ownership reviewed: - docs/truthmark/routes/areas.md Truth docs updated: -- docs/truthmark/truth/repository/overview.md +- docs/truthmark/engineering/repository/overview.md Evidence checked: - Claim: Session timeout behavior is documented in the mapped repository truth doc. diff --git a/.github/skills/truthmark-sync/support/subagents-and-leases.md b/.github/skills/truthmark-sync/support/subagents-and-leases.md index 3ee4ee9..810d3bf 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 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.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/.opencode/agents/truth-claim-verifier.md b/.opencode/agents/truth-claim-verifier.md index 604da61..b89d3b6 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 2.1.0. Rerun truthmark init after upgrades. +# Generated by Truthmark 2.2.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 6f1fbea..202d173 100644 --- a/.opencode/agents/truth-doc-reviewer.md +++ b/.opencode/agents/truth-doc-reviewer.md @@ -16,12 +16,12 @@ permission: "grep *": allow --- -# Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. +# Generated by Truthmark 2.2.0. Rerun truthmark init after upgrades. Manual invocation: @truth-doc-reviewer Stay read-only. -Review assigned canonical truth docs for frontmatter, source_of_truth, required template sections, Evidence checked entries, Product Decisions, and Rationale. +Review assigned canonical truth docs for compact frontmatter, required template sections, final Source References entries, Evidence checked entries, and lane-appropriate decision sections (Product Decisions in product truth, Engineering Decisions in engineering truth). Flag README.md files used as behavior truth targets, mixed-owner docs, and shape repairs that should move to Truth Structure. Do not edit files, stage changes, or rewrite docs. Return JSON only with keys: scope, filesReviewed, findings, evidence, confidence, recommendedWorkflow, notes. diff --git a/.opencode/agents/truth-doc-writer.md b/.opencode/agents/truth-doc-writer.md index a0539af..1593472 100644 --- a/.opencode/agents/truth-doc-writer.md +++ b/.opencode/agents/truth-doc-writer.md @@ -8,7 +8,8 @@ permission: glob: allow edit: "*": deny - "docs/truthmark/truth/**": allow + "docs/truthmark/product/**": allow + "docs/truthmark/engineering/**": allow "docs/truthmark/routes/areas.md": allow "docs/truthmark/routes/areas/**/*.md": allow task: deny @@ -21,7 +22,7 @@ permission: "git diff*": allow --- -# Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. +# Generated by Truthmark 2.2.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 938ca1a..8d2dee9 100644 --- a/.opencode/agents/truth-route-auditor.md +++ b/.opencode/agents/truth-route-auditor.md @@ -16,14 +16,21 @@ permission: "grep *": allow --- -# Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. +# Generated by Truthmark 2.2.0. Rerun truthmark init after upgrades. Manual invocation: @truth-route-auditor Stay read-only. Audit one bounded Truthmark route, area, or doc shard assigned by the parent. Inspect .truthmark/config.yml and route files only when they exist; then inspect mapped truth docs and relevant implementation files directly. +Use a route-first bounded strategy: narrow audits inspect only the routed area and directly linked counterpart docs; root-wide health first builds a cheap route-map/index from route files, then inspects only mismatches and linked leaves. Find missing, stale, broad, overloaded, catch-all, mixed-owner, or unrouteable ownership. +Validate route ownership against lane-specific roots and route kind: +- confirm mapped truth docs resolve to the correct lane root (product or engineering) for their kind +- flag mismatch between assigned route kind and resolved doc kind (for example, product-capability routed to engineering paths) +- verify route-doc linkage for lane pairings via realized_by and realizes before recommending edits +- inspect product counterparts for engineering docs only when route YAML claims a product relationship, or when the parent explicitly asks for user-visible product coverage +- treat missing product links for user-visible engineering docs as a second-pass diagnostic, not a default full-document read. Do not edit files, stage changes, or propose broad rewrites. Return JSON only with keys: scope, filesReviewed, findings, evidence, confidence, recommendedWorkflow, notes. recommendedWorkflow must be one of: none, truthmark-document, truthmark-structure. diff --git a/.opencode/skills/truthmark-check/SKILL.md b/.opencode/skills/truthmark-check/SKILL.md index b8b5902..4f52656 100644 --- a/.opencode/skills/truthmark-check/SKILL.md +++ b/.opencode/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: 2.1.0 +truthmark-version: 2.2.0 --- # Truthmark Check diff --git a/.opencode/skills/truthmark-check/support/procedure.md b/.opencode/skills/truthmark-check/support/procedure.md index 6132ff9..c8c76bd 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 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.0. Rerun truthmark init after upgrades. # Truthmark Check @@ -11,13 +11,31 @@ Invocations: OpenCode /skill truthmark-check; Codex /truthmark-check or $truthma 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/routes/areas.md and relevant child route files under docs/truthmark/routes/areas/ when they exist +- Evidence authority: + - 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. +- Lane classification: + - classify the request or changed surface as product-lane, engineering-lane, both-lane, or ambiguous for reporting only + - product-lane ownership belongs under docs/truthmark/product and describes product promises, boundaries, rationale, decisions, and success criteria + - engineering-lane ownership belongs under docs/truthmark/engineering and describes source-backed current realization, contracts, architecture, workflows, operations, or tests + - both-lane ownership uses separate product and engineering docs cross-linked in route YAML with realized_by and realizes, not in doc frontmatter + - ambiguous lane ownership should be reported as blocked or routed to Truth Structure + - Do not make product docs a summary of engineering docs. Do not make engineering docs a detailed version of product docs. Product truth says what must be true and why. Engineering truth says how the repository currently realizes it. - check that current docs describe current code rather than historical plans +- keep lane and cross-lane checks route-first and bounded: + - for a narrow audit, inspect only the routed area and directly linked counterpart docs + - for root-wide truth health, first build a cheap route-map/index from route files, then inspect only mismatches and linked leaves + - inspect product counterparts for engineering docs only when route YAML claims a product relationship, or when the user explicitly asks for user-visible product coverage +- check lane root/kind alignment for product truth under docs/truthmark/product and engineering truth under docs/truthmark/engineering +- check route YAML cross-lane realized_by and realizes links for existence and lane compatibility +- report missing product links for user-visible engineering docs only as a second-pass review diagnostic, not as default full-document reads or hard errors +- check product docs do not contain engineering execution flow, generated file inventories, or CLI envelope mechanics +- check engineering docs do not contain product promises, product rationale, or Product Decisions sections +- never judge whether a product decision is commercially correct, valuable, prioritized, or desirable - 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 -- check that canonical behavior docs keep active Product Decisions and Rationale sections +- check that canonical docs keep lane-appropriate decisions and rationale sections - optionally run truthmark check when local tooling is available - must not require the truthmark binary; direct inspection is always valid - report issues and suggested fixes without silently rewriting unrelated files @@ -31,7 +49,8 @@ Truthmark hierarchy hints: - Config, when present: .truthmark/config.yml - 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 +- Product truth docs, when present: docs/truthmark/product/**/*.md +- Engineering truth docs, when present: docs/truthmark/engineering/**/*.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. +Product decisions belong in product truth; engineering, architecture, contract, workflow, and operational decisions belong in engineering truth. diff --git a/.opencode/skills/truthmark-check/support/report-template.md b/.opencode/skills/truthmark-check/support/report-template.md index 00a3453..435fdfa 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 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.0. Rerun truthmark init after upgrades. Report completion in this shape: diff --git a/.opencode/skills/truthmark-check/support/subagents-and-leases.md b/.opencode/skills/truthmark-check/support/subagents-and-leases.md index 74eb60a..f6a3302 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 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.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 241a841..d238539 100644 --- a/.opencode/skills/truthmark-document/SKILL.md +++ b/.opencode/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: 2.1.0 +truthmark-version: 2.2.0 --- # Truthmark Document diff --git a/.opencode/skills/truthmark-document/helper-manifest.yml b/.opencode/skills/truthmark-document/helper-manifest.yml index 175e1a0..1763234 100644 --- a/.opencode/skills/truthmark-document/helper-manifest.yml +++ b/.opencode/skills/truthmark-document/helper-manifest.yml @@ -1,8 +1,8 @@ -# Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. +# Generated by Truthmark 2.2.0. Rerun truthmark init after upgrades. helpers: validate-document-report: optional: true - runner: truthmark>=2.1.0 + runner: truthmark>=2.2.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>=2.1.0 + runner: truthmark>=2.2.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 2cb7bd6..58bcb56 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 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.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>=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 +- validate-document-report: optional truthmark>=2.2.0; manual fallback: manually validate support/report-template.md required sections and structured Evidence checked entries +- validate-write-lease: optional truthmark>=2.2.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 be8590f..b787061 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 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.0. Rerun truthmark init after upgrades. # Truthmark Document @@ -11,8 +11,16 @@ Truth Document is manual and implementation-first: - run only when the user explicitly asks to generate or update truth docs for existing behavior, or when Truth Sync, Truth Check, or Truth Structure reports implemented behavior that lacks canonical truth docs - inspect .truthmark/config.yml and configured route files only when they exist; then inspect existing canonical docs, implementation code, and tests 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. +- Evidence authority: + - 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. +- Lane classification: + - before writing canonical truth docs, classify the request or change as product-lane, engineering-lane, both-lane, or ambiguous + - product-lane writes belong under docs/truthmark/product and state product promises, boundaries, rationale, decisions, and success criteria + - engineering-lane writes belong under docs/truthmark/engineering and state source-backed current realization, contracts, architecture, workflows, operations, or tests + - both-lane work must write separate product and engineering docs and cross-link them in route YAML with realized_by and realizes, not in doc frontmatter + - ambiguous lane ownership must block or invoke Truth Structure instead of writing a mixed document + - Do not make product docs a summary of engineering docs. Do not make engineering docs a detailed version of product docs. Product truth says what must be true and why. Engineering truth says how the repository currently realizes it. - document current implemented behavior; do not invent future behavior or planned endpoints - may write canonical truth docs and docs/truthmark/routes/areas.md or relevant child route files only - must not write functional code @@ -20,7 +28,10 @@ Implementation code and canonical truth docs are inspected evidence for current - block and recommend Truth Structure when routing repair is unsafe, ambiguous, or outside the task boundary - keep feature README.md files as indexes rather than truth-document targets - create or update bounded leaf truth docs when behavior does not fit an existing leaf doc -- keep behavior truth docs behavior-oriented, not endpoint-oriented, unless the endpoint itself is the behavior boundary +- write product capability/boundary truth under docs/truthmark/product when documenting product promise, boundary, rationale, or user/stakeholder value +- write engineering truth under docs/truthmark/engineering when documenting implementation behavior, contracts, architecture, workflows, operations, or tests +- for both-lane documentation requests, write separate product and engineering docs and cross-link them in route YAML with realized_by and realizes, not in doc frontmatter +- keep engineering behavior truth behavior-oriented, not endpoint-oriented, unless the endpoint itself is the behavior boundary - keep API endpoint details in the nearest contract truth doc when such a doc owns the API contract - preserve unrelated authored content Truth-doc ownership gate: @@ -28,15 +39,15 @@ Truth-doc ownership gate: - if a target/source doc mixes independent owners, spans unrelated behaviors, acts as an index, or needs cross-owner edits, do not patch or in-place repair it - if the target doc is broad, mixed-owner, index-like, or the documented behavior spans independent owners, run Truth Structure first when safe and in scope; otherwise block and recommend Truth Structure - report Ownership reviewed, Structure required, Truth docs split, Truth docs restructured, or Blocked reason as applicable -Product Decisions/Rationale preservation gate: -- before any truth-doc split, restructure, or shape repair, inventory existing Product Decisions and Rationale sections in every source or touched truth doc -- preserve each current decision and rationale in the bounded owner doc it governs; when splitting, move it to the new owner doc rather than deleting it or leaving it in an index +Decision/Rationale preservation gate: +- before any truth-doc split, restructure, or shape repair, inventory existing Product Decisions, Engineering Decisions, and Rationale sections in every source or touched truth doc +- preserve each current decision and rationale in the correct product or engineering lane owner; when splitting, move it to the new owner doc rather than deleting it or leaving it in an index - 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 +- after the edit, verify every touched truth doc keeps lane-appropriate decision/rationale sections and every pre-existing entry is preserved, moved, narrowed, removed with evidence, or blocked Evidence Gate: - route-first: map the documented behavior to bounded route owners and primary canonical docs -- review new or changed behavior-bearing claims only in touched docs, route ownership, Product Decisions, and Rationale +- review new or changed behavior-bearing claims only in touched docs, route ownership, lane-specific decisions, and rationale - support claims with primary checkout evidence: implementation, config, routing, generated templates, schemas, or contract definitions - tests/examples/canonical docs corroborate; they are not sole proof when implementation conflicts - remove, narrow, or block unsupported claims @@ -45,10 +56,10 @@ Repository intelligence artifacts are optional derived context: RepoIndex, Route 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 template under the configured Truthmark templates root. -Supported kinds: behavior, contract, architecture, workflow, operations, and test-behavior. +Supported kinds: product-capability, engineering-behavior, engineering-contract, engineering-architecture, engineering-workflow, engineering-operations, and engineering-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. +If the template is missing, use lane-specific sections: product truth says what must be true and why; engineering truth says how the repository currently realizes it. 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. @@ -63,10 +74,11 @@ Truthmark hierarchy hints: - Config, when present: .truthmark/config.yml - 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 +- Product truth docs, when present: docs/truthmark/product/**/*.md +- Engineering truth docs, when present: docs/truthmark/engineering/**/*.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. +Product decisions belong in product truth; engineering, architecture, contract, workflow, and operational decisions belong in engineering truth. Helper status reporting: - Validate the report body before adding this validator's own success status; the body may omit `validate-document-report` while validation is pending. - After `truthmark validate document-report --json` returns `data.validation.ok: true`, append or update `validate-document-report: ran, passed` in the final report. diff --git a/.opencode/skills/truthmark-document/support/report-template.md b/.opencode/skills/truthmark-document/support/report-template.md index 5e38b92..6673f6a 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 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.0. Rerun truthmark init after upgrades. Report completion in this shape: ```md @@ -13,13 +13,13 @@ Ownership reviewed: - docs/truthmark/routes/areas.md Truth docs created: -- docs/truthmark/truth/contracts.md +- docs/truthmark/engineering/contracts/routing.md Truth docs updated: -- docs/truthmark/truth/check-diagnostics.md +- docs/truthmark/engineering/behaviors/check-diagnostics.md Truth docs restructured: -- docs/truthmark/truth/check-diagnostics.md +- docs/truthmark/engineering/behaviors/check-diagnostics.md Routing updated: - docs/truthmark/routes/areas.md diff --git a/.opencode/skills/truthmark-document/support/subagents-and-leases.md b/.opencode/skills/truthmark-document/support/subagents-and-leases.md index b4f7b6a..d20c3b6 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 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.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 7db8d92..ae61cf9 100644 --- a/.opencode/skills/truthmark-preview/SKILL.md +++ b/.opencode/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: 2.1.0 +truthmark-version: 2.2.0 --- # Truthmark Preview @@ -14,7 +14,7 @@ Invocations: OpenCode /skill truthmark-preview; Codex /truthmark-preview or $tru 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/routes/areas.md; docs/truthmark/routes/areas/) only when they exist; then inspect only the truth docs or implementation files needed to preview ownership. +- Inspect .truthmark/config.yml and the root route index (docs/truthmark/routes/areas.md) first when present; then inspect only child route files under docs/truthmark/routes/areas/ that are relevant to the selected scope or changed paths, plus 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. diff --git a/.opencode/skills/truthmark-preview/support/procedure.md b/.opencode/skills/truthmark-preview/support/procedure.md index 276926b..9579a10 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 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.0. Rerun truthmark init after upgrades. Use this skill only when the user explicitly asks to preview Truthmark routing or workflow choice before edits. @@ -10,16 +10,25 @@ Truth Preview is read-only. Its report is intended, not authorized. Purpose: - preview the likely Truthmark workflow, route owner, target files, expected write classes, suggested subagent use, and blocking ambiguity before edits happen +- report likely product lane impact, engineering lane impact, target docs, and ambiguity before edits - hand off to the selected workflow after user approval - keep the selector thin so agents can avoid loading or acting through heavier workflows prematurely Read: - .truthmark/config.yml, only when present -- docs/truthmark/routes/areas.md, only when present -- relevant child route files under docs/truthmark/routes/areas/, only when present +- docs/truthmark/routes/areas.md, first, only when present +- relevant child route files under docs/truthmark/routes/areas/ for the selected scope or changed paths, 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. +- Evidence authority: + - 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. +- Lane classification: + - classify the request or changed surface as product-lane, engineering-lane, both-lane, or ambiguous for reporting only + - product-lane ownership belongs under docs/truthmark/product and describes product promises, boundaries, rationale, decisions, and success criteria + - engineering-lane ownership belongs under docs/truthmark/engineering and describes source-backed current realization, contracts, architecture, workflows, operations, or tests + - both-lane ownership uses separate product and engineering docs cross-linked in route YAML with realized_by and realizes, not in doc frontmatter + - ambiguous lane ownership should be reported as blocked or routed to Truth Structure + - Do not make product docs a summary of engineering docs. Do not make engineering docs a detailed version of product docs. Product truth says what must be true and why. Engineering truth says how the repository currently realizes it. Do not: - must not edit files @@ -40,4 +49,5 @@ Truthmark hierarchy hints: - Config, when present: .truthmark/config.yml - 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 +- Product truth docs, when present: docs/truthmark/product/**/*.md +- Engineering truth docs, when present: docs/truthmark/engineering/**/*.md diff --git a/.opencode/skills/truthmark-preview/support/report-template.md b/.opencode/skills/truthmark-preview/support/report-template.md index bff96a9..f529f70 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 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.0. Rerun truthmark init after upgrades. Report completion in this shape: ```md @@ -19,14 +19,16 @@ Why this workflow: Likely route owner: - route file: docs/truthmark/routes/areas.md -- truth doc: docs/truthmark/truth/example.md +- likely lane impact: engineering-lane +- product target docs: none identified +- engineering target docs: docs/truthmark/engineering/behaviors/example.md - confidence: medium Expected write classes: - truth docs Expected target files: -- docs/truthmark/truth/example.md +- docs/truthmark/engineering/behaviors/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 896c506..9b5878a 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 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.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 8256b8e..2c479a7 100644 --- a/.opencode/skills/truthmark-realize/SKILL.md +++ b/.opencode/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: 2.1.0 +truthmark-version: 2.2.0 --- # Truthmark Realize diff --git a/.opencode/skills/truthmark-realize/support/procedure.md b/.opencode/skills/truthmark-realize/support/procedure.md index c419a77..5b3ba33 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 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.0. Rerun truthmark init after upgrades. # Truthmark Realize @@ -33,7 +33,8 @@ Truthmark hierarchy hints: - Config, when present: .truthmark/config.yml - 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 +- Product truth docs, when present: docs/truthmark/product/**/*.md +- Engineering truth docs, when present: docs/truthmark/engineering/**/*.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 b540f61..246d9cf 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 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.0. Rerun truthmark init after upgrades. Report completion in this shape: @@ -8,7 +8,8 @@ Report completion in this shape: Truth Realize: completed Truth docs used: -- docs/truthmark/truth/authentication/session-timeout.md +- docs/truthmark/product/capabilities/authentication-session.md +- docs/truthmark/engineering/behaviors/authentication-session.md Code updated: - src/auth/session.ts diff --git a/.opencode/skills/truthmark-structure/SKILL.md b/.opencode/skills/truthmark-structure/SKILL.md index 4e0d2ab..7c88c52 100644 --- a/.opencode/skills/truthmark-structure/SKILL.md +++ b/.opencode/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: 2.1.0 +truthmark-version: 2.2.0 --- # Truthmark Structure diff --git a/.opencode/skills/truthmark-structure/support/procedure.md b/.opencode/skills/truthmark-structure/support/procedure.md index 5112d6e..34f4e41 100644 --- a/.opencode/skills/truthmark-structure/support/procedure.md +++ b/.opencode/skills/truthmark-structure/support/procedure.md @@ -1,29 +1,38 @@ # Truthmark Structure Procedure -Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.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. 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. +- Evidence authority: + - 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. +- Lane classification: + - before writing canonical truth docs, classify the request or change as product-lane, engineering-lane, both-lane, or ambiguous + - product-lane writes belong under docs/truthmark/product and state product promises, boundaries, rationale, decisions, and success criteria + - engineering-lane writes belong under docs/truthmark/engineering and state source-backed current realization, contracts, architecture, workflows, operations, or tests + - both-lane work must write separate product and engineering docs and cross-link them in route YAML with realized_by and realizes, not in doc frontmatter + - ambiguous lane ownership must block or invoke Truth Structure instead of writing a mixed document + - Do not make product docs a summary of engineering docs. Do not make engineering docs a detailed version of product docs. Product truth says what must be true and why. Engineering truth says how the repository currently realizes it. - 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/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. +- Starter truth docs must use closed YAML frontmatter bounded by opening and closing --- lines; include status, truth_kind, and last_reviewed inside that frontmatter. Put source references in the final ## Source References section, not in frontmatter. +- Starter truth docs must use lane-specific templates and keep product and engineering truth in separate files. 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. +Supported kinds: product-capability, engineering-behavior, engineering-contract, engineering-architecture, engineering-workflow, engineering-operations, and engineering-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. +If the template is missing, use lane-specific sections: product truth says what must be true and why; engineering truth says how the repository currently realizes it. 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 docs/truthmark/product/** for product truth destinations +- use docs/truthmark/engineering/** for engineering 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 +- keep active Product Decisions in product truth and Engineering Decisions in engineering truth - preserve unrelated authored content ## New area setup Use when a user asks to onboard a new code area into Truthmark, a new package, controller, domain, or product area lacks bounded truth ownership, or a new product area needs routing and starter truth docs. @@ -41,7 +50,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/truthmark/truth. Treat the configured truth root as a managed semantic root. +Truth Structure owns documentation topology, lane splits, decision relocation, and relationship repair. Do not depend on humans to manually organize docs/truthmark/product or docs/truthmark/engineering. Treat both configured lane roots as managed semantic roots. 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: @@ -49,17 +58,17 @@ Truth-doc ownership gate: - if a target/source doc mixes independent owners, spans unrelated behaviors, acts as an index, or needs cross-owner edits, do not patch or in-place repair it - if a truth doc mixes independent owners, route ownership is broad, or a split is required for bounded ownership, split and reroute into bounded truth docs when safe; otherwise block with manual-review files - report Ownership reviewed, Structure required, Truth docs split, Truth docs restructured, or Blocked reason as applicable -Product Decisions/Rationale preservation gate: -- before any truth-doc split, restructure, or shape repair, inventory existing Product Decisions and Rationale sections in every source or touched truth doc -- preserve each current decision and rationale in the bounded owner doc it governs; when splitting, move it to the new owner doc rather than deleting it or leaving it in an index +Decision/Rationale preservation gate: +- before any truth-doc split, restructure, or shape repair, inventory existing Product Decisions, Engineering Decisions, and Rationale sections in every source or touched truth doc +- preserve each current decision and rationale in the correct product or engineering lane owner; when splitting, move it to the new owner doc rather than deleting it or leaving it in an index - 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 +- after the edit, verify every touched truth doc keeps lane-appropriate decision/rationale sections and every pre-existing entry is preserved, moved, narrowed, removed with evidence, or blocked Topology pressure signals: - one area maps broad code such as src/**, app/**, server/**, services/**, or packages/** - one area maps multiple unrelated controllers, route groups, services, or bounded contexts - one truth doc owns unrelated behaviors or unrelated endpoint families -- the configured truth root has many direct non-index docs +- either configured lane 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/routes/areas/** @@ -72,9 +81,10 @@ 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/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 +- create engineering behavior truth docs under docs/truthmark/engineering only when behavior lacks a current doc +- create product truth docs under docs/truthmark/product only when product promise, boundary, rationale, or user-visible capability truth is in scope - README.md files are indexes, not Truth Sync targets -- prefer bounded leaf truth docs at //.md +- prefer bounded product docs under product/capabilities or product/decisions and engineering docs under engineering//.md - keep behavior truth docs behavior-oriented, not endpoint-oriented - keep API endpoint details in the nearest contract truth doc when such a doc exists - update routing so future Truth Sync can target small docs @@ -88,13 +98,13 @@ Truth-doc shape repair gate: - preserve supported claims; remove, narrow, or block unsupported or stale claims - report docs restructured and why a narrow edit was not sufficient Evidence Gate: -- apply the Evidence Gate before finishing when Truth Structure writes routed docs, ownership claims, Product Decisions, or Rationale +- apply the Evidence Gate before finishing when Truth Structure writes routed docs, ownership claims, lane-specific decisions, or rationale - support ownership/behavior claims with topology or primary checkout evidence from layout, implementation boundaries, docs, config, route files, tests, templates, schemas, or contracts - tests/examples/canonical docs corroborate; remove, narrow, or block unsupported claims Maintain architecture docs only for structure-level changes: system structure, module boundaries, runtime topology, persistence boundaries, cross-cutting contracts, or generated-surface ownership. Keep ordinary behavior, endpoints, UI copy, validation rules, and bug fixes in behavior or contract docs unless they change those boundaries. -- Do not finish topology repair with routed canonical current-truth docs missing Product Decisions or Rationale sections. -- If an existing canonical doc lacks either section, add the missing heading beside Current Behavior with a concise current-state placeholder or active decision. +- Do not finish topology repair with mixed product/engineering authority in a single canonical truth doc. +- If an existing canonical doc has wrong-lane sections, split or move them into the correct product or engineering lane. Portable fallback: - If this skill surface is unavailable, perform the same workflow directly from committed repository files. - Do not require the truthmark CLI. @@ -104,7 +114,8 @@ Truthmark hierarchy hints: - Config, when present: .truthmark/config.yml - 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 +- Product truth docs, when present: docs/truthmark/product/**/*.md +- Engineering truth docs, when present: docs/truthmark/engineering/**/*.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. +Product decisions belong in product truth; engineering, architecture, contract, workflow, and operational decisions belong in engineering truth. diff --git a/.opencode/skills/truthmark-structure/support/report-template.md b/.opencode/skills/truthmark-structure/support/report-template.md index 1be260b..7d1ae37 100644 --- a/.opencode/skills/truthmark-structure/support/report-template.md +++ b/.opencode/skills/truthmark-structure/support/report-template.md @@ -1,13 +1,14 @@ # Truthmark Structure Report Template -Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.0. Rerun truthmark init after upgrades. Report completion in this shape: ```md Truth Structure: completed Topology reviewed: - controllers: src/auth/** -- docs root: docs/truthmark/truth +- product docs root: docs/truthmark/product +- engineering docs root: docs/truthmark/engineering - route files: docs/truthmark/routes/areas.md Areas reviewed: - src/auth/** @@ -16,12 +17,14 @@ Routing updated: Initial truth boundary: - Area: Authentication - Code: src/auth/** -- Truth owner: docs/truthmark/truth/authentication/session.md +- Product owner: docs/truthmark/product/capabilities/authentication-session.md +- Engineering owner: docs/truthmark/engineering/behaviors/authentication-session.md - Scope: session behavior only Truth docs created: -- docs/truthmark/truth/authentication/session.md +- docs/truthmark/product/capabilities/authentication-session.md +- docs/truthmark/engineering/behaviors/authentication-session.md Truth docs split: -- docs/truthmark/truth/authentication/README.md -> docs/truthmark/truth/authentication/session.md +- docs/truthmark/truth/authentication/README.md -> docs/truthmark/product/capabilities/authentication-session.md and docs/truthmark/engineering/behaviors/authentication-session.md Truth docs restructured: - docs/truthmark/truth/authentication/README.md Evidence checked: diff --git a/.opencode/skills/truthmark-structure/support/subagents-and-leases.md b/.opencode/skills/truthmark-structure/support/subagents-and-leases.md index ac1129b..b624b75 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 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.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 ff1d4eb..bc5514e 100644 --- a/.opencode/skills/truthmark-sync/SKILL.md +++ b/.opencode/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: 2.1.0 +truthmark-version: 2.2.0 --- # Truthmark Sync diff --git a/.opencode/skills/truthmark-sync/helper-manifest.yml b/.opencode/skills/truthmark-sync/helper-manifest.yml index dd0153a..1f9a1f1 100644 --- a/.opencode/skills/truthmark-sync/helper-manifest.yml +++ b/.opencode/skills/truthmark-sync/helper-manifest.yml @@ -1,8 +1,8 @@ -# Generated by Truthmark 2.1.0. Rerun truthmark init after upgrades. +# Generated by Truthmark 2.2.0. Rerun truthmark init after upgrades. helpers: validate-sync-report: optional: true - runner: truthmark>=2.1.0 + runner: truthmark>=2.2.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>=2.1.0 + runner: truthmark>=2.2.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 6c44128..885d6a1 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 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.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>=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 +- validate-sync-report: optional truthmark>=2.2.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.2.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 ff0f6f7..3026dce 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 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.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. @@ -10,10 +10,19 @@ Parent workflow: 1. Inspect git status, staged changes, unstaged changes, and untracked files directly. 2. Inspect .truthmark/config.yml and configured route files only when they exist; then inspect relevant canonical docs. 3. Identify functional-code changes and the nearest truth docs or routing repairs. -4. 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. -5. Code verification is parent-owned: follow repository instructions and task context, and report what ran or why it did not run. -6. Dispatch bounded Truth Sync workers only when the host supports subagent dispatch and the acting agent chooses that path; otherwise execute the same sync task inline. +4. Evidence authority: + - 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. +5. Lane classification gate: + - before writing canonical truth docs, classify the request or change as product-lane, engineering-lane, both-lane, or ambiguous + - product-lane writes belong under docs/truthmark/product and state product promises, boundaries, rationale, decisions, and success criteria + - engineering-lane writes belong under docs/truthmark/engineering and state source-backed current realization, contracts, architecture, workflows, operations, or tests + - both-lane work must write separate product and engineering docs and cross-link them in route YAML with realized_by and realizes, not in doc frontmatter + - ambiguous lane ownership must block or invoke Truth Structure instead of writing a mixed document + - Do not make product docs a summary of engineering docs. Do not make engineering docs a detailed version of product docs. Product truth says what must be true and why. Engineering truth says how the repository currently realizes it. +6. Update engineering truth first after code changes. Update product truth only when implemented user-visible product promise or capability boundary changed and explicit source/user evidence supports it; otherwise report product-lane review needed. +7. Code verification is parent-owned: follow repository instructions and task context, and report what ran or why it did not run. +8. Dispatch bounded Truth Sync workers only when the host supports subagent dispatch and the acting agent chooses that path; otherwise execute the same sync task inline. Topology quality gate: - before updating truth docs, verify the changed code resolves to a specific behavior-owned area and bounded truth owner - if routing is missing, stale, broad, overloaded, catch-all route only, or cannot map changed code to a bounded truth owner, do not create another generic truth doc @@ -23,22 +32,23 @@ Topology quality gate: - README.md files are indexes, not Truth Sync targets - must not append behavior details to a README.md index - create or update a bounded leaf truth doc when behavior changes do not fit an existing leaf doc +- write engineering truth under docs/truthmark/engineering; product truth updates under docs/truthmark/product are allowed only for explicit current product behavior changes Truth-doc ownership gate: - before editing or relying on changed functional files and impacted truth docs, verify each target/source truth doc is a bounded owner for the behavior - if a target/source doc mixes independent owners, spans unrelated behaviors, acts as an index, or needs cross-owner edits, do not patch or in-place repair it - if an impacted doc is broad, mixed-owner, index-like, or the update spans independent behavior owners, run Truth Structure before syncing when safe and in scope; otherwise block and recommend Truth Structure - report Ownership reviewed, Structure required, Truth docs split, Truth docs restructured, or Blocked reason as applicable -Product Decisions/Rationale preservation gate: -- before any truth-doc split, restructure, or shape repair, inventory existing Product Decisions and Rationale sections in every source or touched truth doc -- preserve each current decision and rationale in the bounded owner doc it governs; when splitting, move it to the new owner doc rather than deleting it or leaving it in an index +Decision/Rationale preservation gate: +- before any truth-doc split, restructure, or shape repair, inventory existing Product Decisions, Engineering Decisions, and Rationale sections in every source or touched truth doc +- preserve each current decision and rationale in the correct product or engineering lane owner; when splitting, move it to the new owner doc rather than deleting it or leaving it in an index - 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 +- after the edit, verify every touched truth doc keeps lane-appropriate decision/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 template under the configured Truthmark templates root. -Supported kinds: behavior, contract, architecture, workflow, operations, and test-behavior. +Supported kinds: product-capability, engineering-behavior, engineering-contract, engineering-architecture, engineering-workflow, engineering-operations, and engineering-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. +If the template is missing, use lane-specific sections: product truth says what must be true and why; engineering truth says how the repository currently realizes it. 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. @@ -51,7 +61,7 @@ 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. Evidence Gate: - route-first: map changed functional files to bounded route owners and primary canonical docs -- review new or changed behavior-bearing claims only in touched docs, route ownership, Product Decisions, and Rationale +- review new or changed behavior-bearing claims only in touched docs, route ownership, lane-specific decisions, and rationale - support claims with primary checkout evidence: implementation, config, routing, generated templates, schemas, or contract definitions - tests/examples/canonical docs corroborate; they are not sole proof when implementation conflicts - remove, narrow, or block unsupported claims @@ -63,7 +73,7 @@ Optional validation tooling: - you may run truthmark check when local tooling is available - do not require the truthmark binary; direct checkout inspection is the canonical path - optional validation must not replace agent judgment about docs and routing -- update Product Decisions and Rationale when a behavior change comes from a decision change +- update Product Decisions only in product truth and Engineering Decisions only in engineering truth when evidence supports the lane-specific decision change Helper status reporting: - Validate the report body before adding this validator's own success status; the body may omit `validate-sync-report` while validation is pending. - After `truthmark validate sync-report --json` returns `data.validation.ok: true`, append or update `validate-sync-report: ran, passed` in the final report. @@ -74,10 +84,11 @@ Truthmark hierarchy hints: - Config, when present: .truthmark/config.yml - 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 +- Product truth docs, when present: docs/truthmark/product/**/*.md +- Engineering truth docs, when present: docs/truthmark/engineering/**/*.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. +Product decisions belong in product truth; engineering, architecture, contract, workflow, and operational decisions belong in engineering truth. Parent post-sync verification: - verify only truth docs and leased truth routing files changed during sync - block on any unrelated diff caused by the sync step diff --git a/.opencode/skills/truthmark-sync/support/report-template.md b/.opencode/skills/truthmark-sync/support/report-template.md index 4dfa42d..5331249 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 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.0. Rerun truthmark init after upgrades. Report completion in this shape: ```md @@ -13,7 +13,7 @@ Ownership reviewed: - docs/truthmark/routes/areas.md Truth docs updated: -- docs/truthmark/truth/repository/overview.md +- docs/truthmark/engineering/repository/overview.md Evidence checked: - Claim: Session timeout behavior is documented in the mapped repository truth doc. diff --git a/.opencode/skills/truthmark-sync/support/subagents-and-leases.md b/.opencode/skills/truthmark-sync/support/subagents-and-leases.md index 57c829b..70d96f2 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 2.1.0. Rerun truthmark init after upgrades. +Generated by Truthmark 2.2.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 e6ac65e..d68f68b 100644 --- a/.truthmark/config.yml +++ b/.truthmark/config.yml @@ -7,15 +7,6 @@ platforms: - gemini-cli 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 @@ -25,9 +16,7 @@ frontmatter: required: [] recommended: - status - - doc_type - last_reviewed - - source_of_truth ignore: - node_modules/** - vendor/** diff --git a/AGENTS.md b/AGENTS.md index 5202bc3..9bfa8a8 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -9,8 +9,8 @@ Agent-specific: ## Truthmark Workflow -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. +Generated by Truthmark 2.2.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/product/**/*.md and docs/truthmark/engineering/**/*.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 5202bc3..9bfa8a8 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -9,8 +9,8 @@ Agent-specific: ## Truthmark Workflow -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. +Generated by Truthmark 2.2.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/product/**/*.md and docs/truthmark/engineering/**/*.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/CONTRIBUTING.md similarity index 98% rename from CONTRIBUTORS.md rename to CONTRIBUTING.md index b55290b..ffb1463 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTING.md @@ -1,4 +1,4 @@ -# Contributors +# Contributing This guide is for people contributing to Truthmark itself from this checkout. diff --git a/GEMINI.md b/GEMINI.md index 5202bc3..9bfa8a8 100644 --- a/GEMINI.md +++ b/GEMINI.md @@ -9,8 +9,8 @@ Agent-specific: ## Truthmark Workflow -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. +Generated by Truthmark 2.2.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/product/**/*.md and docs/truthmark/engineering/**/*.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 5ed2d8e..ba5dfba 100644 --- a/README.de.md +++ b/README.de.md @@ -511,12 +511,9 @@ Wichtige Config-Bereiche sind: | `version` | Version des Config-Vertrags. | | `platforms` | Agenten-Hosts, die plattformspezifische generierte Oberflächen erhalten sollen. | | `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`. | +| Feste Routen | Routen liegen unter `routes/areas.md` und `routes/areas/` innerhalb von `truthmark.workspace`; die Standard-Area ist `repository`, die Delegationstiefe ist `1`. | +| Feste Truth-Lanes | Product-Truth liegt unter `product/` und Engineering-Truth unter `engineering/` innerhalb von `truthmark.workspace`. | +| Feste Vorlagen | Truth-Dokumentvorlagen liegen unter `templates/` innerhalb von `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. | @@ -749,7 +746,7 @@ Nützliche Skripte: | `npm run check` | Führt Lint, Typecheck, Tests und Build aus. | | `npm run release:check` | Führt release-orientierte Validierung aus. | -Wenn du Truthmark selbst änderst, siehe [CONTRIBUTORS.md](CONTRIBUTORS.md). +Wenn du Truthmark selbst änderst, siehe [CONTRIBUTING.md](CONTRIBUTING.md). ## Dokumentation diff --git a/README.es.md b/README.es.md index 5729b08..42d85b4 100644 --- a/README.es.md +++ b/README.es.md @@ -511,12 +511,9 @@ Las áreas importantes de configuración incluyen: | `version` | Versión del contrato de configuración. | | `platforms` | Hosts de agentes que deben recibir interfaces generadas específicas de plataforma. | | `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`. | +| Rutas fijas | Las rutas viven en `routes/areas.md` y `routes/areas/` dentro de `truthmark.workspace`; el área predeterminada es `repository` y la profundidad de delegación es `1`. | +| Carriles de verdad fijos | La verdad de producto vive en `product/` y la verdad de ingeniería en `engineering/` dentro de `truthmark.workspace`. | +| Plantillas fijas | Las plantillas de documentos de verdad viven en `templates/` dentro de `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. | @@ -749,7 +746,7 @@ Scripts útiles: | `npm run check` | Ejecuta lint, typecheck, pruebas y build. | | `npm run release:check` | Ejecuta validación orientada a release. | -Cuando cambies Truthmark en sí, consulta [CONTRIBUTORS.md](CONTRIBUTORS.md). +Cuando cambies Truthmark en sí, consulta [CONTRIBUTING.md](CONTRIBUTING.md). ## Documentación diff --git a/README.md b/README.md index fdefc6d..7d3ccaf 100644 --- a/README.md +++ b/README.md @@ -511,12 +511,9 @@ Important config areas include: | `version` | Config contract version. | | `platforms` | Agent hosts that should receive platform-specific generated surfaces. | | `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`. | +| Fixed routes | Routes live under `routes/areas.md` and `routes/areas/` inside `truthmark.workspace`; the default area is `repository` and delegation depth is `1`. | +| Fixed truth lanes | Product truth lives under `product/` and engineering truth under `engineering/` inside `truthmark.workspace`. | +| Fixed templates | Truth-doc templates live under `templates/` inside `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. | @@ -749,7 +746,7 @@ Useful scripts: | `npm run check` | Run lint, typecheck, tests, and build. | | `npm run release:check` | Run release-oriented validation. | -When changing Truthmark itself, see [CONTRIBUTORS.md](CONTRIBUTORS.md). +When changing Truthmark itself, see [CONTRIBUTING.md](CONTRIBUTING.md). ## Documentation diff --git a/README.ru.md b/README.ru.md index 4d22873..ada2081 100644 --- a/README.ru.md +++ b/README.ru.md @@ -511,12 +511,9 @@ truthmark init | `version` | Версия контракта config. | | `platforms` | Agent hosts, которые должны получить сгенерированные интерфейсы для платформы. | | `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`. | +| Фиксированные маршруты | Маршруты находятся в `routes/areas.md` и `routes/areas/` внутри `truthmark.workspace`; область по умолчанию — `repository`, глубина делегирования — `1`. | +| Фиксированные дорожки истины | Product truth находится в `product/`, а engineering truth в `engineering/` внутри `truthmark.workspace`. | +| Фиксированные шаблоны | Шаблоны документов истины находятся в `templates/` внутри `truthmark.workspace`. | | `truthmark.generated.portal` | Опциональное включение ручного презентационного workflow: `enabled`. | | `instruction_targets` | Файлы, которые получают общие управляемые блоки инструкций, например `AGENTS.md`. | | `frontmatter.required` | Поля metadata, которые создают error diagnostics при отсутствии. | @@ -749,7 +746,7 @@ npm run check | `npm run check` | Запускает lint, typecheck, tests и build. | | `npm run release:check` | Запускает release-oriented validation. | -Когда меняете сам Truthmark, смотрите [CONTRIBUTORS.md](CONTRIBUTORS.md). +Когда меняете сам Truthmark, смотрите [CONTRIBUTING.md](CONTRIBUTING.md). ## Документация diff --git a/README.zh.md b/README.zh.md index 399e602..3a557fd 100644 --- a/README.zh.md +++ b/README.zh.md @@ -511,12 +511,9 @@ truthmark init | `version` | 配置契约版本。 | | `platforms` | 应接收平台专属生成接口的代理宿主。 | | `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.workspace` 内的 `routes/areas.md` 和 `routes/areas/`;默认 area 是 `repository`,委托深度为 `1`。 | +| 固定事实分区 | 产品事实位于 `truthmark.workspace` 内的 `product/`,工程事实位于 `engineering/`。 | +| 固定模板 | 事实文档模板固定在 `truthmark.workspace` 内的 `templates/`。 | | `truthmark.generated.portal` | 可选手动展示工作流启用设置:`enabled`。 | | `instruction_targets` | 接收共享受管指令块的文件,例如 `AGENTS.md`。 | | `frontmatter.required` | 缺失时产生错误诊断的元数据字段。 | @@ -749,7 +746,7 @@ npm run check | `npm run check` | 运行 lint、typecheck、测试和 build。 | | `npm run release:check` | 运行面向发布的验证。 | -修改 Truthmark 本身时,请参阅 [CONTRIBUTORS.md](CONTRIBUTORS.md)。 +修改 Truthmark 本身时,请参阅 [CONTRIBUTING.md](CONTRIBUTING.md)。 ## 文档 diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..2b93d41 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,27 @@ +# Security Policy + +## Supported Versions + +Security fixes are handled on the current maintained release line of Truthmark. If you are using an older version, upgrade to the latest published version before reporting unless the issue only exists in the current release. + +## Reporting a Vulnerability + +Please do not post exploitable vulnerability details in a public issue. + +Preferred reporting path: + +1. Use GitHub's private vulnerability reporting or security advisory flow for this repository when available. +2. If private reporting is unavailable, open a GitHub issue with a minimal description and no exploit details, then coordinate details with the maintainer through the channel they provide. + +Useful report details: + +- affected Truthmark version or commit +- operating system and Node.js version +- whether the issue affects the CLI, generated workflow surfaces, validation commands, or repository file handling +- impact and reproduction steps, with secrets and private repository content removed + +## Scope + +Security-sensitive areas include command execution boundaries, generated workflow guidance, path handling, repository write boundaries, package publishing, and handling of untrusted repository Markdown/configuration. + +Truthmark is local-first and Git-native. It should not require a daemon, database, hosted service, or hidden memory layer for normal operation. diff --git a/SUPPORT.md b/SUPPORT.md new file mode 100644 index 0000000..1d430d7 --- /dev/null +++ b/SUPPORT.md @@ -0,0 +1,27 @@ +# Support + +Use GitHub issues for support requests, bug reports, documentation problems, and workflow questions. + +Before opening an issue: + +1. Check the [README](README.md) for the normal install and validation flow. +2. Check the [docs index](docs/README.md) for detailed behavior and architecture references. +3. Run the narrowest relevant command and include its output when possible: + +```bash +truthmark check --json +truthmark index --json +``` + +For source-checkout development, also see [CONTRIBUTING.md](CONTRIBUTING.md). + +## What To Include + +- Truthmark version or commit +- Node.js and npm versions +- operating system +- the command or workflow you ran +- relevant snippets from `.truthmark/config.yml`, routes, truth docs, or generated surfaces +- expected behavior and actual behavior + +Do not include secrets, private repository content, tokens, or exploitable security details in public issues. Use [SECURITY.md](SECURITY.md) for vulnerability reports. diff --git a/changes/2026-06-14-version-2-2-0.md b/changes/2026-06-14-version-2-2-0.md new file mode 100644 index 0000000..dbbd50c --- /dev/null +++ b/changes/2026-06-14-version-2-2-0.md @@ -0,0 +1,20 @@ +# Truthmark 2.2.0 + +Previous version: 2.1.0 +New version: 2.2.0 +Diff basis: release/2.1.0..HEAD plus working tree +Version action: minor +SemVer rationale: This release refreshes package metadata and generated agent-workflow surfaces for the 2.2.0 runtime marker while preserving existing behavior, including updated generated instruction/manifest surfaces that are version-coupled. + +Release payload: +- Update package version metadata in `package.json` and root `package-lock.json` entries from 2.1.0 to 2.2.0. +- Run `truthmark init --json` to refresh generated platform surfaces and managed instruction blocks for the new runtime marker. +- Update repository instruction targets (`AGENTS.md`, `CLAUDE.md`, `GEMINI.md`) to reference the `Truthmark 2.2.0` generated marker. + +User-facing release text: +- `truthmark` is now tagged as 2.2.0, with the generated workflow surfaces and agent helpers refreshed to match the same runtime version marker. + +Verification: +- `npm run release:check` +- `npx tsx src/cli/main.ts check --json` +- `npx tsx src/cli/main.ts index --json` diff --git a/docs/truthmark/engineering/README.md b/docs/truthmark/engineering/README.md new file mode 100644 index 0000000..528c4e9 --- /dev/null +++ b/docs/truthmark/engineering/README.md @@ -0,0 +1,17 @@ +--- +status: active +doc_type: index +last_reviewed: 2026-06-14 +--- + +# Truth Docs + +This directory is an index for current truth docs organized by the configured Truthmark hierarchy. + +Engineering truth owns current realization, contracts, architecture, workflows, operations, and tests. Engineering lane docs describe how the repository currently implements and operates the behavior. + +README.md files are indexes, not Truth Sync targets. Keep engineering truth in bounded behavior, contract, architecture, workflow, operations, and test docs. + +## Source References + +- ../routes/areas.md diff --git a/docs/truthmark/engineering/architecture/overview.md b/docs/truthmark/engineering/architecture/overview.md new file mode 100644 index 0000000..5e26904 --- /dev/null +++ b/docs/truthmark/engineering/architecture/overview.md @@ -0,0 +1,59 @@ +--- +status: active +truth_kind: engineering-architecture +last_reviewed: 2026-06-14 +--- + +# Architecture Overview + +## Purpose + +This doc owns the current source-level architecture of Truthmark as a workflow injector. + +## Scope + +It covers CLI handlers, config loading, routing, checks, generation, repository intelligence, and workflow-surface rendering. + +## Current Implementation Behavior + +Truthmark is a local CLI and generated-surface renderer. It reads checkout files, normalizes configuration, parses route files, emits diagnostics, and writes configured workflow surfaces during init. + +## Boundaries + +- CLI command parsing and handlers live under `src/cli`. +- Config and defaults live under `src/config`. +- Route parsing and resolution live under `src/routing`. +- Checks live under `src/checks`. +- Generated workflow rendering lives under `src/templates` and `src/agents`. + +## Components + +- Config loader +- Route parser and resolver +- Check pipeline +- Init/scaffold renderer +- Workflow manifest and generated surface renderer +- RepoIndex, RouteMap, ImpactSet, ContextPack, and WorkflowState builders + +## Product Truth Links + +- `docs/truthmark/product/capabilities/lane-separated-truth.md` + +## Engineering Decisions + +- Decision (2026-06-14): Architecture docs describe current repository realization and do not redefine product promises. + +## Maintenance Notes + +Update when module boundaries, generated-surface ownership, or command architecture changes. + +## Source References + +- ../../../../src/cli/handlers.ts +- ../../../../src/config/load.ts +- ../../../../src/routing/areas.ts +- ../../../../src/templates/generated-surfaces.ts +- `src/cli/handlers.ts` +- `src/config/load.ts` +- `src/routing/areas.ts` +- `src/templates/generated-surfaces.ts` diff --git a/docs/truthmark/engineering/behaviors/check-diagnostics.md b/docs/truthmark/engineering/behaviors/check-diagnostics.md new file mode 100644 index 0000000..61ec258 --- /dev/null +++ b/docs/truthmark/engineering/behaviors/check-diagnostics.md @@ -0,0 +1,62 @@ +--- +status: active +truth_kind: engineering-behavior +last_reviewed: 2026-06-15 +--- + +# Check Diagnostics + +## Purpose + +This doc owns the implementation behavior of Truthmark Check diagnostics. + +## Scope + +It covers route coverage, lane shape, lane drift, traceability, frontmatter, generated surfaces, and source evidence diagnostics. + +## Current Implementation Behavior + +`truthmark check` combines config, area routing, frontmatter, link, lane-shape, lane-drift, traceability, generated-surface, source-traceability, and freshness diagnostics. Missing product links for engineering behavior, workflow, and contract docs are review diagnostics only when the same routed area includes product truth evidence. Cross-lane route metadata is route-local: product `realized_by` links and engineering `realizes` links must target existing opposite-lane truth docs, but they do not have to be reciprocated by the target entry. Repeated route entries for the same truth document, kind, and lane merge their `realized_by`, `realizes`, and `depends_on` metadata before traceability validation; conflicting duplicate kinds or lanes are area-index errors. + +Frontmatter diagnostics reject relationship metadata fields `realized_by`, `realizes`, and `depends_on` when they appear in truth document frontmatter. Relationship authority stays in fenced route YAML entries. + +Product truth doc structure validation enforces the `product-capability` shape. Product capability docs require capability sections for the capability promise, users and value, capability scope including boundary constraints and adjacent systems, current product behavior, acceptance criteria, product decisions, engineering realization links, and non-goals. + +## Core Rules + +- Product docs must live under the product truth root and use product kinds. +- Engineering docs must live under the engineering truth root and use engineering kinds. +- Product docs under `docs/truthmark/product/**` infer `product-capability` unless explicit route metadata says otherwise. +- Product capability docs do not satisfy product structure by using only boundary headings. +- Relationship metadata belongs in route YAML; truth document frontmatter must not declare `realized_by`, `realizes`, or `depends_on`. +- Traceability links must exist and point to the opposite lane; reciprocal `realized_by` and `realizes` metadata is allowed but not required. +- Duplicate route entries for the same path, kind, and lane merge `realized_by`, `realizes`, and `depends_on` by unique sorted set. +- Check reports structure and evidence only; it does not judge product strategy. + +## Product Truth Links + +- `docs/truthmark/product/capabilities/lane-separated-truth.md` + +## Engineering Decisions + +- Decision (2026-06-14): Wrong-lane content is a lane-drift diagnostic; missing product links for engineering behavior, workflow, and contract docs are review diagnostics only when routed area evidence indicates product truth context. +- Decision (2026-06-14): Downstream injected/default product truth supports `product-capability` only; boundary material belongs inside capability scope, acceptance criteria, and non-goals. +- Decision (2026-06-15): Duplicate route entries with the same path, kind, and lane are an additive relationship model; divergent relationship arrays merge instead of erroring so area-local route entries do not have to repeat the full relationship closure. +- Decision (2026-06-15): `realized_by` and `realizes` route metadata is route-local navigation metadata, not a canonical global graph, so check validates target existence and lane compatibility without requiring reciprocal edges. + +## Maintenance Notes + +Update when check categories, severity rules, lane audit behavior, or product kind section requirements change. + +## Source References + +- ../../../../src/checks/check.ts +- ../../../../src/checks/areas.ts +- ../../../../src/checks/decisions.ts +- ../../../../src/checks/frontmatter.ts +- ../../../../tests/checks/frontmatter.test.ts +- `src/checks/areas.ts` +- `src/checks/decisions.ts` +- `src/checks/frontmatter.ts` +- `tests/checks/frontmatter.test.ts` +- `src/output/diagnostic.ts` diff --git a/docs/truthmark/engineering/behaviors/init-and-scaffold.md b/docs/truthmark/engineering/behaviors/init-and-scaffold.md new file mode 100644 index 0000000..89481a3 --- /dev/null +++ b/docs/truthmark/engineering/behaviors/init-and-scaffold.md @@ -0,0 +1,44 @@ +--- +status: active +truth_kind: engineering-behavior +last_reviewed: 2026-06-14 +--- + +# Init And Scaffold + +## Purpose + +This doc owns current scaffold behavior for Truthmark hierarchy, templates, and default route files. + +## Scope + +It covers config defaults, lane root creation, template files, and starter route metadata. + +## Current Implementation Behavior + +Defaults derive all scaffold paths from `truthmark.workspace`. Routes are fixed at `/routes/areas.md` and `/routes/areas/`; the default scaffolded route area is `repository`; max route delegation depth is `1`; product truth is fixed at `/product`; engineering truth is fixed at `/engineering`; editable truth templates are fixed at `/templates`. Template filenames match `truth_kind` values directly: `product-capability.md`, `engineering-behavior.md`, `engineering-contract.md`, `engineering-architecture.md`, `engineering-workflow.md`, `engineering-operations.md`, and `engineering-test-behavior.md`. Generated truth-doc frontmatter includes `truth_kind` and does not include `doc_type` or `truth_lane`. + +Init reads the default seeded behavior leaf from `engineering-behavior.md`. Downstream product truth uses the `product-capability` template only. Capability docs own a single user-visible capability promise, users/value, scope including boundary constraints and adjacent systems, current product behavior, acceptance criteria, decisions, realization links, and non-goals. + +## Product Truth Links + +- `docs/truthmark/product/capabilities/lane-separated-truth.md` + +## Engineering Decisions + +- Decision (2026-06-14): New scaffold targets do not create `docs/truthmark/truth` as the canonical target root. +- Decision (2026-06-14): Editable template filenames match `truth_kind` values directly so generated docs do not point agents at legacy `*-doc.md` names. +- Decision (2026-06-14): Init scaffolds routes, templates, product truth, and engineering truth at fixed workspace-derived paths rather than accepting route or template roots from config. + +## Maintenance Notes + +Update when init writes new files, changes default paths, changes template filenames, or changes template shape. + +## Source References + +- ../../../../src/init/hierarchy.ts +- ../../../../src/templates/init-files.ts +- ../../../../src/config/defaults.ts +- `src/config/defaults.ts` +- `src/init/hierarchy.ts` +- `src/templates/init-files.ts` diff --git a/docs/truthmark/engineering/contracts/config-route-and-check-contracts.md b/docs/truthmark/engineering/contracts/config-route-and-check-contracts.md new file mode 100644 index 0000000..1d91bbe --- /dev/null +++ b/docs/truthmark/engineering/contracts/config-route-and-check-contracts.md @@ -0,0 +1,70 @@ +--- +status: active +truth_kind: engineering-contract +last_reviewed: 2026-06-15 +--- + +# Config, Route, And Check Contracts + +## Purpose + +This doc owns machine-facing contracts for Truthmark config, lane-aware route metadata, diagnostics, and command envelopes. + +## Scope + +It covers config normalization, route `truth_documents` metadata, diagnostic categories, and JSON result shape. + +## Current Implementation Behavior + +Default config exposes `truthmark.workspace` and `truthmark.generated.portal.enabled`; it does not expose route layout, template layout, or truth lane roots as knobs. Routes are fixed at `/routes/areas.md` and `/routes/areas/`, the default area is the product invariant `repository`, max delegation depth is the product invariant `1`, templates are fixed at `/templates`, product truth is fixed at `/product`, and engineering truth is fixed at `/engineering`. User-provided `truthmark.routes`, `truthmark.templates`, or `truthmark.truth` blocks are rejected as unsupported additional properties. Route entries can declare `kind`, optional `lane`, `realized_by`, `realizes`, and `depends_on`; product `realized_by` and engineering `realizes` links are valid when their targets exist and point to the opposite lane, without requiring reciprocal declarations. Duplicate route entries for the same path, kind, and lane merge relationship metadata for `realized_by`, `realizes`, and `depends_on` by unique sorted set before validation and RouteMap output; conflicting duplicate kinds or lanes are reported as area-index errors. + +## Contract Surface + +- `.truthmark/config.yml` +- `docs/truthmark/routes/areas.md` +- `docs/truthmark/routes/areas/**/*.md` +- `CommandResult` JSON envelopes + +## Inputs + +- Config YAML with version `2` +- Fenced route YAML with `truth_documents` +- Markdown frontmatter fields such as `truth_kind` + +## Outputs + +- Normalized config paths for fixed route, template, product truth, engineering truth, and Portal locations derived from `truthmark.workspace` +- RouteMap data preserving lane and relationship metadata, plus RepoIndex data preserving derived doc type and lane metadata +- Diagnostics including `lane-shape`, `lane-drift`, and `traceability` + +## Compatibility Rules + +The target model is lane-first and does not use `docs/truthmark/truth` as the canonical scaffold target. + +## Product Truth Links + +- `docs/truthmark/product/capabilities/lane-separated-truth.md` + +## Engineering Decisions + +- Decision (2026-06-14): Authored relationship fields use explicit `realized_by`, `realizes`, and `depends_on` fields in route YAML, not doc frontmatter. +- Decision (2026-06-14): Canonical truth docs use `truth_kind` as the frontmatter source for truth lane and doc type; `truth_lane` remains accepted only as an optional consistency check. +- Decision (2026-06-14): Route layout, template layout, default area `repository`, and max delegation depth `1` are product invariants derived from `truthmark.workspace`, not user config fields. +- Decision (2026-06-15): Duplicate route relationship metadata is additive for matching path, kind, and lane entries; kind and lane conflicts remain hard validation errors. +- Decision (2026-06-15): Route relationships are route-local metadata; checks validate relationship targets for existence and lane compatibility without requiring a reciprocal global graph edge. + +## Maintenance Notes + +Update when config fields, route metadata, diagnostics, or route/index output schemas change. + +## Source References + +- ../../../../src/config/schema.ts +- ../../../../src/config/defaults.ts +- ../../../../src/config/load.ts +- ../../../../src/routing/areas.ts +- ../../../../src/output/diagnostic.ts +- `src/config/schema.ts` +- `src/routing/areas.ts` +- `src/repo-index/types.ts` +- `src/output/diagnostic.ts` diff --git a/docs/truthmark/engineering/contracts/generated-host-surfaces.md b/docs/truthmark/engineering/contracts/generated-host-surfaces.md new file mode 100644 index 0000000..e4178ec --- /dev/null +++ b/docs/truthmark/engineering/contracts/generated-host-surfaces.md @@ -0,0 +1,59 @@ +--- +status: active +truth_kind: engineering-contract +last_reviewed: 2026-06-15 +--- + +# Generated Host Surfaces + +## Purpose + +This doc owns the current generated host surface contract. + +## Scope + +It covers configured platform output paths, generated workflow files, managed instruction blocks, and helper metadata. + +## Current Implementation Behavior + +Truthmark renders workflow surfaces for configured platforms and leaves already committed files in place when platforms are removed from config. Host skill packages carry canonical workflow entrypoints plus support files for full procedures, report templates, subagent guidance, and helper policy. GitHub Copilot prompt files and Gemini command files are lightweight workflow adapters: they identify the current host entrypoint, tell the agent not to invoke another Truthmark command from inside that entrypoint, point only to host-local skill package files, and use direct checkout inspection as fallback instead of duplicating full workflow bodies. + +## Contract Surface + +- Codex, OpenCode, Claude Code, GitHub Copilot, and Gemini CLI skills/prompts/commands/agents +- `AGENTS.md`, `CLAUDE.md`, `.github/copilot-instructions.md`, and `GEMINI.md` managed blocks + +## Inputs + +- `platforms` in `.truthmark/config.yml` +- Workflow manifest entries +- Template renderer functions + +## Outputs + +- Host-native workflow skill packages and compact prompt/command adapters +- Optional helper manifests +- Managed instruction blocks with the Truthmark version marker + +## Product Truth Links + +- `docs/truthmark/product/capabilities/agent-native-workflow-injection.md` + +## Engineering Decisions + +- Decision (2026-06-14): Generated surfaces must preserve Truthmark as a workflow injector, not a runtime authority. +- Decision (2026-06-15): GitHub Copilot prompt files and Gemini command files stay compact workflow adapters when a host skill package exists; canonical workflow bodies remain in generated skill support files. +- Decision (2026-06-15): GitHub Copilot prompt files and Gemini command files must not embed cross-host Truthmark invocation lists; those lists belong in human-facing docs or skill metadata, not adapter bodies. + +## Maintenance Notes + +Update when platform paths, supported hosts, helper manifests, or managed block content changes. + +## Source References + +- ../../../../src/templates/generated-surfaces.ts +- ../../../../src/templates/workflow-surfaces.ts +- ../../../../src/templates/agents-block.ts +- `src/templates/generated-surfaces.ts` +- `src/templates/workflow-surfaces.ts` +- `src/templates/agents-block.ts` diff --git a/docs/truthmark/engineering/operations/release-automation.md b/docs/truthmark/engineering/operations/release-automation.md new file mode 100644 index 0000000..7c28fe7 --- /dev/null +++ b/docs/truthmark/engineering/operations/release-automation.md @@ -0,0 +1,47 @@ +--- +status: active +truth_kind: engineering-operations +last_reviewed: 2026-06-14 +--- + +# Release Automation + +## Purpose + +This doc owns current release and CI automation behavior. + +## Scope + +It covers GitHub workflow triggers, verification steps, and generated GitHub Action template behavior. + +## Current Implementation Behavior + +Release and CI behavior is implemented through checked-in GitHub workflow files and the GitHub Action template renderer. + +## Operational Surface + +- GitHub Actions workflows under `.github/workflows/**` +- GitHub Action template rendering in `src/templates/github-action.ts` + +## Runtime Topology + +Automation runs in GitHub Actions. There is no Truthmark daemon or persistent runtime service. + +## Product Truth Links + +- None. + +## Engineering Decisions + +- Decision (2026-06-14): Release automation truth is engineering/operational truth because it describes current repository mechanics. + +## Maintenance Notes + +Update when CI triggers, release prerequisites, publish steps, or action templates change. + +## Source References + +- ../../../../.github/workflows/ci.yml +- ../../../../src/templates/github-action.ts +- `.github/workflows/**` +- `src/templates/github-action.ts` diff --git a/docs/truthmark/engineering/repository/README.md b/docs/truthmark/engineering/repository/README.md new file mode 100644 index 0000000..3034d8d --- /dev/null +++ b/docs/truthmark/engineering/repository/README.md @@ -0,0 +1,18 @@ +--- +status: active +last_reviewed: 2026-06-14 +--- + +# Repository Truth Docs + +This directory indexes bounded repository truth docs. + +README.md files are indexes, not Truth Sync targets. Keep bounded truth in leaf docs in this directory. + +Current leaf docs: + +- [Overview](overview.md) + +## Source References + +- ../../routes/areas/repository.md diff --git a/docs/truthmark/engineering/repository/overview.md b/docs/truthmark/engineering/repository/overview.md new file mode 100644 index 0000000..fa1830f --- /dev/null +++ b/docs/truthmark/engineering/repository/overview.md @@ -0,0 +1,120 @@ +--- +status: active +truth_kind: engineering-behavior +last_reviewed: 2026-05-30 +--- + +# Repository Overview + +## Purpose + + + +Describe why the default repository behavior surface exists and what outcome it protects. + +## Scope + + + +This bounded leaf truth doc owns the default repository behavior surface created by Truthmark. + +This doc was created from the editable engineering-behavior template at docs/truthmark/templates/engineering-behavior.md. + +## Current Implementation Behavior + + + +- Document current behavior here when implementation changes make repository truth incomplete. + +## Core Rules + + + +- Truth README files are indexes; behavior truth belongs in bounded leaf docs. + +## Flows And States + + + +- None beyond current behavior. + +## Contracts + + + +- External contracts should link to the nearest canonical contract doc when one exists. + +## Product Truth Links + +- None. + +## Engineering Decisions + + + +- Decision (2026-06-14): Truth README files are indexes; behavior truth belongs in bounded leaf docs. + +## Engineering Decisions + + + +{{decision}} + +## Rationale + + + +Bounded leaf docs keep agent context focused and prevent large products from accumulating unreviewable feature manuals. + +## Non-Goals + + + +- This doc is not a catch-all for unrelated repository behavior. + +## Maintenance Notes + + + +- Update this doc when routed implementation changes alter current behavior, rules, contracts, or decisions. + +## Source References + +- ../../routes/areas/repository.md diff --git a/docs/truthmark/engineering/repository/repository-intelligence.md b/docs/truthmark/engineering/repository/repository-intelligence.md new file mode 100644 index 0000000..7cacab8 --- /dev/null +++ b/docs/truthmark/engineering/repository/repository-intelligence.md @@ -0,0 +1,46 @@ +--- +status: active +truth_kind: engineering-behavior +last_reviewed: 2026-06-14 +--- + +# Repository Intelligence + +## Purpose + +This doc owns derived repository-intelligence artifacts used by agents and CLI output. + +## Scope + +It covers RepoIndex, RouteMap, ImpactSet, ContextPack, evidence validation, freshness, and WorkflowState behavior. + +## Current Implementation Behavior + +RepoIndex and RouteMap are derived from the active checkout and preserve route lane and relationship metadata. RouteMap emits duplicate truth document entries with the same path, kind, and lane as one relationship view whose `realized_by`, `realizes`, and `depends_on` metadata is merged by unique sorted set. RepoIndex derives truth-doc lane and doc type from `truth_kind` when canonical truth docs omit explicit `truth_lane` and `doc_type` frontmatter. These artifacts guide routing and verification but do not override source files, route files, truth docs, or workflow write boundaries. + +## Product Truth Links + +- `docs/truthmark/product/capabilities/lane-separated-truth.md` + +## Engineering Decisions + +- Decision (2026-06-14): Repository intelligence is derived context, not hidden memory or off-repo authority. + +## Maintenance Notes + +Update when index, route-map, impact, context, evidence, freshness, or workflow-state output changes. + +## Source References + +- ../../../../src/repo-index/build.ts +- ../../../../src/repo-index/file-tree.ts +- ../../../../src/repo-index/route-map.ts +- ../../../../src/repo-index/types.ts +- ../../../../src/impact/build.ts +- ../../../../src/context-pack/build.ts +- `src/repo-index/build.ts` +- `src/repo-index/file-tree.ts` +- `src/repo-index/route-map.ts` +- `src/repo-index/types.ts` +- `src/impact/build.ts` +- `src/context-pack/build.ts` diff --git a/docs/truthmark/engineering/workflows/installed-workflow-runtime.md b/docs/truthmark/engineering/workflows/installed-workflow-runtime.md new file mode 100644 index 0000000..b722ada --- /dev/null +++ b/docs/truthmark/engineering/workflows/installed-workflow-runtime.md @@ -0,0 +1,52 @@ +--- +status: active +truth_kind: engineering-workflow +last_reviewed: 2026-06-15 +--- + +# Installed Workflow Runtime + +## Purpose + +This doc describes how the repository currently realizes host-native Truthmark workflow surfaces. + +## Scope + +It owns generated workflow runtime behavior, managed instruction blocks, helper metadata, and direct-checkout fallback rules. + +## Current Implementation Behavior + +The source manifest and renderers generate host-specific skills, prompts, commands, subagents, helper manifests, and managed instruction blocks. Generated skill packages hold the full workflow procedures and report contracts. Generated GitHub Copilot prompts and Gemini commands act as compact host entrypoint adapters: they direct the current invocation to host-local skill package files and explicitly avoid dispatching another Truthmark command rather than embedding duplicate workflow bodies or cross-host invocation lists. Generated write-capable workflow text instructs agents to classify lane impact before writing canonical truth docs, while read-only Preview and Check surfaces classify lane ownership for reporting without write-authorizing phrasing. The manual Truth Realize prompt path uses Realize-specific lane guidance: read product truth as requirements, read engineering truth as implementation context, and do not write truth docs or truth routing while realizing docs into code. Truth Preview keeps route selection thin by reading the root route index first and then only child route files relevant to the selected scope or changed paths. Truth Check and read-only route auditors use route-first bounded inspection for lane and cross-lane relationship checks: narrow audits stay within the routed area plus directly linked counterpart docs, root-wide health first builds a route-map/index from route files, and missing product links for user-visible engineering docs are second-pass review diagnostics rather than default full-document reads. + +## Triggers + +- `truthmark init` refreshes configured workflow surfaces. +- Explicit host invocations run manual workflows. +- Truth Sync is the finish-time workflow when functional code changed. + +## Execution Model + +Committed workflow files are the runtime contract. The CLI installs and validates surfaces but does not act as daemon, database, or workflow orchestrator. + +## Product Truth Links + +- `docs/truthmark/product/capabilities/agent-native-workflow-injection.md` + +## Engineering Decisions + +- Decision (2026-06-14): Lane classification is part of generated workflow text before any canonical truth write. + +## Maintenance Notes + +Update this doc when workflow manifest fields, generated surface paths, helper metadata, or managed instruction behavior changes. + +## Source References + +- ../../../../src/agents/instructions.ts +- ../../../../src/agents/prompts.ts +- ../../../../src/agents/workflow-manifest.ts +- ../../../../src/templates/workflow-surfaces.ts +- ../../../../src/templates/generated-surfaces.ts +- `src/agents/workflow-manifest.ts` +- `src/templates/workflow-surfaces.ts` +- `src/templates/generated-surfaces.ts` diff --git a/docs/truthmark/product/README.md b/docs/truthmark/product/README.md new file mode 100644 index 0000000..7bccc86 --- /dev/null +++ b/docs/truthmark/product/README.md @@ -0,0 +1,17 @@ +--- +status: active +doc_type: index +last_reviewed: 2026-06-14 +--- + +# Truth Docs + +This directory is an index for current truth docs organized by the configured Truthmark hierarchy. + +Product truth owns capability promises, boundaries, decisions, and acceptance criteria. Product lane docs state what must be true, why it matters, and what success means. + +README.md files are indexes, not Truth Sync targets. Keep product truth in bounded capability docs. + +## Source References + +- ../routes/areas.md diff --git a/docs/truthmark/product/capabilities/agent-native-workflow-injection.md b/docs/truthmark/product/capabilities/agent-native-workflow-injection.md new file mode 100644 index 0000000..0bb3850 --- /dev/null +++ b/docs/truthmark/product/capabilities/agent-native-workflow-injection.md @@ -0,0 +1,48 @@ +--- +status: active +truth_kind: product-capability +last_reviewed: 2026-06-14 +--- + +# Agent-Native Workflow Injection + +## Capability Promise + +Truthmark gives supported AI hosts explicit, committed workflow surfaces for Structure, Document, Sync, Preview, Realize, Check, and Portal. + +## Users And Value + +Repository maintainers and agents can follow the checked-in workflow contract without relying on a live Truthmark daemon, hidden runtime state, or off-repo packet. + +## Capability Scope + +This capability covers generated host-native workflow files, managed instruction blocks, bounded write rules, helper metadata, and direct-checkout fallback behavior. + +## Current Product Behavior + +Supported surfaces include Codex, OpenCode, Claude Code, GitHub Copilot, and Gemini CLI workflow files generated from the source templates and manifest. + +## Acceptance Criteria + +- Each configured platform receives host-native workflow entrypoints. +- Generated surfaces preserve workflow boundaries and direct-checkout fallback. +- Agents can classify product-lane, engineering-lane, both-lane, or ambiguous work before writing truth docs. + +## Product Decisions + +- Decision (2026-06-14): Workflow surfaces remain committed repository files; optional CLI helpers validate after relevant work and do not orchestrate workflow execution. + +## Engineering Realization Links + +- `docs/truthmark/engineering/workflows/installed-workflow-runtime.md` +- `docs/truthmark/engineering/contracts/generated-host-surfaces.md` + +## Non-Goals + +- No mandatory helper payload or runtime packet before an agent can act. + +## Source References + +- ../../../../src/agents/workflow-manifest.ts +- ../../../../src/templates/workflow-surfaces.ts +- ../../../../src/templates/generated-surfaces.ts diff --git a/docs/truthmark/product/capabilities/lane-separated-truth.md b/docs/truthmark/product/capabilities/lane-separated-truth.md new file mode 100644 index 0000000..1c6e17d --- /dev/null +++ b/docs/truthmark/product/capabilities/lane-separated-truth.md @@ -0,0 +1,55 @@ +--- +status: active +truth_kind: product-capability +last_reviewed: 2026-06-14 +--- + +# Lane-Separated Truth + +## Capability Promise + +Truthmark keeps product truth and engineering truth separate, first-class, and cross-linked. + +## Users And Value + +Maintainers can review product promises and implementation realization without either lane becoming a derived summary of the other. + +## Capability Scope + +Product truth belongs under `docs/truthmark/product`; engineering truth belongs under `docs/truthmark/engineering`. Downstream product truth uses `product-capability` only. Product boundary, scope, adjacent-system, and non-goal guidance lives inside capability docs instead of a separate downstream boundary kind. Relationships between lanes are traceability edges, not content inheritance. + +## Current Product Behavior + +Route metadata supports explicit `lane`, `realized_by`, `realizes`, and `depends_on` fields for route-local traceability. Product-path kind inference returns `product-capability`, and init scaffolds `product-capability.md` without scaffolding a downstream `product-boundary` template. + +## Acceptance Criteria + +- New scaffold defaults do not target `docs/truthmark/truth`. +- Product truth defaults, path inference, and templates use `product-capability` only. +- `product-boundary` is rejected as downstream truth kind metadata instead of being listed as supported. +- RouteMap and RepoIndex preserve lane and relationship metadata. +- Check diagnostics report lane shape, lane drift, and route-local traceability. +- Missing product links for user-visible engineering docs remain review diagnostics. + +## Product Decisions + +- Decision (2026-06-14): Product docs may cite code directly as evidence for current product behavior, but detailed mechanics stay in engineering docs. +- Decision (2026-06-14): Missing product links for user-visible engineering docs are review diagnostics, not hard errors. +- Decision (2026-06-14): Downstream product truth supports `product-capability` only; product boundary guidance belongs inside capability scope, acceptance criteria, and non-goals. +- Decision (2026-06-15): Route `realized_by` and `realizes` relationships are local navigation metadata, not a single global doc graph; validation requires existing opposite-lane targets without requiring reciprocal declarations. + +## Engineering Realization Links + +- `docs/truthmark/engineering/contracts/config-route-and-check-contracts.md` +- `docs/truthmark/engineering/behaviors/check-diagnostics.md` + +## Non-Goals + +- No automated business correctness, priority, or desirability judgment. + +## Source References + +- ../../../../src/config/defaults.ts +- ../../../../src/routing/areas.ts +- ../../../../src/init/hierarchy.ts +- ../../../../src/templates/init-files.ts diff --git a/docs/truthmark/routes/areas.md b/docs/truthmark/routes/areas.md index 374e442..9a5d4ef 100644 --- a/docs/truthmark/routes/areas.md +++ b/docs/truthmark/routes/areas.md @@ -2,10 +2,6 @@ status: active doc_type: routing last_reviewed: 2026-05-16 -source_of_truth: - - ../../README.md - - ../../ai/repo-rules.md - - ../../../.truthmark/config.yml --- # Truthmark Areas @@ -15,17 +11,20 @@ The root route index delegates Truthmark's main behavior surfaces to smaller are ## Contracts And Commands Area files: + - docs/truthmark/routes/areas/contracts-and-commands.md Code surface: -- src/cli/** + +- src/cli/\*\* - src/config/command.ts - src/config/defaults.ts - src/config/load.ts - src/config/schema.ts -- src/output/** +- src/output/\*\* Update truth when: + - config file or command contracts change - supported platforms or generated surface contract fields change - user-visible result envelopes, diagnostics, or command options change @@ -33,15 +32,18 @@ Update truth when: ## Initialization And Scaffold Area files: + - docs/truthmark/routes/areas/init-and-scaffold.md Code surface: + - src/fs/paths.ts -- src/init/** -- src/templates/** -- tests/init/** +- src/init/\*\* +- src/templates/\*\* +- tests/init/\*\* Update truth when: + - `truthmark init` scaffolds or refreshes files differently - default canonical docs or generated surface lists change - configured hierarchy scaffold behavior changes @@ -49,17 +51,20 @@ Update truth when: ## Check And Routing Area files: + - docs/truthmark/routes/areas/check-and-routing.md Code surface: -- src/checks/** + +- src/checks/\*\* - src/config/load.ts -- src/git/** -- src/markdown/** -- src/routing/** -- src/types/** +- src/git/\*\* +- src/markdown/\*\* +- src/routing/\*\* +- src/types/\*\* Update truth when: + - validation or area-resolution behavior changes - branch-scope or repository discovery behavior changes - routed code coverage expectations change @@ -67,22 +72,25 @@ Update truth when: ## Installed Workflows Area files: + - docs/truthmark/routes/areas/installed-workflows.md Code surface: -- src/agents/** -- src/generation/** -- src/realize/** -- src/sync/** + +- src/agents/\*\* +- src/generation/\*\* +- src/realize/\*\* +- src/sync/\*\* - src/templates/agents-block.ts - src/templates/workflow-surfaces.ts - src/templates/generated-surfaces.ts -- src/truth/** +- src/truth/\*\* - src/version.ts -- tests/evals/** -- tests/templates/** +- tests/evals/\*\* +- tests/templates/\*\* Update truth when: + - installed workflow boundaries or report shapes change - generated instruction block or skill content changes - workflow version markers or sync classification behavior changes @@ -90,29 +98,41 @@ Update truth when: ## Release Automation Area files: + - docs/truthmark/routes/areas/release-automation.md Code surface: -- .github/workflows/** + +- .github/workflows/\*\* - src/templates/github-action.ts Update truth when: + - CI verification steps or triggers change - release publishing prerequisites or publish steps change ## Repository Intelligence Area files: + - docs/truthmark/routes/areas/repository-intelligence.md Code surface: -- src/repo-index/** -- src/impact/** -- src/evidence/** -- src/freshness/** -- src/context-pack/** -- src/workflow-state/** + +- src/repo-index/\*\* +- src/impact/\*\* +- src/evidence/\*\* +- src/freshness/\*\* +- src/context-pack/\*\* +- src/workflow-state/\*\* Update truth when: + - 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 + +## Source References + +- ../../README.md +- ../../ai/repo-rules.md +- ../../../.truthmark/config.yml diff --git a/docs/truthmark/routes/areas/check-and-routing.md b/docs/truthmark/routes/areas/check-and-routing.md index 3679990..f0a2863 100644 --- a/docs/truthmark/routes/areas/check-and-routing.md +++ b/docs/truthmark/routes/areas/check-and-routing.md @@ -2,10 +2,6 @@ status: active doc_type: routing last_reviewed: 2026-05-14 -source_of_truth: - - ../areas.md - - ../../README.md - - ../../ai/repo-rules.md --- # Check And Routing Areas @@ -13,29 +9,52 @@ source_of_truth: ## Check And Routing Truth documents: + ```yaml truth_documents: - - path: docs/truthmark/truth/contracts.md - kind: contract - - path: docs/truthmark/truth/architecture/overview.md - kind: architecture - - path: docs/truthmark/truth/architecture/module-map.md - kind: architecture - - path: docs/truthmark/truth/check-diagnostics.md - kind: behavior - - path: docs/truthmark/truth/routing-examples.md - kind: behavior + - path: docs/truthmark/product/capabilities/lane-separated-truth.md + kind: product-capability + lane: product + realized_by: + - docs/truthmark/engineering/architecture/overview.md + - docs/truthmark/engineering/behaviors/check-diagnostics.md + - docs/truthmark/engineering/behaviors/init-and-scaffold.md + - docs/truthmark/engineering/contracts/config-route-and-check-contracts.md + - docs/truthmark/engineering/repository/repository-intelligence.md + - path: docs/truthmark/engineering/contracts/config-route-and-check-contracts.md + kind: engineering-contract + lane: engineering + realizes: + - docs/truthmark/product/capabilities/lane-separated-truth.md + - path: docs/truthmark/engineering/architecture/overview.md + kind: engineering-architecture + lane: engineering + realizes: + - docs/truthmark/product/capabilities/lane-separated-truth.md + - path: docs/truthmark/engineering/behaviors/check-diagnostics.md + kind: engineering-behavior + lane: engineering + realizes: + - docs/truthmark/product/capabilities/lane-separated-truth.md ``` Code surface: -- src/checks/** + +- src/checks/\*\* - src/config/load.ts -- src/git/** -- src/markdown/** -- src/routing/** -- src/types/** +- src/git/\*\* +- src/markdown/\*\* +- src/routing/\*\* +- src/types/\*\* Update truth when: + - validation or area-resolution behavior changes - branch-scope or repository discovery behavior changes - routed code coverage expectations change + +## Source References + +- ../areas.md +- ../../README.md +- ../../ai/repo-rules.md diff --git a/docs/truthmark/routes/areas/contracts-and-commands.md b/docs/truthmark/routes/areas/contracts-and-commands.md index 8e2389c..2f1d838 100644 --- a/docs/truthmark/routes/areas/contracts-and-commands.md +++ b/docs/truthmark/routes/areas/contracts-and-commands.md @@ -2,10 +2,6 @@ status: active doc_type: routing last_reviewed: 2026-05-14 -source_of_truth: - - ../areas.md - - ../../README.md - - ../../ai/repo-rules.md --- # Contracts And Commands Areas @@ -13,21 +9,33 @@ source_of_truth: ## Contracts And Commands Truth documents: + ```yaml truth_documents: - - path: docs/truthmark/truth/contracts.md - kind: contract + - path: docs/truthmark/engineering/contracts/config-route-and-check-contracts.md + kind: engineering-contract + lane: engineering + realizes: + - docs/truthmark/product/capabilities/lane-separated-truth.md ``` Code surface: -- src/cli/** + +- src/cli/\*\* - src/config/command.ts - src/config/defaults.ts - src/config/load.ts - src/config/schema.ts -- src/output/** +- src/output/\*\* Update truth when: + - config file shape or defaults change - command names, options, or JSON envelope contracts change - diagnostic categories or severities exposed to users change + +## Source References + +- ../areas.md +- ../../README.md +- ../../ai/repo-rules.md diff --git a/docs/truthmark/routes/areas/init-and-scaffold.md b/docs/truthmark/routes/areas/init-and-scaffold.md index 846c268..2f2e864 100644 --- a/docs/truthmark/routes/areas/init-and-scaffold.md +++ b/docs/truthmark/routes/areas/init-and-scaffold.md @@ -2,10 +2,6 @@ status: active doc_type: routing last_reviewed: 2026-05-14 -source_of_truth: - - ../areas.md - - ../../README.md - - ../../ai/repo-rules.md --- # Initialization And Scaffold Areas @@ -13,25 +9,45 @@ source_of_truth: ## Initialization And Scaffold Truth documents: + ```yaml truth_documents: - - path: docs/truthmark/truth/architecture/overview.md - kind: architecture - - path: docs/truthmark/truth/architecture/module-map.md - kind: architecture - - path: docs/truthmark/truth/init-and-scaffold.md - kind: behavior - - path: docs/truthmark/truth/repository/overview.md - kind: behavior + - path: docs/truthmark/product/capabilities/lane-separated-truth.md + kind: product-capability + lane: product + realized_by: + - docs/truthmark/engineering/architecture/overview.md + - docs/truthmark/engineering/behaviors/check-diagnostics.md + - docs/truthmark/engineering/behaviors/init-and-scaffold.md + - docs/truthmark/engineering/contracts/config-route-and-check-contracts.md + - docs/truthmark/engineering/repository/repository-intelligence.md + - path: docs/truthmark/engineering/architecture/overview.md + kind: engineering-architecture + lane: engineering + realizes: + - docs/truthmark/product/capabilities/lane-separated-truth.md + - path: docs/truthmark/engineering/behaviors/init-and-scaffold.md + kind: engineering-behavior + lane: engineering + realizes: + - docs/truthmark/product/capabilities/lane-separated-truth.md ``` Code surface: + - src/fs/paths.ts -- src/init/** -- src/templates/** -- tests/init/** +- src/init/\*\* +- src/templates/\*\* +- tests/init/\*\* Update truth when: + - `truthmark init` scaffolds or refreshes files differently - default canonical docs or generated surface lists change - configured hierarchy scaffold behavior changes + +## Source References + +- ../areas.md +- ../../README.md +- ../../ai/repo-rules.md diff --git a/docs/truthmark/routes/areas/installed-workflows.md b/docs/truthmark/routes/areas/installed-workflows.md index ffc5b83..3ec12c6 100644 --- a/docs/truthmark/routes/areas/installed-workflows.md +++ b/docs/truthmark/routes/areas/installed-workflows.md @@ -2,10 +2,6 @@ status: active doc_type: routing last_reviewed: 2026-05-16 -source_of_truth: - - ../areas.md - - ../../README.md - - ../../ai/repo-rules.md --- # Installed Workflows Areas @@ -16,28 +12,22 @@ Truth documents: ```yaml truth_documents: - - path: docs/truthmark/truth/contracts.md - kind: contract - - path: docs/truthmark/truth/workflows/overview.md - kind: workflow - - path: docs/truthmark/truth/workflows/shared-gates.md - kind: workflow - - path: docs/truthmark/truth/workflows/truth-structure.md - kind: workflow - - path: docs/truthmark/truth/workflows/truth-document.md - kind: workflow - - path: docs/truthmark/truth/workflows/truth-sync.md - kind: workflow - - path: docs/truthmark/truth/workflows/truth-preview.md - kind: workflow - - path: docs/truthmark/truth/workflows/truth-realize.md - kind: workflow - - path: docs/truthmark/truth/workflows/truth-check.md - kind: workflow - - path: docs/truthmark/truth/workflows/truthmark-portal.md - kind: workflow - - path: docs/truthmark/truth/workflows/content-generation.md - kind: workflow + - path: docs/truthmark/product/capabilities/agent-native-workflow-injection.md + kind: product-capability + lane: product + realized_by: + - docs/truthmark/engineering/workflows/installed-workflow-runtime.md + - docs/truthmark/engineering/contracts/generated-host-surfaces.md + - path: docs/truthmark/engineering/workflows/installed-workflow-runtime.md + kind: engineering-workflow + lane: engineering + realizes: + - docs/truthmark/product/capabilities/agent-native-workflow-injection.md + - path: docs/truthmark/engineering/contracts/generated-host-surfaces.md + kind: engineering-contract + lane: engineering + realizes: + - docs/truthmark/product/capabilities/agent-native-workflow-injection.md ``` Code surface: @@ -51,12 +41,18 @@ Code surface: - src/templates/generated-surfaces.ts - src/truth/\*\* - src/version.ts -- tests/evals/** -- tests/templates/** +- tests/evals/\*\* +- tests/templates/\*\* Update truth when: - installed workflow boundaries or report shapes change - generated instruction block or skill content changes - workflow version markers or sync classification behavior changes -- ownership gates, evidence gates, Product Decisions/Rationale preservation gates, or truth-doc split behavior changes +- ownership gates, evidence gates, lane classification gates, decision/rationale preservation gates, or truth-doc split behavior changes + +## Source References + +- ../areas.md +- ../../README.md +- ../../ai/repo-rules.md diff --git a/docs/truthmark/routes/areas/release-automation.md b/docs/truthmark/routes/areas/release-automation.md index 3c77991..4e68939 100644 --- a/docs/truthmark/routes/areas/release-automation.md +++ b/docs/truthmark/routes/areas/release-automation.md @@ -2,10 +2,6 @@ status: active doc_type: routing last_reviewed: 2026-05-14 -source_of_truth: - - ../areas.md - - ../../README.md - - ../../ai/repo-rules.md --- # Release Automation Areas @@ -13,17 +9,27 @@ source_of_truth: ## Release Automation Truth documents: + ```yaml truth_documents: - - path: docs/truthmark/truth/release/automation.md - kind: workflow + - path: docs/truthmark/engineering/operations/release-automation.md + kind: engineering-operations + lane: engineering ``` Code surface: -- .github/workflows/** + +- .github/workflows/\*\* - src/templates/github-action.ts Update truth when: + - CI verification steps or triggers change - release publishing prerequisites or publish steps change - GitHub Action examples or action template rendering changes + +## Source References + +- ../areas.md +- ../../README.md +- ../../ai/repo-rules.md diff --git a/docs/truthmark/routes/areas/repository-intelligence.md b/docs/truthmark/routes/areas/repository-intelligence.md index 2344a53..11402e8 100644 --- a/docs/truthmark/routes/areas/repository-intelligence.md +++ b/docs/truthmark/routes/areas/repository-intelligence.md @@ -2,10 +2,6 @@ status: active doc_type: routing last_reviewed: 2026-05-16 -source_of_truth: - - ../areas.md - - ../../README.md - - ../../ai/repo-rules.md --- # Repository Intelligence Areas @@ -13,26 +9,41 @@ source_of_truth: ## Repository Intelligence Truth documents: + ```yaml truth_documents: - - path: docs/truthmark/truth/repository/repo-index.md - kind: behavior - - path: docs/truthmark/truth/repository/impact-set.md - kind: behavior - - path: docs/truthmark/truth/repository/context-pack.md - kind: behavior - - path: docs/truthmark/truth/repository/workflow-state.md - kind: behavior + - path: docs/truthmark/product/capabilities/lane-separated-truth.md + kind: product-capability + lane: product + realized_by: + - docs/truthmark/engineering/architecture/overview.md + - docs/truthmark/engineering/behaviors/check-diagnostics.md + - docs/truthmark/engineering/behaviors/init-and-scaffold.md + - docs/truthmark/engineering/contracts/config-route-and-check-contracts.md + - docs/truthmark/engineering/repository/repository-intelligence.md + - path: docs/truthmark/engineering/repository/repository-intelligence.md + kind: engineering-behavior + lane: engineering + realizes: + - docs/truthmark/product/capabilities/lane-separated-truth.md ``` Code surface: -- src/repo-index/** -- src/impact/** -- src/evidence/** -- src/freshness/** -- src/context-pack/** -- src/workflow-state/** + +- src/repo-index/\*\* +- src/impact/\*\* +- src/evidence/\*\* +- src/freshness/\*\* +- src/context-pack/\*\* +- src/workflow-state/\*\* Update truth when: + - RepoIndex, RouteMap, ImpactSet, evidence validation, freshness diagnostics, ContextPack behavior, or WorkflowState behavior changes - repository-intelligence command output changes + +## Source References + +- ../areas.md +- ../../README.md +- ../../ai/repo-rules.md diff --git a/docs/truthmark/templates/architecture-doc.md b/docs/truthmark/templates/engineering-architecture.md similarity index 83% rename from docs/truthmark/templates/architecture-doc.md rename to docs/truthmark/templates/engineering-architecture.md index a6960df..ff8dc5b 100644 --- a/docs/truthmark/templates/architecture-doc.md +++ b/docs/truthmark/templates/engineering-architecture.md @@ -1,10 +1,7 @@ --- status: active -doc_type: architecture -truth_kind: architecture -last_reviewed: 2026-05-30 -source_of_truth: - - {{source_of_truth}} +truth_kind: engineering-architecture +last_reviewed: 2026-06-14 --- # {{title}} @@ -14,7 +11,7 @@ source_of_truth: {{purpose}} @@ -82,15 +79,15 @@ Tie constraints to source evidence, tests, standards, or operational requirement {{cross_cutting_constraints}} -## Product Decisions +## Engineering Decisions -{{decision}} +{{engineering_decisions}} ## Rationale @@ -118,3 +115,11 @@ Keep this operational and current-state focused, not historical. --> {{maintenance_notes}} + +## Source References + + + +{{source_references}} diff --git a/docs/truthmark/templates/behavior-doc.md b/docs/truthmark/templates/engineering-behavior.md similarity index 76% rename from docs/truthmark/templates/behavior-doc.md rename to docs/truthmark/templates/engineering-behavior.md index 398bd67..4603ce1 100644 --- a/docs/truthmark/templates/behavior-doc.md +++ b/docs/truthmark/templates/engineering-behavior.md @@ -1,10 +1,7 @@ --- status: active -doc_type: behavior -truth_kind: behavior -last_reviewed: 2026-05-30 -source_of_truth: - - {{source_of_truth}} +truth_kind: engineering-behavior +last_reviewed: 2026-06-14 --- # {{title}} @@ -14,7 +11,7 @@ source_of_truth: {{purpose}} @@ -30,17 +27,17 @@ Keep README.md files as indexes only. {{scope}} -This doc was created from the editable behavior-doc template at {{template_path}}. +This doc was created from the editable engineering-behavior template at {{template_path}}. -## Current Behavior +## Current Implementation Behavior -{{current_behavior}} +{{current_implementation_behavior}} ## Core Rules @@ -69,14 +66,23 @@ Avoid duplicating a separate canonical contract doc; link to it when contract ow {{contracts}} -## Product Decisions +## Product Truth Links + + + +{{product_truth_links}} + +## Engineering Decisions -{{decision}} +{{engineering_decisions}} ## Rationale @@ -104,3 +110,11 @@ Keep this operational and current-state focused, not historical. --> {{maintenance_notes}} + +## Source References + + + +{{source_references}} diff --git a/docs/truthmark/templates/contract-doc.md b/docs/truthmark/templates/engineering-contract.md similarity index 83% rename from docs/truthmark/templates/contract-doc.md rename to docs/truthmark/templates/engineering-contract.md index bfb8299..05c2246 100644 --- a/docs/truthmark/templates/contract-doc.md +++ b/docs/truthmark/templates/engineering-contract.md @@ -1,10 +1,7 @@ --- status: active -doc_type: contract -truth_kind: contract -last_reviewed: 2026-05-30 -source_of_truth: - - {{source_of_truth}} +truth_kind: engineering-contract +last_reviewed: 2026-06-14 --- # {{title}} @@ -14,7 +11,7 @@ source_of_truth: {{purpose}} @@ -82,15 +79,15 @@ State 'Not versioned' only when the implementation truly has no versioning or mi {{versioning_and_migration}} -## Product Decisions +## Engineering Decisions -{{decision}} +{{engineering_decisions}} ## Rationale @@ -118,3 +115,11 @@ Keep this operational and current-state focused, not historical. --> {{maintenance_notes}} + +## Source References + + + +{{source_references}} diff --git a/docs/truthmark/templates/operations-doc.md b/docs/truthmark/templates/engineering-operations.md similarity index 83% rename from docs/truthmark/templates/operations-doc.md rename to docs/truthmark/templates/engineering-operations.md index 5f60267..c244143 100644 --- a/docs/truthmark/templates/operations-doc.md +++ b/docs/truthmark/templates/engineering-operations.md @@ -1,10 +1,7 @@ --- status: active -doc_type: behavior -truth_kind: operations -last_reviewed: 2026-05-30 -source_of_truth: - - {{source_of_truth}} +truth_kind: engineering-operations +last_reviewed: 2026-06-14 --- # {{title}} @@ -14,7 +11,7 @@ source_of_truth: {{purpose}} @@ -82,15 +79,15 @@ Include what maintainers should inspect first during incidents or degraded behav {{availability_and_observability}} -## Product Decisions +## Engineering Decisions -{{decision}} +{{engineering_decisions}} ## Rationale @@ -118,3 +115,11 @@ Keep this operational and current-state focused, not historical. --> {{maintenance_notes}} + +## Source References + + + +{{source_references}} diff --git a/docs/truthmark/templates/test-behavior-doc.md b/docs/truthmark/templates/engineering-test-behavior.md similarity index 83% rename from docs/truthmark/templates/test-behavior-doc.md rename to docs/truthmark/templates/engineering-test-behavior.md index 6e2ba02..13e733a 100644 --- a/docs/truthmark/templates/test-behavior-doc.md +++ b/docs/truthmark/templates/engineering-test-behavior.md @@ -1,10 +1,7 @@ --- status: active -doc_type: behavior -truth_kind: test-behavior -last_reviewed: 2026-05-30 -source_of_truth: - - {{source_of_truth}} +truth_kind: engineering-test-behavior +last_reviewed: 2026-06-14 --- # {{title}} @@ -14,7 +11,7 @@ source_of_truth: {{purpose}} @@ -82,15 +79,15 @@ Include escalation or quarantine criteria for flaky or environment-sensitive tes {{reporting_and_failure_semantics}} -## Product Decisions +## Engineering Decisions -{{decision}} +{{engineering_decisions}} ## Rationale @@ -118,3 +115,11 @@ Keep this operational and current-state focused, not historical. --> {{maintenance_notes}} + +## Source References + + + +{{source_references}} diff --git a/docs/truthmark/templates/workflow-doc.md b/docs/truthmark/templates/engineering-workflow.md similarity index 82% rename from docs/truthmark/templates/workflow-doc.md rename to docs/truthmark/templates/engineering-workflow.md index 8ab7542..a37badf 100644 --- a/docs/truthmark/templates/workflow-doc.md +++ b/docs/truthmark/templates/engineering-workflow.md @@ -1,10 +1,7 @@ --- status: active -doc_type: behavior -truth_kind: workflow -last_reviewed: 2026-05-30 -source_of_truth: - - {{source_of_truth}} +truth_kind: engineering-workflow +last_reviewed: 2026-06-14 --- # {{title}} @@ -14,7 +11,7 @@ source_of_truth: {{purpose}} @@ -82,15 +79,15 @@ Include success criteria and handoff points to other truth docs or systems. {{outputs}} -## Product Decisions +## Engineering Decisions -{{decision}} +{{engineering_decisions}} ## Rationale @@ -118,3 +115,11 @@ Keep this operational and current-state focused, not historical. --> {{maintenance_notes}} + +## Source References + + + +{{source_references}} diff --git a/docs/truthmark/templates/product-capability.md b/docs/truthmark/templates/product-capability.md new file mode 100644 index 0000000..aff4d77 --- /dev/null +++ b/docs/truthmark/templates/product-capability.md @@ -0,0 +1,94 @@ +--- +status: active +truth_kind: product-capability +last_reviewed: 2026-06-14 +--- + +# {{title}} + + + +## Capability Promise + + + +{{capability_promise}} + +## Users And Value + + + +{{users_and_value}} + +## Capability Scope + + + +{{capability_scope}} + +## Current Product Behavior + + + +{{current_product_behavior}} + +## Acceptance Criteria + + + +{{acceptance_criteria}} + +## Product Decisions + + + +{{decision}} + +## Engineering Realization Links + + + +{{engineering_realization_links}} + +## Non-Goals + + + +{{non_goals}} + +## Source References + + + +{{source_references}} diff --git a/docs/truthmark/truth/README.md b/docs/truthmark/truth/README.md deleted file mode 100644 index 29b7bca..0000000 --- a/docs/truthmark/truth/README.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -status: active -doc_type: index -last_reviewed: 2026-05-09 -source_of_truth: - - ../routes/areas.md ---- - -# Truth Docs - -This directory contains current truth docs organized by the configured Truthmark hierarchy. - -`README.md` files in this tree are indexes. Keep current behavior truth in bounded leaf docs under domain folders such as `repository/overview.md`. diff --git a/docs/truthmark/truth/architecture/README.md b/docs/truthmark/truth/architecture/README.md deleted file mode 100644 index 659fe18..0000000 --- a/docs/truthmark/truth/architecture/README.md +++ /dev/null @@ -1,19 +0,0 @@ ---- -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/truthmark/truth/architecture/module-map.md b/docs/truthmark/truth/architecture/module-map.md deleted file mode 100644 index 1d9ab8d..0000000 --- a/docs/truthmark/truth/architecture/module-map.md +++ /dev/null @@ -1,73 +0,0 @@ ---- -status: active -doc_type: architecture -last_reviewed: 2026-05-14 -source_of_truth: - - overview.md ---- - -# Module Map - -## Purpose - -This is the quick module-level map for the current Truthmark codebase. - -## Scope - -This doc covers the current module grouping of the Truthmark codebase and the primary canonical docs that pair with those modules. - -## Components - -- CLI and config loading: `src/cli/`, `src/config/`, and shared result rendering. -- Scaffold and generated surfaces: `src/init/`, `src/templates/`, and containment-safe write helpers in `src/fs/`. -- Routing and checks: `src/routing/`, `src/checks/`, `src/markdown/`, and repository discovery in `src/git/`. -- Installed workflow support: `src/agents/`, `src/generation/`, `src/sync/`, `src/realize/`, and neutral truth helpers in `src/truth/`. - -## Source Layout - -| Path | Responsibility | -| --- | --- | -| `src/cli/` | Commander program setup and command dispatch | -| `src/init/` | Config-aware repository scaffold orchestration plus hierarchy migration checks | -| `src/templates/` | Text templates for scaffolded files, the AGENTS block, generated-surface manifests, and generated host-specific explicit surfaces | -| `src/checks/` | Validation passes for authority, areas, generated surfaces, decision-bearing docs, frontmatter, links, and branch scope | -| `src/config/` | `.truthmark/config.yml` schema and loader | -| `src/routing/` | Parsing of the root route index and delegated child route files | -| `src/markdown/` | Markdown discovery, parsing, and hashing helpers | -| `src/fs/` | Repository-safe path resolution and file writes shared by init and diagnostics | -| `src/generation/` | Source-internal content prompt contracts, JSON-safe prompt rendering, and structured draft validation | -| `src/truth/` | Neutral helpers for truth root resolution and evidence report formatting shared by scaffold, checks, sync, and agent renderers | -| `src/git/` | Git repository and worktree resolution plus change listing | -| `src/sync/` | Truth Sync policy and completed, skipped, or blocked report rendering | -| `src/agents/` | Installed Truth Structure, Truth Document, Truth Sync, Truth Preview, Truth Realize, and Truth Check instruction text plus shared worker and skill contract fragments | -| `src/realize/` | Truth Realize report rendering | -| `src/output/` | Diagnostic types plus human and JSON rendering shared by CLI and check flows | -| `src/types/` | Local type shims | -| `tests/` | Vitest coverage for CLI, checks, routing, templates, and helpers | - -## Practical Routing - -- If the change affects scaffolded file contents or generated skill surfaces, start in `src/templates/` and `src/init/`. -- If the change affects diagnostics, start in `src/checks/` and `src/output/`. -- If the change affects installed workflow text, content prompt contracts, or explicit skill surfaces, start in `src/agents/`, `src/generation/`, `src/sync/`, `src/realize/`, and `src/templates/`. -- If the change affects path safety or repository detection, start in `src/fs/` and `src/git/`. - -## Documentation Pairings - -- `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 - -- Route ownership stays in Markdown route files rather than being duplicated into config objects. -- `src/agents/` and `src/templates/` render configured hierarchy and decision-truth guidance directly into installed workflow surfaces. -- Content-generation prompt contracts live outside `src/agents/` so workflow authority and draft-content shaping remain separate. -- `src/checks/decisions.ts` belongs with the validation layer because decision-bearing canonical docs are a truth-health concern, not an authoring convenience. -- Shared truth-root and evidence formatting helpers live in `src/truth/` so scaffold, checks, sync reports, and generated agent text do not duplicate the same domain defaults. - -## Rationale - -This split keeps layout contract, route ownership, validation, and generated workflow text in predictable places. Agents and maintainers can change one surface without rediscovering unrelated behavior hidden elsewhere. - -The generation layer is source-internal in this slice because current packaging builds only the CLI entrypoint. Keeping prompt contracts separate from installed workflow renderers preserves the existing workflow authority model while giving future workflow code a tested draft-contract layer to consume. diff --git a/docs/truthmark/truth/architecture/overview.md b/docs/truthmark/truth/architecture/overview.md deleted file mode 100644 index f894453..0000000 --- a/docs/truthmark/truth/architecture/overview.md +++ /dev/null @@ -1,142 +0,0 @@ ---- -status: active -doc_type: architecture -last_reviewed: 2026-05-16 -source_of_truth: - - ../../../../.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 architecture as implemented today. - -## Runtime Model - -Truthmark is a one-shot Node and TypeScript CLI. It runs against the active Git worktree, reads and writes repository files directly, and exits after producing diagnostics or scaffolding updates. - -Truthmark does not currently include: - -- a daemon -- a database -- a hosted service -- an MCP server -- packet or context-cache artifacts -- cross-branch memory - -The durable surfaces are ordinary repository files: - -- `.truthmark/config.yml` -- [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 `.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 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 - -### Config and init pipeline - -`truthmark config` writes the committed hierarchy contract to `.truthmark/config.yml`. - -`truthmark init` requires that config, resolves the active repository, creates missing structural files for the configured hierarchy, reads the configured `platforms` list, writes or refreshes only those platform surfaces, and returns a structured list of created, updated, or unchanged files plus any migration-review diagnostics. The default scaffold creates truth `README.md` files as indexes and seeds current behavior truth in bounded leaf docs such as `//overview.md`. It does not delete platform files when a platform is removed from config, and it does not silently move existing truth docs when hierarchy changes. - -Key implementation surfaces: - -- `src/cli/*` for command wiring -- `src/init/init.ts` for orchestration -- `src/templates/*` for scaffold contents -- `src/fs/paths.ts` for containment-safe writes - -### Check pipeline - -`truthmark check` resolves branch-scope metadata, loads config, then validates authority entries, area mappings, frontmatter, internal links, decision structure, generated surfaces, and unmapped coverage before returning diagnostics plus branch-scope data. - -Key implementation surfaces: - -- `src/checks/*` for individual validation passes -- `src/config/*` for config loading and schema validation -- `src/routing/*` for `docs/truthmark/routes/areas.md` parsing and area resolution -- `src/markdown/*` for document parsing and hashing -- `src/output/*` for result rendering - -### Installed workflow support - -Truthmark also contains support primitives for the installed Truth Structure, Truth Document, Truth Sync, Truth Preview, Truth Realize, and Truth Check workflows: - -- `src/templates/agents-block.ts` renders compact managed instruction blocks -- `src/agents/*` renders detailed workflow and skill text for explicit workflow invocation -- `src/templates/workflow-surfaces.ts` renders generated skill, prompt, command, and metadata content for configured platforms -- `src/templates/generated-surfaces.ts` assembles configured platform surfaces from the renderers -- `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 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 - -Truthmark should maintain architecture docs when a change alters system structure, module boundaries, runtime topology, persistence boundaries, cross-cutting contracts, or generated-surface ownership. - -Ordinary product behavior, endpoint details, UI copy, validation rules, and bug fixes belong in behavior or contract docs unless they change those architecture boundaries. Architecture docs should describe structure and ownership rather than becoming a second home for product truth. - -## Branch Scope - -Branch scope is computed from the active Git worktree, current branch or detached HEAD, and hashes of the core Truthmark control files: - -- `.truthmark/config.yml` -- the configured root route index plus configured child route files - -This keeps routing and diagnostics tied to the active checkout rather than to external memory. - -Normal branch checkouts are identified by branch name plus HEAD SHA. Detached checkouts are identified by commit SHA. Worktrees include the current worktree path in branch-scope data so parallel checkouts do not silently share a truth identity. - -## 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 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. - -## Primary Code Files - -- `src/cli/program.ts` -- `src/init/init.ts` -- `src/checks/check.ts` -- `src/checks/authority.ts` -- `src/checks/areas.ts` -- `src/sync/surfaces.ts` -- `src/agents/instructions.ts` -- `src/templates/workflow-surfaces.ts` -- `src/templates/generated-surfaces.ts` -- `src/templates/agents-block.ts` - -## Product Decisions - -- Truthmark is config-first: repositories review committed hierarchy before installed workflow surfaces are generated. -- 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. -- The current checkout is the truth boundary; Truthmark does not create off-repo memory, packet files, or cache files that compete with branch-local Markdown. -- Branch identity is diagnostic metadata, not an external authority source. It helps agents and humans see which checkout was validated without moving truth outside Git. - -## Rationale - -Separating hierarchy definition from workflow installation reduces accidental churn and makes generated agent behavior easier to reason about. Limiting routing delegation to one level keeps path resolution and diagnostics simple enough to audit. Keeping decisions in canonical docs improves reconstruction and maintenance because the current why lives beside the current what. - -Avoiding generated context artifacts keeps the repository itself reviewable and prevents stale helper output from becoming a shadow source of truth. diff --git a/docs/truthmark/truth/check-diagnostics.md b/docs/truthmark/truth/check-diagnostics.md deleted file mode 100644 index 119bcb2..0000000 --- a/docs/truthmark/truth/check-diagnostics.md +++ /dev/null @@ -1,275 +0,0 @@ ---- -status: active -doc_type: behavior -truth_kind: behavior -last_reviewed: 2026-06-12 -source_of_truth: - - ../../../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 - -## Purpose - -This document protects the user-facing truth-health contract for `truthmark check`: what it validates, what its diagnostics mean, and how maintainers should interpret command output. - -## Scope - -This document owns the current behavior of `truthmark check`: config-aware validation of authority files, route areas, frontmatter, links, decision structure, generated surfaces, coverage, and optional branch-impact freshness diagnostics. Installed agent workflow behavior is covered by the workflow truth docs instead of this CLI diagnostics surface. - -## Current Behavior - -`truthmark check` is validation tooling. It is not the runtime for Truth Sync, Truth Preview, Truth Realize, Truth Structure, or Truth Check skills, and it is not a CI-style merge gate by default. - -The command: - -1. resolves the active repository and worktree -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. 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. - -The command reports repository truth health for the active checkout. It does not prepare mandatory workflow context, choose verification commands, or decide whether a coding task can finish. - -`truthmark check` without `--base` keeps the existing checkout-health behavior and does not compute ImpactSet. `truthmark check --base ` adds branch-impact freshness diagnostics and includes `data.impactSet` in JSON output. - -Topology repair remains an installed workflow responsibility. `truthmark check` may expose routing or coverage symptoms, but AI agents must be able to perform Truth Structure directly from committed config, route files, docs, and implementation when the Truthmark binary is unavailable. - -## Core Rules - -### Authority - -Authority checks validate that configured files and globs stay inside the repository root and that explicit files exist. - -Current severity behavior: - -- missing explicit authority file: `error` -- out-of-repository authority path: `error` -- authority glob with no matches: `review` - -### Area Index - -Area checks resolve the configured root route index and, in V1, one level of child route files under the configured area-files root. - -Delegated child-surface validation follows the parent glob semantics rather than accepting broad shared path prefixes. - -Each resolved leaf area must define: - -- `Truth documents` -- `Code surface` -- `Update truth when` - -`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: - -- malformed or incomplete root or child area block: `error` -- missing truth document: `error` -- out-of-repository truth document or code surface: `error` -- conflicting routed kinds for the same truth document path: `error` -- child route file outside the configured area-files root: `error` -- nested delegation inside a child route file: `error` -- duplicate resolved leaf area key: `error` -- duplicate child route-file reference: `error` -- child code surface outside its delegated parent code surface: `review` -- unreferenced child route file under the configured area-files root: `review` -- code-surface glob with no matches: `review` - -### Coverage - -Coverage diagnostics are emitted when a code file under the current checked surface is not matched by any valid area mapping. - -Coverage scanning uses Truth Sync's functional-code classifier across common code roots: - -- `app/**` -- `api/**` -- `apps/**` -- `bin/**` -- `client/**` -- `cmd/**` -- `frontend/**` -- `infra/**` -- `infrastructure/**` -- `internal/**` -- `k8s/**` -- `kubernetes/**` -- `lib/**` -- `packages/**` -- `pkg/**` -- `proto/**` -- `schema/**` -- `schemas/**` -- `scripts/**` -- `server/**` -- `services/**` -- `src/**` -- `terraform/**` -- `web/**` -- `.github/workflows/**` - -The V1 minimum language requirement is explicit support for Go, Python, C#, and Java, in addition to JavaScript and TypeScript. Coverage also treats Terraform, Kubernetes manifests, API schemas, GraphQL schemas, protobuf schemas, CI workflows, frontend app paths, and monorepo app or package paths as functional surfaces when they sit under the checked roots. - -### Frontmatter - -Frontmatter checks parse only the Markdown files that are in the authority set or referenced as routed truth docs. - -Current severity behavior: - -- invalid frontmatter: `error` -- missing configured required field: `error` -- invalid `truth_kind`: `error` -- present `truth_kind` that disagrees with routed truth kind metadata: `error` -- missing configured recommended field: `review` - -### Internal Links - -Internal-link checks also run only on the authority and routed truth docs. - -Current severity behavior: - -- internal link that resolves outside the repository root: `error` -- internal link to a missing file: `error` - -### Decision Structure - -Decision-structure checks review configured architecture docs and routed truth docs that are part of the current truth surface. - -Current severity behavior: - -- canonical doc missing `Scope`: `review` -- canonical doc missing active `Product Decisions`: `review` -- canonical doc missing active `Rationale`: `review` -- behavior doc missing `Current Behavior`: `review` -- contract doc missing `Contract Surface` or all contract-detail sections: `review` -- architecture doc missing both `Boundaries` and `Components`: `review` -- workflow doc missing `Triggers` or `Execution Model`: `review` -- operations doc missing both `Runtime Topology` and `Configuration`: `review` -- test-behavior doc missing `Execution Model` or both `Fixtures And Data Model` and `Assertions And Invariants`: `review` - -### Generated Surfaces - -Generated-surface checks compare configured installed workflow files against the current renderer output. - -For managed instruction files such as `AGENTS.md` and `CLAUDE.md`, content comparison and version-marker checks are scoped to the Truthmark-managed block. Manual text outside that block is preserved and ignored by the generated-surface validator. - -Current severity behavior: - -- configured generated surface missing: `review` -- configured generated surface content stale: `review` -- generated Truthmark version marker differs from the current package version: `review` - -### Freshness - -Freshness checks run only when `--base ` is supplied. - -Current severity behavior: - -- changed functional code with no route owner: `review` -- 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` -- missing evidence symbol, invalid evidence span, or stale evidence hash: `error` -- evidence line spans are validated even when the evidence block does not include a content hash - -## Flows And States - -`truthmark check` follows this validation flow: - -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, 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. - -## Contracts - -- human output reports the number of `error` and `review` diagnostics -- 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 -- detached checkouts use the commit SHA -- worktree path is reported separately for parallel worktrees -- relevant file hashes track `.truthmark/config.yml`, the configured root route index, and configured child route files - -- `error` means the current routing or contract is invalid and should be fixed before relying on the docs tree. -- `review` means the tree is usable, but maintainers should decide whether the reported gap is intentional. - -## Product Decisions - -- `truthmark check` validates current truth health, but installed workflows remain agent-led and do not depend on the binary. -- Area resolution follows the configured hierarchy contract instead of assuming a flat current-behavior-doc tree. -- Decision-bearing canonical docs are part of truth health because missing rationale weakens future reconstruction. -- Topology pressure is handled by Truth Structure rather than by asking teams to manually maintain truth-folder shape. -- Branch-scope data is advisory metadata for the current checkout; it is not a cache, packet, or off-repo memory layer. -- Decision (2026-05-13): Branch-scope hashes follow the committed config and route files rather than a separate root workflow note. - -## Rationale - -Keeping check config-aware makes the validator match the installed workflow model. Treating decision sections as review-level diagnostics improves doc quality without blocking routine work on every missing explanation in one step. - -Keeping check non-orchestrating means repositories can use it in local audits or CI without turning Truthmark into the workflow runner. - -Keeping topology repair in generated agent workflows preserves portability: a repository with committed Truthmark surfaces remains usable in AI environments that cannot run the Truthmark CLI. - -## Non-Goals - -- `truthmark check` is not a workflow orchestrator. -- `truthmark check` is not the runtime for installed agent skills, prompts, or commands. -- `truthmark check` does not rewrite truth docs, route files, generated surfaces, or functional code. -- Passing `truthmark check` does not prove every truth doc already matches the latest template taxonomy. - -## Maintenance Notes - -Primary implementation files: - -- `src/checks/check.ts` -- `src/checks/scorecard.ts` -- `src/checks/authority.ts` -- `src/checks/areas.ts` -- `src/checks/frontmatter.ts` -- `src/checks/links.ts` -- `src/checks/branch-scope.ts` - -Update this doc when check diagnostics, JSON data shape, branch-scope behavior, generated-surface diagnostics, topology diagnostics, or severity rules change. diff --git a/docs/truthmark/truth/contracts.md b/docs/truthmark/truth/contracts.md deleted file mode 100644 index 6239bc7..0000000 --- a/docs/truthmark/truth/contracts.md +++ /dev/null @@ -1,390 +0,0 @@ ---- -status: active -doc_type: contract -truth_kind: contract -last_reviewed: 2026-06-01 -source_of_truth: - - ../../../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 - -## Purpose - -This document protects Truthmark machine-facing contracts: configuration, route metadata, CLI JSON envelopes, command result data, diagnostics, compatibility, and migration behavior. - -## Scope - -This document defines the current machine-facing contracts exposed by Truthmark: the config file shape, route metadata, repository-intelligence artifacts, and the CLI result envelope. - -## Contract Surface - -- The committed `.truthmark/config.yml` schema and defaults. -- 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/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 `2` -- `platforms`: optional list of agent harnesses to initialize; defaults to all supported platforms -- `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 derived controlled paths include: - -- `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: - -- a legacy Markdown list of document paths -- a fenced YAML block with a `truth_documents` array of `{ path, kind }` entries - -New scaffolded child route files use the fenced YAML form so routed truth kind is explicit from the first generated route. The legacy list form remains a compatibility input for existing repositories. - -Markdown list values normalize Prettier-escaped glob stars before route matching, so formatted entries such as `src/example/\*\*` are treated as `src/example/**`. - -Supported routed truth kinds are: - -- `behavior` -- `contract` -- `architecture` -- `workflow` -- `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/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. - -Supported `platforms` values are: - -- `codex` -- `opencode` -- `claude-code` -- `github-copilot` -- `gemini-cli` - -There is no `.truthmark/local.yml` contract in the current implementation. User preferences that affect generated repository behavior must be expressed through committed config or the generated surfaces cannot be reproduced by another checkout. - -## Outputs - -`truthmark config`, `truthmark init`, `truthmark check`, and `truthmark validate ...` commands return the same JSON envelope when run with `--json`. - -Current shape: - -- `command`: string command name -- `summary`: human-readable summary string -- `diagnostics`: array of diagnostic objects -- `data`: optional command-specific object - -Diagnostic fields: - -- `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/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 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. - -Current helper validator commands: - -- `truthmark validate sync-report --json` -- `truthmark validate document-report --json` -- `truthmark validate write-lease --json` - -`truthmark validate write-lease` parses the lease/report file as YAML before validation. The accepted YAML shape is either a top-level write-lease object or a worker report with a nested `writeLease` or `lease` object. The selected object must provide `allowedWrites` and `forbiddenWrites` as arrays of strings. After structural parsing, the validator applies the same path-safety, supported-pattern, allowed-write, and forbidden-write checks to parsed values and changed files. - -Each validator returns `data.validation` as one of: - -- `{ ok: true, helper: string, checks: string[] }` -- `{ ok: false, helper: string, errors: string[] }` - -The command summary is `Validation passed` when `ok` is true and `Validation failed` when `ok` is false. Missing input files return `ok: false` validation data for the requested helper instead of a generated surface payload. Human output renders the same pass/fail summary and helper checks/errors. - -RepoIndex, RouteMap, ImpactSet, and ContextPack are derived from the active checkout. They do not override route files, source files, truth docs, or installed workflow write boundaries. - -`truthmark config --json` writes only `.truthmark/config.yml` unless `--stdout` is used. - -Current config result data fields include: - -- `repositoryRoot` -- `worktreePath` -- `branchName` -- `isDetached` -- `isUnborn` - -When `--stdout` is used, `data` also includes: - -- `path` -- `content` - -`truthmark init --json` currently returns these data fields: - -- `repositoryRoot` -- `worktreePath` -- `branchName` -- `isDetached` -- `isUnborn` - -The command emits `action` diagnostics describing whether each scaffolded file was created, updated, or unchanged. Generated realization skill files use the `realization` diagnostic category. - -`truthmark init` requires an existing valid `.truthmark/config.yml`. It does not create config; `truthmark config` is the required first step in a new repository. -Configured `instruction_targets` are generated or refreshed independently of platform-specific surfaces, so `AGENTS.md` remains managed even when `claude-code` is not in `platforms`. - -Generated Truth Structure, Truth Document, Truth Sync, Truth Preview, Truth Check, Codex, Claude Code, GitHub Copilot, Gemini CLI, and OpenCode verifier or leased doc-writer agent surfaces, and the managed `AGENTS.md` block use the `truth-sync` diagnostic category. - -Current agent-native scaffold targets include: - -- `.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` -- `.codex/agents/truth-doc-writer.toml` -- `.claude/skills/truthmark-structure/SKILL.md` -- `.claude/skills/truthmark-document/SKILL.md` -- `.claude/skills/truthmark-sync/SKILL.md` -- `.claude/skills/truthmark-realize/SKILL.md` -- `.claude/skills/truthmark-check/SKILL.md` -- `.claude/skills/truthmark-preview/SKILL.md` -- `.claude/skills/truthmark-portal/SKILL.md` when Truthmark Portal is enabled -- `.claude/skills/truthmark-*/support/procedure.md` -- `.claude/skills/truthmark-*/support/report-template.md` -- `.claude/skills/truthmark-*/support/subagents-and-leases.md` when the workflow has generated subagent guidance -- `.claude/skills/truthmark-*/helper-manifest.yml` when the workflow declares helpers -- `.claude/skills/truthmark-*/support/helper-policy.md` when the workflow declares helpers -- `.claude/agents/truth-route-auditor.md` -- `.claude/agents/truth-claim-verifier.md` -- `.claude/agents/truth-doc-reviewer.md` -- `.claude/agents/truth-doc-writer.md` -- `.opencode/skills/truthmark-structure/SKILL.md` -- `.opencode/skills/truthmark-document/SKILL.md` -- `.opencode/skills/truthmark-sync/SKILL.md` -- `.opencode/skills/truthmark-realize/SKILL.md` -- `.opencode/skills/truthmark-check/SKILL.md` -- `.opencode/skills/truthmark-preview/SKILL.md` -- `.opencode/skills/truthmark-portal/SKILL.md` when Truthmark Portal is enabled -- `.opencode/skills/truthmark-*/support/procedure.md` -- `.opencode/skills/truthmark-*/support/report-template.md` -- `.opencode/skills/truthmark-*/support/subagents-and-leases.md` when the workflow has generated subagent guidance -- `.opencode/skills/truthmark-*/helper-manifest.yml` when the workflow declares helpers -- `.opencode/skills/truthmark-*/support/helper-policy.md` when the workflow declares helpers -- `.opencode/agents/truth-route-auditor.md` -- `.opencode/agents/truth-claim-verifier.md` -- `.opencode/agents/truth-doc-reviewer.md` -- `.opencode/agents/truth-doc-writer.md` -- `AGENTS.md` -- `CLAUDE.md` -- `.github/copilot-instructions.md` -- `.github/skills/truthmark-structure/SKILL.md` -- `.github/skills/truthmark-document/SKILL.md` -- `.github/skills/truthmark-sync/SKILL.md` -- `.github/skills/truthmark-realize/SKILL.md` -- `.github/skills/truthmark-check/SKILL.md` -- `.github/skills/truthmark-preview/SKILL.md` -- `.github/skills/truthmark-portal/SKILL.md` when Truthmark Portal is enabled -- `.github/skills/truthmark-*/support/procedure.md` -- `.github/skills/truthmark-*/support/report-template.md` -- `.github/skills/truthmark-*/support/subagents-and-leases.md` when the workflow has generated subagent guidance -- `.github/skills/truthmark-*/helper-manifest.yml` when the workflow declares helpers -- `.github/skills/truthmark-*/support/helper-policy.md` when the workflow declares helpers -- `.github/prompts/truthmark-structure.prompt.md` -- `.github/prompts/truthmark-document.prompt.md` -- `.github/prompts/truthmark-sync.prompt.md` -- `.github/prompts/truthmark-realize.prompt.md` -- `.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.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` -- `.gemini/skills/truthmark-sync/SKILL.md` -- `.gemini/skills/truthmark-realize/SKILL.md` -- `.gemini/skills/truthmark-check/SKILL.md` -- `.gemini/skills/truthmark-preview/SKILL.md` -- `.gemini/skills/truthmark-portal/SKILL.md` when Truthmark Portal is enabled -- `.gemini/skills/truthmark-*/support/procedure.md` -- `.gemini/skills/truthmark-*/support/report-template.md` -- `.gemini/skills/truthmark-*/support/subagents-and-leases.md` when the workflow has generated subagent guidance -- `.gemini/skills/truthmark-*/helper-manifest.yml` when the workflow declares helpers -- `.gemini/skills/truthmark-*/support/helper-policy.md` when the workflow declares helpers -- `.gemini/commands/truthmark/structure.toml` -- `.gemini/commands/truthmark/document.toml` -- `.gemini/commands/truthmark/sync.toml` -- `.gemini/commands/truthmark/realize.toml` -- `.gemini/commands/truthmark/check.toml` -- `.gemini/commands/truthmark/preview.toml` -- `.gemini/commands/truthmark/portal.toml` when Truthmark Portal is enabled -- `.gemini/agents/truth-route-auditor.md` -- `.gemini/agents/truth-claim-verifier.md` -- `.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. 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 `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: - -- `branchScope` -- `truthVisibility` - -`branchScope` contains: - -- `repositoryRoot` -- `worktreePath` -- `branchName` -- `headSha` -- `identity` -- `relevantFileHashes` - -For normal branches, `identity` is branch name plus HEAD SHA. For detached checkouts, `identity` is the commit SHA. `worktreePath` remains separate so callers can distinguish parallel worktrees for the same repository. - -`relevantFileHashes` currently tracks hashes for: - -- `.truthmark/config.yml` -- the configured root route index -- configured child route files under the configured area-files root - -`truthVisibility` contains: - -- `routePrecision.leafAreaCount` -- `routePrecision.broadAreaCount` -- `unmappedSurfaceCount` -- `staleGeneratedSurfaceCount` -- `syncCompletenessIssueCount` -- `topologyPressureCount` - -## Errors And Diagnostics - -- ordinary `truthmark check` emits `config`, `authority`, `frontmatter`, `links`, `area-index`, `coverage`, `doc-structure`, and `generated-surface` diagnostics. -- `truth-sync` and `realization` categories exist for init and generated workflow reporting, but ordinary `check` does not emit workflow payloads. -- `truthmark check` does not support `--workflow truth-sync` in the current contract. -- Missing authority files are `error` diagnostics. -- Authority globs and code-surface globs that match nothing are `review` diagnostics. -- Coverage diagnostics discover unmapped functional code across common code roots with the same path classifier used by Truth Sync. V1 coverage must include Go, Python, C#, Java, JavaScript, TypeScript, frontend roots, monorepo app or package roots, Terraform, Kubernetes manifests, CI workflows, OpenAPI or Swagger, GraphQL, and protobuf surfaces within those roots. -- `frontmatter` emits `error` diagnostics when `truth_kind` is invalid or present and disagrees with routed truth-kind metadata. -- `doc-structure` emits `review` diagnostics when configured architecture or routed truth docs are missing `Scope`, active `Product Decisions`, active `Rationale`, or the kind-specific required headings for their routed truth kind. - -## Compatibility Rules - -- `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. -- 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 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. -- Helper validators must keep helper-specific data under `data.validation` rather than returning raw validator payloads at the top level. - -## Product Decisions - -- 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`, 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 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 - -- This doc does not define human prose style for truth docs; templates and standards own that. -- This doc does not make installed agent workflows CLI subcommands. -- This doc does not define every generated host file path except where those paths are part of command, validator, or generated-surface contracts. - -## Maintenance Notes - -Update this doc when `.truthmark/config.yml` schema, route metadata forms, command names/options, JSON envelopes, command-specific `data` payloads, diagnostic categories/severities, helper validator envelopes, or compatibility guarantees change. diff --git a/docs/truthmark/truth/init-and-scaffold.md b/docs/truthmark/truth/init-and-scaffold.md deleted file mode 100644 index 75a07e5..0000000 --- a/docs/truthmark/truth/init-and-scaffold.md +++ /dev/null @@ -1,287 +0,0 @@ ---- -status: active -doc_type: behavior -truth_kind: behavior -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 ---- - -# Init And Scaffold - -## Purpose - -This document protects the repository setup contract for `truthmark config` and `truthmark init`: how configuration is created, what init scaffolds or refreshes, and which generated surfaces are managed. - -## Scope - -This document owns the current setup and scaffold behavior for `truthmark config` and `truthmark init`: config-file creation, default docs and routes, editable typed templates, managed instruction blocks, generated platform surfaces, and migration-risk reporting. It hands ongoing truth-doc content maintenance to the routed truth docs and workflow surfaces. - -## Current Behavior - -`truthmark config` is the required first step in a new repository. It writes only `.truthmark/config.yml` unless `--stdout` is used. - -`truthmark init` operates on the active Git worktree and does all of the following in one pass: - -1. resolves the active repository and worktree -2. requires an existing valid `.truthmark/config.yml` -3. creates default standards only when they are missing or empty -4. creates missing configured docs and routing structure such as the configured root route index, the configured default child route file with explicit truth kind metadata when the root route index delegates it, the configured truth-root README, a default area index README, six editable typed truth-doc templates, and a default bounded behavior truth doc -5. loads the configured `platforms` list -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 each touched file as `created`, `updated`, or `unchanged` - -## Core Rules - -Current scaffold targets: - -- `.truthmark/config.yml` via `truthmark config` -- [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` -- `.opencode/skills/truthmark-structure/SKILL.md` -- `.opencode/skills/truthmark-document/SKILL.md` -- `.opencode/skills/truthmark-sync/SKILL.md` -- `.opencode/skills/truthmark-realize/SKILL.md` -- `.opencode/skills/truthmark-check/SKILL.md` -- `.opencode/skills/truthmark-preview/SKILL.md` -- `.opencode/skills/truthmark-*/support/procedure.md` -- `.opencode/skills/truthmark-*/support/report-template.md` -- `.opencode/skills/truthmark-*/support/subagents-and-leases.md` when the workflow has generated subagent guidance -- `.opencode/skills/truthmark-*/helper-manifest.yml` when the workflow declares helpers -- `.opencode/skills/truthmark-*/support/helper-policy.md` when the workflow declares helpers -- `.opencode/agents/truth-route-auditor.md` -- `.opencode/agents/truth-claim-verifier.md` -- `.opencode/agents/truth-doc-reviewer.md` -- `.opencode/agents/truth-doc-writer.md` -- `.claude/skills/truthmark-structure/SKILL.md` -- `.claude/skills/truthmark-document/SKILL.md` -- `.claude/skills/truthmark-sync/SKILL.md` -- `.claude/skills/truthmark-realize/SKILL.md` -- `.claude/skills/truthmark-check/SKILL.md` -- `.claude/skills/truthmark-preview/SKILL.md` -- `.claude/skills/truthmark-*/support/procedure.md` -- `.claude/skills/truthmark-*/support/report-template.md` -- `.claude/skills/truthmark-*/support/subagents-and-leases.md` when the workflow has generated subagent guidance -- `.claude/skills/truthmark-*/helper-manifest.yml` when the workflow declares helpers -- `.claude/skills/truthmark-*/support/helper-policy.md` when the workflow declares helpers -- `.claude/agents/truth-route-auditor.md` -- `.claude/agents/truth-claim-verifier.md` -- `.claude/agents/truth-doc-reviewer.md` -- `.claude/agents/truth-doc-writer.md` -- `.github/copilot-instructions.md` -- `.github/skills/truthmark-structure/SKILL.md` -- `.github/skills/truthmark-document/SKILL.md` -- `.github/skills/truthmark-sync/SKILL.md` -- `.github/skills/truthmark-realize/SKILL.md` -- `.github/skills/truthmark-check/SKILL.md` -- `.github/skills/truthmark-preview/SKILL.md` -- `.github/skills/truthmark-*/support/procedure.md` -- `.github/skills/truthmark-*/support/report-template.md` -- `.github/skills/truthmark-*/support/subagents-and-leases.md` when the workflow has generated subagent guidance -- `.github/skills/truthmark-*/helper-manifest.yml` when the workflow declares helpers -- `.github/skills/truthmark-*/support/helper-policy.md` when the workflow declares helpers -- `.github/prompts/truthmark-structure.prompt.md` -- `.github/prompts/truthmark-document.prompt.md` -- `.github/prompts/truthmark-sync.prompt.md` -- `.github/prompts/truthmark-realize.prompt.md` -- `.github/prompts/truthmark-check.prompt.md` -- `.github/prompts/truthmark-preview.prompt.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` -- `.gemini/skills/truthmark-sync/SKILL.md` -- `.gemini/skills/truthmark-realize/SKILL.md` -- `.gemini/skills/truthmark-check/SKILL.md` -- `.gemini/skills/truthmark-preview/SKILL.md` -- `.gemini/skills/truthmark-*/support/procedure.md` -- `.gemini/skills/truthmark-*/support/report-template.md` -- `.gemini/skills/truthmark-*/support/subagents-and-leases.md` when the workflow has generated subagent guidance -- `.gemini/skills/truthmark-*/helper-manifest.yml` when the workflow declares helpers -- `.gemini/skills/truthmark-*/support/helper-policy.md` when the workflow declares helpers -- `.gemini/commands/truthmark/structure.toml` -- `.gemini/commands/truthmark/document.toml` -- `.gemini/commands/truthmark/sync.toml` -- `.gemini/commands/truthmark/realize.toml` -- `.gemini/commands/truthmark/check.toml` -- `.gemini/commands/truthmark/preview.toml` -- `.gemini/commands/truthmark/portal.toml` when Truthmark Portal is enabled -- `.gemini/agents/truth-route-auditor.md` -- `.gemini/agents/truth-claim-verifier.md` -- `.gemini/agents/truth-doc-reviewer.md` -- `.gemini/agents/truth-doc-writer.md` - -`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/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 `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 malformed or duplicated managed blocks when they use the current Truthmark markers or current managed-block content -- preserve manual text outside the managed block -- 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 -- preserve repository instruction authority while clarifying that implementation code and canonical truth docs are behavior evidence, not a way to override workflow write boundaries - -Repository-specific instructions should therefore live outside the managed block. - -Truthmark does not create `OPENCODE.md` in V1. OpenCode-compatible behavior is installed through shared `AGENTS.md` guidance and project skill files under `.opencode/skills/`. - -Hierarchy is configured in `.truthmark/config.yml`: - -- `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, 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/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/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 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/*.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 -- Truth Sync is the only generated skill with implicit invocation enabled because it is the automatic finish-time workflow -- `truthmark check` is optional validation for agent workflows, not a required workflow preflight -- Truth Realize is always installed as an explicit manual surface for configured platforms; it has no separate config toggle and no dedicated CLI subcommand -- Gemini CLI support uses `GEMINI.md` for hierarchical memory, `.gemini/commands/truthmark/*.toml` for explicit workflow commands with `{{args}}` focus forwarding, `.gemini/skills/truthmark-*/` for Agent Skills, and `.gemini/agents/*.md` for project subagents instead of introducing Truthmark-specific top-level CLI verbs or Gemini extensions -- helper files are emitted only for workflows with declared helpers and configured skill-package platforms (`codex`, `opencode`, `claude-code`, `github-copilot`, and `gemini-cli`); helper manifests call installed Truthmark CLI validators and generated packages do not bundle repo-local `scripts/*.mjs` helper copies - -- 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/truthmark/templates/*.md` default sections -- the command should remain safe to run repeatedly in the same repository - -## Flows And States - -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, 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. - -## Contracts - -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 -- `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 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 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/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. - -## Rationale - -This split makes the hierarchy reviewable before generated workflow behavior lands in the repo. Keeping route ownership in Markdown preserves local editing ergonomics. Refusing silent migrations avoids accidental truth loss when a repository reshapes its canonical docs tree. - -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/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 - -- Init does not create `.truthmark/config.yml`; `truthmark config` owns that step. -- Init does not silently migrate existing truth docs to a new hierarchy. -- Init does not overwrite manual text outside managed instruction blocks. -- Init does not replace repository-authored template preambles/frontmatter or custom template sections during template refresh. -- Init does not delete generated files for platforms that were later removed from config. - -## Maintenance Notes - -Primary implementation files: - -- `src/init/init.ts` -- `src/templates/init-files.ts` -- `src/templates/agents-block.ts` -- `src/templates/workflow-surfaces.ts` -- `src/fs/paths.ts` - -Update this doc when scaffold targets, managed-surface categories, template refresh behavior, generated platform surfaces, config defaults, or init diagnostics change. diff --git a/docs/truthmark/truth/release/README.md b/docs/truthmark/truth/release/README.md deleted file mode 100644 index 3f1b310..0000000 --- a/docs/truthmark/truth/release/README.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -status: active -doc_type: index -last_reviewed: 2026-05-13 -source_of_truth: - - ../../routes/areas/release-automation.md ---- - -# Release Truth Docs - -This directory indexes bounded release and automation truth docs. - -README.md files are indexes, not Truth Sync targets. Keep behavior truth in bounded leaf docs in this directory. - -Current leaf docs: - -- [Automation](automation.md) diff --git a/docs/truthmark/truth/release/automation.md b/docs/truthmark/truth/release/automation.md deleted file mode 100644 index 90894c7..0000000 --- a/docs/truthmark/truth/release/automation.md +++ /dev/null @@ -1,88 +0,0 @@ ---- -status: active -doc_type: behavior -truth_kind: workflow -last_reviewed: 2026-05-31 -source_of_truth: - - ../../routes/areas/release-automation.md - - ../../../../.github/workflows/ci.yml - - ../../../../.github/workflows/publish.yml ---- - -# Release Automation - -## Purpose - -This doc owns the repository automation that verifies Truthmark changes in pull requests and publishes the package from GitHub releases. - -## Scope - -This doc covers the committed GitHub Actions workflows under `.github/workflows/`. It does not redefine the `truthmark` CLI contracts or the detailed behavior of `check`, `init`, or installed workflows. - -## Triggers - -- Pushes to the `main` branch start the `CI` workflow. -- Pull request events start the same `CI` verification workflow before merge. -- Published GitHub release events start the `Publish` workflow; branch pushes and pull requests do not publish. - -## Inputs - -- The checked-out repository contents -- GitHub Actions event context for pushes, pull requests, and releases -- npm registry credentials and release-environment configuration for publishing - -## Execution Model - -Release automation runs through the committed GitHub Actions workflows under `.github/workflows/`. The `CI` workflow verifies repository changes, and the `Publish` workflow revalidates release state before publishing to npm. - -The repository also ships `examples/github-actions/truthmark-impact.yml` as a consumer example. It is not a release workflow for this repository. The example shows a non-blocking PR mode that comments with `truthmark impact --base` and `truthmark check --base` results, uploads the JSON reports, and a blocking mode controlled by `TRUTHMARK_BLOCKING`. - -## Steps - -- The `CI` workflow runs on pushes to `main` and on every pull request. -- The `verify` job checks out the repository, installs Node 24 with npm caching, runs `npm ci`, then runs `npm run check` and `npm run package:check`. -- The `Publish` workflow runs when a GitHub release is published. -- The `publish` job checks out the repository, installs Node 24 with the npm registry configured, runs `npm ci`, runs `npm run release:check`, and then runs `npm publish`. - -Core automation rules: - -- Pull request and main-branch automation must verify linting, types, tests, build output, and package-file integrity through the existing npm scripts. -- Publish automation must re-run the full release verification before publishing. -- Publishing is triggered from a GitHub release event, not from branch pushes alone. - -## State, Retry, And Failure Behavior - -- Failed verification or release-check steps stop the current job and prevent later publish steps from running. -- Publishing occurs only for the GitHub release event path; branch pushes and pull requests do not publish. -- GitHub Actions reruns remain host-managed; Truthmark owns the committed workflow definitions, not GitHub's execution controls. -- The example ImpactSet workflow is intentionally opt-in and consumer-copied; it does not run unless a repository installs it. - -## Outputs - -- CI verification results for pushes and pull requests -- npm publication after a successful release-triggered publish job - -## Product Decisions - -- Decision (2026-05-13): Repository automation stays script-driven and reuses committed npm verification commands instead of duplicating verification logic inline in GitHub Actions. - -## Rationale - -Keeping workflow steps thin makes repository automation follow the same verification contract developers run locally. That reduces drift between local validation, CI validation, and release publishing. - -## Non-Goals - -- This doc does not own release-note authoring or GitHub release drafting policy. -- This doc does not define npm package contents beyond invoking the existing package checks. - -## Maintenance Notes - -- Update this doc when workflow triggers, Node versions, or verification commands change. -- Keep this doc aligned with `package.json` scripts used by the workflows. - -Workflow contracts: - -- Both workflows currently run on `ubuntu-latest`. -- Both workflows install Node 24 through `actions/setup-node@v6`. -- The CI workflow constrains `GITHUB_TOKEN` to `contents: read`. -- The publish workflow requires `contents: read`, `id-token: write`, and npm registry access through the configured GitHub Actions environment. diff --git a/docs/truthmark/truth/repository/README.md b/docs/truthmark/truth/repository/README.md deleted file mode 100644 index 8669351..0000000 --- a/docs/truthmark/truth/repository/README.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -status: active -doc_type: index -last_reviewed: 2026-05-13 -source_of_truth: - - ../../routes/areas/init-and-scaffold.md ---- - -# Repository Truth Docs - -This directory indexes bounded repository truth docs. - -README.md files are indexes, not Truth Sync targets. Keep behavior truth in bounded leaf docs in this directory. - -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 deleted file mode 100644 index 6c4e8e6..0000000 --- a/docs/truthmark/truth/repository/context-pack.md +++ /dev/null @@ -1,74 +0,0 @@ ---- -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/truthmark/truth/repository/impact-set.md b/docs/truthmark/truth/repository/impact-set.md deleted file mode 100644 index ffb171a..0000000 --- a/docs/truthmark/truth/repository/impact-set.md +++ /dev/null @@ -1,75 +0,0 @@ ---- -status: active -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 ---- - -# ImpactSet - -## Purpose - -This document protects ImpactSet v0 as the derived mapping from Git changes to routed truth ownership, affected docs, affected tests, and public-symbol impact. - -## Scope - -This document owns ImpactSet v0 behavior. ImpactSet maps Git changes to Truthmark routes, truth docs, owning areas, related tests, and public symbol changes. - -## Current Behavior - -`truthmark impact --base --json` compares the active checkout to the supplied base ref and returns `schemaVersion: impact-set/v0`. The command combines Git diff data with RepoIndex and RouteMap data. - -ImpactSet reports changed files, affected routes, affected truth docs, affected tests, changed public symbols, and diagnostics. It includes staged, unstaged, and untracked worktree changes so local agent work can be evaluated before commit. - -## Core Rules - -- Changed functional code is mapped through `Code surface` entries in Truthmark route files. -- Changed routed truth docs are mapped back to their owning routes and included in `affectedTruthDocs`. -- Renamed files preserve `previousPath`, map both old and new paths to route ownership, and report moved exports as removed from the old path and added at the new path. -- Changed test files are reported as affected tests instead of missing truth-route diagnostics. -- Related tests are selected from direct imports, basename hints, and package-level test path conventions. -- Public symbol changes are computed from JavaScript/TypeScript exports in v0. -- Missing or invalid base refs produce an `impact` error diagnostic instead of silently returning an empty comparison. -- Changed public symbols produce review diagnostics when no affected truth doc exists or when affected truth docs exist but were not changed in the impact set. -- ImpactSet is derived. It does not grant write permission and does not replace route ownership. - -## Flows And States - -`truthmark impact --base --json` compares the active checkout to the supplied base ref, combines Git diff data with RepoIndex and RouteMap data, and reports changed files, affected routes, affected truth docs, affected tests, changed public symbols, and diagnostics. It includes staged, unstaged, and untracked worktree changes so local agent work can be evaluated before commit. - -## Contracts - -`truthmark impact --base --json` returns the shared command envelope with `schemaVersion: impact-set/v0` data. Renames preserve `previousPath`, and changed test files are reported as affected tests rather than missing truth-route diagnostics. - -## Product Decisions - -- Decision (2026-05-16): ImpactSet v0 uses Git plus route ownership as the review boundary instead of a background cache. -- Decision (2026-05-16): Public API impact starts with JavaScript and TypeScript exports because this repository's first implementation stack is TypeScript. - -## Rationale - -ImpactSet gives Truth Sync and CI a stable, reviewable way to explain what code changed and which truth surfaces are affected without making a model decide ownership. - -## Non-Goals - -- ImpactSet is not a background cache. -- ImpactSet does not replace route files as ownership authority. -- ImpactSet does not override the current checkout when an artifact conflicts with local files. - -## Maintenance Notes - -ImpactSet requires the Truthmark CLI or an equivalent local runner. If unavailable, agents must inspect Git changes and route ownership directly. The workflow may proceed manually, but completion reports must say ImpactSet was not generated. - -If an ImpactSet conflicts with the current checkout, agents must trust the checkout and rerun or ignore the artifact. - -Primary implementation files: - -- `src/impact/build.ts` -- `src/impact/git-diff.ts` -- `src/repo-index/build.ts` - -Update this doc when the command output, schema version, derived inputs, fallback behavior, or workflow relationship changes. diff --git a/docs/truthmark/truth/repository/overview.md b/docs/truthmark/truth/repository/overview.md deleted file mode 100644 index 8b0bc20..0000000 --- a/docs/truthmark/truth/repository/overview.md +++ /dev/null @@ -1,60 +0,0 @@ ---- -status: active -doc_type: behavior -truth_kind: behavior -last_reviewed: 2026-06-01 -source_of_truth: - - ../../routes/areas/init-and-scaffold.md - - ../../../../src/init/init.ts - - ../../../../src/templates/init-files.ts ---- - -# Repository Overview - -## Purpose - -This doc owns the default bounded behavior leaf that `truthmark init` scaffolds for repositories using the default `repository` area. - -## Scope - -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/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 - -- Truth `README.md` files are indexes, not current-behavior targets. -- The default scaffold keeps behavior truth in bounded leaf docs under the configured truth root. -- The seeded repository leaf stays intentionally small so later Truth Sync runs can replace it instead of appending to an index file. - -## Flows And States - -- `truthmark init` creates the truth root index, the default area index, and this bounded leaf when those files are missing. -- Later repository work may update or replace the seeded leaf doc without changing the scaffold contract. - -## Contracts - -- 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 - -- Decision (2026-05-14): The default scaffold seeds a bounded behavior truth doc instead of placing current behavior in a truth `README.md`. - -## Rationale - -Bounded seed docs give new repositories an immediately routeable truth target while keeping index files stable and small. - -## Non-Goals - -- This doc does not own the full `truthmark init` workflow. -- This doc does not define repository-specific behavior after downstream teams rewrite the seed content. - -## Maintenance Notes - -- 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/truthmark/truth/repository/repo-index.md b/docs/truthmark/truth/repository/repo-index.md deleted file mode 100644 index 3ac2a5f..0000000 --- a/docs/truthmark/truth/repository/repo-index.md +++ /dev/null @@ -1,75 +0,0 @@ ---- -status: active -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 ---- - -# RepoIndex - -## Purpose - -This document protects RepoIndex v0 and RouteMap v0 as deterministic, local repository-intelligence artifacts derived from the active checkout. - -## Scope - -This document owns RepoIndex v0 and RouteMap v0 behavior. RepoIndex describes the current checkout's files, docs, packages, tests, JavaScript/TypeScript imports and exports, public symbols, and Truthmark route ownership. - -## Current Behavior - -`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/routes/areas.md`, and `docs/truthmark/routes/areas/**/*.md`. - -## Core Rules - -- Paths are repository-relative POSIX paths. -- Arrays are sorted lexicographically unless source order is part of the contract. -- File discovery honors Git ignore rules through `git ls-files --exclude-standard` and then applies Truthmark config ignores, so ignored local artifacts are not indexed. -- Symbol extraction v0 covers JavaScript and TypeScript source files. -- Managed agent Markdown surfaces such as `AGENTS.md`, `CLAUDE.md`, `GEMINI.md`, and Copilot instructions are classified as generated files rather than ordinary docs. -- Route ownership comes from Truthmark area files, not from package structure or import graphs. -- RepoIndex and RouteMap are derived artifacts. They speed up routing and review, but they do not override source files, route files, or truth docs. - -## Flows And States - -`truthmark index --json` reads local files, Git metadata, config, route files, Markdown docs, package metadata, tests, JavaScript/TypeScript imports and exports, public symbols, and route ownership. It does not start a daemon, call a model, call a remote service, or write generated artifacts by default. - -## Contracts - -`truthmark index --json` returns the shared command envelope with `schemaVersion: repo-index/v0` data. RouteMap output uses `schemaVersion: route-map/v0`. Paths are repository-relative POSIX paths, arrays are sorted lexicographically unless source order is contractual, and file discovery honors Git ignore rules plus Truthmark config ignores. - -## 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/routes/areas.md` instead of introducing a parallel ownership schema. - -## Rationale - -Keeping repository intelligence derived preserves Truthmark's branch-local review boundary. Teams can use fast machine-readable context when the CLI is available without making installed workflows unusable in constrained agent environments. - -## Non-Goals - -- RepoIndex is not a source of truth. -- RepoIndex does not grant workflow write permissions. -- RepoIndex does not replace direct inspection when the CLI is unavailable or stale. - -## Maintenance Notes - -RepoIndex requires the Truthmark CLI or an equivalent local runner to compute. If the CLI is unavailable, agents must inspect `.truthmark/config.yml`, route files, changed source files, and routed truth docs directly. Workflows may proceed manually, but completion reports must say RepoIndex and RouteMap were not generated. - -If a RepoIndex or RouteMap artifact conflicts with the current checkout, the checkout wins. Agents must rerun the CLI when available or ignore the stale artifact when it cannot be regenerated. - -Primary implementation files: - -- `src/repo-index/build.ts` -- `src/repo-index/file-tree.ts` -- `src/repo-index/route-map.ts` -- `src/repo-index/types.ts` - -Update this doc when the command output, schema version, derived inputs, fallback behavior, or workflow relationship changes. diff --git a/docs/truthmark/truth/repository/workflow-state.md b/docs/truthmark/truth/repository/workflow-state.md deleted file mode 100644 index 0be17b0..0000000 --- a/docs/truthmark/truth/repository/workflow-state.md +++ /dev/null @@ -1,83 +0,0 @@ ---- -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): WorkflowState does not carry ContextPack; public ContextPack JSON output was removed in v2. -- 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/truthmark/truth/routing-examples.md b/docs/truthmark/truth/routing-examples.md deleted file mode 100644 index b6bc04f..0000000 --- a/docs/truthmark/truth/routing-examples.md +++ /dev/null @@ -1,82 +0,0 @@ ---- -status: active -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 ---- - -# Routing Examples - -This document gives examples for designing explicit Truthmark areas in larger repositories. The examples are patterns, not required folder names. - -## Purpose - -This document protects reusable routing examples that help maintainers split larger repositories by durable behavior ownership rather than broad directory mirroring. - -## Scope - -This doc covers example routing patterns for larger repositories so agents and maintainers can split route ownership by behavior rather than by broad directory mirroring. - -## Current Behavior - -- Truthmark treats frontend, API schema, workflow, infrastructure, and monorepo service paths as functional surfaces when they change production behavior, contracts, or operational ownership. -- Route design should produce bounded truth owners that map changed code to a small set of canonical docs. - -## Core Rules - -- Route production behavior, contracts, and operational ownership explicitly. -- Prefer bounded product, service, workflow, or platform ownership over one broad catch-all route. -- Treat frontend, API schema, workflow, infrastructure, and monorepo service paths as functional surfaces when they change behavior, contracts, deployment, permissions, or availability. -- Use delegated child route files when one root route would otherwise own unrelated services, packages, or user flows. - -## Flows And States - -### Express, Nest, And Fastify - -Large Node API apps should route by product behavior rather than by framework layer. For example, route `src/modules/billing/**`, `src/routes/billing/**`, or `apps/api/src/billing/**` to a billing truth doc instead of routing all controllers through `src/**`. - -API schema files are functional surfaces when they define behavior or contracts. Route `api/openapi.yaml`, `schema/**/*.graphql`, and `proto/**/*.proto` to the nearest contract or behavior truth doc. - -### Frontend Apps - -Frontend repositories should route user-facing flows, app shells, and shared UI behavior explicitly. Useful code surfaces include `frontend/**`, `web/**`, `client/**`, `apps/*/src/**`, and product-owned component folders such as `components/checkout/**`. - -Avoid a single catch-all frontend area once multiple flows have independent product decisions or release risks. - -### Terraform And Kubernetes - -Infrastructure-as-code is functional when it changes runtime behavior, deployment topology, permissions, or availability. Route `infra/**`, `terraform/**`, `k8s/**`, and `kubernetes/**` to operational or platform truth docs. - -Kubernetes and Terraform changes should not disappear under generic config handling when they affect the deployed system. - -### Service Monorepos - -Service monorepos should prefer bounded service or package ownership: `services/payments/**`, `apps/admin/**`, `packages/auth/**`, and similar paths should map to specific behavior or platform docs. - -Use delegated child route files when one root route would otherwise own unrelated services or packages. - -## Contracts - -Routing examples must remain examples of valid `Code surface`, `Truth documents`, and `Update truth when` thinking. They do not change the route-file schema; concrete repositories still express ownership through their configured route files. - -## Product Decisions - -Decision (2026-05-09): Truthmark treats frontend, API schema, workflow, IaC, and monorepo service paths as visible functional surfaces for routing quality. - -## Rationale - -Agents need routeable evidence for the code surfaces that change production behavior. Keeping these examples canonical reduces broad catch-all routing and makes unmapped surfaces easier to review. - -## Non-Goals - -- 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/routes/areas.md` and child area files. - -## Maintenance Notes - -Update this doc when Truthmark routing guidance changes for frontend apps, API schemas, infrastructure-as-code, workflow code, or service monorepos. diff --git a/docs/truthmark/truth/workflows/content-generation.md b/docs/truthmark/truth/workflows/content-generation.md deleted file mode 100644 index 40f1489..0000000 --- a/docs/truthmark/truth/workflows/content-generation.md +++ /dev/null @@ -1,73 +0,0 @@ ---- -status: active -doc_type: behavior -truth_kind: workflow -last_reviewed: 2026-05-31 -source_of_truth: - - ../../../../src/generation/** ---- - -# Workflow Content Generation - -## Purpose - -Content-generation prompt contracts shape draft truth-doc updates without becoming workflow authority. - -## Scope - -This document owns the source-internal prompt, schema, registry, and validation contracts under `src/generation/**` that draft truth-doc updates from bounded evidence context. Installed workflow surfaces own permissions, write boundaries, and final acceptance. - -## Triggers - -- prompt renderer, schema, registry, type, or validator changes under `src/generation/**` -- changes to draft-output semantics such as evidence IDs, relevant-doc path checks, blocked status rules, patch-path validation, or JSON parsing requirements -- workflow changes that alter how generated draft content is consumed or rejected - -## Inputs - -- JSON-backed evidence context -- structured output schemas -- workflow-authorized target docs - -## Execution Model - -Workflow prompts grant permissions and set write boundaries. Content-generation prompt contracts may render evidence context and validate structured draft output, but they do not grant permission to write files or replace direct checkout inspection. - -Generated draft content remains advisory until a workflow-authorized agent applies it to canonical docs. - -## Steps - -1. Source workflow code gathers evidence context and target-doc boundaries. -2. Content-generation prompt contracts render that context for draft generation. -3. Structured output schemas validate draft shape where applicable. -4. A workflow-authorized agent decides whether and how to apply the draft to canonical docs under the installed workflow write boundary. - -Current behavior notes: - -Truthmark keeps content-generation contracts separate from installed workflow authority. Agents still inspect the checkout directly and use installed workflow surfaces for permissions, boundaries, and reporting. - -## State, Retry, And Failure Behavior - -Draft prompt output is advisory state only. If generation fails, schema validation fails, or evidence is insufficient, the owning workflow must fall back to direct checkout inspection and either write a supported truth-doc update or report why it blocked. - -## Outputs - -Generated draft content may become proposed truth-doc prose only after a workflow-authorized agent validates it against checkout evidence and applies it within allowed write paths. The prompt contracts themselves do not produce authoritative repository truth. - -## Product Decisions - -- Decision (2026-05-15): Content-generation prompt contracts are source-internal draft helpers, not workflow authority. - -## Rationale - -Separating draft generation from workflow authority prevents helper prompts from bypassing ownership gates or write boundaries. - -## Non-Goals - -- no permission grants, write leases, or workflow authority from draft prompts -- no replacement for direct checkout inspection, route ownership review, or final workflow acceptance -- no unrestricted patch paths outside repository-relative `docs/**` targets supplied by the bounded context - -## Maintenance Notes - -Update this doc when `src/generation/**` changes prompt contracts, schemas, validation, or runtime relationship to installed workflows. diff --git a/docs/truthmark/truth/workflows/overview.md b/docs/truthmark/truth/workflows/overview.md deleted file mode 100644 index f2bd004..0000000 --- a/docs/truthmark/truth/workflows/overview.md +++ /dev/null @@ -1,142 +0,0 @@ ---- -status: active -doc_type: behavior -truth_kind: workflow -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 - - ../../../../tests/evals/workflow-routing-cases.ts - - ../../../../tests/evals/no-cli-fallback-cases.ts ---- - -# Installed Workflow Overview - -## Purpose - -Truthmark installs agent-native workflow surfaces into configured AI hosts. Those surfaces define invocation, write boundaries, report shapes, and where agents must read before acting. - -## Scope - -This document owns the shared installed-workflow runtime model and generated host surface inventory. Individual workflow behavior lives in sibling workflow docs. - -## Triggers - -- `truthmark init` refreshes managed instruction blocks and explicit workflow surfaces after configuration or renderer changes. -- Explicit host invocations run manual workflows. -- Truth Sync is the only automatic finish-time workflow trigger. -- Truth Preview is an explicit read-only selector for likely workflow routing before edits; it is intended, not authorized. -- Truthmark Portal is an opt-in manual-only presentation workflow; it is not a completion gate or Sync/check substitute. - -## Inputs - -- `.truthmark/config.yml` -- generated host surfaces under configured platform directories -- the package version from `package.json` - -## Execution Model - -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. - -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 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: - -The default platform list includes every supported platform. Teams should remove unused platforms from `.truthmark/config.yml` before rerunning `truthmark init`. - -| Platform | Generated surface | Invocation shape | -| ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- | -| `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/*.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. - -Codex, Claude Code, GitHub Copilot, Gemini CLI, and OpenCode platform generation include project-scoped read-only verifier agents for workflow-owned subagent dispatch plus a write-capable `truth-doc-writer` for parent-leased Truth Sync and Truth Document shards. Codex exposes `truth_route_auditor`, `truth_claim_verifier`, `truth_doc_reviewer`, and `truth_doc_writer`. Claude Code exposes `truth-route-auditor`, `truth-claim-verifier`, `truth-doc-reviewer`, and `truth-doc-writer` project subagents. GitHub Copilot, Gemini CLI, and OpenCode expose `@truth-route-auditor`, `@truth-claim-verifier`, `@truth-doc-reviewer`, and `@truth-doc-writer`. The parent workflow may use them automatically when the host supports subagents and bounded fan-out is useful; read-only verifier agents keep context bounded by avoiding host instruction files and repo-wide policy docs unless assigned as evidence, write workers require explicit leases, and the parent workflow owns final reports, repo-policy interpretation, diff validation, and acceptance. -Read-only verifier agents include an explicit context boundary: they inspect only the parent-assigned shard plus required checkout evidence files and do not preload repo-wide instruction or policy docs unless the parent assigns those files as evidence. - -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.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. - -Managed instruction blocks are compact automatic-Sync trigger and boundary indexes. They intentionally omit platform-specific invocation strings, non-automatic workflow procedures, report examples, and long checklists. Detailed invocations and procedures live in generated skills, skill support files, prompts, and command files. - -## 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 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 - -The installed runtime outputs managed instruction blocks, host-native skills/prompts/commands/agents, optional helper validation reports, and agent completion reports. Canonical truth remains in Markdown docs and route files. - -## Product Decisions - -- 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, 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. -- Decision (2026-05-16): Read-only verifier agents do not preload host instruction files or repo-wide policy docs by default; parent workflows keep that policy context and pass only bounded evidence shards to verifier agents. -- Decision (2026-05-16): Coding and document-writing speed is not a priority over workflow simplicity and agent stability. Truthmark must not make document writing faster by adding project complexity, weaker leases, broader write authority, or less stable agent behavior. -- Decision (2026-05-16): Truth Preview is generated as an explicit read-only workflow surface, not an automatic gate, validator, or Truth Check replacement. -- 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 - -Keeping workflow execution agent-native makes installed repositories usable even when the Truthmark package is unavailable at execution time. Agents can read committed surfaces, inspect the checkout, and act without depending on a daemon, database, or mandatory generated payload. - -Optional CLI-owned helpers fit that model by accelerating deterministic validation without requiring generated repositories to carry executable helper-script copies. - -Compact managed instruction blocks and compact skill entrypoints protect ordinary model context while explicit support files, prompt files, and command files remain available when the agent needs a full procedure. - -## Non-Goals - -- no autonomous background workflow execution -- no required helper payload, packet helper, cache file, daemon, database, or remote service -- no generated repo-root `skills/` workflow surface - -## Maintenance Notes - -Update this doc when supported platforms, generated surface locations, invocation shapes, description routing behavior, or the installed runtime model change. diff --git a/docs/truthmark/truth/workflows/shared-gates.md b/docs/truthmark/truth/workflows/shared-gates.md deleted file mode 100644 index 37e6202..0000000 --- a/docs/truthmark/truth/workflows/shared-gates.md +++ /dev/null @@ -1,121 +0,0 @@ ---- -status: active -doc_type: behavior -truth_kind: workflow -last_reviewed: 2026-05-31 -source_of_truth: - - ../../../../src/agents/shared.ts - - ../../../../src/truth/** - - ../../../../src/sync/report.ts ---- - -# Shared Workflow Gates - -## Purpose - -Shared workflow gates ensure agents choose the correct truth owner before validating claims or repairing document shape. - -## Scope - -This document owns shared ownership, evidence, shape-repair, architecture-boundary, template, and decision-truth guidance rendered into installed workflows. - -## Triggers - -The gates apply whenever Truth Structure, Truth Document, Truth Sync, Truth Preview, Truth Realize, or Truth Check reads, writes, audits, or relies on canonical truth docs. - -## Inputs - -- `.truthmark/config.yml` -- route files under `docs/truthmark/` -- routed truth docs -- implementation, config, generated templates including section comments, schemas, and contract definitions -- tests and existing canonical docs as corroboration - -## Execution Model - -Ownership comes first. Evidence review and shape repair are valid only after the target or source truth doc is confirmed as a bounded owner for the behavior. - -## Steps - -### Ownership Gate - -Before editing or relying on a truth doc, the workflow verifies that each target or source truth doc is a bounded owner for the behavior. If a doc mixes independent owners, spans unrelated behaviors, acts as an index, or needs cross-owner edits, the workflow must not patch or repair it in place. - -Truth Sync and Truth Document switch to Truth Structure when ownership repair is safe and in scope; otherwise they block and recommend Truth Structure. Truth Realize blocks before writing code when source truth is broad, mixed-owner, stale, unrouteable, or conflicting. Truth Check reports mixed-owner truth docs as topology issues. Truth Structure owns split and reroute repair. - -Reports name the ownership result: `Ownership reviewed`, `Structure required`, `Truth docs split`, `Truth docs restructured`, or `Blocked reason`. - -### Product Decisions/Rationale Preservation Gate - -Before any truth-doc split, restructure, or shape repair, the workflow inventories existing `Product Decisions` and `Rationale` sections in every source or touched truth doc. - -Current decisions and rationale are preserved in the bounded owner doc they govern. When a doc is split, the workflow moves each entry to the new owner doc instead of deleting it or leaving it stranded in an index. - -A decision or rationale may be removed or narrowed only when checkout evidence shows it is stale or unsupported, and the report names the claim, evidence, and result. If ownership is unclear, the workflow blocks with manual-review files rather than guessing or deleting the entry. - -After the edit, every touched truth doc must still have `Product Decisions` and `Rationale` sections, and every pre-existing entry must be preserved, moved, narrowed, removed with evidence, or blocked. - -### Evidence Gate - -Truth Structure, Truth Document, and Truth Sync validate new or changed behavior-bearing claims only. Agents map the changed or documented behavior to bounded route owners and primary canonical docs, support changed claims with primary checkout evidence, use tests and existing docs only as corroboration when implementation conflicts, and remove, narrow, or block unsupported claims. - -Primary checkout evidence includes implementation, config, routing, generated-surface templates, schemas, and contract definitions. - -Truth Check uses an audit-shaped gate: findings and suggested fixes need evidence from config, route files, canonical docs, implementation, templates, or tests. Unsupported findings are removed or marked as open questions with confidence. If an audit edits docs, changed claims pass through the claim-level gate before completion. - -Truth Sync and Truth Document completed reports have deterministic structured parsers for Markdown reports with `Evidence checked` entries shaped as `- Claim: ...`, indented `Evidence: ...`, and indented `Result: supported | narrowed | removed | blocked`. - -### Repository Intelligence Boundary - -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/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. - -### Shape Repair Gate - -Shape repair is in-place cleanup inside an already-bounded truth owner. It covers missing template sections, stale evidence conflicts, cross-section updates within one owner, or wrong frontmatter/source/headings. - -Shape repair does not cover ownership splits. Broad or mixed-owner docs require Truth Structure before claim updates. - -### Template And Decision Guidance - -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. - -## State, Retry, And Failure Behavior - -If ownership is unclear, broad, mixed, stale, catch-all, or unrouteable, workflows must stop local claim edits and run or recommend Truth Structure. If evidence is insufficient, workflows narrow or remove unsupported claims or block with a report. If CLI-derived context conflicts with checkout evidence, the checkout wins and derived artifacts must be rerun or ignored. - -## Outputs - -The gates output workflow decisions: proceed inside a bounded owner, repair shape in place, hand off to Truth Structure, block for ambiguity, or report unsupported/stale claims. They do not output canonical content by themselves. - -## Product Decisions - -- Decision (2026-05-15): Shared generated workflow gates are correctness gates first. Compactness is allowed only after ownership routing, evidence validation, and report obligations remain explicit. -- Decision (2026-05-15): Ownership repair is not shape repair. Mixed-owner truth docs require Truth Structure, split/reroute, or a blocked report. -- Decision (2026-05-15): Evidence validation is changed-claim-only and requires primary checkout evidence. -- Decision (2026-05-15): Generated workflow surfaces refer to routed truth-doc templates instead of embedding full template text. -- Decision (2026-05-15): Truth-doc split, restructure, and shape repair must preserve, move, explicitly narrow/remove with evidence, or block every pre-existing Product Decision and Rationale entry. -- Decision (2026-05-31): Template section comments are normative authoring guidance for truth-doc content. Agents must satisfy those comments, not merely copy the matching `##` headings. - -## Rationale - -The product is the workflow. Agents must choose the correct owner before making local edits, otherwise evidence-backed prose can still preserve the wrong truth boundary. - -Keeping ownership, evidence, and shape repair separate prevents broad-doc cleanup from hiding topology drift. - -Treating section comments as authoring guidance keeps templates lightweight while still carrying the quality bar agents need for useful section content. - -## Non-Goals - -- no inline evidence ledger in canonical docs by default -- no in-place repair for mixed-owner truth docs -- no full truth-doc template embedding inside generated workflow prompts - -## Maintenance Notes - -Update this doc when shared gate wording, template-comment guidance, template rules, decision-truth behavior, evidence reporting, or ownership/split behavior changes. diff --git a/docs/truthmark/truth/workflows/truth-check.md b/docs/truthmark/truth/workflows/truth-check.md deleted file mode 100644 index e3cdad9..0000000 --- a/docs/truthmark/truth/workflows/truth-check.md +++ /dev/null @@ -1,86 +0,0 @@ ---- -status: active -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 ---- - -# Truth Check Workflow - -## Purpose - -Truth Check protects repository-truth health by auditing configured routes, canonical docs, implementation evidence, and optional CLI diagnostics without becoming a code verifier or silent repair workflow. - -## Scope - -Truth Check owns agent-led truth-health review. It reports issues and suggested fixes without silently rewriting unrelated files. - -## Triggers - -- explicit user invocation through an installed host surface such as `/truthmark-check`, `$truthmark-check`, `/skill truthmark-check`, or `/truthmark:check` -- a user request to audit an area, document path, route owner, stale claim, topology concern, or overall truth-health state - -## Inputs - -- `.truthmark/config.yml` -- root and child route files -- canonical docs -- relevant implementation code -- optional local `truthmark check` output - -## Execution Model - -Truth Check inspects the checkout directly and may optionally run `truthmark check` when local tooling is available. Installed workflows must not depend on the binary being present. In Codex, Claude Code, GitHub Copilot, Gemini CLI, or OpenCode, Truth Check may automatically use generated read-only verifier subagents when the host supports subagent dispatch and the parent agent chooses bounded fan-out. - -## Steps - -1. Inspect configured Truthmark config, route files, canonical docs, implementation, and tests. -2. Optionally run local `truthmark check` when available. -3. Identify stale claims, weak route ownership, missing decision/rationale coverage, topology issues, and unsupported truth-doc content. -4. Support each finding and suggested fix with checkout evidence. -5. Report issues without silently rewriting unrelated files. - -Current behavior notes: - -Truth Check verifies that current docs describe current code rather than historical plans, route files map code surfaces to canonical truth docs, canonical behavior docs keep active Product Decisions and Rationale sections, and broad, catch-all, index-like, or mixed-owner truth docs are reported as topology issues requiring Truth Structure. - -Truth Check supports each finding and suggested fix with evidence from config, route files, canonical docs, implementation, templates, or tests. Unsupported findings are removed or marked as open questions with confidence. - -If follow-up docs edits are needed for mixed-owner docs, Truth Check runs or recommends Truth Structure before editing. - -When subagent mode is available, the parent agent may dispatch read-only route, claim, and doc-shape verifier workers across bounded shards. Codex exposes `truth_route_auditor`, `truth_claim_verifier`, and `truth_doc_reviewer`; Claude Code exposes `truth-route-auditor`, `truth-claim-verifier`, and `truth-doc-reviewer` project subagents; GitHub Copilot, Gemini CLI, and OpenCode expose `@truth-route-auditor`, `@truth-claim-verifier`, and `@truth-doc-reviewer`. Workers return structured findings only and must not edit files. They inspect only the parent-assigned shard plus required checkout evidence files and do not preload repo-wide instruction or policy docs unless the parent assigns those files as evidence. The parent agent deduplicates findings, spot-checks evidence, optionally runs validation, and owns repo-policy interpretation and the final Truth Check report. - -Completed reports include `Files reviewed`, `Issues found`, `Fixes suggested`, `Evidence checked`, and `Validation`. - -## State, Retry, And Failure Behavior - -Truth Check is read-only by default. If local CLI tooling is unavailable, it proceeds by direct checkout inspection and reports that optional CLI diagnostics were not generated. Mixed-owner docs are reported as topology issues instead of silently repaired. - -## Outputs - -Truth Check outputs an audit report with findings, evidence, severity or priority, and suggested fixes. It does not replace lint, tests, typecheck, code review, or Truth Sync. - -## Product Decisions - -- Decision (2026-05-15): Truth Check is an audit workflow, not a substitute for lint, tests, typecheck, code review, or Truth Sync. -- Decision (2026-05-15): Truth Check reports mixed-owner truth docs as topology issues and does not silently repair them outside the proper workflow. -- Decision (2026-05-16): Codex, Claude Code, GitHub Copilot, Gemini CLI, and OpenCode subagent mode is read-only, automatic when host-supported, parent-owned, and context-bounded; verifier agents may gather evidence but never write docs, preload repo-wide policy unless assigned, or replace the final audit report. - -## Rationale - -Audits must identify ownership drift, not only stale claims. Reporting mixed-owner docs pushes repair into Truth Structure, where routing and split decisions are allowed. - -## Non-Goals - -- no silent rewrite of unrelated files, functional code, route files, or truth docs -- no replacement for normal lint, tests, typecheck, build checks, or code review -- no topology repair in place when findings require Truth Structure ownership - -## Maintenance Notes - -Update this doc when Check audit scope, evidence requirements, topology finding behavior, or report shape changes. diff --git a/docs/truthmark/truth/workflows/truth-document.md b/docs/truthmark/truth/workflows/truth-document.md deleted file mode 100644 index 90dce2f..0000000 --- a/docs/truthmark/truth/workflows/truth-document.md +++ /dev/null @@ -1,101 +0,0 @@ ---- -status: active -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 ---- - -# Truth Document Workflow - -## Purpose - -Truth Document records existing implemented behavior when no functional-code change is required. - -## Scope - -Truth Document owns manual missing-truth generation for implemented behavior. It may write canonical truth docs and routing files only. - -## Triggers - -- explicit user request to document existing implemented behavior -- handoff from Truth Sync, Truth Check, or Truth Structure when implemented behavior lacks canonical truth docs - -## Inputs - -- implementation code and tests -- `.truthmark/config.yml` -- root and child route files -- existing canonical docs - -## Execution Model - -Truth Document is implementation-first and never writes functional code. It documents current implemented behavior only and does not invent future behavior or planned endpoints. In Codex, Claude Code, GitHub Copilot, Gemini CLI, or OpenCode, Truth Document may automatically use generated read-only verifier subagents and explicit-lease `truth-doc-writer` subagents when the host supports subagent dispatch and the parent agent chooses bounded fan-out. - -## Steps - -1. Confirm the user is asking to document existing implemented behavior rather than change functional code. -2. Inspect implementation, tests, config, route files, and existing canonical docs. -3. Apply the ownership gate and run Truth Structure first when routing or truth ownership is unsafe and repair is in scope. -4. Create or update only routed canonical truth docs and route files needed for the documented behavior, using the routed truth kind's template and its section-comment guidance for touched truth-doc content. -5. Preserve active Product Decisions and Rationale during bounded shape repair or Structure handoff. -6. Report evidence, written docs, routing changes, and blocked ambiguities. - -Current behavior notes: - -Truth Document applies the ownership gate before writing. If routing is missing, stale, broad, overloaded, catch-all, or cannot map behavior to a bounded truth owner, it runs Truth Structure first when repair is safe and in scope. If repair is unsafe, ambiguous, or outside the task boundary, it blocks and recommends Truth Structure. - -If the candidate truth doc is broad, mixed-owner, index-like, or the documented behavior spans independent owners, Truth Document does not repair it in place. It switches to Truth Structure or blocks. - -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/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. - -ContextPack may be used to gather bounded source context when available. It does not replace checkout inspection, does not create write permission, and cannot be cited as evidence unless it points to real checkout files, tests, route files, truth docs, schemas, or explicit evidence blocks. If ContextPack is unavailable, Truth Document proceeds manually and reports that repository-intelligence artifacts were not generated. - -When the installed `truthmark` CLI is available at the declared version, Truth Document surfaces expose optional read-only `truthmark validate document-report` and `truthmark validate write-lease` helper commands through helper manifests. Agents may use those CLI validators as accelerators, but must visibly skip them and continue manual validation when the CLI is unavailable, too old, or a helper cannot run. The document-report validator validates the report body before its own helper status is appended; after it returns `data.validation.ok: true`, the workflow appends or updates `validate-document-report: ran, passed` in the final report. Helper output is derived evidence; parent validation against checkout evidence, report requirements, lease boundaries, and actual diffs remains authoritative. Completed reports must not record `ran, failed` for helper statuses; required helper statuses other than the report validator's own pending status must be reported as `ran, passed` or `skipped, ` for the completed report validator to accept them. The write-lease helper rejects absolute paths, Windows drive-letter paths, and any `..` path segment in lease patterns or changed-file inputs instead of normalizing them back under an allowed prefix. - -When subagent mode is available, the parent agent may dispatch read-only route and claim verifier workers to gather route and evidence findings. Codex exposes `truth_route_auditor` and `truth_claim_verifier`; Claude Code exposes `truth-route-auditor` and `truth-claim-verifier` project subagents; GitHub Copilot, Gemini CLI, and OpenCode expose `@truth-route-auditor` and `@truth-claim-verifier`. Read-only verifier workers inspect only the parent-assigned shard plus required checkout evidence files and do not preload repo-wide instruction or policy docs unless the parent assigns those files as evidence. The same hosts expose `truth_doc_writer` or `@truth-doc-writer` for leased truth-doc shards. The parent agent creates each lease, requires allowedWrites and forbiddenWrites, validates the actual checkout diff against the lease, and owns repo-policy interpretation, final acceptance, routing decisions, shape repair scope, and the final report. - -Completed reports include `Implementation reviewed`, `Ownership reviewed`, `Structure required` when applicable, `Truth docs created`, `Truth docs updated`, `Truth docs restructured`, `Routing updated`, `Evidence checked`, `Helper scripts`, and `Notes`. Required completed-report sections must contain at least one bullet entry, `Evidence checked` must use structured `Claim`, indented `Evidence`, and `Result` entries, and blocked reports must include `Reason` for helper validation to accept them. -When write workers are used, each worker report must include `status`, `worker`, `workflow`, `shard`, `filesChanged`, `claimsChecked`, `evidenceChecked`, `offLeaseChanges`, `blockers`, and `notes`. The parent accepts a completed worker report only after validating the parsed report against the lease identity, required report fields, actual worker diff, `allowedWrites`, `forbiddenWrites`, reported `filesChanged`, reported `offLeaseChanges`, and reported `blockers`. Blocked worker reports remain blocked outcomes and must include blockers; off-lease or forbidden actual diffs are rejected rather than trusted from self-report. - -## State, Retry, And Failure Behavior - -If routing is missing, stale, broad, overloaded, catch-all, or cannot map behavior to a bounded owner, Truth Document either runs Truth Structure when safe and in scope or blocks and recommends it. If helper/subagent support is unavailable, the parent agent performs the same checks manually. - -## Outputs - -Truth Document outputs canonical truth-doc and route-file changes plus a completion report. It does not output functional-code changes or planned-behavior docs. - -## Product Decisions - -- Decision (2026-05-15): Truth Document exists because documenting existing implemented behavior without code changes is not a Truth Sync run. -- Decision (2026-05-15): Truth Document must switch to Truth Structure rather than patching mixed-owner truth docs. -- Decision (2026-05-15): Truth Document must not lose Product Decisions or Rationale during bounded shape repair or Structure handoff. -- Decision (2026-05-16): Codex, Claude Code, GitHub Copilot, Gemini CLI, and OpenCode subagents may gather bounded read-only evidence for Document without preloading repo-wide policy by default. Document may also dispatch `truth-doc-writer` only with an explicit write lease, while parent agents retain policy, acceptance, and diff-validation ownership. -- Decision (2026-05-31): Truth Document treats template section comments as the section-level content standard for authored or repaired truth-doc prose. - -## Rationale - -Documentation-only work can still damage repository truth if it appends implemented behavior to the wrong owner. The ownership gate keeps Document from turning broad docs into larger broad docs. - -## Non-Goals - -- no functional-code edits or generated code changes -- no planned behavior documentation, speculative endpoints, or roadmap prose -- no in-place ownership repair for mixed-owner docs; hand off to Truth Structure instead - -## Maintenance Notes - -Update this doc when Truth Document triggers, write boundaries, template-authoring guidance, ownership handoff behavior, or report shape changes. diff --git a/docs/truthmark/truth/workflows/truth-preview.md b/docs/truthmark/truth/workflows/truth-preview.md deleted file mode 100644 index 5eafc2e..0000000 --- a/docs/truthmark/truth/workflows/truth-preview.md +++ /dev/null @@ -1,88 +0,0 @@ ---- -status: active -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 ---- - -# Truth Preview - -## Purpose - -Truth Preview protects a read-only, explicit planning surface for previewing likely Truthmark routing, workflow choice, write classes, target files, and handoff before edits. - -## Scope - -Truth Preview previews likely Truthmark routing before edits. - -It is an explicit read-only planning surface. It is intended, not authorized, and hands off to the selected workflow after user approval. - -## Triggers - -- explicit user invocation through the installed host surface -- questions about likely workflow routing, route ownership, target files, write classes, or subagent use before edits - -## Inputs - -- `.truthmark/config.yml` -- root and child route files -- relevant canonical docs -- relevant implementation files -- the user's requested focus or proposed change - -## Execution Model - -Truth Preview reads only the context needed to preview ownership: - -- `.truthmark/config.yml` -- root and child route files -- relevant canonical docs -- relevant implementation files - -Truth Preview reports the likely Truthmark workflow, why that workflow was selected, likely route owner, expected write classes, expected target files, suggested subagent use, blocking ambiguity, and handoff. - -Truth Preview may suggest the read-only route auditor when bounded verifier input would reduce context or clarify route ownership. It does not use write workers and does not issue write leases. - -Truth Preview must not edit files, create truth docs, update routing, run Truth Sync automatically, replace Truth Check, claim final correctness, issue write leases, or mutate code. - -Completed reports include `Requested outcome`, `Likely workflow`, `Why this workflow`, `Likely route owner`, `Expected write classes`, `Expected target files`, `Suggested subagent use`, `Blocking ambiguity`, and `Handoff`. - -## Steps - -1. Read only the config, routes, canonical docs, and implementation needed to preview ownership. -2. Identify the likely Truthmark workflow, route owner, write classes, target files, and useful subagent mode. -3. Report ambiguity or blocking ownership risk instead of mutating files. -4. Hand off to the selected workflow only after user approval or explicit follow-up. - -## State, Retry, And Failure Behavior - -Truth Preview is read-only and has no retry state beyond re-running the preview with more specific context. If ownership is ambiguous, the output states the ambiguity and recommends the next workflow instead of authorizing edits. - -## Outputs - -Truth Preview outputs a planning report: likely workflow, selection rationale, likely route owner, expected write classes, expected target files, suggested subagent use, blocking ambiguity, and handoff. It does not create, update, or validate repository files. - -## Product Decisions - -- Decision (2026-05-16): Truth Preview is a first-class explicit workflow because routing transparency before mutation can prevent agents from loading or acting through the wrong heavier workflow. -- Decision (2026-05-16): Truth Preview is not automatic. Its value is a cheap selector for ambiguous routing or write-boundary questions, not a required gate before normal edits. -- Decision (2026-05-16): Truth Preview reports intended next steps only; it does not authorize writes or validate final correctness. - -## Rationale - -Preview improves agent performance only when it prevents unnecessary workflow loading, broad context gathering, or wrong-owner edits. Making it automatic would add ceremony and context to straightforward tasks. - -## Non-Goals - -- no automatic invocation, mutation, or approval bypass before the user chooses a follow-up workflow -- no validation gate, final correctness claim, or replacement for Truth Check -- no write leases, write-worker dispatch, route updates, truth-doc edits, or functional-code mutation - -## Maintenance Notes - -Update this doc when Preview triggers, read boundaries, report shape, generated surfaces, or handoff behavior change. diff --git a/docs/truthmark/truth/workflows/truth-realize.md b/docs/truthmark/truth/workflows/truth-realize.md deleted file mode 100644 index b84aa53..0000000 --- a/docs/truthmark/truth/workflows/truth-realize.md +++ /dev/null @@ -1,81 +0,0 @@ ---- -status: active -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 ---- - -# Truth Realize Workflow - -## Purpose - -Truth Realize protects doc-first implementation by turning bounded, current canonical truth claims into functional code while keeping truth docs and routing read-only for the run. - -## Scope - -Truth Realize is doc-first and manual. Truth docs lead, code follows, and the agent may write functional code only. - -## Triggers - -- explicit user invocation through an installed host surface such as `/truthmark-realize`, `$truthmark-realize`, `/skill truthmark-realize`, or `/truthmark:realize` -- a user request that specifically asks to realize existing truth docs into code, not a generic code edit or documentation task - -## Inputs - -- source truth docs -- route metadata -- relevant implementation code and tests -- `.truthmark/config.yml` - -## Execution Model - -Truth Realize must read source truth docs, routing, and relevant code before writing functional code. It must not edit truth docs or truth routing. - -## Steps - -1. Read source truth docs, routing metadata, relevant implementation code, tests, and config. -2. Verify the source truth docs are bounded, current, routeable, and not mixed-owner or index-like. -3. Implement only the bounded current truth claims from the source docs. -4. Run relevant tests or report why they could not run. -5. Report changed functional-code files and verification. - -Current behavior notes: - -Truth Realize applies the ownership gate to source truth docs before writing code. If a source truth doc is broad, mixed-owner, index-like, unrouteable, stale, or conflicts with implementation evidence, Truth Realize blocks before writing code and recommends Truth Structure or Truth Document. - -When source truth is bounded and current, Truth Realize implements only the bounded current truth claims from the source docs and reports changed code files plus verification. - -Completion reports include `Truth docs used`, `Code updated`, and `Verification`. - -ContextPack may be used to collect bounded implementation context when available. It does not replace checkout inspection, does not grant write permission outside the workflow boundary, and cannot override source truth docs or current code. If ContextPack is unavailable, Truth Realize proceeds manually and reports that repository-intelligence artifacts were not generated. - -## State, Retry, And Failure Behavior - -Truth Realize blocks before writing code when source truth is broad, mixed-owner, stale, unrouteable, or conflicts with implementation evidence. It remains explicit and manual-only. - -## Outputs - -Truth Realize outputs functional-code changes and a verification report. It must not output truth-doc edits or route-file edits. - -## Product Decisions - -- Decision (2026-05-15): Truth Realize remains available only through explicit user invocation and is always generated for configured platforms instead of being gated by a config toggle. -- Decision (2026-05-15): Truth Realize must not implement from broad, mixed-owner, stale, or unrouteable truth docs. - -## Rationale - -Doc-first implementation is only reliable when the source truth has a bounded owner. Implementing ambiguous truth turns documentation drift into code behavior. - -## Non-Goals - -- no truth-doc edits, template rewrites, or truth-routing changes -- no automatic invocation as a finish gate for ordinary code tasks -- no implementation from broad, mixed-owner, stale, unrouteable, or implementation-conflicting source truth - -## Maintenance Notes - -Update this doc when Realize invocation, source-doc checks, write boundaries, or report shape changes. diff --git a/docs/truthmark/truth/workflows/truth-structure.md b/docs/truthmark/truth/workflows/truth-structure.md deleted file mode 100644 index a9b4760..0000000 --- a/docs/truthmark/truth/workflows/truth-structure.md +++ /dev/null @@ -1,98 +0,0 @@ ---- -status: active -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/** ---- - -# Truth Structure Workflow - -## Purpose - -Truth Structure protects bounded repository-truth topology so generated agent workflows can route code areas, truth docs, and ownership repair to the right current-state owner before any truth prose is expanded. - -## Scope - -Truth Structure owns area routing, child route-file structure, ownership splits, and starter truth-doc placement when topology is missing, stale, broad, overloaded, catch-all, unrouteable, or explicitly requested. -Truth Structure also owns new area setup when a user asks to onboard a new code area into Truthmark, a new package/controller/domain lacks bounded truth ownership, or a new product area needs routing and starter truth docs. - -## Triggers - -- explicit user invocation -- handoff from Truth Sync or Truth Document when routing or truth ownership is unsafe -- handoff from Truth Check when audit findings require topology repair - -## Inputs - -- repository layout -- `.truthmark/config.yml` -- root and child route files -- current canonical docs -- representative implementation boundaries and tests - -## Execution Model - -Truth Structure inspects the checkout directly and defines areas by product or behavior ownership, not mechanical directory mirroring. -For new area setup, Truth Structure inspects the named code area, infers bounded product or behavior ownership, chooses the owning route when ownership is clear, and otherwise proposes the route and blocks for review. It creates or updates the child route entry or file, creates starter truth docs only where current truth is missing, and reports the initial truth boundary. - -## Steps - -1. Inspect repository layout, config, root and child route files, current canonical docs, representative implementation boundaries, and tests. -2. Identify topology pressure such as broad code mappings, overloaded child route files, mixed-owner docs, catch-all routing, or unrouteable changed code. -3. Design bounded behavior or product ownership areas rather than mechanical directory mirrors. -4. Update route files and create or move starter truth docs where ownership is clear and current-state evidence supports them, using the routed truth kind's template and section-comment guidance for any starter or repaired truth doc. -5. Preserve or explicitly account for Product Decisions and Rationale when splitting or restructuring truth docs. -6. Verify route and truth health with Truthmark checks when available. - -Current behavior notes: - -When topology pressure exists, Truth Structure repairs structure before creating or extending truth docs. - -Topology pressure includes broad code mappings, overloaded child route files, multiple unrelated controllers or bounded contexts in one area, mixed-owner truth docs, too many direct truth docs in one folder, catch-all routing, or changed code that cannot map to a specific behavior doc. - -Truth Structure splits broad, overloaded, catch-all, or mixed-owner areas into behavior-owned route files and bounded leaf truth docs when safe. It updates routing so future Truth Sync can target small docs. If a split is unsafe or ambiguous, it blocks with manual-review files. - -In Codex, Claude Code, GitHub Copilot, Gemini CLI, and OpenCode, Truth Structure surfaces may reference the generated read-only route auditor when the parent agent chooses bounded validation fan-out. Codex exposes `truth_route_auditor`; Claude Code exposes the `truth-route-auditor` project subagent; GitHub Copilot, Gemini CLI, and OpenCode expose the generated `@truth-route-auditor` custom agent. The route auditor gathers topology and ownership findings only, inspects only the parent-assigned shard plus required checkout evidence files, and does not preload repo-wide instruction or policy docs unless the parent assigns those files as evidence. The parent workflow owns repo-policy interpretation, all route edits, starter truth-doc writes, topology decisions, and the final report. - -Before splitting or restructuring truth docs, Truth Structure inventories Product Decisions and Rationale in every source doc. It moves each current entry into the bounded owner doc it governs, removes or narrows entries only with checkout evidence, and blocks with manual-review files when ownership is unclear. - -Starter truth docs use closed YAML frontmatter with `status`, `doc_type`, `last_reviewed`, and `source_of_truth`, and include `Product Decisions` and `Rationale` sections. When a routed template exists, Structure follows the HTML comments under each template section as the authoring guidance for starter or repaired section content rather than treating the template as headings only. -New area setup must not edit functional code, perform full behavior documentation unless evidence is inspected and the task explicitly asks for it, patch broad or mixed-owner docs in place, create generic catch-all docs, or treat README files as Sync targets. - -Completed reports include `Topology reviewed`, `Areas reviewed`, `Routing updated`, `Initial truth boundary`, `Truth docs created`, `Truth docs split`, `Truth docs restructured`, `Evidence checked`, `Topology decisions`, and `Notes`. - -## State, Retry, And Failure Behavior - -Truth Structure may block instead of writing when ownership is ambiguous, route repair is outside task scope, or evidence is insufficient. It performs topology repair before claim expansion. - -## Outputs - -Truth Structure outputs route topology changes, bounded starter truth docs when supported, and a report explaining ownership decisions, preserved decisions/rationale, verification, and any blocked ambiguities. - -## Product Decisions - -- Decision (2026-05-15): Truth Structure owns ownership repair. Mixed-owner docs must be split/rerouted when safe, not repaired in place by Sync or Document. -- Decision (2026-05-15): Truth Structure must satisfy canonical decision-section expectations for new starter docs and repaired routed docs. -- Decision (2026-05-15): Truth Structure must preserve or explicitly account for Product Decisions and Rationale when splitting or restructuring truth docs. -- Decision (2026-05-16): Codex, Claude Code, GitHub Copilot, Gemini CLI, and OpenCode Truth Structure may use the generated read-only route auditor for bounded validation input without preloading repo-wide policy by default, while parent agents retain policy and topology write ownership. -- Decision (2026-05-16): New area setup is a Truth Structure scenario, not a separate workflow surface. It may add routing and starter truth docs, but detailed behavior documentation remains bounded by evidence and explicit task scope. -- Decision (2026-05-31): Starter and repaired truth docs must satisfy routed template section comments when templates are available, because topology repair should leave useful bounded content, not only valid headings. - -## Rationale - -Ownership repair needs a workflow that can change route topology and create bounded docs. Letting Sync or Document patch broad docs preserves drift. - -## Non-Goals - -- no mechanical directory mirroring when behavior ownership is clearer -- no generic truth docs behind broad catch-all routing -- no full behavior documentation during new area setup unless evidence is inspected and the task explicitly asks for it - -## Maintenance Notes - -Update this doc when topology pressure signals, split behavior, starter-doc template guidance, Structure subagent behavior, or Structure report shape changes. diff --git a/docs/truthmark/truth/workflows/truth-sync.md b/docs/truthmark/truth/workflows/truth-sync.md deleted file mode 100644 index cad3ff5..0000000 --- a/docs/truthmark/truth/workflows/truth-sync.md +++ /dev/null @@ -1,116 +0,0 @@ ---- -status: active -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 ---- - -# Truth Sync Workflow - -## Purpose - -Truth Sync protects the completion-time contract that changed functional code is reflected in bounded canonical truth docs and truth routing without letting documentation-only updates or topology repair blur workflow ownership. - -## Scope - -Truth Sync is code-first. Code leads, truth docs follow, and functional code must not be rewritten during sync. - -## Triggers - -- automatic finish-time trigger after functional code changes since the last successful Truth Sync -- explicit user invocation through the installed host surface - -## Inputs - -- staged, unstaged, and untracked functional-code changes -- `.truthmark/config.yml` -- root and child route files -- relevant canonical docs and nearby implementation - -## Execution Model - -Truth Sync may update routed truth docs and routing when routing repair is needed. It may create missing canonical truth docs when routeable implementation would otherwise remain undocumented. In Codex, Claude Code, GitHub Copilot, Gemini CLI, or OpenCode, Truth Sync may automatically use generated read-only verifier subagents and explicit-lease `truth-doc-writer` subagents when the host supports subagent dispatch and the parent agent chooses bounded fan-out. - -## Steps - -1. Determine whether functional code changed since the last successful Sync or whether the user explicitly invoked Sync. -2. Inspect changed code, config, route files, impacted truth docs, nearby implementation, and tests. -3. Apply topology and ownership gates before changing truth docs. -4. Update only routed truth docs and routing needed to keep canonical truth aligned with changed code, using the routed truth kind's template and its section-comment guidance for touched truth-doc content. -5. Preserve active Product Decisions and Rationale during bounded shape repair or Structure handoff. -6. Report changed truth files, evidence, skipped cases, verification, and any blocked topology repair. - -Current behavior notes: - -Before updating truth docs, Truth Sync applies the topology and ownership gates. If routing is missing, stale, broad, overloaded, catch-all, or cannot map changed code to a bounded truth owner, it must not create another generic truth doc. It runs Truth Structure first when repair is safe and in scope, or blocks and recommends Truth Structure when topology repair is unsafe, ambiguous, or outside the task boundary. - -If an impacted truth doc is broad, mixed-owner, index-like, or the code change spans independent behavior owners, Truth Sync switches to Truth Structure when safe and in scope. Otherwise it blocks and reports manual-review files. - -Truth Sync updates active decisions and rationale in the routed canonical doc when implementation changes are driven by a decision change. It dates active decisions inline when added or changed and replaces stale active decisions rather than appending separate timestamped decision notes. - -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/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. - -ContextPack may be used to accelerate Truth Sync when available. It does not replace checkout inspection, does not create write permission, and cannot be cited as evidence unless it points to real checkout files, tests, route files, truth docs, schemas, or explicit evidence blocks. If ContextPack or ImpactSet is unavailable, Truth Sync proceeds manually and reports that repository-intelligence artifacts were not generated. - -When the installed `truthmark` CLI is available at the declared version, Truth Sync surfaces expose optional read-only `truthmark validate sync-report` and `truthmark validate write-lease` helper commands through helper manifests. Agents may use those CLI validators as accelerators, but must visibly skip them and continue manual validation when the CLI is unavailable, too old, or a helper cannot run. The sync-report validator validates the report body before its own helper status is appended; after it returns `data.validation.ok: true`, the workflow appends or updates `validate-sync-report: ran, passed` in the final report. Helper output is derived evidence; parent validation against checkout evidence, report requirements, lease boundaries, and actual diffs remains authoritative. Completed reports must not record `ran, failed` for helper statuses; required helper statuses other than the report validator's own pending status must be reported as `ran, passed` or `skipped, ` for the completed report validator to accept them. The write-lease helper rejects absolute paths, Windows drive-letter paths, and any `..` path segment in lease patterns or changed-file inputs instead of normalizing them back under an allowed prefix. - -Completed reports include `Changed code reviewed`, `Ownership reviewed`, `Structure required` when applicable, `Truth docs updated`, `Truth docs split` when Structure is run inline, `Evidence checked`, `Helper scripts`, and `Notes`. Required completed-report sections must contain at least one bullet entry, and `Evidence checked` must use structured `Claim`, indented `Evidence`, and `Result` entries. The structured completed-report parser preserves optional `Helper scripts` statuses when that section is present. Skipped reports include `Reason`. Blocked reports include `Reason`, `Files requiring manual review`, and `Next action`; helper validation rejects skipped or blocked reports with missing required body sections. -When write workers are used, each worker report must include `status`, `worker`, `workflow`, `shard`, `filesChanged`, `claimsChecked`, `evidenceChecked`, `offLeaseChanges`, `blockers`, and `notes`. The parent accepts a completed worker report only after validating the parsed report against the lease identity, required report fields, actual worker diff, `allowedWrites`, `forbiddenWrites`, reported `filesChanged`, reported `offLeaseChanges`, and reported `blockers`. Blocked worker reports remain blocked outcomes and must include blockers; off-lease or forbidden actual diffs are rejected rather than trusted from self-report. - -Current skip reasons are: - -- documentation-only change -- formatting-only change -- clearly behavior-preserving rename with no truth impact -- no Truthmark config exists yet -- no functional code changes - -Truth Sync's generated frontmatter description and Codex metadata carry those skip cases because skill metadata is the host-visible routing boundary before the full workflow body is loaded. - -Truth Sync delegation is host-owned. Generated workflow surfaces may describe when delegation is allowed, but must not create unrestricted writable helpers or a project-local subagent preference file. Codex, Claude Code, GitHub Copilot, Gemini CLI, and OpenCode generated surfaces may name project-scoped read-only verifier agents for workflow-owned automatic verification and `truth-doc-writer` for leased truth-doc shards. Read-only verifier agents inspect only the parent-assigned shard plus required checkout evidence files and do not preload repo-wide instruction or policy docs unless the parent assigns those files as evidence. The parent workflow creates each lease, requires allowedWrites and forbiddenWrites, validates the actual checkout diff against the lease, and owns repo-policy interpretation and final acceptance. - -## State, Retry, And Failure Behavior - -Truth Sync is skipped for docs-only, formatting-only, behavior-preserving rename, missing-config, or no-code changes. It blocks or hands off to Truth Structure when routing is missing, stale, broad, overloaded, catch-all, or unrouteable. It must not rewrite functional code during sync. - -## Outputs - -Truth Sync outputs truth-doc and route-file updates plus a completion report. It does not output functional-code rewrites or generic docs behind weak routing. - -## Product Decisions - -- Decision (2026-05-15): Truth Sync metadata carries skip cases because docs-only, formatting-only, behavior-preserving rename, missing-config, and no-code changes should not trigger the finish-time sync path. -- Decision (2026-05-15): Truth Sync must not worsen weak topology by adding generic truth docs behind missing, stale, broad, overloaded, catch-all, or unrouteable routing. -- Decision (2026-05-15): Truth Sync must switch to Truth Structure or block when impacted truth docs are mixed-owner or broad. -- Decision (2026-05-15): Truth Sync must not lose Product Decisions or Rationale during bounded shape repair or inline Structure handoff. -- Decision (2026-05-16): Codex, Claude Code, GitHub Copilot, Gemini CLI, and OpenCode subagents may automatically gather bounded read-only route and claim evidence for Sync when host-supported without preloading repo-wide policy by default. Sync may also dispatch `truth-doc-writer` only with an explicit write lease, while parent agents retain policy, acceptance, and diff-validation ownership. -- Decision (2026-05-16): Truth Sync write authority is bounded by file class and route ownership, not by the root route index alone. It may write canonical truth docs and truth routing files, while functional code remains outside Sync authority. -- Decision (2026-05-31): Truth Sync follows the selected truth-doc template's section comments as content guidance for touched sections, because template compliance requires useful section content as well as matching headings. - -## Rationale - -Truth Sync is the finish-time bridge from code to truth, so it must protect route ownership before claim evidence. Otherwise it can accurately document behavior in the wrong place. Routing repair can require child route-file edits as well as root index edits, so Sync's safe boundary is leased truth routing files rather than one hard-coded route file. - -## Non-Goals - -- no functional-code rewrites during sync -- no generic docs behind weak routing -- no unleased writable subagent ownership baked into generated surfaces - -## Maintenance Notes - -Update this doc when Sync triggers, skip reasons, report shape, delegation language, template-authoring guidance, or ownership handoff behavior changes. diff --git a/docs/truthmark/truth/workflows/truthmark-portal.md b/docs/truthmark/truth/workflows/truthmark-portal.md deleted file mode 100644 index 1ba5b2f..0000000 --- a/docs/truthmark/truth/workflows/truthmark-portal.md +++ /dev/null @@ -1,103 +0,0 @@ ---- -status: active -doc_type: behavior -truth_kind: workflow -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 ---- - -# Truthmark Portal Workflow - -## Purpose - -Truthmark Portal is an opt-in installed workflow for generating a committed, human-facing, multi-page static HTML presentation site from repository Markdown truth sources. - -## Scope - -This document owns the installed Portal workflow boundary, config toggle, generated surface behavior, and generated-site safety rules. It does not define a deterministic Portal renderer CLI or make generated HTML canonical truth. - -## Triggers - -Portal runs only from an explicit user request to generate, refresh, or update the committed static HTML presentation site. It is not triggered by Truth Sync, `truthmark check`, `truthmark init`, repository indexing, or normal completion workflows. - -## Inputs - -- `.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 -- 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 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 `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 fixed Portal output directory. -5. Keep generated HTML, assets, and metadata non-canonical and report what was refreshed. - -Current behavior notes: - -`.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 -``` - -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 rejects extra custom `output` or `template` properties under `truthmark.generated.portal`. - -`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. - -Portal is manual-only. It is never a completion gate, never Truth Sync, and runs only when the user explicitly asks to generate, refresh, or update the committed static HTML Portal. - -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 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. - -## State, Retry, And Failure Behavior - -Portal remains disabled when the config block is omitted or `enabled` is omitted/false. Portal is manual-only and is not triggered by Truth Sync, `truthmark check`, `truthmark init`, repository indexing, or normal completion workflows. Generated output is replaceable presentation state, not repository truth. - -## Outputs - -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-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. - -## Rationale - -Large repositories need a human browsable entrypoint over routed truth docs, but Truthmark's authority model stays Markdown-first. Keeping Portal as an optional installed workflow gives humans a committed static site without changing agent truth sources or normal completion workflows. - -## Non-Goals - -- 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 fixed Portal output directory - -## Maintenance Notes - -Update this document when Portal config, generated surfaces, write boundaries, default output/template behavior, or generated-site safety rules change. diff --git a/package-lock.json b/package-lock.json index 9797a57..2068cb9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "truthmark", - "version": "2.1.0", + "version": "2.2.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "truthmark", - "version": "2.1.0", + "version": "2.2.0", "license": "MIT", "dependencies": { "ajv": "^8.17.1", diff --git a/package.json b/package.json index 8085258..e2db9bc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "truthmark", - "version": "2.1.0", + "version": "2.2.0", "description": "Git-native, branch-scoped truth workflow installer for local AI coding agents.", "license": "MIT", "type": "module", diff --git a/src/agents/instructions.ts b/src/agents/instructions.ts index 4fb22cb..04a0e14 100644 --- a/src/agents/instructions.ts +++ b/src/agents/instructions.ts @@ -1,5 +1,8 @@ import type { TruthmarkConfig } from "../config/schema.js"; -import { defaultAgentConfig } from "./shared.js"; +import { + defaultAgentConfig, + renderLaneClassificationInstructions, +} from "./shared.js"; import { TRUTH_CHECK_EXPLICIT_INVOCATIONS } from "./truth-check.js"; import { TRUTH_STRUCTURE_EXPLICIT_INVOCATIONS } from "./truth-structure.js"; import { TRUTH_SYNC_EXPLICIT_INVOCATIONS } from "./truth-sync.js"; @@ -13,7 +16,9 @@ Use when area routing is missing, stale, broad, overloaded, catch-all, unrouteab Invocations: ${TRUTH_STRUCTURE_EXPLICIT_INVOCATIONS} 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. +Own topology pressure: split broad/catch-all routing by inferred product or engineering behavior ownership. +Own lane splits, decision relocation, and cross-lane relationship repair. +${renderLaneClassificationInstructions(config)} If the skill is unavailable, perform the same direct checkout workflow from any present config, route files, docs, and implementation.`; }; @@ -38,6 +43,8 @@ Delegate to a subagent only when the host supports subagent dispatch; the acting Inspect the current checkout directly. ImpactSet and ContextPack are optional derived context; they do not override checkout evidence or write boundaries. 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. +${renderLaneClassificationInstructions(config)} +Update engineering truth first after functional-code changes. Update product truth only from explicit product evidence, otherwise report product-lane review needed. 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.truthmark.paths.routesIndex}; ${config.truthmark.paths.routeAreasRoot}/) only when present; must not rewrite functional code. diff --git a/src/agents/prompts.ts b/src/agents/prompts.ts index f331cc7..42178d5 100644 --- a/src/agents/prompts.ts +++ b/src/agents/prompts.ts @@ -4,27 +4,51 @@ import { EVIDENCE_AUTHORITY_INSTRUCTIONS, REPOSITORY_INTELLIGENCE_INSTRUCTIONS, defaultAgentConfig, + renderBulletBlock, renderHierarchySummary, renderTruthDocOwnershipGateSection, - resolveTruthDocsRoot, + resolveEngineeringTruthRoot, + resolveProductTruthRoot, } from "./shared.js"; const renderMarkdownExample = (content: string): string => { return [`\`\`\`md`, content, `\`\`\``].join("\n"); }; +const renderTruthRealizeLaneClassificationRuleBlock = ( + config: TruthmarkConfig, +): string => { + const productTruthRoot = resolveProductTruthRoot(config); + const engineeringTruthRoot = resolveEngineeringTruthRoot(config); + + return renderBulletBlock( + [ + "classify the source truth docs and requested code change as product-lane, engineering-lane, both-lane, or ambiguous before writing code", + `read product truth under ${productTruthRoot} as requirements: product promises, boundaries, rationale, decisions, and success criteria`, + `read engineering truth under ${engineeringTruthRoot} as implementation context: source-backed current realization, contracts, architecture, workflows, operations, or tests`, + "do not write truth docs or truth routing; leave route YAML, realized_by, and realizes updates to Truth Structure, Truth Document, or finish-time Truth Sync", + "ambiguous lane ownership should block before code changes or route to Truth Structure", + ].join("\n"), + ); +}; + export const renderTruthRealizePrompt = ( config: TruthmarkConfig = defaultAgentConfig(), ): string => { - const truthDocsRoot = resolveTruthDocsRoot(config); + const productTruthRoot = resolveProductTruthRoot(config); + const engineeringTruthRoot = resolveEngineeringTruthRoot(config); return `### Manual Truth Realize Only run when the user explicitly asks to realize truth docs into code. This is a manual installed instruction or skill, not a dedicated CLI command. Invocations: OpenCode /skill truthmark-realize; Codex /truthmark-realize or $truthmark-realize; Claude Code /truthmark-realize; GitHub Copilot /truthmark-realize; Gemini CLI /truthmark:realize. Doc first: - read the updated truth docs plus any present Truthmark config, route files, relevant code, and tests -- ${EVIDENCE_AUTHORITY_INSTRUCTIONS} +- Evidence authority: +${renderBulletBlock(EVIDENCE_AUTHORITY_INSTRUCTIONS)} - ${REPOSITORY_INTELLIGENCE_INSTRUCTIONS} +- Lane classification: +${renderTruthRealizeLaneClassificationRuleBlock(config)} +- use product truth as requirements and engineering truth as current implementation context; do not redefine product truth inside engineering docs ${renderTruthDocOwnershipGateSection( "source truth docs before writing code", "if a source truth doc is broad, mixed-owner, index-like, unrouteable, stale, or conflicts with implementation evidence, block before writing code and recommend Truth Structure or Truth Document", @@ -32,11 +56,15 @@ ${renderTruthDocOwnershipGateSection( - write functional code only - do not edit truth docs or truth routing - implement only bounded, current truth claims from the source docs +- after code changes, run Truth Sync to update engineering truth and reconcile product truth only for current implemented behavior or explicit product truth changes ${renderHierarchySummary(config)} Report changed code files and verification steps: ${renderMarkdownExample( renderTruthRealizeCompletedReport({ - truthDocsUsed: [`${truthDocsRoot}/authentication/session-timeout.md`], + truthDocsUsed: [ + `${productTruthRoot}/capabilities/authentication-session.md`, + `${engineeringTruthRoot}/behaviors/authentication-session.md`, + ], codeUpdated: ["src/auth/session.ts"], verification: ["npm test -- auth"], }), diff --git a/src/agents/shared.ts b/src/agents/shared.ts index bad5709..38d2db6 100644 --- a/src/agents/shared.ts +++ b/src/agents/shared.ts @@ -1,8 +1,60 @@ import { createDefaultConfig } from "../config/defaults.js"; import type { TruthmarkConfig } from "../config/schema.js"; -import { resolveTruthDocsRoot } from "../truth/docs.js"; +import { + resolveEngineeringTruthRoot, + resolveProductTruthRoot, +} from "../truth/docs.js"; + +export { + resolveEngineeringTruthRoot, + resolveProductTruthRoot, + resolveTruthDocsRoot, +} from "../truth/docs.js"; + +const renderBulletLine = (line: string): string => { + const normalized = line.trim().replace(/^-\s*/u, ""); + return `- ${normalized}`; +}; + +export const renderBulletBlock = (lines: string, indent = " "): string => { + return lines + .split(/\n/u) + .map((line) => line.trim()) + .filter((line) => line.length > 0) + .map((line) => `${indent}${renderBulletLine(line)}`) + .join("\n"); +}; + +export const renderLaneClassificationRuleBlock = ( + config: TruthmarkConfig = defaultAgentConfig(), + indent = " ", +): string => { + const [, ...rules] = + renderLaneClassificationInstructions(config).split(/\n/u); + + return renderBulletBlock(rules.join("\n"), indent); +}; + +export const renderReadOnlyLaneClassificationRuleBlock = ( + config: TruthmarkConfig = defaultAgentConfig(), + indent = " ", +): string => { + const productTruthRoot = resolveProductTruthRoot(config); + const engineeringTruthRoot = resolveEngineeringTruthRoot(config); + + return renderBulletBlock( + [ + "classify the request or changed surface as product-lane, engineering-lane, both-lane, or ambiguous for reporting only", + `product-lane ownership belongs under ${productTruthRoot} and describes product promises, boundaries, rationale, decisions, and success criteria`, + `engineering-lane ownership belongs under ${engineeringTruthRoot} and describes source-backed current realization, contracts, architecture, workflows, operations, or tests`, + "both-lane ownership uses separate product and engineering docs cross-linked in route YAML with realized_by and realizes, not in doc frontmatter", + "ambiguous lane ownership should be reported as blocked or routed to Truth Structure", + LANE_INVARIANT, + ].join("\n"), + indent, + ); +}; -export { resolveTruthDocsRoot } from "../truth/docs.js"; export { renderAuditEvidenceCheckedSection, renderClaimEvidenceCheckedSection, @@ -11,9 +63,29 @@ export { export const DECISION_TRUTH_INSTRUCTIONS = [ "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.", + "Product decisions belong in product truth; engineering, architecture, contract, workflow, and operational decisions belong in engineering truth.", ].join("\n"); +export const LANE_INVARIANT = + "Do not make product docs a summary of engineering docs. Do not make engineering docs a detailed version of product docs. Product truth says what must be true and why. Engineering truth says how the repository currently realizes it."; + +export const renderLaneClassificationInstructions = ( + config: TruthmarkConfig = defaultAgentConfig(), +): string => { + const productTruthRoot = resolveProductTruthRoot(config); + const engineeringTruthRoot = resolveEngineeringTruthRoot(config); + + return [ + "Lane classification gate:", + "- before writing canonical truth docs, classify the request or change as product-lane, engineering-lane, both-lane, or ambiguous", + `- product-lane writes belong under ${productTruthRoot} and state product promises, boundaries, rationale, decisions, and success criteria`, + `- engineering-lane writes belong under ${engineeringTruthRoot} and state source-backed current realization, contracts, architecture, workflows, operations, or tests`, + "- both-lane work must write separate product and engineering docs and cross-link them in route YAML with realized_by and realizes, not in doc frontmatter", + "- ambiguous lane ownership must block or invoke Truth Structure instead of writing a mixed document", + `- ${LANE_INVARIANT}`, + ].join("\n"); +}; + export const EVIDENCE_AUTHORITY_INSTRUCTIONS = [ "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.", @@ -27,10 +99,10 @@ export const REPOSITORY_INTELLIGENCE_INSTRUCTIONS = [ export const FEATURE_DOC_TEMPLATE_INSTRUCTIONS = [ "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.", + "Supported kinds: product-capability, engineering-behavior, engineering-contract, engineering-architecture, engineering-workflow, engineering-operations, and engineering-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.", + "If the template is missing, use lane-specific sections: product truth says what must be true and why; engineering truth says how the repository currently realizes it.", "Teams may edit template files under the configured Truthmark templates root to define their local truth-doc standards.", ].join("\n"); @@ -48,12 +120,12 @@ export const renderTruthDocOwnershipGateSection = ( }; export const TRUTH_DOC_DECISION_RATIONALE_PRESERVATION_INSTRUCTIONS = [ - "Product Decisions/Rationale preservation gate:", - "- before any truth-doc split, restructure, or shape repair, inventory existing Product Decisions and Rationale sections in every source or touched truth doc", - "- preserve each current decision and rationale in the bounded owner doc it governs; when splitting, move it to the new owner doc rather than deleting it or leaving it in an index", + "Decision/Rationale preservation gate:", + "- before any truth-doc split, restructure, or shape repair, inventory existing Product Decisions, Engineering Decisions, and Rationale sections in every source or touched truth doc", + "- preserve each current decision and rationale in the correct product or engineering lane owner; when splitting, move it to the new owner doc rather than deleting it or leaving it in an index", "- 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", + "- after the edit, verify every touched truth doc keeps lane-appropriate decision/rationale sections and every pre-existing entry is preserved, moved, narrowed, removed with evidence, or blocked", ].join("\n"); export const renderTruthDocRestructureGateSection = (scope: string): string => { @@ -80,7 +152,7 @@ export const renderRouteFirstEvidenceGateSection = ( return [ "Evidence Gate:", `- route-first: map ${subject} to bounded route owners and primary canonical docs`, - "- review new or changed behavior-bearing claims only in touched docs, route ownership, Product Decisions, and Rationale", + "- review new or changed behavior-bearing claims only in touched docs, route ownership, lane-specific decisions, and rationale", "- support claims with primary checkout evidence: implementation, config, routing, generated templates, schemas, or contract definitions", "- tests/examples/canonical docs corroborate; they are not sole proof when implementation conflicts", "- remove, narrow, or block unsupported claims", @@ -91,7 +163,7 @@ export const renderRouteFirstEvidenceGateSection = ( export const renderTopologyEvidenceGateSection = (): string => { return [ "Evidence Gate:", - "- apply the Evidence Gate before finishing when Truth Structure writes routed docs, ownership claims, Product Decisions, or Rationale", + "- apply the Evidence Gate before finishing when Truth Structure writes routed docs, ownership claims, lane-specific decisions, or rationale", "- support ownership/behavior claims with topology or primary checkout evidence from layout, implementation boundaries, docs, config, route files, tests, templates, schemas, or contracts", "- tests/examples/canonical docs corroborate; remove, narrow, or block unsupported claims", ].join("\n"); @@ -121,7 +193,8 @@ export const renderCodexSubagentModeSection = ( ] : []; const readOnlyScope = writeAgents.length > 0 ? "for verification" : "only"; - const readOnlyWorkerLabel = writeAgents.length > 0 ? "read-only workers" : "workers"; + const readOnlyWorkerLabel = + writeAgents.length > 0 ? "read-only workers" : "workers"; return [ "Codex subagent mode:", @@ -140,7 +213,9 @@ export const renderOpenCodeSubagentModeSection = ( writeAgents: string[] = [], ): string => { const mentions = agents.map((agent) => `@${agent.replace(/_/gu, "-")}`); - const writeMentions = writeAgents.map((agent) => `@${agent.replace(/_/gu, "-")}`); + const writeMentions = writeAgents.map( + (agent) => `@${agent.replace(/_/gu, "-")}`, + ); const writeAgentLines = writeMentions.length > 0 ? [ @@ -151,7 +226,8 @@ export const renderOpenCodeSubagentModeSection = ( ] : []; const readOnlyScope = writeAgents.length > 0 ? "for verification" : "only"; - const readOnlyWorkerLabel = writeAgents.length > 0 ? "read-only workers" : "workers"; + const readOnlyWorkerLabel = + writeAgents.length > 0 ? "read-only workers" : "workers"; return [ "OpenCode subagent mode:", @@ -169,7 +245,9 @@ export const renderClaudeSubagentModeSection = ( parentRule: string, writeAgents: string[] = [], ): string => { - const mentions = agents.map((agent) => `${agent.replace(/_/gu, "-")} subagent`); + const mentions = agents.map( + (agent) => `${agent.replace(/_/gu, "-")} subagent`, + ); const writeMentions = writeAgents.map( (agent) => `${agent.replace(/_/gu, "-")} subagent`, ); @@ -203,7 +281,9 @@ export const renderCopilotCustomAgentModeSection = ( writeAgents: string[] = [], ): string => { const mentions = agents.map((agent) => `@${agent.replace(/_/gu, "-")}`); - const writeMentions = writeAgents.map((agent) => `@${agent.replace(/_/gu, "-")}`); + const writeMentions = writeAgents.map( + (agent) => `@${agent.replace(/_/gu, "-")}`, + ); const writeAgentLines = writeMentions.length > 0 ? [ @@ -234,7 +314,9 @@ export const renderGeminiSubagentModeSection = ( writeAgents: string[] = [], ): string => { const mentions = agents.map((agent) => `@${agent.replace(/_/gu, "-")}`); - const writeMentions = writeAgents.map((agent) => `@${agent.replace(/_/gu, "-")}`); + const writeMentions = writeAgents.map( + (agent) => `@${agent.replace(/_/gu, "-")}`, + ); const writeAgentLines = writeMentions.length > 0 ? [ @@ -264,13 +346,15 @@ export const defaultAgentConfig = (): TruthmarkConfig => { }; export const renderHierarchySummary = (config: TruthmarkConfig): string => { - const truthRoot = resolveTruthDocsRoot(config); + const productRoot = resolveProductTruthRoot(config); + const engineeringRoot = resolveEngineeringTruthRoot(config); return [ "Truthmark hierarchy hints:", "- Config, when present: .truthmark/config.yml", `- 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`, + `- Product truth docs, when present: ${productRoot}/**/*.md`, + `- Engineering truth docs, when present: ${engineeringRoot}/**/*.md`, ].join("\n"); }; diff --git a/src/agents/truth-check.ts b/src/agents/truth-check.ts index 907728c..4992b32 100644 --- a/src/agents/truth-check.ts +++ b/src/agents/truth-check.ts @@ -9,7 +9,9 @@ import { DECISION_TRUTH_INSTRUCTIONS, EVIDENCE_AUTHORITY_INSTRUCTIONS, defaultAgentConfig, + renderBulletBlock, renderHierarchySummary, + renderReadOnlyLaneClassificationRuleBlock, } from "./shared.js"; import { TRUTHMARK_VERSION } from "../version.js"; import { getTruthmarkWorkflow } from "./workflow-manifest.js"; @@ -21,7 +23,7 @@ const renderMarkdownExample = (content: string): string => { export const TRUTH_CHECK_EXPLICIT_INVOCATIONS = "OpenCode /skill truthmark-check; Codex /truthmark-check or $truthmark-check; Claude Code /truthmark-check; GitHub Copilot /truthmark-check; Gemini CLI /truthmark:check."; -const renderTruthCheckReportExample = ( +export const renderTruthCheckReportExample = ( config: TruthmarkConfig = defaultAgentConfig(), ): string => { const rootRouteIndex = config.truthmark.paths.routesIndex; @@ -37,19 +39,20 @@ Fixes suggested: - none ${renderAuditEvidenceCheckedSection([ - { - finding: "The root route index is present and maps repository truth owners.", - evidence: [`${rootRouteIndex}:1`], - suggestedFix: "none", - confidence: "high", - }, - ])} + { + finding: + "The root route index is present and maps repository truth owners.", + evidence: [`${rootRouteIndex}:1`], + suggestedFix: "none", + confidence: "high", + }, +])} Validation: - truthmark check`; }; -export const renderTruthCheckSkillBody = ( +export const renderTruthCheckProcedureBody = ( config: TruthmarkConfig = defaultAgentConfig(), options: { includeClaudeSubagentMode?: boolean; @@ -85,15 +88,7 @@ export const renderTruthCheckSkillBody = ( : ""; const subagentMode = `${claudeSubagentMode}${codexSubagentMode}${copilotCustomAgentMode}${openCodeSubagentMode}`; - return `--- -name: truthmark-check -description: ${workflow.description} -argument-hint: Optional area, doc path, or audit focus -user-invocable: true -truthmark-version: ${TRUTHMARK_VERSION} ---- - -# Truthmark Check + return `# Truthmark Check Use this skill to audit repository truth health. @@ -102,12 +97,25 @@ Invocations: ${TRUTH_CHECK_EXPLICIT_INVOCATIONS} 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.truthmark.paths.routesIndex} and relevant child route files under ${config.truthmark.paths.routeAreasRoot}/ when they exist +- Evidence authority: +${renderBulletBlock(EVIDENCE_AUTHORITY_INSTRUCTIONS)} +- Lane classification: +${renderReadOnlyLaneClassificationRuleBlock(config)} - check that current docs describe current code rather than historical plans +- keep lane and cross-lane checks route-first and bounded: + - for a narrow audit, inspect only the routed area and directly linked counterpart docs + - for root-wide truth health, first build a cheap route-map/index from route files, then inspect only mismatches and linked leaves + - inspect product counterparts for engineering docs only when route YAML claims a product relationship, or when the user explicitly asks for user-visible product coverage +- check lane root/kind alignment for product truth under ${config.truthmark.paths.productTruthRoot} and engineering truth under ${config.truthmark.paths.engineeringTruthRoot} +- check route YAML cross-lane realized_by and realizes links for existence and lane compatibility +- report missing product links for user-visible engineering docs only as a second-pass review diagnostic, not as default full-document reads or hard errors +- check product docs do not contain engineering execution flow, generated file inventories, or CLI envelope mechanics +- check engineering docs do not contain product promises, product rationale, or Product Decisions sections +- never judge whether a product decision is commercially correct, valuable, prioritized, or desirable - 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 -- check that canonical behavior docs keep active Product Decisions and Rationale sections +- check that canonical docs keep lane-appropriate decisions and rationale sections - optionally run truthmark check when local tooling is available - must not require the truthmark binary; direct inspection is always valid - report issues and suggested fixes without silently rewriting unrelated files @@ -115,8 +123,29 @@ Truth Check is agent-led: ${renderAuditEvidenceGateSection()} ${subagentMode}${renderHierarchySummary(config)} -${DECISION_TRUTH_INSTRUCTIONS} +${DECISION_TRUTH_INSTRUCTIONS}`; +}; +export const renderTruthCheckSkillBody = ( + config: TruthmarkConfig = defaultAgentConfig(), + options: { + includeClaudeSubagentMode?: boolean; + includeCodexSubagentMode?: boolean; + includeCopilotCustomAgentMode?: boolean; + includeOpenCodeSubagentMode?: boolean; + } = {}, +): string => { + const workflow = getTruthmarkWorkflow("truthmark-check"); + + return `--- +name: truthmark-check +description: ${workflow.description} +argument-hint: Optional area, doc path, or audit focus +user-invocable: true +truthmark-version: ${TRUTHMARK_VERSION} +--- + +${renderTruthCheckProcedureBody(config, options)} Report completion in this shape: ${renderMarkdownExample(renderTruthCheckReportExample(config))}`; diff --git a/src/agents/truth-document.ts b/src/agents/truth-document.ts index 677b6f8..5255f8b 100644 --- a/src/agents/truth-document.ts +++ b/src/agents/truth-document.ts @@ -7,18 +7,21 @@ import { REPOSITORY_INTELLIGENCE_INSTRUCTIONS, TRUTH_DOC_DECISION_RATIONALE_PRESERVATION_INSTRUCTIONS, defaultAgentConfig, + renderBulletBlock, + renderLaneClassificationRuleBlock, + renderClaimEvidenceCheckedSection, renderClaudeSubagentModeSection, renderCodexSubagentModeSection, renderCopilotCustomAgentModeSection, renderOpenCodeSubagentModeSection, - renderClaimEvidenceCheckedSection, renderRouteFirstEvidenceGateSection, renderHierarchySummary, renderTruthDocOwnershipGateSection, renderTruthDocRestructureGateSection, - resolveTruthDocsRoot, + resolveEngineeringTruthRoot, } from "./shared.js"; import { TRUTHMARK_VERSION } from "../version.js"; + import { getTruthmarkWorkflow } from "./workflow-manifest.js"; const renderMarkdownExample = (content: string): string => { @@ -31,7 +34,7 @@ export const TRUTH_DOCUMENT_EXPLICIT_INVOCATIONS = export const renderTruthDocumentReportExample = ( config: TruthmarkConfig = defaultAgentConfig(), ): string => { - const truthDocsRoot = resolveTruthDocsRoot(config); + const engineeringTruthRoot = resolveEngineeringTruthRoot(config); const helperScripts = ["validate-write-lease: skipped, no write lease used"]; return `Truth Document: completed @@ -43,13 +46,13 @@ Ownership reviewed: - ${config.truthmark.paths.routesIndex} Truth docs created: -- ${truthDocsRoot}/contracts.md +- ${engineeringTruthRoot}/contracts/routing.md Truth docs updated: -- ${truthDocsRoot}/check-diagnostics.md +- ${engineeringTruthRoot}/behaviors/check-diagnostics.md Truth docs restructured: -- ${truthDocsRoot}/check-diagnostics.md +- ${engineeringTruthRoot}/behaviors/check-diagnostics.md Routing updated: - ${config.truthmark.paths.routesIndex} @@ -72,7 +75,7 @@ Notes: - Documented routing and behavior from route handlers and tests.`; }; -export const renderTruthDocumentSkillBody = ( +export const renderTruthDocumentProcedureBody = ( config: TruthmarkConfig = defaultAgentConfig(), options: { includeClaudeSubagentMode?: boolean; @@ -112,15 +115,7 @@ export const renderTruthDocumentSkillBody = ( : ""; const subagentMode = `${claudeSubagentMode}${codexSubagentMode}${copilotCustomAgentMode}${openCodeSubagentMode}`; - return `--- -name: truthmark-document -description: ${workflow.description} -argument-hint: Optional implemented behavior, API endpoint, route, controller, package, or truth-doc area to document -user-invocable: true -truthmark-version: ${TRUTHMARK_VERSION} ---- - -# Truthmark Document + return `# Truthmark Document Use this skill to document existing implemented behavior when no functional-code changes are required for the task. Invocations: ${TRUTH_DOCUMENT_EXPLICIT_INVOCATIONS} @@ -129,7 +124,10 @@ Truth Document is manual and implementation-first: - run only when the user explicitly asks to generate or update truth docs for existing behavior, or when Truth Sync, Truth Check, or Truth Structure reports implemented behavior that lacks canonical truth docs - 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} +- Evidence authority: +${renderBulletBlock(EVIDENCE_AUTHORITY_INSTRUCTIONS)} +- Lane classification: +${renderLaneClassificationRuleBlock(config)} - document current implemented behavior; do not invent future behavior or planned endpoints - may write canonical truth docs and ${config.truthmark.paths.routesIndex} or relevant child route files only - must not write functional code @@ -137,7 +135,10 @@ Truth Document is manual and implementation-first: - block and recommend Truth Structure when routing repair is unsafe, ambiguous, or outside the task boundary - keep feature README.md files as indexes rather than truth-document targets - create or update bounded leaf truth docs when behavior does not fit an existing leaf doc -- keep behavior truth docs behavior-oriented, not endpoint-oriented, unless the endpoint itself is the behavior boundary +- write product capability/boundary truth under ${config.truthmark.paths.productTruthRoot} when documenting product promise, boundary, rationale, or user/stakeholder value +- write engineering truth under ${config.truthmark.paths.engineeringTruthRoot} when documenting implementation behavior, contracts, architecture, workflows, operations, or tests +- for both-lane documentation requests, write separate product and engineering docs and cross-link them in route YAML with realized_by and realizes, not in doc frontmatter +- keep engineering behavior truth behavior-oriented, not endpoint-oriented, unless the endpoint itself is the behavior boundary - keep API endpoint details in the nearest contract truth doc when such a doc owns the API contract - preserve unrelated authored content ${renderTruthDocOwnershipGateSection( @@ -167,8 +168,29 @@ Parent post-document verification: - verify only truth docs and leased truth routing files changed during document work - block on functional code, generated host surfaces, or unrelated diffs caused by document work - for each write lease, validate the worker report against the actual worker diff, allowedWrites, forbiddenWrites, identity fields, filesChanged, offLeaseChanges, blockers, and required report fields before accepting it -- verify the final report records ownership review, structure requirement, restructure, routing update, or blocked reason when applicable +- verify the final report records ownership review, structure requirement, restructure, routing update, or blocked reason when applicable`; +}; +export const renderTruthDocumentSkillBody = ( + config: TruthmarkConfig = defaultAgentConfig(), + options: { + includeClaudeSubagentMode?: boolean; + includeCodexSubagentMode?: boolean; + includeCopilotCustomAgentMode?: boolean; + includeOpenCodeSubagentMode?: boolean; + } = {}, +): string => { + const workflow = getTruthmarkWorkflow("truthmark-document"); + + return `--- +name: truthmark-document +description: ${workflow.description} +argument-hint: Optional implemented behavior, API endpoint, route, controller, package, or truth-doc area to document +user-invocable: true +truthmark-version: ${TRUTHMARK_VERSION} +--- + +${renderTruthDocumentProcedureBody(config, options)} Report completion in this shape: ${renderMarkdownExample(renderTruthDocumentReportExample(config))}`; }; diff --git a/src/agents/truth-preview.ts b/src/agents/truth-preview.ts index 9505e07..acf4bbb 100644 --- a/src/agents/truth-preview.ts +++ b/src/agents/truth-preview.ts @@ -2,8 +2,9 @@ import type { TruthmarkConfig } from "../config/schema.js"; import { EVIDENCE_AUTHORITY_INSTRUCTIONS, defaultAgentConfig, + renderBulletBlock, renderHierarchySummary, - resolveTruthDocsRoot, + renderReadOnlyLaneClassificationRuleBlock, } from "./shared.js"; import { TRUTHMARK_VERSION } from "../version.js"; import { getTruthmarkWorkflow } from "./workflow-manifest.js"; @@ -15,11 +16,9 @@ const renderMarkdownExample = (content: string): string => { export const TRUTH_PREVIEW_EXPLICIT_INVOCATIONS = "OpenCode /skill truthmark-preview; Codex /truthmark-preview or $truthmark-preview; Claude Code /truthmark-preview; GitHub Copilot /truthmark-preview; Gemini CLI /truthmark:preview."; -const renderTruthPreviewReportExample = ( +export const renderTruthPreviewReportExample = ( config: TruthmarkConfig = defaultAgentConfig(), ): string => { - const truthDocsRoot = resolveTruthDocsRoot(config); - return `Truth Preview: completed Requested outcome: @@ -35,14 +34,16 @@ Why this workflow: Likely route owner: - route file: ${config.truthmark.paths.routesIndex} -- truth doc: ${truthDocsRoot}/example.md +- likely lane impact: engineering-lane +- product target docs: none identified +- engineering target docs: ${config.truthmark.paths.engineeringTruthRoot}/behaviors/example.md - confidence: medium Expected write classes: - truth docs Expected target files: -- ${truthDocsRoot}/example.md +- ${config.truthmark.paths.engineeringTruthRoot}/behaviors/example.md Suggested subagent use: - read-only verifiers: truth_route_auditor @@ -56,20 +57,10 @@ Handoff: - Run the selected Truthmark workflow after user approval.`; }; -export const renderTruthPreviewSkillBody = ( +export const renderTruthPreviewProcedureBody = ( config: TruthmarkConfig = defaultAgentConfig(), ): string => { - const workflow = getTruthmarkWorkflow("truthmark-preview"); - - return `--- -name: truthmark-preview -description: ${workflow.description} -argument-hint: Optional requested outcome, code area, doc path, or routing question -user-invocable: true -truthmark-version: ${TRUTHMARK_VERSION} ---- - -Use this skill only when the user explicitly asks to preview Truthmark routing or workflow choice before edits. + return `Use this skill only when the user explicitly asks to preview Truthmark routing or workflow choice before edits. Invocations: ${TRUTH_PREVIEW_EXPLICIT_INVOCATIONS} @@ -77,15 +68,19 @@ Truth Preview is read-only. Its report is intended, not authorized. Purpose: - preview the likely Truthmark workflow, route owner, target files, expected write classes, suggested subagent use, and blocking ambiguity before edits happen +- report likely product lane impact, engineering lane impact, target docs, and ambiguity before edits - hand off to the selected workflow after user approval - keep the selector thin so agents can avoid loading or acting through heavier workflows prematurely Read: - .truthmark/config.yml, only when present -- ${config.truthmark.paths.routesIndex}, only when present -- relevant child route files under ${config.truthmark.paths.routeAreasRoot}/, only when present +- ${config.truthmark.paths.routesIndex}, first, only when present +- relevant child route files under ${config.truthmark.paths.routeAreasRoot}/ for the selected scope or changed paths, only when present - relevant truth docs and implementation files needed to preview ownership -- ${EVIDENCE_AUTHORITY_INSTRUCTIONS} +- Evidence authority: +${renderBulletBlock(EVIDENCE_AUTHORITY_INSTRUCTIONS)} +- Lane classification: +${renderReadOnlyLaneClassificationRuleBlock(config)} Do not: - must not edit files @@ -102,8 +97,23 @@ Suggested subagent use: - write workers: none - leases needed: none -${renderHierarchySummary(config)} +${renderHierarchySummary(config)}`; +}; +export const renderTruthPreviewSkillBody = ( + config: TruthmarkConfig = defaultAgentConfig(), +): string => { + const workflow = getTruthmarkWorkflow("truthmark-preview"); + + return `--- +name: truthmark-preview +description: ${workflow.description} +argument-hint: Optional requested outcome, code area, doc path, or routing question +user-invocable: true +truthmark-version: ${TRUTHMARK_VERSION} +--- + +${renderTruthPreviewProcedureBody(config)} Report completion in this shape: ${renderMarkdownExample(renderTruthPreviewReportExample(config))}`; }; diff --git a/src/agents/truth-structure.ts b/src/agents/truth-structure.ts index 7eb5830..a9205c3 100644 --- a/src/agents/truth-structure.ts +++ b/src/agents/truth-structure.ts @@ -6,16 +6,21 @@ import { FEATURE_DOC_TEMPLATE_INSTRUCTIONS, TRUTH_DOC_DECISION_RATIONALE_PRESERVATION_INSTRUCTIONS, defaultAgentConfig, + renderBulletBlock, renderClaudeSubagentModeSection, renderClaimEvidenceCheckedSection, renderCopilotCustomAgentModeSection, renderHierarchySummary, + renderLaneClassificationRuleBlock, renderTopologyEvidenceGateSection, renderTruthDocOwnershipGateSection, renderTruthDocRestructureGateSection, - resolveTruthDocsRoot, + resolveEngineeringTruthRoot, + resolveProductTruthRoot, } from "./shared.js"; + import { TRUTHMARK_VERSION } from "../version.js"; + import { getTruthmarkWorkflow } from "./workflow-manifest.js"; const renderMarkdownExample = (content: string): string => { @@ -28,12 +33,14 @@ export const TRUTH_STRUCTURE_EXPLICIT_INVOCATIONS = export const renderTruthStructureReportExample = ( config: TruthmarkConfig = defaultAgentConfig(), ): string => { - const truthDocsRoot = resolveTruthDocsRoot(config); + const productTruthRoot = resolveProductTruthRoot(config); + const engineeringTruthRoot = resolveEngineeringTruthRoot(config); return `Truth Structure: completed Topology reviewed: - controllers: src/auth/** -- docs root: ${truthDocsRoot} +- product docs root: ${productTruthRoot} +- engineering docs root: ${engineeringTruthRoot} - route files: ${config.truthmark.paths.routesIndex} Areas reviewed: - src/auth/** @@ -42,35 +49,39 @@ Routing updated: Initial truth boundary: - Area: Authentication - Code: src/auth/** -- Truth owner: ${truthDocsRoot}/authentication/session.md +- Product owner: ${productTruthRoot}/capabilities/authentication-session.md +- Engineering owner: ${engineeringTruthRoot}/behaviors/authentication-session.md - Scope: session behavior only Truth docs created: -- ${truthDocsRoot}/authentication/session.md +- ${productTruthRoot}/capabilities/authentication-session.md +- ${engineeringTruthRoot}/behaviors/authentication-session.md Truth docs split: -- ${truthDocsRoot}/authentication/README.md -> ${truthDocsRoot}/authentication/session.md +- docs/truthmark/truth/authentication/README.md -> ${productTruthRoot}/capabilities/authentication-session.md and ${engineeringTruthRoot}/behaviors/authentication-session.md Truth docs restructured: -- ${truthDocsRoot}/authentication/README.md +- docs/truthmark/truth/authentication/README.md ${renderClaimEvidenceCheckedSection([ - { - claim: "Session behavior belongs to a dedicated Authentication truth owner.", - evidence: ["src/auth/**", `${config.truthmark.paths.routesIndex}:7`], - result: "supported", - }, - ])} + { + claim: + "Session behavior belongs to a dedicated Authentication truth owner.", + evidence: ["src/auth/**", `${config.truthmark.paths.routesIndex}:7`], + result: "supported", + }, +])} Topology decisions: - Added an Authentication area because session behavior has a distinct code surface and truth owner. Notes: - Added an Authentication area for session behavior.`; }; -export const renderTruthStructureSkillBody = ( +export const renderTruthStructureProcedureBody = ( config: TruthmarkConfig = defaultAgentConfig(), options: { includeClaudeSubagentMode?: boolean; includeCopilotCustomAgentMode?: boolean; } = {}, ): string => { - const truthDocsRoot = resolveTruthDocsRoot(config); + const productTruthRoot = resolveProductTruthRoot(config); + const engineeringTruthRoot = resolveEngineeringTruthRoot(config); const workflow = getTruthmarkWorkflow("truthmark-structure"); const claudeSubagentMode = options.includeClaudeSubagentMode ? `${renderClaudeSubagentModeSection( @@ -86,30 +97,26 @@ export const renderTruthStructureSkillBody = ( : ""; const subagentMode = `${claudeSubagentMode}${copilotCustomAgentMode}`; - return `--- -name: truthmark-structure -description: ${workflow.description} -argument-hint: Optional area, directory, or routing concern -user-invocable: true -truthmark-version: ${TRUTHMARK_VERSION} ---- - -Use this skill to design or repair Truthmark area structure. + return `Use this skill to design or repair Truthmark area structure. 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} +- Evidence authority: +${renderBulletBlock(EVIDENCE_AUTHORITY_INSTRUCTIONS)} +- Lane classification: +${renderLaneClassificationRuleBlock(config)} - 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.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. +- Starter truth docs must use closed YAML frontmatter bounded by opening and closing --- lines; include status, truth_kind, and last_reviewed inside that frontmatter. Put source references in the final ## Source References section, not in frontmatter. +- Starter truth docs must use lane-specific templates and keep product and engineering truth in separate files. ${subagentMode} ${FEATURE_DOC_TEMPLATE_INSTRUCTIONS} -- use ${truthDocsRoot}/** for current truth destinations +- use ${productTruthRoot}/** for product truth destinations +- use ${engineeringTruthRoot}/** for engineering 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 +- keep active Product Decisions in product truth and Engineering Decisions in engineering truth - preserve unrelated authored content ## New area setup Use when a user asks to onboard a new code area into Truthmark, a new package, controller, domain, or product area lacks bounded truth ownership, or a new product area needs routing and starter truth docs. @@ -127,7 +134,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 ${truthDocsRoot}. Treat the configured truth root as a managed semantic root. +Truth Structure owns documentation topology, lane splits, decision relocation, and relationship repair. Do not depend on humans to manually organize ${productTruthRoot} or ${engineeringTruthRoot}. Treat both configured lane roots as managed semantic roots. 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. ${renderTruthDocOwnershipGateSection( @@ -139,7 +146,7 @@ Topology pressure signals: - one area maps broad code such as src/**, app/**, server/**, services/**, or packages/** - one area maps multiple unrelated controllers, route groups, services, or bounded contexts - one truth doc owns unrelated behaviors or unrelated endpoint families -- the configured truth root has many direct non-index docs +- either configured lane 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.truthmark.paths.routeAreasRoot}/** @@ -152,9 +159,10 @@ 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.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 +- create engineering behavior truth docs under ${engineeringTruthRoot} only when behavior lacks a current doc +- create product truth docs under ${productTruthRoot} only when product promise, boundary, rationale, or user-visible capability truth is in scope - README.md files are indexes, not Truth Sync targets -- prefer bounded leaf truth docs at //.md +- prefer bounded product docs under product/capabilities or product/decisions and engineering docs under engineering//.md - keep behavior truth docs behavior-oriented, not endpoint-oriented - keep API endpoint details in the nearest contract truth doc when such a doc exists - update routing so future Truth Sync can target small docs @@ -165,15 +173,35 @@ ${renderTruthDocRestructureGateSection( )} ${renderTopologyEvidenceGateSection()} ${ARCHITECTURE_DOC_BOUNDARY_INSTRUCTIONS} -- Do not finish topology repair with routed canonical current-truth docs missing Product Decisions or Rationale sections. -- If an existing canonical doc lacks either section, add the missing heading beside Current Behavior with a concise current-state placeholder or active decision. +- Do not finish topology repair with mixed product/engineering authority in a single canonical truth doc. +- If an existing canonical doc has wrong-lane sections, split or move them into the correct product or engineering lane. Portable fallback: - If this skill surface is unavailable, perform the same workflow directly from committed repository files. - Do not require the truthmark CLI. - Inspect .truthmark/config.yml and configured route files only when they exist; then inspect canonical docs and representative implementation code. - Use a subagent only when the host supports that pattern; otherwise perform the topology repair inline. ${renderHierarchySummary(config)} -${DECISION_TRUTH_INSTRUCTIONS} +${DECISION_TRUTH_INSTRUCTIONS}`; +}; + +export const renderTruthStructureSkillBody = ( + config: TruthmarkConfig = defaultAgentConfig(), + options: { + includeClaudeSubagentMode?: boolean; + includeCopilotCustomAgentMode?: boolean; + } = {}, +): string => { + const workflow = getTruthmarkWorkflow("truthmark-structure"); + + return `--- +name: truthmark-structure +description: ${workflow.description} +argument-hint: Optional area, directory, or routing concern +user-invocable: true +truthmark-version: ${TRUTHMARK_VERSION} +--- + +${renderTruthStructureProcedureBody(config, options)} Report completion in this shape: ${renderMarkdownExample(renderTruthStructureReportExample(config))}`; }; diff --git a/src/agents/truth-sync.ts b/src/agents/truth-sync.ts index 36b1f70..73a3848 100644 --- a/src/agents/truth-sync.ts +++ b/src/agents/truth-sync.ts @@ -13,9 +13,11 @@ import { renderOpenCodeSubagentModeSection, renderRouteFirstEvidenceGateSection, renderHierarchySummary, + renderBulletBlock, + renderLaneClassificationRuleBlock, renderTruthDocOwnershipGateSection, renderTruthDocRestructureGateSection, - resolveTruthDocsRoot, + resolveEngineeringTruthRoot, } from "./shared.js"; import { renderTruthSyncBlockedReport, @@ -40,6 +42,8 @@ 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.truthmark.paths.routesIndex}; ${config.truthmark.paths.routeAreasRoot}/) only when they exist; then inspect canonical truth docs directly +- classify lane impact as product-lane, engineering-lane, both-lane, or ambiguous before writing +- update engineering truth first after functional-code changes; update product truth only from explicit product evidence or report product-lane review needed - 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 @@ -62,7 +66,7 @@ Return result in this shape: - manualReviewFiles: string[] required when status is blocked; at least one file`; }; -export const renderTruthSyncSkillBody = ( +export const renderTruthSyncProcedureBody = ( config: TruthmarkConfig = defaultAgentConfig(), options: { includeClaudeSubagentMode?: boolean; @@ -71,9 +75,7 @@ export const renderTruthSyncSkillBody = ( includeOpenCodeSubagentMode?: boolean; } = {}, ): string => { - const truthDocsRoot = resolveTruthDocsRoot(config); const workflow = getTruthmarkWorkflow("truthmark-sync"); - const helperScripts = ["validate-write-lease: skipped, no write lease used"]; const claudeSubagentMode = options.includeClaudeSubagentMode ? `${renderClaudeSubagentModeSection( workflow.subagents ?? [], @@ -104,15 +106,7 @@ export const renderTruthSyncSkillBody = ( : ""; const subagentMode = `${claudeSubagentMode}${codexSubagentMode}${copilotCustomAgentMode}${openCodeSubagentMode}`; - return `--- -name: truthmark-sync -description: ${workflow.description} -argument-hint: Optional changed-code area, truth-doc area, or sync focus -user-invocable: true -truthmark-version: ${TRUTHMARK_VERSION} ---- - -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. + return `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: ${TRUTH_SYNC_EXPLICIT_INVOCATIONS} Explicit invocation runs immediately. Later functional-code changes reopen the finish-time requirement, and an earlier explicit run satisfies the finish gate only if no later functional-code changes occur. Skip when changes are documentation-only, formatting-only, clearly behavior-preserving renames with no truth impact, when no Truthmark config exists yet, or when there are no functional code changes. @@ -120,9 +114,13 @@ Parent workflow: 1. Inspect git status, staged changes, unstaged changes, and untracked files directly. 2. Inspect .truthmark/config.yml and configured route files only when they exist; then inspect relevant canonical docs. 3. Identify functional-code changes and the nearest truth docs or routing repairs. -4. ${EVIDENCE_AUTHORITY_INSTRUCTIONS} -5. Code verification is parent-owned: follow repository instructions and task context, and report what ran or why it did not run. -6. Dispatch bounded Truth Sync workers only when the host supports subagent dispatch and the acting agent chooses that path; otherwise execute the same sync task inline. +4. Evidence authority: +${renderBulletBlock(EVIDENCE_AUTHORITY_INSTRUCTIONS)} +5. Lane classification gate: +${renderLaneClassificationRuleBlock(config)} +6. Update engineering truth first after code changes. Update product truth only when implemented user-visible product promise or capability boundary changed and explicit source/user evidence supports it; otherwise report product-lane review needed. +7. Code verification is parent-owned: follow repository instructions and task context, and report what ran or why it did not run. +8. Dispatch bounded Truth Sync workers only when the host supports subagent dispatch and the acting agent chooses that path; otherwise execute the same sync task inline. ${subagentMode}Topology quality gate: - before updating truth docs, verify the changed code resolves to a specific behavior-owned area and bounded truth owner - if routing is missing, stale, broad, overloaded, catch-all route only, or cannot map changed code to a bounded truth owner, do not create another generic truth doc @@ -132,6 +130,7 @@ ${subagentMode}Topology quality gate: - README.md files are indexes, not Truth Sync targets - must not append behavior details to a README.md index - create or update a bounded leaf truth doc when behavior changes do not fit an existing leaf doc +- write engineering truth under ${config.truthmark.paths.engineeringTruthRoot}; product truth updates under ${config.truthmark.paths.productTruthRoot} are allowed only for explicit current product behavior changes ${renderTruthDocOwnershipGateSection( "changed functional files and impacted truth docs", "if an impacted doc is broad, mixed-owner, index-like, or the update spans independent behavior owners, run Truth Structure before syncing when safe and in scope; otherwise block and recommend Truth Structure", @@ -151,7 +150,7 @@ Optional validation tooling: - you may run truthmark check when local tooling is available - do not require the truthmark binary; direct checkout inspection is the canonical path - optional validation must not replace agent judgment about docs and routing -- update Product Decisions and Rationale when a behavior change comes from a decision change +- update Product Decisions only in product truth and Engineering Decisions only in engineering truth when evidence supports the lane-specific decision change Helper status reporting: - Validate the report body before adding this validator's own success status; the body may omit \`validate-sync-report\` while validation is pending. - After \`truthmark validate sync-report --json\` returns \`data.validation.ok: true\`, append or update \`validate-sync-report: ran, passed\` in the final report. @@ -168,13 +167,37 @@ Parent post-sync verification: - validate the final report against the structured Truth Sync report contract, including Claim, indented Evidence, and Result values supported, narrowed, removed, or blocked under Evidence checked - verify the updated docs correspond to the reviewed changed-code surface - verify the final report records ownership review, structure requirement, split, restructure, or blocked reason when the ownership gate fired -- blocked outcomes must preserve the working tree as-is: no rollback, no post-block cleanup edits, and manual-review reporting of any remaining files +- blocked outcomes must preserve the working tree as-is: no rollback, no post-block cleanup edits, and manual-review reporting of any remaining files`; +}; + +export const renderTruthSyncSkillBody = ( + config: TruthmarkConfig = defaultAgentConfig(), + options: { + includeClaudeSubagentMode?: boolean; + includeCodexSubagentMode?: boolean; + includeCopilotCustomAgentMode?: boolean; + includeOpenCodeSubagentMode?: boolean; + } = {}, +): string => { + const engineeringTruthRoot = resolveEngineeringTruthRoot(config); + const workflow = getTruthmarkWorkflow("truthmark-sync"); + const helperScripts = ["validate-write-lease: skipped, no write lease used"]; + + return `--- +name: truthmark-sync +description: ${workflow.description} +argument-hint: Optional changed-code area, truth-doc area, or sync focus +user-invocable: true +truthmark-version: ${TRUTHMARK_VERSION} +--- + +${renderTruthSyncProcedureBody(config, options)} Report completion in this shape: ${renderMarkdownExample( renderTruthSyncCompletedReport({ changedCode: ["src/auth/session.ts"], ownershipReviewed: [config.truthmark.paths.routesIndex], - truthDocsUpdated: [`${truthDocsRoot}/repository/overview.md`], + truthDocsUpdated: [`${engineeringTruthRoot}/repository/overview.md`], evidenceChecked: [ { claim: "Session timeout behavior is documented in the mapped repository truth doc.", diff --git a/src/agents/truthmark-portal.ts b/src/agents/truthmark-portal.ts index feee21b..609acbb 100644 --- a/src/agents/truthmark-portal.ts +++ b/src/agents/truthmark-portal.ts @@ -6,22 +6,13 @@ import { getTruthmarkWorkflow } from "./workflow-manifest.js"; export const TRUTHMARK_PORTAL_EXPLICIT_INVOCATIONS = "OpenCode /skill truthmark-portal; Codex /truthmark-portal or $truthmark-portal; Claude Code /truthmark-portal; GitHub Copilot /truthmark-portal; Gemini CLI /truthmark:portal."; -export const renderTruthmarkPortalSkillBody = ( +export const renderTruthmarkPortalProcedureBody = ( config: TruthmarkConfig = defaultAgentConfig(), ): string => { - const workflow = getTruthmarkWorkflow("truthmark-portal"); const output = config.truthmark.paths.portalOutput; const template = config.truthmark.paths.portalTemplate; - return `--- -name: truthmark-portal -description: ${workflow.description} -argument-hint: Optional portal generation focus -user-invocable: true -truthmark-version: ${TRUTHMARK_VERSION} ---- - -# Truthmark Portal + return `# Truthmark Portal Truthmark Portal is a manual-only presentation workflow. It is never a completion gate, never Truth Sync, and runs only when the user explicitly asks to generate, refresh, or update the committed static HTML Portal. @@ -52,8 +43,24 @@ Workflow: 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. 7. Validate entry page, links where practical, provenance/disclaimers, local-only assets, and that metadata remains under ${output}/assets. -${renderHierarchySummary(config)} +${renderHierarchySummary(config)}`; +}; +export const renderTruthmarkPortalSkillBody = ( + config: TruthmarkConfig = defaultAgentConfig(), +): string => { + const workflow = getTruthmarkWorkflow("truthmark-portal"); + const output = config.truthmark.paths.portalOutput; + + return `--- +name: truthmark-portal +description: ${workflow.description} +argument-hint: Optional portal generation focus +user-invocable: true +truthmark-version: ${TRUTHMARK_VERSION} +--- + +${renderTruthmarkPortalProcedureBody(config)} Report completion in this shape: \`\`\`md diff --git a/src/agents/workflow-manifest.ts b/src/agents/workflow-manifest.ts index 3faaa86..b544955 100644 --- a/src/agents/workflow-manifest.ts +++ b/src/agents/workflow-manifest.ts @@ -124,7 +124,8 @@ export const TRUTHMARK_WORKFLOW_MANIFEST = { requiredGates: [ "topology quality", "truth-doc ownership", - "Product Decisions/Rationale preservation", + "lane classification", + "Decision/Rationale preservation", "truth-doc shape repair when restructuring", "Evidence Gate", ], @@ -169,7 +170,9 @@ export const TRUTHMARK_WORKFLOW_MANIFEST = { ], requiredGates: [ "truth-doc ownership", - "Product Decisions/Rationale preservation", + "lane classification", + "Decision/Rationale preservation", + "lane split and relationship repair", "truth-doc shape repair when restructuring", "Evidence Gate", ], @@ -212,7 +215,8 @@ export const TRUTHMARK_WORKFLOW_MANIFEST = { ], requiredGates: [ "truth-doc ownership", - "Product Decisions/Rationale preservation", + "lane classification", + "Decision/Rationale preservation", "Evidence Gate", "truth-doc shape repair when restructuring", ], @@ -249,10 +253,10 @@ export const TRUTHMARK_WORKFLOW_MANIFEST = { "truth audit", ], forbiddenAdjacency: [ - "must not edit truth docs", - "must not edit truth routing", + "must not edit truth docs except through follow-up Truth Sync", + "must not edit truth routing except through follow-up Truth Sync", ], - requiredGates: ["truth-doc ownership"], + requiredGates: ["lane classification", "truth-doc ownership"], allowedWrites: ["functional code"], reportSections: ["Truth docs used", "Code updated", "Verification"], }, diff --git a/src/checks/areas.ts b/src/checks/areas.ts index 5108082..e3eb68b 100644 --- a/src/checks/areas.ts +++ b/src/checks/areas.ts @@ -7,9 +7,16 @@ import type { TruthmarkConfig } from "../config/schema.js"; import { assertRepoContainment, resolveRepoPath } from "../fs/paths.js"; import { resolveAreaRouting } from "../routing/area-resolver.js"; import type { Diagnostic } from "../output/diagnostic.js"; -import type { TruthDocumentEntry } from "../routing/areas.js"; +import { + laneForTruthDocumentKind, + mergeTruthDocumentEntryRelationships, + type TruthDocumentEntry, +} from "../routing/areas.js"; import { classifyPath } from "../sync/classify.js"; -import { resolveTruthDocsRoot } from "../truth/docs.js"; +import { + resolveEngineeringTruthRoot, + resolveProductTruthRoot, +} from "../truth/docs.js"; export type AreasCheckResult = { diagnostics: Diagnostic[]; @@ -80,6 +87,145 @@ const isBroadCodeSurface = (pattern: string): boolean => { return BROAD_CODE_SURFACES.has(pattern.replace(/\/\*\*\/\*$/u, "/**")); }; +const PRODUCT_LINK_REVIEW_KINDS = new Set([ + "engineering-behavior", + "engineering-workflow", + "engineering-contract", +]); + +const normalizeRoot = (value: string): string => + value.replaceAll("\\", "/").replace(/\/+$/u, ""); + +const validateLaneShape = ( + entry: TruthDocumentEntry, + config: TruthmarkConfig, + areaName: string, +): Diagnostic[] => { + const diagnostics: Diagnostic[] = []; + const productRoot = normalizeRoot(resolveProductTruthRoot(config)); + const engineeringRoot = normalizeRoot(resolveEngineeringTruthRoot(config)); + const normalizedPath = entry.path.replaceAll("\\", "/"); + const expectedLane = laneForTruthDocumentKind(entry.kind); + + if (entry.lane !== expectedLane) { + diagnostics.push({ + category: "lane-shape", + severity: "error", + message: `Truth document ${entry.path} declares ${entry.kind} in ${entry.lane} lane; ${entry.kind} belongs to the ${expectedLane} lane.`, + area: areaName, + file: entry.path, + }); + } + + if ( + entry.lane === "product" && + !normalizedPath.startsWith(`${productRoot}/`) + ) { + diagnostics.push({ + category: "lane-shape", + severity: "error", + message: `Product truth document ${entry.path} must live under ${productRoot}.`, + area: areaName, + file: entry.path, + }); + } + + if ( + entry.lane === "engineering" && + !normalizedPath.startsWith(`${engineeringRoot}/`) + ) { + diagnostics.push({ + category: "lane-shape", + severity: "error", + message: `Engineering truth document ${entry.path} must live under ${engineeringRoot}.`, + area: areaName, + file: entry.path, + }); + } + + return diagnostics; +}; + +const validateRelationshipTargets = ( + entries: TruthDocumentEntry[], +): Diagnostic[] => { + const diagnostics: Diagnostic[] = []; + const byPath = new Map(entries.map((entry) => [entry.path, entry])); + + for (const entry of entries) { + for (const target of entry.realizedBy) { + const targetEntry = byPath.get(target); + if (!targetEntry) { + diagnostics.push({ + category: "traceability", + severity: "error", + message: `Product truth document ${entry.path} declares missing engineering realization ${target}.`, + file: entry.path, + }); + } else if (targetEntry.lane !== "engineering") { + diagnostics.push({ + category: "traceability", + severity: "error", + message: `Product truth document ${entry.path} realized_by target ${target} must point to engineering truth.`, + file: entry.path, + }); + } + } + + for (const target of entry.realizes) { + const targetEntry = byPath.get(target); + if (!targetEntry) { + diagnostics.push({ + category: "traceability", + severity: "error", + message: `Engineering truth document ${entry.path} declares missing product truth ${target}.`, + file: entry.path, + }); + } else if (targetEntry.lane !== "product") { + diagnostics.push({ + category: "traceability", + severity: "error", + message: `Engineering truth document ${entry.path} realizes target ${target} must point to product truth.`, + file: entry.path, + }); + } + } + } + + return diagnostics; +}; + +const validateMissingProductLinkReviews = ( + entries: TruthDocumentEntry[], + reportedPaths: Set, +): Diagnostic[] => { + const diagnostics: Diagnostic[] = []; + const hasProductTruth = entries.some((entry) => entry.lane === "product"); + + if (!hasProductTruth) { + return diagnostics; + } + + for (const entry of entries) { + if ( + entry.lane === "engineering" && + PRODUCT_LINK_REVIEW_KINDS.has(entry.kind) && + entry.realizes.length === 0 && + !reportedPaths.has(entry.path) + ) { + reportedPaths.add(entry.path); + diagnostics.push({ + category: "traceability", + severity: "review", + message: `User-visible engineering truth document ${entry.path} should link product truth with realizes when it implements a product capability.`, + file: entry.path, + }); + } + } + + return diagnostics; +}; + export const checkAreas = async ( rootDir: string, config: TruthmarkConfig, @@ -87,7 +233,8 @@ export const checkAreas = async ( const routing = await resolveAreaRouting(rootDir, { rootIndex: config.truthmark.paths.routesIndex, areaFilesRoot: config.truthmark.paths.routeAreasRoot, - truthDocsRoot: resolveTruthDocsRoot(config), + productTruthRoot: resolveProductTruthRoot(config), + engineeringTruthRoot: resolveEngineeringTruthRoot(config), }); const discoveredCodeFiles = await fg([...COVERAGE_SCAN_PATTERNS], { @@ -104,6 +251,7 @@ export const checkAreas = async ( const truthDocumentPaths: string[] = []; const seenTruthDocumentPaths = new Set(); const truthDocumentEntryMap = new Map(); + const reportedMissingProductLinkPaths = new Set(); const areaCoverage = routing.areas.map((area) => ({ area, valid: true, @@ -124,7 +272,10 @@ export const checkAreas = async ( for (const area of truthReferences) { let areaHasTruthDocumentErrors = false; - const registerTruthDocumentEntry = (truthDocumentEntry: TruthDocumentEntry): boolean => { + const areaTruthDocumentEntries: TruthDocumentEntry[] = []; + const registerTruthDocumentEntry = ( + truthDocumentEntry: TruthDocumentEntry, + ): boolean => { const existingEntry = truthDocumentEntryMap.get(truthDocumentEntry.path); if (existingEntry && existingEntry.kind !== truthDocumentEntry.kind) { @@ -138,19 +289,47 @@ export const checkAreas = async ( return false; } + if (existingEntry && existingEntry.lane !== truthDocumentEntry.lane) { + diagnostics.push({ + category: "area-index", + severity: "error", + message: `Truth document ${truthDocumentEntry.path} is routed with conflicting lanes ${existingEntry.lane} and ${truthDocumentEntry.lane}.`, + area: area.name, + file: truthDocumentEntry.path, + }); + return false; + } + if (!existingEntry) { truthDocumentEntryMap.set(truthDocumentEntry.path, truthDocumentEntry); + } else { + truthDocumentEntryMap.set( + truthDocumentEntry.path, + mergeTruthDocumentEntryRelationships( + existingEntry, + truthDocumentEntry, + ), + ); } + areaTruthDocumentEntries.push(truthDocumentEntry); + diagnostics.push( + ...validateLaneShape(truthDocumentEntry, config, area.name), + ); + return true; }; - for (const truthDocument of area.truthDocuments) { + for (const [ + truthDocumentIndex, + truthDocument, + ] of area.truthDocuments.entries()) { + const routedEntry = area.truthDocumentEntries[truthDocumentIndex]; + if (looksLikeGlob(truthDocument)) { - const routedGlobEntry = area.truthDocumentEntries.find( - (entry) => entry.path === truthDocument, - ); - const matches = (await fg([truthDocument], { cwd: rootDir, onlyFiles: true })).sort(); + const matches = ( + await fg([truthDocument], { cwd: rootDir, onlyFiles: true }) + ).sort(); if (matches.length === 0) { diagnostics.push({ @@ -185,9 +364,9 @@ export const checkAreas = async ( truthDocumentPaths.push(match); } if ( - routedGlobEntry && + routedEntry && !registerTruthDocumentEntry({ - ...routedGlobEntry, + ...routedEntry, path: match, }) ) { @@ -232,8 +411,6 @@ export const checkAreas = async ( truthDocumentPaths.push(truthDocument); } - const routedEntry = area.truthDocumentEntries.find((entry) => entry.path === truthDocument); - if (routedEntry && !registerTruthDocumentEntry(routedEntry)) { areaHasTruthDocumentErrors = true; } @@ -245,13 +422,21 @@ export const checkAreas = async ( entry.area.name === area.name && entry.area.truthDocuments.length === area.truthDocuments.length && entry.area.truthDocuments.every( - (truthDocument, index) => truthDocument === area.truthDocuments[index], + (truthDocument, index) => + truthDocument === area.truthDocuments[index], ), ); if (matchingArea) { matchingArea.valid = false; } } + + diagnostics.push( + ...validateMissingProductLinkReviews( + areaTruthDocumentEntries, + reportedMissingProductLinkPaths, + ), + ); } for (const entry of areaCoverage) { @@ -282,7 +467,10 @@ export const checkAreas = async ( for (const match of matches) { try { - await assertRepoContainment(rootDir, resolveRepoPath(rootDir, match)); + await assertRepoContainment( + rootDir, + resolveRepoPath(rootDir, match), + ); containedMatches += 1; } catch { diagnostics.push({ @@ -345,7 +533,8 @@ export const checkAreas = async ( for (const codeFile of codeFiles.sort()) { const matched = areaCoverage.some( (entry) => - entry.valid && entry.patterns.some((pattern) => micromatch.isMatch(codeFile, pattern)), + entry.valid && + entry.patterns.some((pattern) => micromatch.isMatch(codeFile, pattern)), ); if (!matched) { @@ -364,13 +553,18 @@ export const checkAreas = async ( const topologyPressureCount = broadAreaCount + diagnostics.filter( - (diagnostic) => diagnostic.category === "area-index" && diagnostic.severity === "review", + (diagnostic) => + diagnostic.category === "area-index" && + diagnostic.severity === "review", ).length; + const truthDocumentEntries = [...truthDocumentEntryMap.values()]; + diagnostics.push(...validateRelationshipTargets(truthDocumentEntries)); + return { diagnostics, truthDocumentPaths, - truthDocumentEntries: [...truthDocumentEntryMap.values()], + truthDocumentEntries, routePrecision: { leafAreaCount: routing.areas.length, broadAreaCount, diff --git a/src/checks/decisions.ts b/src/checks/decisions.ts index b814e08..7893c11 100644 --- a/src/checks/decisions.ts +++ b/src/checks/decisions.ts @@ -9,12 +9,47 @@ import type { Diagnostic } from "../output/diagnostic.js"; import { TRUTH_DOCUMENT_KINDS, inferTruthDocumentKindFromPath, + laneForTruthDocumentKind, type TruthDocumentEntry, type TruthDocumentKind, } from "../routing/areas.js"; -import { resolveTruthDocsRoot } from "../truth/docs.js"; +import { + resolveEngineeringTruthRoot, + resolveProductTruthRoot, +} from "../truth/docs.js"; -const REQUIRED_DECISION_HEADINGS = ["Scope", "Product Decisions", "Rationale"]; +const PRODUCT_CAPABILITY_REQUIRED_HEADINGS = [ + "Capability Promise", + "Users And Value", + "Capability Scope", + "Current Product Behavior", + "Acceptance Criteria", + "Product Decisions", + "Engineering Realization Links", + "Non-Goals", +]; +const ENGINEERING_REQUIRED_HEADINGS = [ + "Purpose", + "Scope", + "Current Implementation Behavior", + "Source References", + "Product Truth Links", + "Maintenance Notes", +]; +const FORBIDDEN_PRODUCT_HEADINGS = [ + "Execution Flow", + "Execution Model", + "Generated File Inventory", + "CLI Envelope Details", + "Data And Control Flow", +]; +const FORBIDDEN_ENGINEERING_HEADINGS = [ + "Product Promise", + "User / Stakeholder Value", + "Product Decisions", + "Product Rationale", + "Business Boundary", +]; const isTruthDocumentKind = (value: string): value is TruthDocumentKind => { return TRUTH_DOCUMENT_KINDS.includes(value as TruthDocumentKind); @@ -25,7 +60,9 @@ const escapeRegExp = (value: string): string => { }; const hasHeading = (source: string, heading: string): boolean => { - return new RegExp(`^#{2,3}\\s+${escapeRegExp(heading)}\\s*$`, "mu").test(source); + return new RegExp(`^#{2,3}\\s+${escapeRegExp(heading)}\\s*$`, "mu").test( + source, + ); }; const kindSpecificHeadingMessages = ( @@ -36,11 +73,13 @@ const kindSpecificHeadingMessages = ( return []; } - if (kind === "behavior") { - return hasHeading(source, "Current Behavior") ? [] : ["Current Behavior"]; + if (kind === "engineering-behavior") { + return hasHeading(source, "Current Implementation Behavior") + ? [] + : ["Current Implementation Behavior"]; } - if (kind === "contract") { + if (kind === "engineering-contract") { const missingMessages: string[] = []; if (!hasHeading(source, "Contract Surface")) { @@ -58,13 +97,13 @@ const kindSpecificHeadingMessages = ( return missingMessages; } - if (kind === "architecture") { + if (kind === "engineering-architecture") { return hasHeading(source, "Boundaries") || hasHeading(source, "Components") ? [] : ["Boundaries or Components"]; } - if (kind === "workflow") { + if (kind === "engineering-workflow") { const missingMessages: string[] = []; if (!hasHeading(source, "Triggers")) { @@ -78,13 +117,14 @@ const kindSpecificHeadingMessages = ( return missingMessages; } - if (kind === "operations") { - return hasHeading(source, "Runtime Topology") || hasHeading(source, "Configuration") + if (kind === "engineering-operations") { + return hasHeading(source, "Runtime Topology") || + hasHeading(source, "Configuration") ? [] : ["Runtime Topology or Configuration"]; } - if (kind === "test-behavior") { + if (kind === "engineering-test-behavior") { const missingMessages: string[] = []; if (!hasHeading(source, "Execution Model")) { @@ -95,7 +135,9 @@ const kindSpecificHeadingMessages = ( !hasHeading(source, "Fixtures And Data Model") && !hasHeading(source, "Assertions And Invariants") ) { - missingMessages.push("Fixtures And Data Model or Assertions And Invariants"); + missingMessages.push( + "Fixtures And Data Model or Assertions And Invariants", + ); } return missingMessages; @@ -104,12 +146,29 @@ const kindSpecificHeadingMessages = ( return []; }; -const decisionTruthGlobs = (config: TruthmarkConfig): string[] => { - return [`${resolveTruthDocsRoot(config)}/**/*.md`]; +const productRequiredHeadings = (kind: TruthDocumentKind | null): string[] => { + if (kind === "product-capability") { + return PRODUCT_CAPABILITY_REQUIRED_HEADINGS; + } + + return PRODUCT_CAPABILITY_REQUIRED_HEADINGS; }; -const isDecisionTruthCandidate = (config: TruthmarkConfig, filePath: string): boolean => { - return !filePath.endsWith("/README.md") && micromatch.isMatch(filePath, decisionTruthGlobs(config)); +const decisionTruthGlobs = (config: TruthmarkConfig): string[] => { + return [ + `${resolveProductTruthRoot(config)}/**/*.md`, + `${resolveEngineeringTruthRoot(config)}/**/*.md`, + ]; +}; + +const isDecisionTruthCandidate = ( + config: TruthmarkConfig, + filePath: string, +): boolean => { + return ( + !filePath.endsWith("/README.md") && + micromatch.isMatch(filePath, decisionTruthGlobs(config)) + ); }; export const checkDecisionSections = async ( @@ -125,12 +184,16 @@ export const checkDecisionSections = async ( const candidatePaths = [...new Set(markdownPaths)] .filter( (filePath) => - truthDocumentMap.has(filePath) || isDecisionTruthCandidate(config, filePath), + truthDocumentMap.has(filePath) || + isDecisionTruthCandidate(config, filePath), ) .sort(); for (const filePath of candidatePaths) { - const source = await fs.readFile(resolveRepoPath(rootDir, filePath), "utf8"); + const source = await fs.readFile( + resolveRepoPath(rootDir, filePath), + "utf8", + ); const document = parseMarkdownDocument(source); const routedTruthDocument = truthDocumentMap.get(filePath); const frontmatterTruthKind = @@ -138,27 +201,58 @@ export const checkDecisionSections = async ( ? document.frontmatter.truth_kind : null; const routedTruthKind = - routedTruthDocument?.kindSource === "defaulted" ? null : routedTruthDocument?.kind; + routedTruthDocument?.kindSource === "defaulted" + ? null + : routedTruthDocument?.kind; const truthKind = routedTruthKind ?? (frontmatterTruthKind && isTruthDocumentKind(frontmatterTruthKind) ? frontmatterTruthKind : inferTruthDocumentKindFromPath(filePath)); - const missingHeadings = REQUIRED_DECISION_HEADINGS.filter( + const lane = + routedTruthDocument?.lane ?? + (truthKind + ? laneForTruthDocumentKind(truthKind) + : filePath.startsWith(resolveProductTruthRoot(config)) + ? "product" + : "engineering"); + const requiredHeadings = + lane === "product" + ? productRequiredHeadings(truthKind) + : ENGINEERING_REQUIRED_HEADINGS; + const missingHeadings = requiredHeadings.filter( (heading) => !hasHeading(source, heading), ); - missingHeadings.push(...kindSpecificHeadingMessages(source, truthKind)); + if (lane === "engineering") { + missingHeadings.push(...kindSpecificHeadingMessages(source, truthKind)); + } + const forbiddenHeadings = ( + lane === "product" + ? FORBIDDEN_PRODUCT_HEADINGS + : FORBIDDEN_ENGINEERING_HEADINGS + ).filter((heading) => hasHeading(source, heading)); - if (missingHeadings.length === 0) { + if (missingHeadings.length === 0 && forbiddenHeadings.length === 0) { continue; } - diagnostics.push({ - category: "doc-structure", - severity: "review", - message: `Canonical truth doc ${filePath} should include ${missingHeadings.join(" and ")} section(s). Decisions should live beside current behavior, not in timestamped planning logs.`, - file: filePath, - }); + if (missingHeadings.length > 0) { + diagnostics.push({ + category: "doc-structure", + severity: "review", + message: `Canonical ${lane} truth doc ${filePath} should include ${missingHeadings.join(" and ")} section(s). Product truth says what must be true and why; engineering truth says how the repository currently realizes it.`, + file: filePath, + }); + } + + if (forbiddenHeadings.length > 0) { + diagnostics.push({ + category: "lane-drift", + severity: "error", + message: `Canonical ${lane} truth doc ${filePath} contains wrong-lane section(s): ${forbiddenHeadings.join(", ")}.`, + file: filePath, + }); + } } return diagnostics; diff --git a/src/checks/frontmatter.ts b/src/checks/frontmatter.ts index ed3d37b..a63b0ff 100644 --- a/src/checks/frontmatter.ts +++ b/src/checks/frontmatter.ts @@ -6,15 +6,20 @@ import { parseMarkdownDocument } from "../markdown/parse.js"; import type { Diagnostic } from "../output/diagnostic.js"; import { TRUTH_DOCUMENT_KINDS, + laneForTruthDocumentKind, type TruthDocumentEntry, type TruthDocumentKind, } from "../routing/areas.js"; -const isTruthDocumentKind = ( - value: string, -): value is TruthDocumentKind => +const isTruthDocumentKind = (value: string): value is TruthDocumentKind => TRUTH_DOCUMENT_KINDS.includes(value as TruthDocumentKind); +const ROUTE_RELATIONSHIP_FRONTMATTER_FIELDS = [ + "realized_by", + "realizes", + "depends_on", +]; + export const checkFrontmatter = async ( rootDir: string, config: TruthmarkConfig, @@ -74,6 +79,35 @@ export const checkFrontmatter = async ( const routedTruthDocument = truthDocumentMap.get(markdownPath); const truthKind = document.frontmatter.truth_kind; + const truthLane = document.frontmatter.truth_lane; + const isTruthDocument = + routedTruthDocument !== undefined || truthKind !== undefined; + + if (isTruthDocument) { + for (const field of ROUTE_RELATIONSHIP_FRONTMATTER_FIELDS) { + if (field in document.frontmatter) { + diagnostics.push({ + category: "frontmatter", + severity: "error", + message: `Frontmatter field ${field} is not allowed on truth documents; author relationship metadata in fenced route YAML entries instead.`, + file: markdownPath, + }); + } + } + } + + if ( + truthLane !== undefined && + truthLane !== "product" && + truthLane !== "engineering" + ) { + diagnostics.push({ + category: "frontmatter", + severity: "error", + message: "Frontmatter truth_lane must be product or engineering.", + file: markdownPath, + }); + } if (truthKind !== undefined) { if (typeof truthKind !== "string" || !isTruthDocumentKind(truthKind)) { @@ -98,8 +132,23 @@ export const checkFrontmatter = async ( file: markdownPath, }); } + + if ( + typeof truthKind === "string" && + isTruthDocumentKind(truthKind) && + truthLane !== undefined && + (truthLane === "product" || truthLane === "engineering") && + truthLane !== laneForTruthDocumentKind(truthKind) + ) { + diagnostics.push({ + category: "frontmatter", + severity: "error", + message: `Frontmatter truth_lane ${truthLane} must match truth_kind ${truthKind}.`, + file: markdownPath, + }); + } } } return diagnostics; -}; \ No newline at end of file +}; diff --git a/src/config/defaults.ts b/src/config/defaults.ts index 323e866..b88d6d2 100644 --- a/src/config/defaults.ts +++ b/src/config/defaults.ts @@ -2,18 +2,6 @@ import { DEFAULT_PLATFORMS, type TruthmarkConfig } from "./schema.js"; 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, @@ -21,6 +9,18 @@ export const DEFAULT_TRUTHMARK_WORKSPACE = { }, } as const; +export const DERIVED_TRUTHMARK_PATHS = { + routesIndex: "routes/areas.md", + routeAreasRoot: "routes/areas", + defaultArea: "repository", + maxDelegationDepth: 1, + productTruthRoot: "product", + engineeringTruthRoot: "engineering", + templatesRoot: "templates", + portalOutput: "generated/portal", + portalTemplate: "templates/portal.html", +} as const; + export const DEFAULT_INSTRUCTION_TARGETS = ["AGENTS.md"] as const; export const createDefaultRawConfig = () => ({ @@ -28,9 +28,6 @@ export const createDefaultRawConfig = () => ({ platforms: [...DEFAULT_PLATFORMS], 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 }, }, @@ -38,7 +35,7 @@ export const createDefaultRawConfig = () => ({ instruction_targets: [...DEFAULT_INSTRUCTION_TARGETS], frontmatter: { required: [], - recommended: ["status", "doc_type", "last_reviewed", "source_of_truth"], + recommended: ["status", "last_reviewed"], }, ignore: ["node_modules/**", "vendor/**", "dist/**", "build/**"], }); @@ -49,20 +46,24 @@ export const createDefaultConfig = (): TruthmarkConfig => ({ 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, + index: DERIVED_TRUTHMARK_PATHS.routesIndex, + areas: DERIVED_TRUTHMARK_PATHS.routeAreasRoot, + defaultArea: DERIVED_TRUTHMARK_PATHS.defaultArea, + maxDelegationDepth: DERIVED_TRUTHMARK_PATHS.maxDelegationDepth, }, - truth: { root: DEFAULT_TRUTHMARK_WORKSPACE.truth.root }, - templates: { root: DEFAULT_TRUTHMARK_WORKSPACE.templates.root }, + truth: { + productRoot: DERIVED_TRUTHMARK_PATHS.productTruthRoot, + engineeringRoot: DERIVED_TRUTHMARK_PATHS.engineeringTruthRoot, + }, + templates: { root: DERIVED_TRUTHMARK_PATHS.templatesRoot }, generated: { portal: { ...DEFAULT_TRUTHMARK_WORKSPACE.generated.portal }, }, paths: { routesIndex: "docs/truthmark/routes/areas.md", routeAreasRoot: "docs/truthmark/routes/areas", - truthRoot: "docs/truthmark/truth", + productTruthRoot: "docs/truthmark/product", + engineeringTruthRoot: "docs/truthmark/engineering", templatesRoot: "docs/truthmark/templates", portalOutput: "docs/truthmark/generated/portal", portalTemplate: "docs/truthmark/templates/portal.html", @@ -70,14 +71,15 @@ export const createDefaultConfig = (): TruthmarkConfig => ({ controlledPaths: [ "docs/truthmark/routes/areas.md", "docs/truthmark/routes/areas/**/*.md", - "docs/truthmark/truth/**/*.md", + "docs/truthmark/product/**/*.md", + "docs/truthmark/engineering/**/*.md", "docs/truthmark/templates/*.md", ], }, instructionTargets: [...DEFAULT_INSTRUCTION_TARGETS], frontmatter: { required: [], - recommended: ["status", "doc_type", "last_reviewed", "source_of_truth"], + recommended: ["status", "last_reviewed"], }, ignore: ["node_modules/**", "vendor/**", "dist/**", "build/**"], }); diff --git a/src/config/load.ts b/src/config/load.ts index ba3b8e6..81f25d9 100644 --- a/src/config/load.ts +++ b/src/config/load.ts @@ -6,7 +6,7 @@ import { parse } from "yaml"; import type { Diagnostic } from "../output/diagnostic.js"; import { resolveRepoPath } from "../fs/paths.js"; -import { DEFAULT_INSTRUCTION_TARGETS } from "./defaults.js"; +import { DEFAULT_INSTRUCTION_TARGETS, DERIVED_TRUTHMARK_PATHS } from "./defaults.js"; import { DEFAULT_PLATFORMS, type RawTruthmarkConfig, @@ -58,9 +58,8 @@ 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 portalOutputFor = (workspace: string): string => + joinWorkspacePath(workspace, DERIVED_TRUTHMARK_PATHS.portalOutput); const pathsOverlap = (left: string, right: string): boolean => { const normalizedLeft = normalizeRepoRelativePath(left); @@ -120,12 +119,6 @@ const validateWorkspacePaths = ( ): 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) || @@ -139,36 +132,6 @@ const validateWorkspacePaths = ( ); } - 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( @@ -185,12 +148,16 @@ const validateWorkspacePaths = ( const normalizeConfig = (rawConfig: RawTruthmarkConfig): TruthmarkConfig => { 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 routesIndex = joinWorkspacePath(workspace, DERIVED_TRUTHMARK_PATHS.routesIndex); + const routeAreasRoot = joinWorkspacePath(workspace, DERIVED_TRUTHMARK_PATHS.routeAreasRoot); + const productTruthRoot = joinWorkspacePath(workspace, DERIVED_TRUTHMARK_PATHS.productTruthRoot); + const engineeringTruthRoot = joinWorkspacePath( + workspace, + DERIVED_TRUTHMARK_PATHS.engineeringTruthRoot, + ); + const templatesRoot = joinWorkspacePath(workspace, DERIVED_TRUTHMARK_PATHS.templatesRoot); const portalOutput = portalOutputFor(workspace); - const portalTemplate = portalTemplateFor(templatesRoot); + const portalTemplate = joinWorkspacePath(workspace, DERIVED_TRUTHMARK_PATHS.portalTemplate); return { version: rawConfig.version, @@ -198,16 +165,17 @@ const normalizeConfig = (rawConfig: RawTruthmarkConfig): TruthmarkConfig => { 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, + index: DERIVED_TRUTHMARK_PATHS.routesIndex, + areas: DERIVED_TRUTHMARK_PATHS.routeAreasRoot, + defaultArea: DERIVED_TRUTHMARK_PATHS.defaultArea, + maxDelegationDepth: DERIVED_TRUTHMARK_PATHS.maxDelegationDepth, }, truth: { - root: normalizeRepoRelativePath(rawConfig.truthmark.truth.root), + productRoot: DERIVED_TRUTHMARK_PATHS.productTruthRoot, + engineeringRoot: DERIVED_TRUTHMARK_PATHS.engineeringTruthRoot, }, templates: { - root: normalizeRepoRelativePath(rawConfig.truthmark.templates.root), + root: DERIVED_TRUTHMARK_PATHS.templatesRoot, }, generated: { portal: { @@ -217,7 +185,8 @@ const normalizeConfig = (rawConfig: RawTruthmarkConfig): TruthmarkConfig => { paths: { routesIndex, routeAreasRoot, - truthRoot, + productTruthRoot, + engineeringTruthRoot, templatesRoot, portalOutput, portalTemplate, @@ -225,7 +194,8 @@ const normalizeConfig = (rawConfig: RawTruthmarkConfig): TruthmarkConfig => { controlledPaths: [ routesIndex, `${routeAreasRoot}/**/*.md`, - `${truthRoot}/**/*.md`, + `${productTruthRoot}/**/*.md`, + `${engineeringTruthRoot}/**/*.md`, `${templatesRoot}/*.md`, ], }, diff --git a/src/config/schema.ts b/src/config/schema.ts index 9f20036..ecc43b7 100644 --- a/src/config/schema.ts +++ b/src/config/schema.ts @@ -25,18 +25,6 @@ type TruthmarkPortalConfig = { type RawTruthmarkWorkspaceConfig = { workspace: string; - routes: { - index: string; - areas: string; - default_area: string; - max_delegation_depth: 1; - }; - truth: { - root: string; - }; - templates: { - root: string; - }; generated: { portal: TruthmarkPortalConfig; }; @@ -51,7 +39,8 @@ type TruthmarkWorkspaceConfig = { maxDelegationDepth: 1; }; truth: { - root: string; + productRoot: string; + engineeringRoot: string; }; templates: { root: string; @@ -62,7 +51,9 @@ type TruthmarkWorkspaceConfig = { paths: { routesIndex: string; routeAreasRoot: string; - truthRoot: string; + productTruthRoot: string; + engineeringTruthRoot: string; + truthRoot?: string; templatesRoot: string; portalOutput: string; portalTemplate: string; @@ -115,38 +106,11 @@ export const truthmarkConfigSchema = { truthmark: { type: "object", additionalProperties: false, - required: ["workspace", "routes", "truth", "templates", "generated"], + required: ["workspace", "generated"], properties: { workspace: { type: "string", }, - routes: { - type: "object", - additionalProperties: false, - required: ["index", "areas", "default_area", "max_delegation_depth"], - properties: { - 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, diff --git a/src/evidence/parse.ts b/src/evidence/parse.ts index cb75d2a..90d5eca 100644 --- a/src/evidence/parse.ts +++ b/src/evidence/parse.ts @@ -5,39 +5,46 @@ import matter from "gray-matter"; import { parse } from "yaml"; import type { EvidenceReference } from "./types.js"; +import { + normalizeSourceReferencePath, + parseSourceReferences, +} from "../truth/source-references.js"; const yamlFencePattern = /```ya?ml\s*\n([\s\S]*?)```/giu; const topLevelEvidenceMarkerPattern = /^evidence\s*:/imu; -const repoRootPrefixes = [".codex/", ".github/", ".truthmark/", "docs/", "src/", "tests/"]; - -const normalizeReferencePath = (truthDocPath: string, referencePath: string): string => { - const strippedPath = referencePath.split("#")[0]?.trim() ?? ""; - const isRepoRelative = repoRootPrefixes.some((prefix) => strippedPath.startsWith(prefix)); - - if (!isRepoRelative && (strippedPath.startsWith(".") || !strippedPath.includes("/"))) { - return path.posix.normalize(path.posix.join(path.posix.dirname(truthDocPath), strippedPath)); - } - - return path.posix.normalize(strippedPath); -}; - const toEvidenceReference = ( truthDocPath: string, raw: unknown, ): EvidenceReference | null => { - if (!raw || typeof raw !== "object" || !("path" in raw) || typeof raw.path !== "string") { + if ( + !raw || + typeof raw !== "object" || + !("path" in raw) || + typeof raw.path !== "string" + ) { return null; } return { truthDocPath, - path: normalizeReferencePath(truthDocPath, raw.path), - symbol: "symbol" in raw && typeof raw.symbol === "string" ? raw.symbol : undefined, - startLine: "start_line" in raw && typeof raw.start_line === "number" ? raw.start_line : undefined, - endLine: "end_line" in raw && typeof raw.end_line === "number" ? raw.end_line : undefined, + path: normalizeSourceReferencePath(truthDocPath, raw.path), + symbol: + "symbol" in raw && typeof raw.symbol === "string" + ? raw.symbol + : undefined, + startLine: + "start_line" in raw && typeof raw.start_line === "number" + ? raw.start_line + : undefined, + endLine: + "end_line" in raw && typeof raw.end_line === "number" + ? raw.end_line + : undefined, contentHash: - "content_hash" in raw && typeof raw.content_hash === "string" ? raw.content_hash : undefined, + "content_hash" in raw && typeof raw.content_hash === "string" + ? raw.content_hash + : undefined, source: "evidence-block", }; }; @@ -49,17 +56,12 @@ export const parseEvidenceReferences = async ( const source = await fs.readFile(path.join(rootDir, truthDocPath), "utf8"); const parsed = matter(source); const references: EvidenceReference[] = []; - const sourceOfTruth = Array.isArray(parsed.data.source_of_truth) ? parsed.data.source_of_truth : []; - - for (const entry of sourceOfTruth) { - if (typeof entry !== "string") { - continue; - } + for (const entry of parseSourceReferences(source, truthDocPath)) { references.push({ truthDocPath, - path: normalizeReferencePath(truthDocPath, entry), - source: "frontmatter", + path: entry, + source: "source-references", }); } diff --git a/src/evidence/types.ts b/src/evidence/types.ts index dc62be9..993d9b4 100644 --- a/src/evidence/types.ts +++ b/src/evidence/types.ts @@ -5,5 +5,5 @@ export type EvidenceReference = { startLine?: number; endLine?: number; contentHash?: string; - source: "frontmatter" | "evidence-block"; + source: "frontmatter" | "source-references" | "evidence-block"; }; diff --git a/src/init/hierarchy.ts b/src/init/hierarchy.ts index 9cd3c93..a68488a 100644 --- a/src/init/hierarchy.ts +++ b/src/init/hierarchy.ts @@ -3,7 +3,10 @@ import type { TruthmarkConfig } from "../config/schema.js"; import type { FileWriteResult } from "../fs/paths.js"; import { ensureRepoFile, resolveRepoPath, writeRepoFile } from "../fs/paths.js"; import { parseAreasMarkdown } from "../routing/areas.js"; -import { resolveTruthDocsRoot } from "../truth/docs.js"; +import { + resolveEngineeringTruthRoot, + resolveTruthDocsRoot, +} from "../truth/docs.js"; import { renderChildAreaTemplate, mergeTruthDocTemplate, @@ -14,19 +17,30 @@ import { renderTruthRootReadmeTemplate, renderHierarchicalAreasIndexTemplate, renderOperationsDocTemplateFile, + renderProductCapabilityDocTemplateFile, renderBehaviorLeafDocTemplate, renderTestBehaviorDocTemplateFile, renderWorkflowDocTemplateFile, } from "../templates/init-files.js"; const truthRoot = resolveTruthDocsRoot; +const BEHAVIOR_DOC_TEMPLATE_FILE_NAME = "engineering-behavior.md"; +const CONTRACT_DOC_TEMPLATE_FILE_NAME = "engineering-contract.md"; +const ARCHITECTURE_DOC_TEMPLATE_FILE_NAME = "engineering-architecture.md"; +const WORKFLOW_DOC_TEMPLATE_FILE_NAME = "engineering-workflow.md"; +const OPERATIONS_DOC_TEMPLATE_FILE_NAME = "engineering-operations.md"; +const TEST_BEHAVIOR_DOC_TEMPLATE_FILE_NAME = "engineering-test-behavior.md"; +const PRODUCT_CAPABILITY_DOC_TEMPLATE_FILE_NAME = "product-capability.md"; const rootIndexReferencesChildRoute = async ( rootDir: string, rootIndexPath: string, childRoutePath: string, ): Promise => { - const rootIndexSource = await fs.readFile(resolveRepoPath(rootDir, rootIndexPath), "utf8"); + const rootIndexSource = await fs.readFile( + resolveRepoPath(rootDir, rootIndexPath), + "utf8", + ); const parsedRootIndex = parseAreasMarkdown(rootIndexSource); return parsedRootIndex.areaFileReferences.some((areaReference) => @@ -34,7 +48,10 @@ const rootIndexReferencesChildRoute = async ( ); }; -const truthTemplatePath = (config: TruthmarkConfig, fileName: string): string => { +const truthTemplatePath = ( + config: TruthmarkConfig, + fileName: string, +): string => { return `${config.truthmark.paths.templatesRoot}/${fileName}`; }; @@ -44,7 +61,10 @@ const readBehaviorDocTemplate = async ( ): Promise => { try { return await fs.readFile( - resolveRepoPath(rootDir, truthTemplatePath(config, "behavior-doc.md")), + resolveRepoPath( + rootDir, + truthTemplatePath(config, BEHAVIOR_DOC_TEMPLATE_FILE_NAME), + ), "utf8", ); } catch (error: unknown) { @@ -60,14 +80,24 @@ const ensureOrUpdateTruthDocTemplate = async ( templatePath: string, defaultTemplate: string, ): Promise => { - const seededResult = await ensureRepoFile(rootDir, templatePath, defaultTemplate); + const seededResult = await ensureRepoFile( + rootDir, + templatePath, + defaultTemplate, + ); if (seededResult.status !== "unchanged") { return seededResult; } - const existingTemplate = await fs.readFile(resolveRepoPath(rootDir, templatePath), "utf8"); - const mergedTemplate = mergeTruthDocTemplate(existingTemplate, defaultTemplate); + const existingTemplate = await fs.readFile( + resolveRepoPath(rootDir, templatePath), + "utf8", + ); + const mergedTemplate = mergeTruthDocTemplate( + existingTemplate, + defaultTemplate, + ); return writeRepoFile(rootDir, templatePath, mergedTemplate); }; @@ -89,15 +119,32 @@ export const scaffoldHierarchy = async ( ), ); if ( - await rootIndexReferencesChildRoute(rootDir, config.truthmark.paths.routesIndex, childRoutePath) + await rootIndexReferencesChildRoute( + rootDir, + config.truthmark.paths.routesIndex, + childRoutePath, + ) ) { - results.push(await ensureRepoFile(rootDir, childRoutePath, renderChildAreaTemplate(config))); + results.push( + await ensureRepoFile( + rootDir, + childRoutePath, + renderChildAreaTemplate(config), + ), + ); } results.push( await ensureRepoFile( rootDir, - `${truthDocsRoot}/README.md`, - renderTruthRootReadmeTemplate(config), + `${resolveEngineeringTruthRoot(config)}/README.md`, + renderTruthRootReadmeTemplate(config, "engineering"), + ), + ); + results.push( + await ensureRepoFile( + rootDir, + `${config.truthmark.paths.productTruthRoot}/README.md`, + renderTruthRootReadmeTemplate(config, "product"), ), ); results.push( @@ -110,45 +157,52 @@ export const scaffoldHierarchy = async ( results.push( await ensureOrUpdateTruthDocTemplate( rootDir, - truthTemplatePath(config, "behavior-doc.md"), + truthTemplatePath(config, BEHAVIOR_DOC_TEMPLATE_FILE_NAME), renderBehaviorDocTemplateFile(), ), ); results.push( await ensureOrUpdateTruthDocTemplate( rootDir, - truthTemplatePath(config, "contract-doc.md"), + truthTemplatePath(config, CONTRACT_DOC_TEMPLATE_FILE_NAME), renderContractDocTemplateFile(), ), ); results.push( await ensureOrUpdateTruthDocTemplate( rootDir, - truthTemplatePath(config, "architecture-doc.md"), + truthTemplatePath(config, ARCHITECTURE_DOC_TEMPLATE_FILE_NAME), renderArchitectureDocTemplateFile(), ), ); results.push( await ensureOrUpdateTruthDocTemplate( rootDir, - truthTemplatePath(config, "workflow-doc.md"), + truthTemplatePath(config, WORKFLOW_DOC_TEMPLATE_FILE_NAME), renderWorkflowDocTemplateFile(), ), ); results.push( await ensureOrUpdateTruthDocTemplate( rootDir, - truthTemplatePath(config, "operations-doc.md"), + truthTemplatePath(config, OPERATIONS_DOC_TEMPLATE_FILE_NAME), renderOperationsDocTemplateFile(), ), ); results.push( await ensureOrUpdateTruthDocTemplate( rootDir, - truthTemplatePath(config, "test-behavior-doc.md"), + truthTemplatePath(config, TEST_BEHAVIOR_DOC_TEMPLATE_FILE_NAME), renderTestBehaviorDocTemplateFile(), ), ); + results.push( + await ensureOrUpdateTruthDocTemplate( + rootDir, + truthTemplatePath(config, PRODUCT_CAPABILITY_DOC_TEMPLATE_FILE_NAME), + renderProductCapabilityDocTemplateFile(), + ), + ); const behaviorDocTemplate = await readBehaviorDocTemplate(rootDir, config); results.push( await ensureRepoFile( diff --git a/src/output/diagnostic.ts b/src/output/diagnostic.ts index 07b186d..b219773 100644 --- a/src/output/diagnostic.ts +++ b/src/output/diagnostic.ts @@ -8,6 +8,9 @@ export const DIAGNOSTIC_CATEGORIES = [ "truth-sync", "realization", "doc-structure", + "lane-shape", + "lane-drift", + "traceability", "generated-surface", "repo-index", "impact", diff --git a/src/repo-index/file-tree.ts b/src/repo-index/file-tree.ts index c0921be..27ddbc3 100644 --- a/src/repo-index/file-tree.ts +++ b/src/repo-index/file-tree.ts @@ -7,8 +7,20 @@ import matter from "gray-matter"; import micromatch from "micromatch"; import { parseMarkdownDocument } from "../markdown/parse.js"; +import { + TRUTH_DOCUMENT_KINDS, + docTypeForTruthDocumentKind, + laneForTruthDocumentKind, + type TruthDocumentKind, +} from "../routing/areas.js"; import { classifyPath } from "../sync/classify.js"; -import type { RepoDocEntry, RepoFileEntry, RepoFileKind, RepoTestEntry } from "./types.js"; +import { parseSourceReferences } from "../truth/source-references.js"; +import type { + RepoDocEntry, + RepoFileEntry, + RepoFileKind, + RepoTestEntry, +} from "./types.js"; const languageByExtension = new Map([ [".ts", "typescript"], @@ -24,7 +36,14 @@ const languageByExtension = new Map([ [".toml", "toml"], ]); -const sourceExtensions = new Set([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"]); +const sourceExtensions = new Set([ + ".ts", + ".tsx", + ".js", + ".jsx", + ".mjs", + ".cjs", +]); export const isJavaScriptLikePath = (filePath: string): boolean => { return sourceExtensions.has(path.posix.extname(filePath)); @@ -64,13 +83,17 @@ const fileKind = (filePath: string, ignore: string[]): RepoFileKind => { const targetHintsForTest = (filePath: string): string[] => { const hints = new Set(); - const basename = path.posix.basename(filePath).replace(/\.(test|spec)\.[cm]?[jt]sx?$/u, ""); + const basename = path.posix + .basename(filePath) + .replace(/\.(test|spec)\.[cm]?[jt]sx?$/u, ""); if (basename.length > 0) { hints.add(basename); } const segments = filePath.split("/"); - const testRootIndex = segments.findIndex((segment) => segment === "tests" || segment === "__tests__"); + const testRootIndex = segments.findIndex( + (segment) => segment === "tests" || segment === "__tests__", + ); if (testRootIndex >= 0) { for (const segment of segments.slice(testRootIndex + 1, -1)) { if (segment.length > 0) { @@ -84,9 +107,19 @@ const targetHintsForTest = (filePath: string): string[] => { const defaultIgnore = [".git/**", "node_modules/**", "dist/**", "build/**"]; -const normalizePath = (filePath: string): string => filePath.replaceAll("\\", "/").replace(/^\.\/+/u, ""); +const normalizePath = (filePath: string): string => + filePath.replaceAll("\\", "/").replace(/^\.\/+/u, ""); -const gitDiscoverableFiles = async (rootDir: string): Promise => { +const isTruthDocumentKind = (value: unknown): value is TruthDocumentKind => { + return ( + typeof value === "string" && + TRUTH_DOCUMENT_KINDS.includes(value as TruthDocumentKind) + ); +}; + +const gitDiscoverableFiles = async ( + rootDir: string, +): Promise => { const result = await execa( "git", ["ls-files", "--cached", "--others", "--exclude-standard", "--deduplicate"], @@ -111,7 +144,11 @@ const isIgnoredPath = (filePath: string, ignore: string[]): boolean => { export const discoverRepoFiles = async ( rootDir: string, ignore: string[], -): Promise<{ files: RepoFileEntry[]; docs: RepoDocEntry[]; tests: RepoTestEntry[] }> => { +): Promise<{ + files: RepoFileEntry[]; + docs: RepoDocEntry[]; + tests: RepoTestEntry[]; +}> => { const discoveredFiles = (await gitDiscoverableFiles(rootDir)) ?? (await fg(["**/*"], { @@ -125,12 +162,18 @@ export const discoverRepoFiles = async ( const docs: RepoDocEntry[] = []; const tests: RepoTestEntry[] = []; - for (const filePath of discoveredFiles.filter((entry) => !isIgnoredPath(entry, ignore)).sort()) { + for (const filePath of discoveredFiles + .filter((entry) => !isIgnoredPath(entry, ignore)) + .sort()) { let stat: Awaited>; try { stat = await fs.stat(path.join(rootDir, filePath)); } catch (error: unknown) { - if (error instanceof Error && "code" in error && error.code === "ENOENT") { + if ( + error instanceof Error && + "code" in error && + error.code === "ENOENT" + ) { continue; } throw error; @@ -160,17 +203,37 @@ export const discoverRepoFiles = async ( const source = await fs.readFile(path.join(rootDir, filePath), "utf8"); const parsed = matter(source); const markdown = parseMarkdownDocument(parsed.content); - const title = markdown.headings.find((heading) => heading.depth === 1)?.text ?? null; - const sourceOfTruth = Array.isArray(parsed.data.source_of_truth) - ? parsed.data.source_of_truth.filter((entry: unknown): entry is string => typeof entry === "string") - : []; + const title = + markdown.headings.find((heading) => heading.depth === 1)?.text ?? null; + const sourceOfTruth = parseSourceReferences(source, filePath); + const truthKind = + typeof parsed.data.truth_kind === "string" + ? parsed.data.truth_kind + : null; + const derivedTruthKind = isTruthDocumentKind(truthKind) + ? truthKind + : null; docs.push({ path: filePath, title, - docType: typeof parsed.data.doc_type === "string" ? parsed.data.doc_type : null, - truthKind: typeof parsed.data.truth_kind === "string" ? parsed.data.truth_kind : null, + docType: + typeof parsed.data.doc_type === "string" + ? parsed.data.doc_type + : derivedTruthKind + ? docTypeForTruthDocumentKind(derivedTruthKind) + : null, + truthKind, + truthLane: + typeof parsed.data.truth_lane === "string" + ? parsed.data.truth_lane + : derivedTruthKind + ? laneForTruthDocumentKind(derivedTruthKind) + : null, sourceOfTruth: sourceOfTruth.sort(), + realizedBy: [], + realizes: [], + dependsOn: [], }); } } diff --git a/src/repo-index/route-map.ts b/src/repo-index/route-map.ts index 5c516b5..e6f1161 100644 --- a/src/repo-index/route-map.ts +++ b/src/repo-index/route-map.ts @@ -1,8 +1,39 @@ import { loadConfig } from "../config/load.js"; import { resolveAreaRouting } from "../routing/area-resolver.js"; -import { resolveTruthDocsRoot } from "../truth/docs.js"; +import { + mergeTruthDocumentEntryRelationships, + type TruthDocumentEntry, +} from "../routing/areas.js"; +import { + resolveEngineeringTruthRoot, + resolveProductTruthRoot, +} from "../truth/docs.js"; import type { RouteMap } from "./types.js"; +const mergedEntryMap = ( + entries: TruthDocumentEntry[], +): Map => { + const byPath = new Map(); + + for (const entry of entries) { + const existingEntry = byPath.get(entry.path); + if ( + existingEntry && + existingEntry.kind === entry.kind && + existingEntry.lane === entry.lane + ) { + byPath.set( + entry.path, + mergeTruthDocumentEntryRelationships(existingEntry, entry), + ); + } else if (!existingEntry) { + byPath.set(entry.path, entry); + } + } + + return byPath; +}; + export const buildRouteMap = async (rootDir: string): Promise => { const loadResult = await loadConfig(rootDir); @@ -17,9 +48,14 @@ export const buildRouteMap = async (rootDir: string): Promise => { const routing = await resolveAreaRouting(rootDir, { rootIndex: loadResult.config.truthmark.paths.routesIndex, areaFilesRoot: loadResult.config.truthmark.paths.routeAreasRoot, - truthDocsRoot: resolveTruthDocsRoot(loadResult.config), + productTruthRoot: resolveProductTruthRoot(loadResult.config), + engineeringTruthRoot: resolveEngineeringTruthRoot(loadResult.config), }); + const mergedTruthDocumentEntries = mergedEntryMap( + routing.areas.flatMap((area) => area.truthDocumentEntries), + ); + return { schemaVersion: "route-map/v0", routes: routing.areas @@ -31,6 +67,14 @@ export const buildRouteMap = async (rootDir: string): Promise => { parentName: area.parentName, codeSurface: [...area.codeSurface].sort(), truthDocs: [...area.truthDocuments].sort(), + truthDocumentEntries: [ + ...new Map( + area.truthDocumentEntries.map((entry) => [ + entry.path, + mergedTruthDocumentEntries.get(entry.path) ?? entry, + ]), + ).values(), + ].sort((left, right) => left.path.localeCompare(right.path)), updateTruthWhen: [...area.updateTruthWhen], })) .sort((left, right) => left.key.localeCompare(right.key)), diff --git a/src/repo-index/types.ts b/src/repo-index/types.ts index 51df25d..e7cae20 100644 --- a/src/repo-index/types.ts +++ b/src/repo-index/types.ts @@ -1,4 +1,5 @@ import type { Diagnostic } from "../output/diagnostic.js"; +import type { TruthDocumentEntry } from "../routing/areas.js"; export type PackageMetadata = { path: string; @@ -22,7 +23,11 @@ export type RepoDocEntry = { title: string | null; docType: string | null; truthKind: string | null; + truthLane: string | null; sourceOfTruth: string[]; + realizedBy: string[]; + realizes: string[]; + dependsOn: string[]; }; export type RepoTestEntry = { @@ -62,6 +67,7 @@ export type RouteMapRoute = { parentName?: string; codeSurface: string[]; truthDocs: string[]; + truthDocumentEntries: TruthDocumentEntry[]; updateTruthWhen: string[]; }; diff --git a/src/routing/area-resolver.ts b/src/routing/area-resolver.ts index 1f1650c..4cd48c9 100644 --- a/src/routing/area-resolver.ts +++ b/src/routing/area-resolver.ts @@ -15,6 +15,8 @@ export type AreaRoutingConfig = { rootIndex: string; areaFilesRoot: string; truthDocsRoot?: string; + productTruthRoot?: string; + engineeringTruthRoot?: string; }; type ResolvedTruthArea = TruthArea & { @@ -138,6 +140,8 @@ export const resolveAreaRouting = async ( const rootParsed = parseAreasMarkdown(rootRead.source ?? "", { truthDocsRoot: config.truthDocsRoot, + productTruthRoot: config.productTruthRoot, + engineeringTruthRoot: config.engineeringTruthRoot, }); diagnostics.push( ...rootParsed.diagnostics.map((diagnostic) => ({ @@ -185,6 +189,8 @@ export const resolveAreaRouting = async ( routeFiles.push(areaFile); const childParsed = parseAreasMarkdown(childRead.source ?? "", { truthDocsRoot: config.truthDocsRoot, + productTruthRoot: config.productTruthRoot, + engineeringTruthRoot: config.engineeringTruthRoot, }); diagnostics.push( ...childParsed.diagnostics.map((diagnostic) => ({ diff --git a/src/routing/areas.ts b/src/routing/areas.ts index c0c9933..c5544dc 100644 --- a/src/routing/areas.ts +++ b/src/routing/areas.ts @@ -3,20 +3,27 @@ import { parse } from "yaml"; import type { Diagnostic } from "../output/diagnostic.js"; export const TRUTH_DOCUMENT_KINDS = [ - "behavior", - "contract", - "architecture", - "workflow", - "operations", - "test-behavior", + "product-capability", + "engineering-behavior", + "engineering-contract", + "engineering-workflow", + "engineering-architecture", + "engineering-operations", + "engineering-test-behavior", ] as const; export type TruthDocumentKind = (typeof TRUTH_DOCUMENT_KINDS)[number]; +export type TruthDocumentLane = "product" | "engineering"; export type TruthDocumentEntry = { path: string; kind: TruthDocumentKind; kindSource: "explicit" | "inferred" | "defaulted"; + lane: TruthDocumentLane; + laneSource: "explicit" | "inferred" | "defaulted"; + realizedBy: string[]; + realizes: string[]; + dependsOn: string[]; }; export type TruthArea = { @@ -37,6 +44,19 @@ export type TruthAreaReference = { truthDocumentEntries: TruthDocumentEntry[]; }; +const uniqueSorted = (values: string[]): string[] => + [...new Set(values)].sort(); + +export const mergeTruthDocumentEntryRelationships = ( + first: TruthDocumentEntry, + second: TruthDocumentEntry, +): TruthDocumentEntry => ({ + ...first, + realizedBy: uniqueSorted([...first.realizedBy, ...second.realizedBy]), + realizes: uniqueSorted([...first.realizes, ...second.realizes]), + dependsOn: uniqueSorted([...first.dependsOn, ...second.dependsOn]), +}); + type TruthAreaFileReference = { id: string; name: string; @@ -55,9 +75,12 @@ type ParseAreasMarkdownResult = { export type ParseAreasMarkdownOptions = { truthDocsRoot?: string; + productTruthRoot?: string; + engineeringTruthRoot?: string; }; -const DEFAULT_WORKSPACE_TRUTH_DOCS_ROOT = "docs/truthmark/truth"; +const DEFAULT_PRODUCT_TRUTH_DOCS_ROOT = "docs/truthmark/product"; +const DEFAULT_ENGINEERING_TRUTH_DOCS_ROOT = "docs/truthmark/engineering"; const slugify = (value: string): string => { return value @@ -100,17 +123,98 @@ export const inferTruthDocumentKindFromPath = ( options: ParseAreasMarkdownOptions = {}, ): TruthDocumentKind | null => { const normalizedPath = documentPath.replaceAll("\\", "/"); - const truthDocsRoot = (options.truthDocsRoot ?? DEFAULT_WORKSPACE_TRUTH_DOCS_ROOT) + const productTruthRoot = ( + options.productTruthRoot ?? DEFAULT_PRODUCT_TRUTH_DOCS_ROOT + ) + ?.replaceAll("\\", "/") + .replace(/\/+$/u, ""); + const engineeringTruthRoot = ( + options.engineeringTruthRoot ?? + options.truthDocsRoot ?? + DEFAULT_ENGINEERING_TRUTH_DOCS_ROOT + ) ?.replaceAll("\\", "/") .replace(/\/+$/u, ""); - if (truthDocsRoot && normalizedPath.startsWith(`${truthDocsRoot}/`)) { - return "behavior"; + if (productTruthRoot && normalizedPath.startsWith(`${productTruthRoot}/`)) { + return "product-capability"; + } + + if ( + engineeringTruthRoot && + normalizedPath.startsWith(`${engineeringTruthRoot}/`) + ) { + if (normalizedPath.includes("/contracts/")) return "engineering-contract"; + if (normalizedPath.includes("/workflows/")) return "engineering-workflow"; + if (normalizedPath.includes("/architecture/")) + return "engineering-architecture"; + if (normalizedPath.includes("/operations/")) + return "engineering-operations"; + if (normalizedPath.includes("/tests/")) return "engineering-test-behavior"; + return "engineering-behavior"; } return null; }; +const inferTruthDocumentLaneFromPath = ( + documentPath: string, + options: ParseAreasMarkdownOptions = {}, +): TruthDocumentLane | null => { + const normalizedPath = documentPath.replaceAll("\\", "/"); + const productTruthRoot = ( + options.productTruthRoot ?? DEFAULT_PRODUCT_TRUTH_DOCS_ROOT + ) + .replaceAll("\\", "/") + .replace(/\/+$/u, ""); + const engineeringTruthRoot = ( + options.engineeringTruthRoot ?? + options.truthDocsRoot ?? + DEFAULT_ENGINEERING_TRUTH_DOCS_ROOT + ) + .replaceAll("\\", "/") + .replace(/\/+$/u, ""); + + if (normalizedPath.startsWith(`${productTruthRoot}/`)) { + return "product"; + } + + if (normalizedPath.startsWith(`${engineeringTruthRoot}/`)) { + return "engineering"; + } + + return null; +}; + +export const laneForTruthDocumentKind = ( + kind: TruthDocumentKind, +): TruthDocumentLane => { + return kind.startsWith("product-") ? "product" : "engineering"; +}; + +export const docTypeForTruthDocumentKind = ( + kind: TruthDocumentKind, +): string => { + if (kind.startsWith("product-")) { + return "product"; + } + return kind.slice("engineering-".length); +}; + +const parseStringListField = (rawEntry: unknown, field: string): string[] => { + if (!rawEntry || typeof rawEntry !== "object" || !(field in rawEntry)) { + return []; + } + + const value = (rawEntry as Record)[field]; + + if (!Array.isArray(value)) { + return []; + } + + return value.filter((entry): entry is string => typeof entry === "string"); +}; + type TruthDocumentsSectionResult = { truthDocuments: string[]; truthDocumentEntries: TruthDocumentEntry[]; @@ -153,6 +257,7 @@ const parseTruthDocumentsFromList = ( const truthDocuments = parseListSection(sectionLines); const truthDocumentEntries = truthDocuments.map((documentPath) => { const inferredKind = inferTruthDocumentKindFromPath(documentPath, options); + const inferredLane = inferTruthDocumentLaneFromPath(documentPath, options); if (!inferredKind) { diagnostics.push( @@ -166,8 +271,13 @@ const parseTruthDocumentsFromList = ( return { path: documentPath, - kind: inferredKind ?? "behavior", + kind: inferredKind ?? "engineering-behavior", kindSource: inferredKind ? ("inferred" as const) : ("defaulted" as const), + lane: inferredLane ?? "engineering", + laneSource: inferredLane ? ("inferred" as const) : ("defaulted" as const), + realizedBy: [], + realizes: [], + dependsOn: [], }; }); @@ -181,6 +291,7 @@ const parseTruthDocumentsFromList = ( const parseTruthDocumentsFromYaml = ( sectionLines: string[], areaName: string, + options: ParseAreasMarkdownOptions, ): TruthDocumentsSectionResult => { const yamlFenceRange = findTruthDocumentsYamlFenceRange(sectionLines); @@ -261,15 +372,35 @@ const parseTruthDocumentsFromYaml = ( rawEntry && typeof rawEntry === "object" && "kind" in rawEntry ? (rawEntry as { kind?: unknown }).kind : null; + const lane = + rawEntry && typeof rawEntry === "object" && "lane" in rawEntry + ? (rawEntry as { lane?: unknown }).lane + : null; + const inferredKind = + typeof path === "string" + ? inferTruthDocumentKindFromPath(path, options) + : null; + const inferredLane = + typeof path === "string" + ? inferTruthDocumentLaneFromPath(path, options) + : null; + const normalizedKind = isTruthDocumentKind(kind) ? kind : inferredKind; + const normalizedLane = + lane === "product" || lane === "engineering" + ? lane + : normalizedKind + ? laneForTruthDocumentKind(normalizedKind) + : inferredLane; if ( typeof path !== "string" || path.trim().length === 0 || - !isTruthDocumentKind(kind) + !normalizedKind || + !normalizedLane ) { diagnostics.push( createAreaDiagnostic( - `Area ${areaName} truth_documents entries must include non-empty path and valid kind fields.`, + `Area ${areaName} truth_documents entries must include non-empty path plus valid lane and kind fields.`, areaName, ), ); @@ -278,8 +409,14 @@ const parseTruthDocumentsFromYaml = ( truthDocumentEntries.push({ path: path.trim(), - kind, - kindSource: "explicit", + kind: normalizedKind, + kindSource: isTruthDocumentKind(kind) ? "explicit" : "inferred", + lane: normalizedLane, + laneSource: + lane === "product" || lane === "engineering" ? "explicit" : "inferred", + realizedBy: parseStringListField(rawEntry, "realized_by"), + realizes: parseStringListField(rawEntry, "realizes"), + dependsOn: parseStringListField(rawEntry, "depends_on"), }); } @@ -301,7 +438,11 @@ const parseTruthDocumentsSection = ( return parseTruthDocumentsFromList(sectionLines, areaName, options); } - const yamlResult = parseTruthDocumentsFromYaml(sectionLines, areaName); + const yamlResult = parseTruthDocumentsFromYaml( + sectionLines, + areaName, + options, + ); if ( yamlResult.diagnostics.length > 0 || @@ -405,8 +546,9 @@ export const parseAreasMarkdown = ( const areaHeadingMatch = line.match(/^\s{0,3}##\s+(.*)$/u); if (areaHeadingMatch) { + const heading = areaHeadingMatch[1]?.trim() ?? null; flushArea(); - currentAreaName = areaHeadingMatch[1]?.trim() ?? null; + currentAreaName = heading === "Source References" ? null : heading; continue; } diff --git a/src/templates/agents-block.ts b/src/templates/agents-block.ts index 1ea2c8b..7a90a36 100644 --- a/src/templates/agents-block.ts +++ b/src/templates/agents-block.ts @@ -1,13 +1,22 @@ import type { TruthmarkConfig } from "../config/schema.js"; -import { defaultAgentConfig, resolveTruthDocsRoot } from "../agents/shared.js"; +import { + defaultAgentConfig, + resolveProductTruthRoot, + resolveEngineeringTruthRoot, +} from "../agents/shared.js"; import { TRUTHMARK_VERSION } from "../version.js"; export const TRUTHMARK_BLOCK_START = ""; 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.truthmark.paths.routesIndex} and ${config.truthmark.paths.routeAreasRoot}/**/*.md when present; Truth docs: ${truthRoot}/**/*.md when present.`; + const productTruthRoot = resolveProductTruthRoot(config); + const engineeringTruthRoot = resolveEngineeringTruthRoot(config); + const truthDocRoots = Array.from(new Set([productTruthRoot, engineeringTruthRoot])).map( + (truthRoot) => `${truthRoot}/**/*.md`, + ); + + return `Hierarchy hints: config .truthmark/config.yml when present; routes ${config.truthmark.paths.routesIndex} and ${config.truthmark.paths.routeAreasRoot}/**/*.md when present; Truth docs: ${truthDocRoots.join(" and ")} when present.`; }; export const renderAgentsBlock = ( diff --git a/src/templates/init-files.ts b/src/templates/init-files.ts index e3136f4..2b0a780 100644 --- a/src/templates/init-files.ts +++ b/src/templates/init-files.ts @@ -8,7 +8,7 @@ import { createDefaultRawConfig, } from "../config/defaults.js"; import { inferTruthDocumentKindFromPath } from "../routing/areas.js"; -import { resolveTruthDocsRoot } from "../truth/docs.js"; +import { resolveEngineeringTruthRoot, resolveProductTruthRoot } from "../truth/docs.js"; const asRelativePath = (value: string): string => { return value.split(path.sep).join("/"); @@ -20,7 +20,31 @@ const resolveRelativePath = (fromPath: string, toPath: string): string => { return asRelativePath(path.relative(path.dirname(fromPath), toPath)); }; -const truthRoot = resolveTruthDocsRoot; +const truthRoot = resolveEngineeringTruthRoot; + +const renderLaneRootReadmeSummary = (lane: "product" | "engineering"): string => { + if (lane === "product") { + return [ + "Product truth owns capability promises, boundaries, decisions, and acceptance criteria.", + "Product lane docs state what must be true, why it matters, and what success means.", + ].join(" "); + } + + return [ + "Engineering truth owns current realization, contracts, architecture, workflows, operations, and tests.", + "Engineering lane docs describe how the repository currently implements and operates the behavior.", + ].join(" "); +}; + +const renderLaneRootLeafDocGuidance = ( + lane: "product" | "engineering", +): string => { + if (lane === "product") { + return "README.md files are indexes, not Truth Sync targets. Keep product truth in bounded capability docs."; + } + + return "README.md files are indexes, not Truth Sync targets. Keep engineering truth in bounded behavior, contract, architecture, workflow, operations, and test docs."; +}; const renderTruthDocumentsMetadata = ( documents: Array<{ path: string; kind: string }>, @@ -43,9 +67,17 @@ export const renderAreasTemplate = ( documents.length > 0 ? documents.map((document) => ({ path: document.path, - kind: inferTruthDocumentKindFromPath(document.path) ?? "behavior", + kind: + inferTruthDocumentKindFromPath(document.path) ?? + "engineering-behavior", })) - : [{ path: `${createDefaultConfig().truthmark.paths.truthRoot}/**/*.md`, kind: "behavior" }]; + : [ + { + path: `${createDefaultConfig().truthmark.paths.engineeringTruthRoot}/**/*.md`, + kind: "engineering-behavior", + lane: "engineering", + }, + ]; return [ "# Truthmark Areas", @@ -89,8 +121,6 @@ export const renderHierarchicalAreasIndexTemplate = ( "status: active", "doc_type: route-index", `last_reviewed: ${currentDate()}`, - "source_of_truth:", - ` - ${sourceOfTruth}`, "---", "", "# Truthmark Areas", @@ -107,6 +137,10 @@ export const renderHierarchicalAreasIndexTemplate = ( "- behavior changes affect the routed truth documents", "- API contracts or current feature behavior changes", "", + "## Source References", + "", + `- ${sourceOfTruth}`, + "", ].join("\n"); }; @@ -116,15 +150,16 @@ export const renderChildAreaTemplate = (config: TruthmarkConfig): string => { const truthDocsRoot = truthRoot(config); const leafTruthDoc = `${truthDocsRoot}/${defaultArea}/overview.md`; const templatePath = `${config.truthmark.paths.routeAreasRoot}/${defaultArea}.md`; - const sourceOfTruth = resolveRelativePath(templatePath, ".truthmark/config.yml"); + const sourceOfTruth = resolveRelativePath( + templatePath, + ".truthmark/config.yml", + ); return [ "---", "status: active", "doc_type: area-route", `last_reviewed: ${currentDate()}`, - "source_of_truth:", - ` - ${sourceOfTruth}`, "---", "", `# ${title} Areas`, @@ -135,7 +170,8 @@ export const renderChildAreaTemplate = (config: TruthmarkConfig): string => { "```yaml", "truth_documents:", ` - path: ${leafTruthDoc}`, - " kind: behavior", + " kind: engineering-behavior", + " lane: engineering", "```", "", "Code surface:", @@ -144,13 +180,18 @@ export const renderChildAreaTemplate = (config: TruthmarkConfig): string => { "Update truth when:", "- behavior changes affect repository truth", "", + "## Source References", + "", + `- ${sourceOfTruth}`, + "", ].join("\n"); }; export const renderTruthRootReadmeTemplate = ( config: TruthmarkConfig = createDefaultConfig(), + lane: "product" | "engineering" = "engineering", ): string => { - const templatePath = `${truthRoot(config)}/README.md`; + const templatePath = `${lane === "product" ? resolveProductTruthRoot(config) : resolveEngineeringTruthRoot(config)}/README.md`; const sourceOfTruth = resolveRelativePath( templatePath, config.truthmark.paths.routesIndex, @@ -161,20 +202,26 @@ export const renderTruthRootReadmeTemplate = ( "status: active", "doc_type: index", `last_reviewed: ${currentDate()}`, - "source_of_truth:", - ` - ${sourceOfTruth}`, "---", "", "# Truth Docs", "", "This directory is an index for current truth docs organized by the configured Truthmark hierarchy.", "", - "README.md files are indexes, not Truth Sync targets. Keep bounded truth in leaf docs under `/.md`.", + renderLaneRootReadmeSummary(lane), + "", + renderLaneRootLeafDocGuidance(lane), + "", + "## Source References", + "", + `- ${sourceOfTruth}`, "", ].join("\n"); }; -export const renderTruthDomainReadmeTemplate = (config: TruthmarkConfig): string => { +export const renderTruthDomainReadmeTemplate = ( + config: TruthmarkConfig, +): string => { const defaultArea = config.truthmark.routes.defaultArea; const title = titleCase(defaultArea); const templatePath = `${truthRoot(config)}/${defaultArea}/README.md`; @@ -188,8 +235,6 @@ export const renderTruthDomainReadmeTemplate = (config: TruthmarkConfig): string "status: active", "doc_type: index", `last_reviewed: ${currentDate()}`, - "source_of_truth:", - ` - ${sourceOfTruth}`, "---", "", `# ${title} Truth Docs`, @@ -202,15 +247,27 @@ export const renderTruthDomainReadmeTemplate = (config: TruthmarkConfig): string "", "- [Overview](overview.md)", "", + "## Source References", + "", + `- ${sourceOfTruth}`, + "", ].join("\n"); }; -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"; +export const BEHAVIOR_DOC_TEMPLATE_PATH = + "docs/truthmark/templates/engineering-behavior.md"; +export const CONTRACT_DOC_TEMPLATE_PATH = + "docs/truthmark/templates/engineering-contract.md"; +export const ARCHITECTURE_DOC_TEMPLATE_PATH = + "docs/truthmark/templates/engineering-architecture.md"; +export const WORKFLOW_DOC_TEMPLATE_PATH = + "docs/truthmark/templates/engineering-workflow.md"; +export const OPERATIONS_DOC_TEMPLATE_PATH = + "docs/truthmark/templates/engineering-operations.md"; +export const TEST_BEHAVIOR_DOC_TEMPLATE_PATH = + "docs/truthmark/templates/engineering-test-behavior.md"; +export const PRODUCT_CAPABILITY_DOC_TEMPLATE_PATH = + "docs/truthmark/templates/product-capability.md"; type TemplateSectionSpec = { heading: string; @@ -244,7 +301,9 @@ const titleToPlaceholder = (title: string): string => { .replace(/^_+|_+$/g, ""); }; -const findTemplateSectionHeadings = (template: string): Array<{ heading: string; index: number }> => { +const findTemplateSectionHeadings = ( + template: string, +): Array<{ heading: string; index: number }> => { const matches: Array<{ heading: string; index: number }> = []; let fencedCodeMarker: "`" | "~" | null = null; let fencedCodeLength = 0; @@ -281,7 +340,9 @@ const findTemplateSectionHeadings = (template: string): Array<{ heading: string; return matches; }; -const parseTemplateSections = (template: string): { preamble: string; sections: ParsedTemplateSection[] } => { +const parseTemplateSections = ( + template: string, +): { preamble: string; sections: ParsedTemplateSection[] } => { const matches = findTemplateSectionHeadings(template); if (matches.length === 0) { @@ -305,30 +366,87 @@ const parseTemplateSections = (template: string): { preamble: string; sections: }; }; -export const mergeTruthDocTemplate = (existingTemplate: string, defaultTemplate: string): string => { +const LEGACY_MANAGED_TEMPLATE_HEADINGS = new Map([ + ["## Current Behavior", "## Current Implementation Behavior"], + ["## Source Evidence", "## Source References"], +]); + +const resolveManagedTemplateHeading = (heading: string): string => { + return LEGACY_MANAGED_TEMPLATE_HEADINGS.get(heading) ?? heading; +}; + +const stripManagedFrontmatterFields = (preamble: string): string => { + if (!preamble.startsWith("---\n")) { + return preamble; + } + + const lines = preamble.split("\n"); + const closingIndex = lines.findIndex( + (line, index) => index > 0 && line.trim() === "---", + ); + if (closingIndex < 0) { + return preamble; + } + + const fieldsToRemove = new Set(["source_of_truth", "doc_type", "truth_lane"]); + const keptFrontmatterLines: string[] = []; + let skippingManagedField = false; + + for (const line of lines.slice(1, closingIndex)) { + const keyMatch = /^([A-Za-z0-9_-]+):(\s|$)/u.exec(line); + if (keyMatch) { + skippingManagedField = fieldsToRemove.has(keyMatch[1] ?? ""); + } + + if (!skippingManagedField) { + keptFrontmatterLines.push(line); + } + } + + return [ + "---", + ...keptFrontmatterLines, + "---", + ...lines.slice(closingIndex + 1), + ] + .join("\n") + .trimEnd(); +}; + +export const mergeTruthDocTemplate = ( + existingTemplate: string, + defaultTemplate: string, +): string => { if (existingTemplate.trim().length === 0) { return defaultTemplate; } const defaultParsed = parseTemplateSections(defaultTemplate); const existingParsed = parseTemplateSections(existingTemplate); - const defaultHeadings = new Set(defaultParsed.sections.map((section) => section.heading)); + const defaultHeadings = new Set( + defaultParsed.sections.map((section) => section.heading), + ); const customBeforeDefault = new Map(); const trailingCustomSections: ParsedTemplateSection[] = []; existingParsed.sections.forEach((section, index) => { - if (defaultHeadings.has(section.heading)) { + if (defaultHeadings.has(resolveManagedTemplateHeading(section.heading))) { return; } const nextDefaultSection = existingParsed.sections .slice(index + 1) - .find((candidate) => defaultHeadings.has(candidate.heading)); + .find((candidate) => + defaultHeadings.has(resolveManagedTemplateHeading(candidate.heading)), + ); if (nextDefaultSection) { - const bucket = customBeforeDefault.get(nextDefaultSection.heading) ?? []; + const nextDefaultHeading = resolveManagedTemplateHeading( + nextDefaultSection.heading, + ); + const bucket = customBeforeDefault.get(nextDefaultHeading) ?? []; bucket.push(section); - customBeforeDefault.set(nextDefaultSection.heading, bucket); + customBeforeDefault.set(nextDefaultHeading, bucket); return; } @@ -341,7 +459,7 @@ export const mergeTruthDocTemplate = (existingTemplate: string, defaultTemplate: ]); return [ - existingParsed.preamble, + stripManagedFrontmatterFields(existingParsed.preamble), ...mergedSections.map((section) => section.block), ...trailingCustomSections.map((section) => section.block), "", @@ -354,11 +472,8 @@ export const renderBehaviorDocTemplateFile = (): string => { return [ "---", "status: active", - "doc_type: behavior", - "truth_kind: behavior", + "truth_kind: engineering-behavior", `last_reviewed: ${currentDate()}`, - "source_of_truth:", - " - {{source_of_truth}}", "---", "", "# {{title}}", @@ -368,7 +483,7 @@ export const renderBehaviorDocTemplateFile = (): string => { "", "", "{{purpose}}", @@ -384,17 +499,17 @@ export const renderBehaviorDocTemplateFile = (): string => { "", "{{scope}}", "", - "This doc was created from the editable behavior-doc template at {{template_path}}.", + "This doc was created from the editable engineering-behavior template at {{template_path}}.", "", - "## Current Behavior", + "## Current Implementation Behavior", "", "", "", - "{{current_behavior}}", + "{{current_implementation_behavior}}", "", "## Core Rules", "", @@ -423,14 +538,23 @@ export const renderBehaviorDocTemplateFile = (): string => { "", "{{contracts}}", "", - "## Product Decisions", + "## Product Truth Links", + "", + "", + "", + "{{product_truth_links}}", + "", + "## Engineering Decisions", "", "", "", - "{{decision}}", + "{{engineering_decisions}}", "", "## Rationale", "", @@ -459,6 +583,14 @@ export const renderBehaviorDocTemplateFile = (): string => { "", "{{maintenance_notes}}", "", + "## Source References", + "", + "", + "", + "{{source_references}}", + "", ].join("\n"); }; @@ -471,7 +603,7 @@ const sectionSpec = ( const PURPOSE_SECTION = sectionSpec("## Purpose", [ "State the software-engineering outcome this document protects and why the documented surface exists.", "Include durable value, impacted users/systems, and the problem boundary; exclude roadmap, implementation plans, and historical narrative.", - "Keep claims traceable to source_of_truth evidence rather than prose-only assertion.", + "Keep claims traceable to Source References rather than prose-only assertion.", ]); const SCOPE_SECTION = sectionSpec("## Scope", [ @@ -479,11 +611,25 @@ const SCOPE_SECTION = sectionSpec("## Scope", [ "Call out important out-of-scope boundaries here or in Non-Goals; split the doc when it mixes distinct outcomes, lifecycles, contracts, or owners.", ]); -const PRODUCT_DECISIONS_SECTION = sectionSpec("## Product Decisions", [ - "Keep active decisions only, dated inline when added or changed.", - "Capture decisions that shape behavior, interfaces, boundaries, compatibility, risk acceptance, or migration constraints.", - "Replace stale decisions instead of appending historical logs.", -], "decision"); +const PRODUCT_DECISIONS_SECTION = sectionSpec( + "## Product Decisions", + [ + "Keep active decisions only, dated inline when added or changed.", + "Capture decisions that shape behavior, interfaces, boundaries, compatibility, risk acceptance, or migration constraints.", + "Replace stale decisions instead of appending historical logs.", + ], + "decision", +); + +const ENGINEERING_DECISIONS_SECTION = sectionSpec( + "## Engineering Decisions", + [ + "Keep active engineering, architecture, contract, workflow, or operational decisions only, dated inline when added or changed.", + "Do not restate product promises, product rationale, or business decisions here; link product truth instead.", + "Replace stale decisions instead of appending historical logs.", + ], + "engineering_decisions", +); const RATIONALE_SECTION = sectionSpec("## Rationale", [ "Explain why the current behavior, structure, or contract is this way, including tradeoffs and constraints.", @@ -500,20 +646,24 @@ const MAINTENANCE_NOTES_SECTION = sectionSpec("## Maintenance Notes", [ "Keep this operational and current-state focused, not historical.", ]); +const SOURCE_REFERENCES_SECTION = sectionSpec( + "## Source References", + [ + "List source files, tests, configs, generated templates, route files, or product instructions that support current claims.", + ], + "source_references", +); + const renderTypedTruthDocTemplate = ( truthKind: string, - docType: string, title: string, sections: TemplateSectionSpec[], ): string => { return [ "---", "status: active", - `doc_type: ${docType}`, `truth_kind: ${truthKind}`, `last_reviewed: ${currentDate()}`, - "source_of_truth:", - " - {{source_of_truth}}", "---", "", `# ${title}`, @@ -521,15 +671,87 @@ const renderTypedTruthDocTemplate = ( ...renderTemplateSection(PURPOSE_SECTION), ...renderTemplateSection(SCOPE_SECTION), ...sections.flatMap(renderTemplateSection), - ...renderTemplateSection(PRODUCT_DECISIONS_SECTION), + ...renderTemplateSection(ENGINEERING_DECISIONS_SECTION), ...renderTemplateSection(RATIONALE_SECTION), ...renderTemplateSection(NON_GOALS_SECTION), ...renderTemplateSection(MAINTENANCE_NOTES_SECTION), + ...renderTemplateSection(SOURCE_REFERENCES_SECTION), ].join("\n"); }; +const CORE_LANE_INVARIANT = + "Do not make product docs a summary of engineering docs. Do not make engineering docs a detailed version of product docs. Product truth says what must be true and why. Engineering truth says how the repository currently realizes it."; + +const renderProductTruthDocTemplate = ( + truthKind: "product-capability", + title: string, + sections: TemplateSectionSpec[], + includeNonGoals: boolean, +): string => { + return [ + "---", + "status: active", + `truth_kind: ${truthKind}`, + `last_reviewed: ${currentDate()}`, + "---", + "", + `# ${title}`, + "", + "", + "", + ...sections.flatMap(renderTemplateSection), + ...renderTemplateSection(PRODUCT_DECISIONS_SECTION), + ...renderTemplateSection( + sectionSpec( + "## Engineering Realization Links", + [ + "List engineering truth that realizes this product truth; author canonical realized_by links in route YAML, not doc frontmatter.", + "Do not summarize those engineering docs.", + ], + "engineering_realization_links", + ), + ), + ...(includeNonGoals ? renderTemplateSection(NON_GOALS_SECTION) : []), + ...renderTemplateSection(SOURCE_REFERENCES_SECTION), + ].join("\n"); +}; + +export const renderProductCapabilityDocTemplateFile = (): string => { + return renderProductTruthDocTemplate( + "product-capability", + "{{title}}", + [ + sectionSpec("## Capability Promise", [ + "State the single user-visible capability and what must be true for users or stakeholders.", + "Do not describe implementation mechanics here.", + ]), + sectionSpec("## Users And Value", [ + "Describe who benefits from the capability and the durable value it protects.", + "Tie claims to repository evidence, explicit user instruction, or current behavior.", + ]), + sectionSpec("## Capability Scope", [ + "Define what this capability includes and excludes, including product boundary constraints and adjacent systems.", + "Capture important scope limits, ownership boundaries, and non-goal pointers here; keep technical contracts in engineering truth.", + ]), + sectionSpec("## Current Product Behavior", [ + "Describe current implemented user-visible behavior in present tense.", + "Code files may appear in Source References when they directly prove current behavior.", + ]), + sectionSpec("## Acceptance Criteria", [ + "List observable criteria that show the capability promise is currently satisfied.", + "Include criteria that review whether the capability stays within its stated scope and boundary.", + "Use criteria that can be reviewed from repository evidence or explicit product instruction.", + ]), + ], + true, + ); +}; + export const renderContractDocTemplateFile = (): string => { - return renderTypedTruthDocTemplate("contract", "contract", "{{title}}", [ + return renderTypedTruthDocTemplate("engineering-contract", "{{title}}", [ sectionSpec("## Contract Surface", [ "Identify the owned API, CLI, file format, event, protocol, permission boundary, or integration surface.", "State consumers/producers, stability level, and the source files/tests that define the contract.", @@ -558,7 +780,7 @@ export const renderContractDocTemplateFile = (): string => { }; export const renderArchitectureDocTemplateFile = (): string => { - return renderTypedTruthDocTemplate("architecture", "architecture", "{{title}}", [ + return renderTypedTruthDocTemplate("engineering-architecture", "{{title}}", [ sectionSpec("## System Role", [ "Describe the current architectural role of this subsystem/component in the larger system.", "State the primary responsibilities, consumers, providers, and why this boundary exists now.", @@ -587,7 +809,7 @@ export const renderArchitectureDocTemplateFile = (): string => { }; export const renderWorkflowDocTemplateFile = (): string => { - return renderTypedTruthDocTemplate("workflow", "behavior", "{{title}}", [ + return renderTypedTruthDocTemplate("engineering-workflow", "{{title}}", [ sectionSpec("## Triggers", [ "List events, commands, schedules, user actions, webhooks, or dependency signals that start this workflow.", "Include preconditions, authorization requirements, debounce/coalescing behavior, and disabled states when applicable.", @@ -616,7 +838,7 @@ export const renderWorkflowDocTemplateFile = (): string => { }; export const renderOperationsDocTemplateFile = (): string => { - return renderTypedTruthDocTemplate("operations", "behavior", "{{title}}", [ + return renderTypedTruthDocTemplate("engineering-operations", "{{title}}", [ sectionSpec("## Operational Surface", [ "Describe what operators, maintainers, or automated systems can observe or control for this surface.", "Include commands, dashboards, alerts, runbooks, jobs, or operational APIs that define current operations.", @@ -645,7 +867,7 @@ export const renderOperationsDocTemplateFile = (): string => { }; export const renderTestBehaviorDocTemplateFile = (): string => { - return renderTypedTruthDocTemplate("test-behavior", "behavior", "{{title}}", [ + return renderTypedTruthDocTemplate("engineering-test-behavior", "{{title}}", [ sectionSpec("## Test Surface", [ "Define the behavior, contract, architecture, or workflow surface these tests verify.", "Link the canonical truth docs and code paths the tests are meant to protect.", @@ -673,7 +895,10 @@ export const renderTestBehaviorDocTemplateFile = (): string => { ]); }; -const renderTemplate = (template: string, values: Record): string => { +const renderTemplate = ( + template: string, + values: Record, +): string => { return Object.entries(values).reduce((rendered, [key, value]) => { return rendered.split(`{{${key}}}`).join(value); }, template); @@ -698,9 +923,9 @@ export const renderBehaviorLeafDocTemplate = ( "- External contracts should link to the nearest canonical contract doc when one exists.", core_rules: "- Truth README files are indexes; behavior truth belongs in bounded leaf docs.", - current_behavior: + current_implementation_behavior: "- Document current behavior here when implementation changes make repository truth incomplete.", - decision: `- Decision (${today}): Truth README files are indexes; behavior truth belongs in bounded leaf docs.`, + engineering_decisions: `- Decision (${today}): Truth README files are indexes; behavior truth belongs in bounded leaf docs.`, flows_and_states: "- None beyond current behavior.", maintenance_notes: "- Update this doc when routed implementation changes alter current behavior, rules, contracts, or decisions.", @@ -709,10 +934,11 @@ export const renderBehaviorLeafDocTemplate = ( purpose: `Describe why the default ${title.toLowerCase()} behavior surface exists and what outcome it protects.`, rationale: "Bounded leaf docs keep agent context focused and prevent large products from accumulating unreviewable feature manuals.", + product_truth_links: "- None.", scope: `This bounded leaf truth doc owns the default ${title.toLowerCase()} behavior surface created by Truthmark.`, - source_of_truth: sourceOfTruth, + source_references: `- ${sourceOfTruth}`, template_path: BEHAVIOR_DOC_TEMPLATE_PATH, title: `${title} Overview`, - truth_kind: "behavior", + truth_kind: "engineering-behavior", }); }; diff --git a/src/templates/workflow-surfaces.ts b/src/templates/workflow-surfaces.ts index ff53b63..9337258 100644 --- a/src/templates/workflow-surfaces.ts +++ b/src/templates/workflow-surfaces.ts @@ -11,32 +11,47 @@ import { renderHierarchySummary, renderOpenCodeSubagentModeSection, renderTruthDocOwnershipGateSection, - resolveTruthDocsRoot, + resolveEngineeringTruthRoot, + resolveProductTruthRoot, } from "../agents/shared.js"; import { TRUTH_CHECK_EXPLICIT_INVOCATIONS, + renderTruthCheckProcedureBody, + renderTruthCheckReportExample, renderTruthCheckSkillBody, } from "../agents/truth-check.js"; import { TRUTH_DOCUMENT_EXPLICIT_INVOCATIONS, + renderTruthDocumentProcedureBody, + renderTruthDocumentReportExample, renderTruthDocumentSkillBody, } from "../agents/truth-document.js"; import { TRUTH_PREVIEW_EXPLICIT_INVOCATIONS, + renderTruthPreviewProcedureBody, + renderTruthPreviewReportExample, renderTruthPreviewSkillBody, } from "../agents/truth-preview.js"; import { TRUTHMARK_PORTAL_EXPLICIT_INVOCATIONS, + renderTruthmarkPortalProcedureBody, renderTruthmarkPortalSkillBody, } from "../agents/truthmark-portal.js"; import { TRUTH_STRUCTURE_EXPLICIT_INVOCATIONS, + renderTruthStructureProcedureBody, + renderTruthStructureReportExample, renderTruthStructureSkillBody, } from "../agents/truth-structure.js"; import { TRUTH_SYNC_EXPLICIT_INVOCATIONS, + renderTruthSyncProcedureBody, renderTruthSyncSkillBody, } from "../agents/truth-sync.js"; +import { + renderTruthSyncBlockedReport, + renderTruthSyncCompletedReport, +} from "../sync/report.js"; import { TRUTHMARK_WRITE_WORKER_REPORT_FIELDS } from "../agents/write-lease.js"; import { getTruthmarkWorkflow, @@ -209,6 +224,46 @@ ${prompt} `; }; +const workflowSupportFiles = (workflowId: TruthmarkWorkflowId): string[] => { + const workflow = getTruthmarkWorkflow(workflowId); + const definition = WORKFLOW_PACKAGE_DEFINITIONS[workflowId]; + const hasSubagentSupport = + definition.parentRule !== undefined && + ((workflow.subagents?.length ?? 0) > 0 || + (workflow.writeSubagents?.length ?? 0) > 0); + const hasHelperSupport = (workflow.helpers?.length ?? 0) > 0; + + return [ + "support/procedure.md", + "support/report-template.md", + ...(hasSubagentSupport ? ["support/subagents-and-leases.md"] : []), + ...(hasHelperSupport + ? ["helper-manifest.yml", "support/helper-policy.md"] + : []), + ]; +}; + +const renderWorkflowCommandAdapterInstructions = ( + workflowId: TruthmarkWorkflowId, + root: string, + hostName: string, + surfaceKind: "command" | "prompt", +): string => { + const definition = WORKFLOW_PACKAGE_DEFINITIONS[workflowId]; + const canonicalFiles = ["SKILL.md", ...workflowSupportFiles(workflowId)] + .map((supportFile) => `- ${root}/${supportFile}`) + .join("\n"); + + return `This ${surfaceKind} is the ${hostName} entrypoint for ${definition.title}. + +Do not invoke another Truthmark command from here. + +Read these host-local files in order only as needed: +${canonicalFiles} + +If skill entrypoints are unavailable, use the host's direct evidence-first manual fallback procedure.`; +}; + const renderTomlString = (value: string): string => { return `"${value.replace(/\\/gu, "\\\\").replace(/"/gu, '\\"')}"`; }; @@ -311,7 +366,7 @@ const WORKFLOW_PACKAGE_DEFINITIONS: Record< "Use this skill only when the user explicitly asks to preview Truthmark routing or workflow choice before edits.", quickRules: (config) => [ "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 only the truth docs or implementation files needed to preview ownership.`, + `Inspect .truthmark/config.yml and the root route index (${config.truthmark.paths.routesIndex}) first when present; then inspect only child route files under ${config.truthmark.paths.routeAreasRoot}/ that are relevant to the selected scope or changed paths, plus 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.", @@ -371,27 +426,108 @@ const WORKFLOW_PACKAGE_DEFINITIONS: Record< }, }; -const stripWorkflowSkillFrontmatter = (body: string): string => { - return body.replace(/^---\n[\s\S]*?\n---\n\n?/u, "").trim(); +const renderMarkdownExample = (content: string): string => { + return ["```md", content, "```"].join("\n"); }; -const splitWorkflowSupport = ( - body: string, -): { procedure: string; reportTemplate: string } => { - const stripped = stripWorkflowSkillFrontmatter(body); - const marker = "Report completion in this shape:"; - const markerIndex = stripped.indexOf(marker); +const renderWorkflowReportTemplate = ( + workflowId: TruthmarkWorkflowId, + config: TruthmarkConfig, +): string => { + const productTruthRoot = resolveProductTruthRoot(config); + const engineeringTruthRoot = resolveEngineeringTruthRoot(config); - if (markerIndex === -1) { - return { - procedure: stripped, - reportTemplate: "Report completion in the workflow-specific shape.", - }; + switch (workflowId) { + case "truthmark-structure": + return `Report completion in this shape:\n${renderMarkdownExample( + renderTruthStructureReportExample(config), + )}`; + case "truthmark-document": + return `Report completion in this shape:\n${renderMarkdownExample( + renderTruthDocumentReportExample(config), + )}`; + case "truthmark-sync": + return `Report completion in this shape:\n${renderMarkdownExample( + renderTruthSyncCompletedReport({ + changedCode: ["src/auth/session.ts"], + ownershipReviewed: [config.truthmark.paths.routesIndex], + truthDocsUpdated: [`${engineeringTruthRoot}/repository/overview.md`], + evidenceChecked: [ + { + claim: + "Session timeout behavior is documented in the mapped repository truth doc.", + evidence: [ + "src/auth/session.ts:12", + `${config.truthmark.paths.routesIndex}:11`, + ], + result: "supported", + }, + ], + helperScripts: [ + "validate-write-lease: skipped, no write lease used", + ], + notes: ["Updated session timeout behavior."], + }), + )}\nBlocked report example:\n${renderMarkdownExample( + renderTruthSyncBlockedReport({ + reason: "routing repair is not allowed", + manualReviewFiles: [config.truthmark.paths.routesIndex], + nextAction: "update routing metadata and rerun Truth Sync", + }), +)}`; + case "truthmark-preview": + return `Report completion in this shape:\n${renderMarkdownExample( + renderTruthPreviewReportExample(config), + )}`; + case "truthmark-realize": + return `Report completion in this shape:\n\n${renderMarkdownExample(`Truth Realize: completed + +Truth docs used: +- ${productTruthRoot}/capabilities/authentication-session.md +- ${engineeringTruthRoot}/behaviors/authentication-session.md + +Code updated: +- src/auth/session.ts + +Verification: +- npm test -- auth`)}`; + case "truthmark-check": + return `Report completion in this shape:\n\n${renderMarkdownExample( + renderTruthCheckReportExample(config), + )}`; + case "truthmark-portal": + return `Report completion in this shape:\n\n${renderMarkdownExample(`Truthmark Portal: completed + +Output path: +- ${config.truthmark.paths.portalOutput} + +Page count: +- + +Diagrams/assets: +- + +Source docs reviewed: +- + +Skipped/ambiguous docs: +- + +Validation: +- + +Markdown canonical statement: +- Markdown remains canonical; generated Portal HTML is non-canonical presentation only.`)}`; } +}; +const renderWorkflowSupportParts = ( + workflowId: TruthmarkWorkflowId, + config: TruthmarkConfig, +): { procedure: string; reportTemplate: string } => { return { - procedure: stripped.slice(0, markerIndex).trim(), - reportTemplate: stripped.slice(markerIndex).trim(), + procedure: renderWorkflowProcedure(workflowId, config), + reportTemplate: renderWorkflowReportTemplate(workflowId, config), }; }; @@ -435,7 +571,8 @@ const renderHelperPolicySupport = ( helpers: TruthmarkWorkflowHelper[], ): string => { const reportHelperId = - helpers.find((helper) => helper.id.endsWith("-report"))?.id ?? helpers[0]?.id; + helpers.find((helper) => helper.id.endsWith("-report"))?.id ?? + helpers[0]?.id; const helperLines = helpers .map( (helper) => @@ -466,25 +603,25 @@ Helper scripts: ); }; -const renderStandaloneWorkflowSkillBody = ( +const renderWorkflowProcedure = ( workflowId: TruthmarkWorkflowId, config: TruthmarkConfig, ): string => { switch (workflowId) { case "truthmark-structure": - return renderTruthStructureSkillBody(config); + return renderTruthStructureProcedureBody(config); case "truthmark-document": - return renderTruthDocumentSkillBody(config); + return renderTruthDocumentProcedureBody(config); case "truthmark-sync": - return renderTruthSyncSkillBody(config); + return renderTruthSyncProcedureBody(config); case "truthmark-preview": - return renderTruthPreviewSkillBody(config); + return renderTruthPreviewProcedureBody(config); case "truthmark-realize": - return renderTruthmarkRealizeSkillBody(config); + return renderTruthmarkRealizeProcedureBody(config); case "truthmark-check": - return renderTruthCheckSkillBody(config); + return renderTruthCheckProcedureBody(config); case "truthmark-portal": - return renderTruthmarkPortalSkillBody(config); + return renderTruthmarkPortalProcedureBody(config); } }; @@ -618,17 +755,13 @@ export const renderTruthmarkSkillPackage = ({ }): TruthmarkSkillPackageFile[] => { const skillDirectory = skillPath.replace(/\/SKILL\.md$/u, ""); const supportDirectory = `${skillDirectory}/support`; - const { procedure, reportTemplate } = splitWorkflowSupport( - renderStandaloneWorkflowSkillBody(workflowId, config), + const { procedure, reportTemplate } = renderWorkflowSupportParts( + workflowId, + config, ); const subagents = renderWorkflowSubagentSupport(workflowId, host); const helpers = getTruthmarkWorkflow(workflowId).helpers ?? []; - const supportFiles = [ - "support/procedure.md", - "support/report-template.md", - ...(subagents === undefined ? [] : ["support/subagents-and-leases.md"]), - ...(helpers.length === 0 ? [] : ["helper-manifest.yml", "support/helper-policy.md"]), - ]; + const supportFiles = workflowSupportFiles(workflowId); const definition = WORKFLOW_PACKAGE_DEFINITIONS[workflowId]; const files: TruthmarkSkillPackageFile[] = [ { @@ -693,8 +826,11 @@ const appendOpenCodePermissionGlob = (root: string, glob: string): string => { const renderOpenCodeWriterEditAllowRules = ( config: TruthmarkConfig, ): string => { - const truthDocsRoot = normalizeOpenCodePermissionPath( - resolveTruthDocsRoot(config), + const truthDocRoots = Array.from( + new Set([ + normalizeOpenCodePermissionPath(resolveProductTruthRoot(config)), + normalizeOpenCodePermissionPath(resolveEngineeringTruthRoot(config)), + ]), ); const rootRouteIndex = normalizeOpenCodePermissionPath( config.truthmark.paths.routesIndex, @@ -703,7 +839,7 @@ const renderOpenCodeWriterEditAllowRules = ( config.truthmark.paths.routeAreasRoot, ); const allowedPatterns = [ - appendOpenCodePermissionGlob(truthDocsRoot, "/**"), + ...truthDocRoots.map((root) => appendOpenCodePermissionGlob(root, "/**")), rootRouteIndex, appendOpenCodePermissionGlob(areaFilesRoot, "/**/*.md"), ]; @@ -741,7 +877,14 @@ const TRUTHMARK_SUBAGENT_PROFILES = { instructions: `Stay read-only. Audit one bounded Truthmark route, area, or doc shard assigned by the parent. Inspect .truthmark/config.yml and route files only when they exist; then inspect mapped truth docs and relevant implementation files directly. +Use a route-first bounded strategy: narrow audits inspect only the routed area and directly linked counterpart docs; root-wide health first builds a cheap route-map/index from route files, then inspects only mismatches and linked leaves. Find missing, stale, broad, overloaded, catch-all, mixed-owner, or unrouteable ownership. +Validate route ownership against lane-specific roots and route kind: +- confirm mapped truth docs resolve to the correct lane root (product or engineering) for their kind +- flag mismatch between assigned route kind and resolved doc kind (for example, product-capability routed to engineering paths) +- verify route-doc linkage for lane pairings via realized_by and realizes before recommending edits +- inspect product counterparts for engineering docs only when route YAML claims a product relationship, or when the parent explicitly asks for user-visible product coverage +- treat missing product links for user-visible engineering docs as a second-pass diagnostic, not a default full-document read. Do not edit files, stage changes, or propose broad rewrites. Return JSON only with keys: scope, filesReviewed, findings, evidence, confidence, recommendedWorkflow, notes. recommendedWorkflow must be one of: none, truthmark-document, truthmark-structure.`, @@ -767,7 +910,7 @@ Return JSON only with keys: scope, filesReviewed, claimsChecked, evidence, unsup "Read-only Truthmark doc reviewer for shape, decision, rationale, and evidence hygiene.", nicknameCandidates: ["Doc Audit", "Doc Shape", "Doc Check"], instructions: `Stay read-only. -Review assigned canonical truth docs for frontmatter, source_of_truth, required template sections, Evidence checked entries, Product Decisions, and Rationale. +Review assigned canonical truth docs for compact frontmatter, required template sections, final Source References entries, Evidence checked entries, and lane-appropriate decision sections (Product Decisions in product truth, Engineering Decisions in engineering truth). Flag README.md files used as behavior truth targets, mixed-owner docs, and shape repairs that should move to Truth Structure. Do not edit files, stage changes, or rewrite docs. Return JSON only with keys: scope, filesReviewed, findings, evidence, confidence, recommendedWorkflow, notes. @@ -1309,21 +1452,10 @@ truthmark: `; }; -const renderTruthmarkRealizeSkillBody = ( +const renderTruthmarkRealizeProcedureBody = ( config: TruthmarkConfig = defaultAgentConfig(), ): string => { - const truthDocsRoot = resolveTruthDocsRoot(config); - const workflow = getTruthmarkWorkflow("truthmark-realize"); - - return `--- -name: truthmark-realize -description: ${workflow.description} -argument-hint: Optional truth doc path, area, or desired code behavior to realize -user-invocable: true -truthmark-version: ${TRUTHMARK_VERSION} ---- - -# Truthmark Realize + return `# Truthmark Realize Use this skill only when the user explicitly asks to realize truth docs into code. @@ -1354,15 +1486,33 @@ Read and write boundaries: - may read truth docs, routing docs, and relevant functional code - may write functional code only -- must not edit truth docs or truth routing while realizing those docs +- must not edit truth docs or truth routing while realizing those docs`; +}; +const renderTruthmarkRealizeSkillBody = ( + config: TruthmarkConfig = defaultAgentConfig(), +): string => { + const productTruthRoot = resolveProductTruthRoot(config); + const engineeringTruthRoot = resolveEngineeringTruthRoot(config); + const workflow = getTruthmarkWorkflow("truthmark-realize"); + + return `--- +name: truthmark-realize +description: ${workflow.description} +argument-hint: Optional truth doc path, area, or desired code behavior to realize +user-invocable: true +truthmark-version: ${TRUTHMARK_VERSION} +--- + +${renderTruthmarkRealizeProcedureBody(config)} Report completion in this shape: \`\`\`md Truth Realize: completed Truth docs used: -- ${truthDocsRoot}/authentication/session-timeout.md +- ${productTruthRoot}/capabilities/authentication-session.md +- ${engineeringTruthRoot}/behaviors/authentication-session.md Code updated: - src/auth/session.ts @@ -1483,164 +1633,176 @@ truthmark: `; }; -export const renderTruthmarkGeminiStructureCommand = ( - config: TruthmarkConfig = defaultAgentConfig(), +const renderGeminiWorkflowCommand = ( + workflowId: TruthmarkWorkflowId, + root: string, ): string => { - const workflow = getTruthmarkWorkflow("truthmark-structure"); + const workflow = getTruthmarkWorkflow(workflowId); return renderGeminiCommand( workflow.description, - renderTruthStructureSkillBody(config), + renderWorkflowCommandAdapterInstructions( + workflowId, + root, + "Gemini CLI", + "command", + ), + ); +}; + +const renderCopilotWorkflowPrompt = ( + workflowId: TruthmarkWorkflowId, + root: string, +): string => { + const workflow = getTruthmarkWorkflow(workflowId); + + return renderCopilotPromptFile( + workflow.description, + renderWorkflowCommandAdapterInstructions( + workflowId, + root, + "GitHub Copilot", + "prompt", + ), + ); +}; + +export const renderTruthmarkGeminiStructureCommand = ( + config: TruthmarkConfig = defaultAgentConfig(), +): string => { + void config; + return renderGeminiWorkflowCommand( + "truthmark-structure", + ".gemini/skills/truthmark-structure", ); }; export const renderTruthmarkGeminiDocumentCommand = ( config: TruthmarkConfig = defaultAgentConfig(), ): string => { - const workflow = getTruthmarkWorkflow("truthmark-document"); - - return renderGeminiCommand( - workflow.description, - renderTruthDocumentSkillBody(config), + void config; + return renderGeminiWorkflowCommand( + "truthmark-document", + ".gemini/skills/truthmark-document", ); }; export const renderTruthmarkGeminiSyncCommand = ( config: TruthmarkConfig = defaultAgentConfig(), ): string => { - const workflow = getTruthmarkWorkflow("truthmark-sync"); - - return renderGeminiCommand( - workflow.description, - renderTruthSyncSkillBody(config), + void config; + return renderGeminiWorkflowCommand( + "truthmark-sync", + ".gemini/skills/truthmark-sync", ); }; export const renderTruthmarkGeminiRealizeCommand = ( config: TruthmarkConfig = defaultAgentConfig(), ): string => { - const workflow = getTruthmarkWorkflow("truthmark-realize"); - - return renderGeminiCommand( - workflow.description, - renderTruthmarkRealizeSkillBody(config), + void config; + return renderGeminiWorkflowCommand( + "truthmark-realize", + ".gemini/skills/truthmark-realize", ); }; export const renderTruthmarkGeminiCheckCommand = ( config: TruthmarkConfig = defaultAgentConfig(), ): string => { - const workflow = getTruthmarkWorkflow("truthmark-check"); - - return renderGeminiCommand( - workflow.description, - renderTruthCheckSkillBody(config), + void config; + return renderGeminiWorkflowCommand( + "truthmark-check", + ".gemini/skills/truthmark-check", ); }; export const renderTruthmarkGeminiPreviewCommand = ( config: TruthmarkConfig = defaultAgentConfig(), ): string => { - const workflow = getTruthmarkWorkflow("truthmark-preview"); - - return renderGeminiCommand( - workflow.description, - renderTruthPreviewSkillBody(config), + void config; + return renderGeminiWorkflowCommand( + "truthmark-preview", + ".gemini/skills/truthmark-preview", ); }; export const renderTruthmarkGeminiPortalCommand = ( config: TruthmarkConfig = defaultAgentConfig(), ): string => { - const workflow = getTruthmarkWorkflow("truthmark-portal"); - - return renderGeminiCommand( - workflow.description, - renderTruthmarkPortalSkillBody(config), + void config; + return renderGeminiWorkflowCommand( + "truthmark-portal", + ".gemini/skills/truthmark-portal", ); }; export const renderTruthmarkCopilotStructurePrompt = ( config: TruthmarkConfig = defaultAgentConfig(), ): string => { - const workflow = getTruthmarkWorkflow("truthmark-structure"); - - return renderCopilotPromptFile( - workflow.description, - renderTruthStructureSkillBody(config, { - includeCopilotCustomAgentMode: true, - }), + void config; + return renderCopilotWorkflowPrompt( + "truthmark-structure", + ".github/skills/truthmark-structure", ); }; export const renderTruthmarkCopilotDocumentPrompt = ( config: TruthmarkConfig = defaultAgentConfig(), ): string => { - const workflow = getTruthmarkWorkflow("truthmark-document"); - - return renderCopilotPromptFile( - workflow.description, - renderTruthDocumentSkillBody(config, { - includeCopilotCustomAgentMode: true, - }), + void config; + return renderCopilotWorkflowPrompt( + "truthmark-document", + ".github/skills/truthmark-document", ); }; export const renderTruthmarkCopilotSyncPrompt = ( config: TruthmarkConfig = defaultAgentConfig(), ): string => { - const workflow = getTruthmarkWorkflow("truthmark-sync"); - - return renderCopilotPromptFile( - workflow.description, - renderTruthSyncSkillBody(config, { - includeCopilotCustomAgentMode: true, - }), + void config; + return renderCopilotWorkflowPrompt( + "truthmark-sync", + ".github/skills/truthmark-sync", ); }; export const renderTruthmarkCopilotRealizePrompt = ( config: TruthmarkConfig = defaultAgentConfig(), ): string => { - const workflow = getTruthmarkWorkflow("truthmark-realize"); - - return renderCopilotPromptFile( - workflow.description, - renderTruthmarkRealizeSkillBody(config), + void config; + return renderCopilotWorkflowPrompt( + "truthmark-realize", + ".github/skills/truthmark-realize", ); }; export const renderTruthmarkCopilotCheckPrompt = ( config: TruthmarkConfig = defaultAgentConfig(), ): string => { - const workflow = getTruthmarkWorkflow("truthmark-check"); - - return renderCopilotPromptFile( - workflow.description, - renderTruthCheckSkillBody(config, { - includeCopilotCustomAgentMode: true, - }), + void config; + return renderCopilotWorkflowPrompt( + "truthmark-check", + ".github/skills/truthmark-check", ); }; export const renderTruthmarkCopilotPreviewPrompt = ( config: TruthmarkConfig = defaultAgentConfig(), ): string => { - const workflow = getTruthmarkWorkflow("truthmark-preview"); - - return renderCopilotPromptFile( - workflow.description, - renderTruthPreviewSkillBody(config), + void config; + return renderCopilotWorkflowPrompt( + "truthmark-preview", + ".github/skills/truthmark-preview", ); }; export const renderTruthmarkCopilotPortalPrompt = ( config: TruthmarkConfig = defaultAgentConfig(), ): string => { - const workflow = getTruthmarkWorkflow("truthmark-portal"); - - return renderCopilotPromptFile( - workflow.description, - renderTruthmarkPortalSkillBody(config), + void config; + return renderCopilotWorkflowPrompt( + "truthmark-portal", + ".github/skills/truthmark-portal", ); }; diff --git a/src/truth/docs.ts b/src/truth/docs.ts index 4e3a6e7..77f506d 100644 --- a/src/truth/docs.ts +++ b/src/truth/docs.ts @@ -1,5 +1,32 @@ import type { TruthmarkConfig } from "../config/schema.js"; +export type TruthLane = "product" | "engineering"; + +export const PRODUCT_TRUTH_KINDS = ["product-capability"] as const; +export const ENGINEERING_TRUTH_KINDS = [ + "engineering-behavior", + "engineering-contract", + "engineering-workflow", + "engineering-architecture", + "engineering-operations", + "engineering-test-behavior", +] as const; + export const resolveTruthDocsRoot = (config: Pick): string => { - return config.truthmark.paths.truthRoot; + return config.truthmark.paths.engineeringTruthRoot; }; + +export const resolveProductTruthRoot = (config: Pick): string => { + return config.truthmark.paths.productTruthRoot; +}; + +export const resolveEngineeringTruthRoot = ( + config: Pick, +): string => { + return config.truthmark.paths.engineeringTruthRoot; +}; + +export const truthLaneRoots = (config: Pick) => ({ + product: resolveProductTruthRoot(config), + engineering: resolveEngineeringTruthRoot(config), +}); diff --git a/src/truth/source-references.ts b/src/truth/source-references.ts new file mode 100644 index 0000000..527b7f0 --- /dev/null +++ b/src/truth/source-references.ts @@ -0,0 +1,105 @@ +import path from "node:path"; + +import matter from "gray-matter"; + +const repoRootPrefixes = [ + ".codex/", + ".github/", + ".truthmark/", + "docs/", + "src/", + "tests/", +]; +const sourceReferencesHeadingPattern = /^##\s+Source References\s*$/imu; +const nextSecondLevelHeadingPattern = /^##\s+/imu; +const bulletReferencePattern = /^\s*[-*]\s+(.+?)\s*$/u; +const markdownLinkPattern = /^\s*\[[^\]]+\]\(([^)]+)\)\s*$/u; +const backtickPathPattern = /^\s*`([^`]+)`\s*$/u; + +export const normalizeSourceReferencePath = ( + truthDocPath: string, + referencePath: string, +): string => { + const strippedPath = referencePath.split("#")[0]?.trim() ?? ""; + const isRepoRelative = repoRootPrefixes.some((prefix) => + strippedPath.startsWith(prefix), + ); + + if ( + !isRepoRelative && + (strippedPath.startsWith(".") || !strippedPath.includes("/")) + ) { + return path.posix.normalize( + path.posix.join(path.posix.dirname(truthDocPath), strippedPath), + ); + } + + return path.posix.normalize(strippedPath); +}; + +const normalizeReferenceText = (value: string): string => { + const trimmed = value.trim(); + const markdownLinkMatch = markdownLinkPattern.exec(trimmed); + if (markdownLinkMatch) { + return markdownLinkMatch[1]?.trim() ?? ""; + } + + const backtickMatch = backtickPathPattern.exec(trimmed); + if (backtickMatch) { + return backtickMatch[1]?.trim() ?? ""; + } + + return trimmed; +}; + +const parseSourceReferencesSection = (content: string): string[] => { + const headingMatch = sourceReferencesHeadingPattern.exec(content); + if (!headingMatch || typeof headingMatch.index !== "number") { + return []; + } + + const sectionStart = headingMatch.index + headingMatch[0].length; + const afterHeading = content.slice(sectionStart); + const nextHeadingMatch = nextSecondLevelHeadingPattern.exec(afterHeading); + const section = nextHeadingMatch + ? afterHeading.slice(0, nextHeadingMatch.index) + : afterHeading; + const references: string[] = []; + + for (const line of section.split("\n")) { + const bulletMatch = bulletReferencePattern.exec(line); + if (!bulletMatch) { + continue; + } + + const reference = normalizeReferenceText(bulletMatch[1] ?? ""); + if (reference.length > 0 && !reference.startsWith("{{")) { + references.push(reference); + } + } + + return references; +}; + +export const parseSourceReferences = ( + source: string, + truthDocPath: string, +): string[] => { + const parsed = matter(source); + const references = new Set(); + const frontmatterSourceOfTruth = Array.isArray(parsed.data.source_of_truth) + ? parsed.data.source_of_truth + : []; + + for (const entry of frontmatterSourceOfTruth) { + if (typeof entry === "string") { + references.add(normalizeSourceReferencePath(truthDocPath, entry)); + } + } + + for (const entry of parseSourceReferencesSection(parsed.content)) { + references.add(normalizeSourceReferencePath(truthDocPath, entry)); + } + + return [...references].sort(); +}; diff --git a/tests/agents/instructions.test.ts b/tests/agents/instructions.test.ts index 8256fc5..1e02210 100644 --- a/tests/agents/instructions.test.ts +++ b/tests/agents/instructions.test.ts @@ -46,7 +46,7 @@ describe("renderTruthSyncInstructions", () => { const lines = instructions.split("\n"); expect(lines.slice(0, 4).join("\n")).toContain("Truth Sync"); - expect(lines.length).toBeLessThanOrEqual(18); + expect(lines.length).toBeLessThanOrEqual(24); }); it("uses the configured route index in the compact Sync reminder", () => { diff --git a/tests/agents/prompts.test.ts b/tests/agents/prompts.test.ts index 2a8f194..aadcb83 100644 --- a/tests/agents/prompts.test.ts +++ b/tests/agents/prompts.test.ts @@ -22,8 +22,18 @@ describe("renderTruthRealizePrompt", () => { ); expect(prompt).toContain("RepoIndex, RouteMap, ImpactSet, and ContextPack"); expect(prompt).toContain("workflow write boundaries"); + expect(prompt).toContain( + "read product truth under docs/truthmark/product as requirements", + ); + expect(prompt).toContain( + "read engineering truth under docs/truthmark/engineering as implementation context", + ); expect(prompt).toContain("write functional code only"); expect(prompt).toContain("do not edit truth docs or truth routing"); + expect(prompt).toContain("do not write truth docs or truth routing"); + expect(prompt).not.toContain("before writing canonical truth docs"); + expect(prompt).not.toContain("product-lane writes belong"); + expect(prompt).not.toContain("engineering-lane writes belong"); expect(prompt).not.toContain("Truth-doc restructure gate"); expect(prompt).not.toContain("Truth-doc shape repair gate"); expect(prompt).not.toContain("restructure truth docs"); @@ -39,12 +49,16 @@ describe("renderTruthRealizePrompt", () => { it("uses the configured truth root in its example report", () => { const config = createDefaultConfig(); - config.truthmark.paths.truthRoot = "docs/product"; + config.truthmark.paths.productTruthRoot = "docs/product/product"; + config.truthmark.paths.engineeringTruthRoot = "docs/product/engineering"; const prompt = renderTruthRealizePrompt(config); - expect(prompt).toContain("docs/product/authentication/session-timeout.md"); - expect(prompt).not.toContain("docs/truthmark/truth/authentication/session-timeout.md"); + expect(prompt).toContain("docs/product/product/capabilities/authentication-session.md"); + expect(prompt).toContain( + "read engineering truth under docs/product/engineering as implementation context", + ); + expect(prompt).not.toContain("docs/truthmark/product/capabilities/authentication-session.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 aa20559..3c74426 100644 --- a/tests/agents/truth-check.test.ts +++ b/tests/agents/truth-check.test.ts @@ -54,6 +54,18 @@ describe("renderTruthCheckSkillBody", () => { ); expect(skill).toContain("optionally run truthmark check"); expect(skill).toContain("must not require the truthmark binary"); + expect(skill).toContain( + "keep lane and cross-lane checks route-first and bounded", + ); + expect(skill).toContain( + "for a narrow audit, inspect only the routed area and directly linked counterpart docs", + ); + expect(skill).toContain( + "for root-wide truth health, first build a cheap route-map/index from route files", + ); + expect(skill).toContain( + "report missing product links for user-visible engineering docs only as a second-pass review diagnostic", + ); expect(skill).toContain( "support each finding and suggested fix with evidence from config, route files, canonical docs, implementation, templates, or tests", ); @@ -62,7 +74,6 @@ describe("renderTruthCheckSkillBody", () => { ); expect(skill).toContain("Truthmark hierarchy hints:"); expect(skill).toContain("Product Decisions"); - expect(skill).toContain("Rationale"); expect(skill).toContain("Truth Check: completed"); expect(skill).toContain("Files reviewed"); expect(skill).toContain("Issues found"); @@ -125,6 +136,13 @@ describe("Truth Check generated surfaces", () => { expect(routeAuditor).toContain('name = "truth_route_auditor"'); expect(routeAuditor).toContain('sandbox_mode = "read-only"'); expect(routeAuditor).toContain(readOnlyContextBoundary); + expect(routeAuditor).toContain("Use a route-first bounded strategy"); + expect(routeAuditor).toContain( + "inspect product counterparts for engineering docs only when route YAML claims a product relationship", + ); + expect(routeAuditor).toContain( + "missing product links for user-visible engineering docs as a second-pass diagnostic", + ); expect(routeAuditor).toContain("Return JSON only"); expect(routeAuditor).toContain("recommendedWorkflow"); expect(routeAuditor).not.toContain("write truth docs"); @@ -139,7 +157,8 @@ describe("Truth Check generated surfaces", () => { expect(docReviewer).toContain('sandbox_mode = "read-only"'); expect(docReviewer).toContain(readOnlyContextBoundary); expect(docReviewer).toContain("Product Decisions"); - expect(docReviewer).toContain("Rationale"); + expect(docReviewer).toContain("Engineering Decisions"); + expect(docReviewer).toContain("lane-appropriate decision sections"); }); it("renders read-only Claude Code verifier subagents for truth audits", () => { const routeAuditor = renderTruthmarkClaudeRouteAuditorAgent(); @@ -160,7 +179,8 @@ describe("Truth Check generated surfaces", () => { expect(docReviewer).toContain("tools: Read, Grep, Glob, LS"); expect(docReviewer).toContain(readOnlyContextBoundary); expect(docReviewer).toContain("Product Decisions"); - expect(docReviewer).toContain("Rationale"); + expect(docReviewer).toContain("Engineering Decisions"); + expect(docReviewer).toContain("lane-appropriate decision sections"); }); it("renders read-only OpenCode verifier subagents for truth audits", () => { const routeAuditor = renderTruthmarkOpenCodeRouteAuditorAgent(); @@ -182,7 +202,8 @@ describe("Truth Check generated surfaces", () => { expect(docReviewer).toContain("edit: deny"); expect(docReviewer).toContain(readOnlyContextBoundary); expect(docReviewer).toContain("Product Decisions"); - expect(docReviewer).toContain("Rationale"); + expect(docReviewer).toContain("Engineering Decisions"); + expect(docReviewer).toContain("lane-appropriate decision sections"); }); it("renders read-only Copilot verifier agents with bounded context", () => { @@ -199,7 +220,9 @@ describe("Truth Check generated surfaces", () => { expect(claimVerifier).toContain("supported | narrowed | removed | blocked"); expect(docReviewer).toContain("name: truth-doc-reviewer"); expect(docReviewer).toContain(readOnlyContextBoundary); - expect(docReviewer).toContain("Rationale"); + expect(docReviewer).toContain("Product Decisions"); + expect(docReviewer).toContain("Engineering Decisions"); + expect(docReviewer).toContain("lane-appropriate decision sections"); }); it("renders write-capable doc writer agents behind explicit leases", () => { @@ -208,7 +231,8 @@ describe("Truth Check generated surfaces", () => { const claudeWriter = renderTruthmarkClaudeDocWriterAgent(); const copilotWriter = renderTruthmarkCopilotDocWriterAgent(); const customConfig = createDefaultConfig(); - customConfig.truthmark.paths.truthRoot = "product/truth"; + customConfig.truthmark.paths.productTruthRoot = "product/truth"; + customConfig.truthmark.paths.engineeringTruthRoot = "product/engineering"; customConfig.truthmark.paths.routesIndex = "product/routes/index.md"; customConfig.truthmark.paths.routeAreasRoot = "product/routes/areas"; const customOpenCodeWriter = renderTruthmarkOpenCodeDocWriterAgent(customConfig); @@ -219,17 +243,17 @@ 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/truthmark/truth/**": allow'); + expect(openCodeWriter).toContain('"docs/truthmark/engineering/**": 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('"product/engineering/**": allow'); expect(customOpenCodeWriter).toContain( '"product/routes/index.md": allow', ); expect(customOpenCodeWriter).toContain( '"product/routes/areas/**/*.md": allow', ); - expect(customOpenCodeWriter).not.toContain('"docs/truthmark/truth/**": allow'); + expect(customOpenCodeWriter).not.toContain('"docs/truthmark/engineering/**": 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 313e90e..13410da 100644 --- a/tests/agents/truth-document.test.ts +++ b/tests/agents/truth-document.test.ts @@ -57,13 +57,13 @@ describe("renderTruthDocumentSkillBody", () => { "report Ownership reviewed, Structure required, Truth docs split, Truth docs restructured, or Blocked reason", ); expect(skill).toContain( - "Product Decisions/Rationale preservation gate", + "Decision/Rationale preservation gate", ); expect(skill).toContain( - "before any truth-doc split, restructure, or shape repair, inventory existing Product Decisions and Rationale sections", + "before any truth-doc split, restructure, or shape repair, inventory existing Product Decisions, Engineering Decisions, and Rationale sections", ); expect(skill).toContain( - "preserve each current decision and rationale in the bounded owner doc it governs", + "preserve each current decision and rationale in the correct product or engineering lane owner", ); expect(skill).toContain( "if ownership of a decision or rationale is unclear, block with manual-review files", @@ -119,7 +119,7 @@ describe("renderTruthDocumentSkillBody", () => { expect(report).toContain("Truth Document: completed"); expect(report).toContain("src/routing/area-resolver.ts"); - expect(report).toContain("docs/truthmark/truth/contracts.md"); + expect(report).toContain("docs/truthmark/engineering/contracts/routing.md"); expect(report).toContain("Evidence checked"); expect(report).toContain("Claim:"); }); @@ -131,8 +131,8 @@ describe("renderTruthDocumentSkillBody", () => { const skill = renderTruthDocumentSkillBody(config); - expect(skill).toContain("docs/truthmark/truth/contracts.md"); - expect(skill).toContain("docs/truthmark/truth/check-diagnostics.md"); + expect(skill).toContain("docs/truthmark/engineering/contracts/routing.md"); + expect(skill).toContain("docs/truthmark/engineering/behaviors/check-diagnostics.md"); expect(skill).toContain("docs/routes/index.md"); }); }); @@ -190,20 +190,23 @@ describe("Truth Document generated surfaces", () => { expect(renderTruthmarkDocumentSkillMetadata()).toContain( `version: "${TRUTHMARK_VERSION}"`, ); + expect(renderTruthmarkGeminiDocumentCommand()).toContain( + "This command is the Gemini CLI entrypoint for Truthmark Document.", + ); + expect(renderTruthmarkCopilotDocumentPrompt()).toContain( + "This prompt is the GitHub Copilot entrypoint for Truthmark Document.", + ); for (const surface of [ renderTruthmarkGeminiDocumentCommand(), renderTruthmarkCopilotDocumentPrompt(), ]) { + expect(surface).toContain("support/procedure.md"); + expect(surface).toContain("support/report-template.md"); + expect(surface).toContain("Do not invoke another Truthmark command from here."); expect(surface).toContain( - "Validate the report body before adding this validator's own success status; the body may omit `validate-document-report` while validation is pending.", + "If skill entrypoints are unavailable, use the host's direct evidence-first manual fallback procedure.", ); - expect(surface).toContain( - "After `truthmark validate document-report --json` returns `data.validation.ok: true`, append or update `validate-document-report: ran, passed` in the final report.", - ); - expect(surface).toContain( - "If the installed Truthmark CLI is unavailable or the helper is skipped, record `validate-document-report: skipped, ` and manually validate the report shape.", - ); - expect(surface).not.toContain("helper package unavailable"); + expect(surface).not.toContain("render the full workflow"); } }); }); diff --git a/tests/agents/truth-preview.test.ts b/tests/agents/truth-preview.test.ts index 42815f5..0fc51bc 100644 --- a/tests/agents/truth-preview.test.ts +++ b/tests/agents/truth-preview.test.ts @@ -4,6 +4,7 @@ import { renderTruthPreviewSkillBody, } from "../../src/agents/truth-preview.js"; import { + renderTruthmarkSkillPackage, renderTruthmarkPreviewLocalSkill, renderTruthmarkPreviewSkill, renderTruthmarkPreviewSkillMetadata, @@ -36,6 +37,31 @@ describe("renderTruthPreviewSkillBody", () => { expect(skill).toContain("truth_route_auditor"); expect(skill).not.toContain("truth_doc_writer"); }); + + it("bounds route reads to the root route index and relevant child route files", () => { + const skill = renderTruthPreviewSkillBody(); + const packageEntrypoint = renderTruthmarkSkillPackage({ + skillPath: ".agents/skills/truthmark-preview/SKILL.md", + workflowId: "truthmark-preview", + host: "codex", + }).find((file) => file.path.endsWith("/SKILL.md"))?.content; + + expect(skill).toContain( + "- docs/truthmark/routes/areas.md, first, only when present", + ); + expect(skill).toContain( + "- relevant child route files under docs/truthmark/routes/areas/ for the selected scope or changed paths, only when present", + ); + expect(packageEntrypoint).toContain( + "the root route index (docs/truthmark/routes/areas.md) first when present", + ); + expect(packageEntrypoint).toContain( + "only child route files under docs/truthmark/routes/areas/ that are relevant to the selected scope or changed paths", + ); + expect(packageEntrypoint).not.toContain( + "configured route files (docs/truthmark/routes/areas.md; docs/truthmark/routes/areas/)", + ); + }); }); describe("Truth Preview generated surfaces", () => { diff --git a/tests/agents/truth-structure.test.ts b/tests/agents/truth-structure.test.ts index 06bc210..cbc133e 100644 --- a/tests/agents/truth-structure.test.ts +++ b/tests/agents/truth-structure.test.ts @@ -39,10 +39,10 @@ describe("renderTruthStructureSkillBody", () => { expect(lines[0]).toBe("---"); expect(lines[6]).toBe("---"); expect(skill).toContain( - "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 use closed YAML frontmatter bounded by opening and closing --- lines; include status, truth_kind, and last_reviewed inside that frontmatter. Put source references in the final ## Source References section, not in frontmatter.", ); expect(skill).toContain( - "Starter truth docs must include ## Product Decisions and ## Rationale sections.", + "Starter truth docs must use lane-specific templates and keep product and engineering truth in separate files.", ); expect(skill).toContain("When creating or updating a truth doc"); expect(skill).toContain("configured Truthmark templates root"); @@ -54,14 +54,12 @@ describe("renderTruthStructureSkillBody", () => { expect(skill).toContain( "if a truth doc mixes independent owners, route ownership is broad, or a split is required for bounded ownership", ); + expect(skill).toContain("Decision/Rationale preservation gate"); expect(skill).toContain( - "Product Decisions/Rationale preservation gate", + "before any truth-doc split, restructure, or shape repair, inventory existing Product Decisions, Engineering Decisions, and Rationale sections", ); expect(skill).toContain( - "before any truth-doc split, restructure, or shape repair, inventory existing Product Decisions and Rationale sections", - ); - expect(skill).toContain( - "preserve each current decision and rationale in the bounded owner doc it governs", + "preserve each current decision and rationale in the correct product or engineering lane owner", ); expect(skill).toContain( "if ownership of a decision or rationale is unclear, block with manual-review files", @@ -94,29 +92,27 @@ describe("renderTruthStructureSkillBody", () => { ); expect(skill).toContain("docs/truthmark/routes/areas.md"); expect(skill).toContain("create starter truth docs"); - expect(skill).toContain("docs/truthmark/truth/**"); + expect(skill).toContain("docs/truthmark/engineering/**"); expect(skill).not.toContain("docs/architecture/**"); expect(skill).toContain("canonical current-truth destinations"); expect(skill).toContain("Truthmark hierarchy hints:"); expect(skill).toContain("Product Decisions"); expect(skill).toContain("Rationale"); expect(skill).toContain( - "Do not finish topology repair with routed canonical current-truth docs missing Product Decisions or Rationale sections.", + "Do not finish topology repair with mixed product/engineering authority in a single canonical truth doc.", ); expect(skill).toContain( - "If an existing canonical doc lacks either section, add the missing heading beside Current Behavior with a concise current-state placeholder or active decision.", + "If an existing canonical doc has wrong-lane sections, split or move them into the correct product or engineering lane.", ); expect(skill).toContain("Evidence Gate"); - expect(skill).toContain( - "apply the Evidence Gate before finishing", - ); + expect(skill).toContain("apply the Evidence Gate before finishing"); expect(skill).toContain( "support ownership/behavior claims with topology or primary checkout evidence", ); + expect(skill).toContain("remove, narrow, or block unsupported claims"); expect(skill).toContain( - "remove, narrow, or block unsupported claims", + "date active decisions inline when added or changed", ); - expect(skill).toContain("date active decisions inline when added or changed"); expect(skill).toContain("Topology Governance"); expect(skill).toContain("Topology pressure signals"); expect(skill).toContain("one area maps broad code"); @@ -142,9 +138,7 @@ describe("renderTruthStructureSkillBody", () => { "a new package, controller, domain, or product area lacks bounded truth ownership", ); expect(skill).toContain("inspect the named code area"); - expect(skill).toContain( - "infer bounded product or behavior ownership", - ); + expect(skill).toContain("infer bounded product or behavior ownership"); expect(skill).toContain( "choose the owning route when ownership is clear; otherwise propose the route and block for review", ); @@ -163,8 +157,10 @@ describe("renderTruthStructureSkillBody", () => { expect(skill).toContain( "report Truth docs split when one broad or mixed-owner truth doc becomes multiple bounded docs", ); - expect(skill).toContain("bounded leaf truth docs"); - expect(skill).toContain("//.md"); + expect(skill).toContain("bounded truth docs"); + expect(skill).toContain( + "product/capabilities or product/decisions and engineering docs under engineering//.md", + ); expect(skill).toContain("If this skill surface is unavailable"); expect(skill).toContain("Topology decisions"); expect(skill).toContain("Truth Structure: completed"); @@ -184,9 +180,11 @@ describe("renderTruthStructureSkillBody", () => { const report = renderTruthStructureReportExample(config); - expect(report).toContain("docs root: docs/truthmark/truth"); + expect(report).toContain("product docs root: docs/truthmark/product"); expect(report).toContain("docs/routes/index.md"); - expect(report).toContain("docs/truthmark/truth/authentication/session.md"); + expect(report).toContain( + "docs/truthmark/product/capabilities/authentication-session.md", + ); }); it("uses the default truth root consistently when current truth root are absent", () => { @@ -195,7 +193,9 @@ describe("renderTruthStructureSkillBody", () => { const skill = renderTruthStructureSkillBody(config); expect(skill).toContain("managed semantic root"); - expect(skill).toContain("organize docs/truthmark/truth"); + expect(skill).toContain( + "Product truth docs, when present: docs/truthmark/product/**/*.md", + ); 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 e713f6a..8270274 100644 --- a/tests/agents/truth-sync.test.ts +++ b/tests/agents/truth-sync.test.ts @@ -1,9 +1,13 @@ +import { readFileSync } from "node:fs"; + import { describe, expect, it } from "vitest"; import matter from "gray-matter"; import { createDefaultConfig } from "../../src/config/defaults.js"; +import type { TruthmarkWorkflowId } from "../../src/agents/workflow-manifest.js"; import { TRUTH_SYNC_EXPLICIT_INVOCATIONS, + renderTruthSyncProcedureBody, renderTruthSyncSkillBody, renderTruthSyncWorkerPrompt, } from "../../src/agents/truth-sync.js"; @@ -12,6 +16,7 @@ import { renderTruthmarkGeminiSyncCommand, renderTruthmarkSyncClaudeSkill, renderTruthmarkSyncLocalSkill, + renderTruthmarkSkillPackage, renderTruthmarkSyncSkill, renderTruthmarkSyncSkillMetadata, } from "../../src/templates/workflow-surfaces.js"; @@ -139,13 +144,13 @@ describe("renderTruthSyncSkillBody", () => { "report Ownership reviewed, Structure required, Truth docs split, Truth docs restructured, or Blocked reason", ); expect(skillBody).toContain( - "Product Decisions/Rationale preservation gate", + "Decision/Rationale preservation gate", ); expect(skillBody).toContain( - "before any truth-doc split, restructure, or shape repair, inventory existing Product Decisions and Rationale sections", + "before any truth-doc split, restructure, or shape repair, inventory existing Product Decisions, Engineering Decisions, and Rationale sections", ); expect(skillBody).toContain( - "preserve each current decision and rationale in the bounded owner doc it governs", + "preserve each current decision and rationale in the correct product or engineering lane owner", ); expect(skillBody).toContain( "if ownership of a decision or rationale is unclear, block with manual-review files", @@ -163,7 +168,7 @@ describe("renderTruthSyncSkillBody", () => { ); expect(skillBody).not.toContain("# {{title}}"); expect(skillBody).toContain( - "update Product Decisions and Rationale when a behavior change comes from a decision change", + "update Product Decisions only in product truth and Engineering Decisions only in engineering truth when evidence supports the lane-specific decision change", ); expect(skillBody).toContain("Evidence checked"); expect(skillBody).toContain("Claim:"); @@ -186,7 +191,7 @@ describe("renderTruthSyncSkillBody", () => { const skillBody = renderTruthSyncSkillBody(config); - expect(skillBody).toContain("docs/truthmark/truth/repository/overview.md"); + expect(skillBody).toContain("docs/truthmark/engineering/repository/overview.md"); expect(skillBody).toContain("docs/routes/index.md:11"); expect(skillBody).toContain( "verify only truth docs and leased truth routing files changed", @@ -195,6 +200,107 @@ describe("renderTruthSyncSkillBody", () => { }); describe("Truth Sync generated metadata", () => { + it("keeps package procedure support wired to the explicit procedure renderer", () => { + const config = createDefaultConfig(); + const files = renderTruthmarkSkillPackage({ + skillPath: ".agents/skills/truthmark-sync/SKILL.md", + workflowId: "truthmark-sync", + host: "codex", + config, + }); + const procedure = files.find((file) => + file.path.endsWith("/support/procedure.md"), + )?.content; + const reportTemplate = files.find((file) => + file.path.endsWith("/support/report-template.md"), + )?.content; + + expect(procedure).toContain(renderTruthSyncProcedureBody(config)); + expect(procedure).not.toContain("Truth Sync: completed"); + expect(reportTemplate).toContain("Truth Sync: completed"); + expect(reportTemplate).not.toContain("Parent workflow:"); + }); + + it("does not split package support by slicing the standalone workflow body", () => { + const source = readFileSync( + new URL("../../src/templates/workflow-surfaces.ts", import.meta.url), + "utf8", + ); + + expect(source).not.toContain("stripWorkflowSkillFrontmatter"); + expect(source).not.toContain("renderStandaloneWorkflowSkillBody"); + expect(source).not.toContain("slice(0, -reportTemplate.length)"); + expect(source).not.toContain("endsWith(reportTemplate)"); + }); + + + it("renders every workflow package from structured procedure and report support files", () => { + const workflowIds: TruthmarkWorkflowId[] = [ + "truthmark-structure", + "truthmark-document", + "truthmark-sync", + "truthmark-preview", + "truthmark-realize", + "truthmark-check", + "truthmark-portal", + ]; + + for (const workflowId of workflowIds) { + const files = renderTruthmarkSkillPackage({ + skillPath: `.agents/skills/${workflowId}/SKILL.md`, + workflowId, + host: "codex", + }); + const entrypoint = files.find((file) => file.path.endsWith("/SKILL.md")) + ?.content; + const procedure = files.find((file) => + file.path.endsWith("/support/procedure.md"), + )?.content; + const reportTemplate = files.find((file) => + file.path.endsWith("/support/report-template.md"), + )?.content; + + expect(entrypoint, workflowId).toContain("Progressive disclosure:"); + expect(entrypoint, workflowId).toContain("support/procedure.md"); + expect(entrypoint, workflowId).toContain("support/report-template.md"); + expect(procedure, workflowId).toContain("Generated by Truthmark"); + expect(procedure, workflowId).not.toContain( + "Report completion in this shape:", + ); + expect(reportTemplate, workflowId).toContain( + "Report completion in this shape:", + ); + } + }); + + it("renders package support files from structured report parts instead of the first marker text", () => { + const config = createDefaultConfig(); + config.truthmark.paths.routesIndex = + "docs/Report completion in this shape:/areas.md"; + + const files = renderTruthmarkSkillPackage({ + skillPath: ".agents/skills/truthmark-sync/SKILL.md", + workflowId: "truthmark-sync", + host: "codex", + config, + }); + const procedure = files.find((file) => + file.path.endsWith("/support/procedure.md"), + )?.content; + const reportTemplate = files.find((file) => + file.path.endsWith("/support/report-template.md"), + )?.content; + + expect(procedure).toContain("Parent post-sync verification"); + expect(procedure).toContain( + "docs/Report completion in this shape:/areas.md", + ); + expect(procedure).not.toContain("Truth Sync: completed"); + expect(reportTemplate).toContain("Report completion in this shape:"); + expect(reportTemplate).toContain("Truth Sync: completed"); + expect(reportTemplate).not.toContain("Parent post-sync verification"); + }); + it("carries skip cases in Codex-visible metadata", () => { const metadata = renderTruthmarkSyncSkillMetadata(); @@ -208,19 +314,24 @@ describe("Truth Sync generated metadata", () => { expect(renderTruthmarkCopilotSyncPrompt()).toContain( "description: 'Use automatically at finish-time after functional code changes", ); + expect(renderTruthmarkGeminiSyncCommand()).toContain( + "This command is the Gemini CLI entrypoint for Truthmark Sync.", + ); + expect(renderTruthmarkCopilotSyncPrompt()).toContain( + "This prompt is the GitHub Copilot entrypoint for Truthmark Sync.", + ); for (const surface of [ renderTruthmarkGeminiSyncCommand(), renderTruthmarkCopilotSyncPrompt(), ]) { expect(surface).toContain( - "Validate the report body before adding this validator's own success status; the body may omit `validate-sync-report` while validation is pending.", - ); - expect(surface).toContain( - "After `truthmark validate sync-report --json` returns `data.validation.ok: true`, append or update `validate-sync-report: ran, passed` in the final report.", - ); - expect(surface).toContain( - "If the installed Truthmark CLI is unavailable or the helper is skipped, record `validate-sync-report: skipped, ` and manually validate the report shape.", + "If skill entrypoints are unavailable, use the host's direct evidence-first manual fallback procedure.", ); + expect(surface).toContain("Do not invoke another Truthmark command from here."); + expect(surface).toContain("support/procedure.md"); + expect(surface).toContain("support/report-template.md"); + expect(surface).toContain("helper-manifest.yml"); + expect(surface).toContain("support/helper-policy.md"); expect(surface).not.toContain("helper package unavailable"); } }); diff --git a/tests/checks/check-truth-kinds.test.ts b/tests/checks/check-truth-kinds.test.ts index d74af94..96afdca 100644 --- a/tests/checks/check-truth-kinds.test.ts +++ b/tests/checks/check-truth-kinds.test.ts @@ -23,8 +23,8 @@ Truth documents: ${"```"}yaml truth_documents: - - path: docs/truthmark/truth/repository/overview.md - kind: contract + - path: docs/truthmark/engineering/repository/overview.md + kind: engineering-contract ${"```"} Code surface: @@ -35,11 +35,11 @@ Update truth when: `, ); await repo.writeFile( - "docs/truthmark/truth/repository/overview.md", + "docs/truthmark/engineering/repository/overview.md", `--- status: active doc_type: behavior -truth_kind: behavior +truth_kind: engineering-behavior last_reviewed: 2026-05-14 source_of_truth: - docs/truthmark/routes/areas/repository.md @@ -76,7 +76,7 @@ Bounded truth is easier to maintain. expect.objectContaining({ category: "frontmatter", severity: "error", - file: "docs/truthmark/truth/repository/overview.md", + file: "docs/truthmark/engineering/repository/overview.md", message: expect.stringContaining("truth_kind"), }), ]), diff --git a/tests/checks/check.test.ts b/tests/checks/check.test.ts index 21a57dd..97f1a73 100644 --- a/tests/checks/check.test.ts +++ b/tests/checks/check.test.ts @@ -15,7 +15,9 @@ const initializeRepo = async (rootDir: string): Promise => { await runInit(rootDir); }; -const scorecardFrom = (result: Awaited>): TruthHealthScorecard => { +const scorecardFrom = ( + result: Awaited>, +): TruthHealthScorecard => { const scorecard = result.data?.scorecard; expect(scorecard).toBeDefined(); return scorecard as TruthHealthScorecard; @@ -25,7 +27,9 @@ const scorecardDimension = ( scorecard: TruthHealthScorecard, id: TruthHealthScorecard["dimensions"][number]["id"], ) => { - const dimension = scorecard.dimensions.find((candidate) => candidate.id === id); + const dimension = scorecard.dimensions.find( + (candidate) => candidate.id === id, + ); expect(dimension).toBeDefined(); return dimension!; }; @@ -50,8 +54,12 @@ describe("runCheck", () => { 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(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(); @@ -88,8 +96,8 @@ describe("runCheck", () => { await runConfig(repo.rootDir, {}); await initializeRepo(repo.rootDir); await repo.writeFile( - "docs/truthmark/truth/repository/overview.md", - `${await repo.readFile("docs/truthmark/truth/repository/overview.md")}\nSee [Missing](docs/missing.md).\n`, + "docs/truthmark/engineering/repository/overview.md", + `${await repo.readFile("docs/truthmark/engineering/repository/overview.md")}\nSee [Missing](docs/missing.md).\n`, ); const result = await runCheck(repo.rootDir); @@ -99,7 +107,9 @@ describe("runCheck", () => { (diagnostic) => diagnostic.category === "links", ), ).toBe(true); - expect(scorecardDimension(scorecardFrom(result), "truth-doc-structure").status).toBe("fail"); + expect( + scorecardDimension(scorecardFrom(result), "truth-doc-structure").status, + ).toBe("fail"); } finally { await repo.cleanup(); } @@ -117,8 +127,8 @@ describe("runCheck", () => { "utf8", ); await repo.writeFile( - "docs/truthmark/truth/repository/overview.md", - `${await repo.readFile("docs/truthmark/truth/repository/overview.md")}\nSee [Outside](../truthmark-outside-link.md).\n`, + "docs/truthmark/engineering/repository/overview.md", + `${await repo.readFile("docs/truthmark/engineering/repository/overview.md")}\nSee [Outside](../truthmark-outside-link.md).\n`, ); const result = await runCheck(repo.rootDir); @@ -127,7 +137,8 @@ describe("runCheck", () => { result.diagnostics.some( (diagnostic) => diagnostic.category === "links" && - diagnostic.file === "docs/truthmark/truth/repository/overview.md", + diagnostic.file === + "docs/truthmark/engineering/repository/overview.md", ), ).toBe(true); } finally { @@ -158,8 +169,8 @@ describe("runCheck", () => { path.resolve(repo.rootDir, "docs", "linked-outside.md"), ); await repo.writeFile( - "docs/truthmark/truth/repository/overview.md", - `${await repo.readFile("docs/truthmark/truth/repository/overview.md")}\nSee [Outside](docs/linked-outside.md).\n`, + "docs/truthmark/engineering/repository/overview.md", + `${await repo.readFile("docs/truthmark/engineering/repository/overview.md")}\nSee [Outside](docs/linked-outside.md).\n`, ); const result = await runCheck(repo.rootDir); @@ -168,7 +179,8 @@ describe("runCheck", () => { result.diagnostics.some( (diagnostic) => diagnostic.category === "links" && - diagnostic.file === "docs/truthmark/truth/repository/overview.md", + diagnostic.file === + "docs/truthmark/engineering/repository/overview.md", ), ).toBe(true); } finally { @@ -242,14 +254,17 @@ ignore: [] ).toBe(true); expect( result.diagnostics.some( - (diagnostic) => - diagnostic.category === "authority", + (diagnostic) => diagnostic.category === "authority", ), ).toBe(false); const scorecard = scorecardFrom(result); - expect(scorecardDimension(scorecard, "routing-coverage").status).toBe("fail"); - expect(scorecardDimension(scorecard, "branch-freshness").status).toBe("not-run"); + 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"), @@ -336,7 +351,7 @@ ignore: [] `version: 1 authority: - docs/truthmark/routes/areas.md - - docs/truthmark/truth/**/*.md + - docs/truthmark/engineering/**/*.md - docs/optional/**/*.md instruction_targets: - AGENTS.md @@ -359,8 +374,7 @@ ignore: [] ).toBe(true); expect( result.diagnostics.some( - (diagnostic) => - diagnostic.category === "authority", + (diagnostic) => diagnostic.category === "authority", ), ).toBe(false); } finally { @@ -378,7 +392,7 @@ ignore: [] "export const session = true;\n", ); await repo.writeFile( - "docs/truthmark/truth/authentication.md", + "docs/truthmark/engineering/authentication.md", "---\nstatus: active\n---\n\n# Authentication\n", ); await repo.writeFile( @@ -388,7 +402,7 @@ ignore: [] ## Authentication Truth documents: -- docs/truthmark/truth/authentication.md +- docs/truthmark/engineering/authentication.md `, ); @@ -407,7 +421,7 @@ Truth documents: ## Authentication Truth documents: -- docs/truthmark/truth/authentication.md +- docs/truthmark/engineering/authentication.md Code surface: - src/billing/** @@ -435,7 +449,7 @@ Update truth when: try { await initializeRepo(repo.rootDir); await repo.writeFile( - "docs/truthmark/truth/platform.md", + "docs/truthmark/engineering/platform.md", "---\nstatus: active\n---\n\n# Platform\n", ); await repo.writeFile( @@ -458,7 +472,7 @@ Update truth when: ## Platform Truth documents: -- docs/truthmark/truth/platform.md +- docs/truthmark/engineering/platform.md Code surface: - web/** @@ -492,7 +506,7 @@ Update truth when: try { await initializeRepo(repo.rootDir); await repo.writeFile( - "docs/truthmark/truth/platform.md", + "docs/truthmark/engineering/platform.md", "---\nstatus: active\n---\n\n# Platform\n", ); await repo.writeFile( @@ -535,7 +549,7 @@ Update truth when: ## Platform Truth documents: -- docs/truthmark/truth/platform.md +- docs/truthmark/engineering/platform.md Code surface: - src/** @@ -577,15 +591,6 @@ Update truth when: `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 @@ -618,7 +623,7 @@ Update truth when: ## Checkout Truth documents: -- docs/truthmark/truth/payments/checkout.md +- docs/truthmark/engineering/payments/checkout.md Code surface: - services/payments/checkout/** @@ -628,7 +633,7 @@ Update truth when: `, ); await repo.writeFile( - "docs/truthmark/truth/payments/checkout.md", + "docs/truthmark/engineering/payments/checkout.md", "# Checkout\n", ); await repo.writeFile( @@ -640,7 +645,8 @@ Update truth when: expect( result.diagnostics.some( - (diagnostic) => diagnostic.category === "config" && diagnostic.severity === "error", + (diagnostic) => + diagnostic.category === "config" && diagnostic.severity === "error", ), ).toBe(false); expect(result.diagnostics).not.toEqual( @@ -731,15 +737,6 @@ platforms: - 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: false @@ -807,15 +804,6 @@ platforms: - gemini-cli 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 @@ -827,7 +815,10 @@ frontmatter: ignore: [] `, ); - await repo.writeFile("docs/truthmark/routes/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", @@ -898,7 +889,7 @@ ignore: [] ## Authentication Truth documents: -- docs/truthmark/truth/missing-authentication.md +- docs/truthmark/engineering/missing-authentication.md Code surface: - src/auth/** @@ -934,7 +925,7 @@ Update truth when: ## Authentication Truth documents: -- docs/truthmark/truth/authentication.md +- docs/truthmark/engineering/authentication.md Code surface: - src/typo/** @@ -968,7 +959,7 @@ Update truth when: "export const session = true;\n", ); await repo.writeFile( - "docs/truthmark/truth/authentication.md", + "docs/truthmark/engineering/authentication.md", "---\nstatus: active\n---\n\n# Authentication\n", ); await repo.writeFile( @@ -978,7 +969,7 @@ Update truth when: ## Authentication Truth documents: -- docs/truthmark/truth/authentication.md +- docs/truthmark/engineering/authentication.md Code surface: - src/auth/** @@ -1016,7 +1007,7 @@ Update truth when: try { await initializeRepo(repo.rootDir); await repo.writeFile( - "docs/truthmark/truth/authentication.md", + "docs/truthmark/engineering/authentication.md", "# Authentication\n", ); @@ -1035,15 +1026,6 @@ Update truth when: `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 @@ -1175,7 +1157,7 @@ Update truth when: ## Broken Area Truth documents: -- docs/truthmark/truth/authentication.md +- docs/truthmark/engineering/authentication.md ## Valid Area @@ -1306,6 +1288,356 @@ Update truth when: } }); + it("does not report missing product links for engineering-only route areas", async () => { + const repo = await createTempRepo(); + + try { + await initializeRepo(repo.rootDir); + await repo.writeFile( + "docs/truthmark/engineering/contracts/internal-cache.md", + "# Internal Cache\n", + ); + await repo.writeFile( + "docs/truthmark/routes/areas.md", + `# Truthmark Areas + +## Internal Cache + +Truth documents: +\`\`\`yaml +truth_documents: + - path: docs/truthmark/engineering/contracts/internal-cache.md + kind: engineering-contract +\`\`\` + +Code surface: +- src/cache/** + +Update truth when: +- internal cache contracts change +`, + ); + + const result = await runCheck(repo.rootDir); + + expect( + result.diagnostics.filter( + (diagnostic) => + diagnostic.category === "traceability" && + diagnostic.severity === "review" && + diagnostic.file === + "docs/truthmark/engineering/contracts/internal-cache.md" && + diagnostic.message.includes( + "User-visible engineering truth document", + ), + ), + ).toEqual([]); + } finally { + await repo.cleanup(); + } + }); + + it("reports missing product links when an engineering doc shares an area with product truth", async () => { + const repo = await createTempRepo(); + + try { + await initializeRepo(repo.rootDir); + await repo.writeFile( + "docs/truthmark/product/payments/checkout.md", + "# Checkout Capability\n", + ); + await repo.writeFile( + "docs/truthmark/engineering/behaviors/checkout.md", + "# Checkout Behavior\n", + ); + await repo.writeFile( + "docs/truthmark/routes/areas.md", + `# Truthmark Areas + +## Checkout + +Truth documents: +\`\`\`yaml +truth_documents: + - path: docs/truthmark/product/payments/checkout.md + kind: product-capability + - path: docs/truthmark/engineering/behaviors/checkout.md + kind: engineering-behavior +\`\`\` + +Code surface: +- src/checkout/** + +Update truth when: +- checkout behavior changes +`, + ); + + const result = await runCheck(repo.rootDir); + + expect(result.diagnostics).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + category: "traceability", + severity: "review", + file: "docs/truthmark/engineering/behaviors/checkout.md", + message: expect.stringContaining( + "User-visible engineering truth document", + ), + }), + ]), + ); + } finally { + await repo.cleanup(); + } + }); + + it("allows product realized_by links without reciprocal engineering realizes links", async () => { + const repo = await createTempRepo(); + + try { + await initializeRepo(repo.rootDir); + await repo.writeFile( + "docs/truthmark/product/payments/checkout.md", + "# Checkout Capability\n", + ); + await repo.writeFile( + "docs/truthmark/engineering/behaviors/checkout.md", + "# Checkout Behavior\n", + ); + await repo.writeFile( + "docs/truthmark/routes/areas.md", + `# Truthmark Areas + +## Checkout + +Truth documents: +\`\`\`yaml +truth_documents: + - path: docs/truthmark/product/payments/checkout.md + kind: product-capability + realized_by: + - docs/truthmark/engineering/behaviors/checkout.md + - path: docs/truthmark/engineering/behaviors/checkout.md + kind: engineering-behavior +\`\`\` + +Code surface: +- src/checkout/** + +Update truth when: +- checkout behavior changes +`, + ); + + const result = await runCheck(repo.rootDir); + const traceabilityErrors = result.diagnostics.filter( + (diagnostic) => + diagnostic.category === "traceability" && + diagnostic.severity === "error" && + diagnostic.file === "docs/truthmark/product/payments/checkout.md", + ); + + expect(traceabilityErrors).toEqual([]); + } finally { + await repo.cleanup(); + } + }); + + it("allows engineering realizes links without reciprocal product realized_by links", async () => { + const repo = await createTempRepo(); + + try { + await initializeRepo(repo.rootDir); + await repo.writeFile( + "docs/truthmark/product/payments/checkout.md", + "# Checkout Capability\n", + ); + await repo.writeFile( + "docs/truthmark/engineering/behaviors/checkout.md", + "# Checkout Behavior\n", + ); + await repo.writeFile( + "docs/truthmark/routes/areas.md", + `# Truthmark Areas + +## Checkout + +Truth documents: +\`\`\`yaml +truth_documents: + - path: docs/truthmark/product/payments/checkout.md + kind: product-capability + - path: docs/truthmark/engineering/behaviors/checkout.md + kind: engineering-behavior + realizes: + - docs/truthmark/product/payments/checkout.md +\`\`\` + +Code surface: +- src/checkout/** + +Update truth when: +- checkout behavior changes +`, + ); + + const result = await runCheck(repo.rootDir); + const traceabilityErrors = result.diagnostics.filter( + (diagnostic) => + diagnostic.category === "traceability" && + diagnostic.severity === "error" && + diagnostic.file === + "docs/truthmark/engineering/behaviors/checkout.md", + ); + + expect(traceabilityErrors).toEqual([]); + } finally { + await repo.cleanup(); + } + }); + + it("merges duplicate route entries with divergent relationship metadata", async () => { + const repo = await createTempRepo(); + + try { + await initializeRepo(repo.rootDir); + await repo.writeFile( + "docs/truthmark/product/payments/checkout.md", + "# Checkout Capability\n", + ); + await repo.writeFile( + "docs/truthmark/engineering/behaviors/checkout.md", + "# Checkout Behavior\n", + ); + await repo.writeFile( + "docs/truthmark/routes/areas.md", + `# Truthmark Areas + +## Checkout + +Truth documents: +\`\`\`yaml +truth_documents: + - path: docs/truthmark/product/payments/checkout.md + kind: product-capability + realized_by: + - docs/truthmark/engineering/behaviors/checkout.md + - path: docs/truthmark/engineering/behaviors/checkout.md + kind: engineering-behavior + realizes: + - docs/truthmark/product/payments/checkout.md + - path: docs/truthmark/engineering/behaviors/checkout.md + kind: engineering-behavior +\`\`\` + +Code surface: +- src/checkout/** + +Update truth when: +- checkout behavior changes +`, + ); + + const result = await runCheck(repo.rootDir); + const duplicateDiagnostics = result.diagnostics.filter( + (diagnostic) => + diagnostic.category === "area-index" && + diagnostic.severity === "error" && + diagnostic.file === + "docs/truthmark/engineering/behaviors/checkout.md" && + diagnostic.message.includes("conflicting relationship metadata"), + ); + const traceabilityErrors = result.diagnostics.filter( + (diagnostic) => + diagnostic.category === "traceability" && + diagnostic.severity === "error" && + diagnostic.file === "docs/truthmark/product/payments/checkout.md", + ); + + expect(duplicateDiagnostics).toEqual([]); + expect(traceabilityErrors).toEqual([]); + } finally { + await repo.cleanup(); + } + }); + + it("merges duplicate route relationship metadata before validating targets", async () => { + const repo = await createTempRepo(); + + try { + await initializeRepo(repo.rootDir); + await repo.writeFile( + "docs/truthmark/product/payments/checkout.md", + "# Checkout Capability\n", + ); + await repo.writeFile( + "docs/truthmark/product/payments/refunds.md", + "# Refunds Capability\n", + ); + await repo.writeFile( + "docs/truthmark/engineering/behaviors/checkout.md", + "# Checkout Behavior\n", + ); + await repo.writeFile( + "docs/truthmark/routes/areas.md", + `# Truthmark Areas + +## Checkout + +Truth documents: +\`\`\`yaml +truth_documents: + - path: docs/truthmark/product/payments/checkout.md + kind: product-capability + realized_by: + - docs/truthmark/engineering/behaviors/checkout.md + - path: docs/truthmark/product/payments/refunds.md + kind: product-capability + realized_by: + - docs/truthmark/engineering/behaviors/checkout.md + - path: docs/truthmark/engineering/behaviors/checkout.md + kind: engineering-behavior + realizes: + - docs/truthmark/product/payments/checkout.md + - path: docs/truthmark/engineering/behaviors/checkout.md + kind: engineering-behavior + realizes: + - docs/truthmark/product/payments/refunds.md +\`\`\` + +Code surface: +- src/checkout/** + +Update truth when: +- checkout behavior changes +`, + ); + + const result = await runCheck(repo.rootDir); + + expect( + result.diagnostics.filter( + (diagnostic) => + diagnostic.category === "area-index" && + diagnostic.file === + "docs/truthmark/engineering/behaviors/checkout.md" && + diagnostic.message.includes("conflicting relationship metadata"), + ), + ).toEqual([]); + expect( + result.diagnostics.filter( + (diagnostic) => + diagnostic.category === "traceability" && + diagnostic.severity === "error" && + diagnostic.file === "docs/truthmark/product/payments/refunds.md", + ), + ).toEqual([]); + } finally { + await repo.cleanup(); + } + }); + it("propagates explicit truth kind metadata from glob routes to matched docs", async () => { const repo = await createTempRepo(); @@ -1313,11 +1645,11 @@ Update truth when: await initializeRepo(repo.rootDir); await repo.writeFile("src/api.ts", "export const api = true;\n"); await repo.writeFile( - "docs/truthmark/truth/api.md", + "docs/truthmark/engineering/api.md", `--- status: active doc_type: behavior -truth_kind: behavior +truth_kind: engineering-behavior last_reviewed: 2026-05-14 source_of_truth: - docs/truthmark/routes/areas.md @@ -1329,11 +1661,11 @@ source_of_truth: API truth. -## Current Behavior +## Current Implementation Behavior API behavior. -## Product Decisions +## Engineering Decisions - Decision (2026-05-14): Test glob kind propagation. @@ -1351,8 +1683,8 @@ This doc intentionally disagrees with the routed glob kind. Truth documents: \`\`\`yaml truth_documents: - - path: docs/truthmark/truth/**/*.md - kind: contract + - path: docs/truthmark/engineering/**/*.md + kind: engineering-contract \`\`\` Code surface: @@ -1370,8 +1702,10 @@ Update truth when: expect.objectContaining({ category: "frontmatter", severity: "error", - file: "docs/truthmark/truth/api.md", - message: expect.stringContaining("routed truth kind contract"), + file: "docs/truthmark/engineering/api.md", + message: expect.stringContaining( + "routed truth kind engineering-contract", + ), }), ]), ); @@ -1523,7 +1857,7 @@ Update truth when: "export const session = true;\n", ); await repo.writeFile( - "docs/truthmark/truth/authentication.md", + "docs/truthmark/engineering/authentication.md", "---\nstatus: active\n---\n\n# Authentication\n", ); await repo.writeFile( @@ -1533,7 +1867,7 @@ Update truth when: ## Auth API Truth documents: -- docs/truthmark/truth/authentication.md +- docs/truthmark/engineering/authentication.md Code surface: - src/auth/** @@ -1544,7 +1878,7 @@ Update truth when: ## Auth/API Truth documents: -- docs/truthmark/truth/missing-authentication.md +- docs/truthmark/engineering/missing-authentication.md Code surface: - src/billing/** @@ -1574,7 +1908,7 @@ Update truth when: try { await initializeRepo(repo.rootDir); await repo.writeFile( - "docs/truthmark/truth/authentication.md", + "docs/truthmark/engineering/authentication.md", "---\nstatus: active\n---\n\n# Authentication\n", ); await repo.writeFile( @@ -1594,15 +1928,6 @@ Update truth when: `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 @@ -1623,7 +1948,7 @@ ignore: ## Authentication Truth documents: - - docs/truthmark/truth/authentication.md + - docs/truthmark/engineering/authentication.md Code surface: - src/auth/** @@ -1640,7 +1965,8 @@ ignore: expect( result.diagnostics.some( - (diagnostic) => diagnostic.category === "config" && diagnostic.severity === "error", + (diagnostic) => + diagnostic.category === "config" && diagnostic.severity === "error", ), ).toBe(false); expect(coverageFiles).toContain("src/unmapped/manual.ts"); @@ -1662,7 +1988,7 @@ ignore: await initializeRepo(repo.rootDir); await repo.writeFile( - "docs/truthmark/truth/authentication.md", + "docs/truthmark/engineering/authentication.md", "---\nstatus: active\n---\n\n# Authentication\n", ); await fs.mkdir(outsideDir, { recursive: true }); @@ -1680,7 +2006,7 @@ ignore: ## Authentication Truth documents: -- docs/truthmark/truth/authentication.md +- docs/truthmark/engineering/authentication.md Code surface: - src/external/** diff --git a/tests/checks/decisions.test.ts b/tests/checks/decisions.test.ts index 573b058..cb06a51 100644 --- a/tests/checks/decisions.test.ts +++ b/tests/checks/decisions.test.ts @@ -7,12 +7,12 @@ import { createTempRepo } from "../helpers/temp-repo.js"; const decisionConfig = createDefaultConfig(); describe("checkDecisionSections", () => { - it("emits review diagnostics for current workflow docs missing decision truth sections", async () => { + it("emits review diagnostics for current workflow docs missing engineering structure sections", async () => { const repo = await createTempRepo(); try { await repo.writeFile( - "docs/truthmark/truth/installed-workflows.md", + "docs/truthmark/engineering/installed-workflows.md", `# Installed Workflows ## Scope @@ -32,12 +32,17 @@ Agents inspect the checkout directly. const diagnostics = await checkDecisionSections( repo.rootDir, decisionConfig, - ["docs/truthmark/truth/installed-workflows.md"], + ["docs/truthmark/engineering/installed-workflows.md"], [ { - path: "docs/truthmark/truth/installed-workflows.md", - kind: "workflow", + path: "docs/truthmark/engineering/installed-workflows.md", + kind: "engineering-workflow", kindSource: "explicit", + lane: "engineering", + laneSource: "inferred", + realizedBy: [], + realizes: [], + dependsOn: [], }, ], ); @@ -46,8 +51,8 @@ Agents inspect the checkout directly. expect.objectContaining({ category: "doc-structure", severity: "review", - file: "docs/truthmark/truth/installed-workflows.md", - message: expect.stringContaining("Product Decisions"), + file: "docs/truthmark/engineering/installed-workflows.md", + message: expect.stringContaining("Purpose"), }), ]); } finally { @@ -60,13 +65,17 @@ Agents inspect the checkout directly. try { await repo.writeFile( - "docs/truthmark/truth/installed-workflows.md", + "docs/truthmark/engineering/installed-workflows.md", `# Installed Workflows ## Scope Installed workflow truth. +## Purpose + +Defines installed workflow runtime behavior. + ## Triggers Explicit workflow invocations. @@ -75,25 +84,46 @@ Explicit workflow invocations. Agents inspect the checkout directly. -## Product Decisions +## Current Implementation Behavior + +Installed workflow surfaces provide the current runtime. + +## Source References + +- AGENTS.md + +## Product Truth Links + +None. + +## Engineering Decisions - Installed skills and AGENTS blocks are the workflow runtime. ## Rationale This keeps installed repositories usable when the Truthmark package is unavailable. + +## Maintenance Notes + +Update when installed workflow surfaces change. `, ); const diagnostics = await checkDecisionSections( repo.rootDir, decisionConfig, - ["docs/truthmark/truth/installed-workflows.md"], + ["docs/truthmark/engineering/installed-workflows.md"], [ { - path: "docs/truthmark/truth/installed-workflows.md", - kind: "workflow", + path: "docs/truthmark/engineering/installed-workflows.md", + kind: "engineering-workflow", kindSource: "explicit", + lane: "engineering", + laneSource: "inferred", + realizedBy: [], + realizes: [], + dependsOn: [], }, ], ); @@ -109,12 +139,15 @@ 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/truthmark/truth/README.md", "# Current Feature Docs\n"); + await repo.writeFile( + "docs/truthmark/engineering/README.md", + "# Current Feature Docs\n", + ); const diagnostics = await checkDecisionSections( repo.rootDir, decisionConfig, - ["docs/notes/future.md", "docs/truthmark/truth/README.md"], + ["docs/notes/future.md", "docs/truthmark/engineering/README.md"], ); expect(diagnostics).toEqual([]); @@ -128,10 +161,10 @@ This keeps installed repositories usable when the Truthmark package is unavailab try { await repo.writeFile( - "docs/truthmark/truth/repository/overview.md", + "docs/truthmark/engineering/repository/overview.md", `# Repository Overview -## Product Decisions +## Engineering Decisions - Decision (2026-05-14): Keep routed truth bounded. @@ -144,12 +177,17 @@ Bounded truth docs are easier to maintain. const diagnostics = await checkDecisionSections( repo.rootDir, decisionConfig, - ["docs/truthmark/truth/repository/overview.md"], + ["docs/truthmark/engineering/repository/overview.md"], [ { - path: "docs/truthmark/truth/repository/overview.md", - kind: "behavior", + path: "docs/truthmark/engineering/repository/overview.md", + kind: "engineering-behavior", kindSource: "explicit", + lane: "engineering", + laneSource: "inferred", + realizedBy: [], + realizes: [], + dependsOn: [], }, ], ); @@ -158,11 +196,13 @@ Bounded truth docs are easier to maintain. expect.objectContaining({ category: "doc-structure", severity: "review", - file: "docs/truthmark/truth/repository/overview.md", + file: "docs/truthmark/engineering/repository/overview.md", message: expect.stringContaining("Scope"), }), ]); - expect(diagnostics[0]?.message).toContain("Current Behavior"); + expect(diagnostics[0]?.message).toContain( + "Current Implementation Behavior", + ); } finally { await repo.cleanup(); } @@ -173,9 +213,9 @@ Bounded truth docs are easier to maintain. try { await repo.writeFile( - "docs/truthmark/truth/contract-surface.md", + "docs/truthmark/engineering/contract-surface.md", `--- -truth_kind: contract +truth_kind: engineering-contract --- # Contract Surface @@ -201,24 +241,26 @@ Structured JSON output. const diagnostics = await checkDecisionSections( repo.rootDir, decisionConfig, - ["docs/truthmark/truth/contract-surface.md"], + ["docs/truthmark/engineering/contract-surface.md"], ); expect(diagnostics).toEqual([ expect.objectContaining({ category: "doc-structure", severity: "review", - file: "docs/truthmark/truth/contract-surface.md", - message: expect.stringContaining("Product Decisions"), + file: "docs/truthmark/engineering/contract-surface.md", + message: expect.stringContaining("Purpose"), }), ]); - expect(diagnostics[0]?.message).not.toContain("Current Behavior"); + expect(diagnostics[0]?.message).toContain( + "Current Implementation Behavior", + ); } finally { await repo.cleanup(); } }); - it("does not apply behavior-specific checks to defaulted routed docs", async () => { + it("applies common engineering structure checks to defaulted routed docs", async () => { const repo = await createTempRepo(); try { @@ -230,7 +272,7 @@ Structured JSON output. Indexes the canonical docs tree. -## Product Decisions +## Engineering Decisions - Keep the docs tree split by role. @@ -247,13 +289,25 @@ This keeps onboarding and current truth separate. [ { path: "docs/README.md", - kind: "behavior", + kind: "engineering-behavior", kindSource: "defaulted", + lane: "engineering", + laneSource: "defaulted", + realizedBy: [], + realizes: [], + dependsOn: [], }, ], ); - expect(diagnostics).toEqual([]); + expect(diagnostics).toEqual([ + expect.objectContaining({ + category: "doc-structure", + severity: "review", + file: "docs/README.md", + message: expect.stringContaining("Source References"), + }), + ]); } finally { await repo.cleanup(); } diff --git a/tests/checks/frontmatter.test.ts b/tests/checks/frontmatter.test.ts index 4e1b791..a251fc6 100644 --- a/tests/checks/frontmatter.test.ts +++ b/tests/checks/frontmatter.test.ts @@ -7,6 +7,114 @@ import { createTempRepo } from "../helpers/temp-repo.js"; const config = createDefaultConfig(); describe("checkFrontmatter", () => { + it("does not require doc_type or truth_lane frontmatter on routed truth docs", async () => { + const repo = await createTempRepo(); + + try { + await repo.writeFile( + "docs/truthmark/engineering/contracts/api.md", + `--- +status: active +truth_kind: engineering-contract +last_reviewed: 2026-05-14 +source_of_truth: + - docs/truthmark/routes/areas/repository.md +--- + +# API Contract + +## Scope + +Contract truth. +`, + ); + + const diagnostics = await checkFrontmatter( + repo.rootDir, + config, + ["docs/truthmark/engineering/contracts/api.md"], + [ + { + path: "docs/truthmark/engineering/contracts/api.md", + kind: "engineering-contract", + kindSource: "explicit", + lane: "engineering", + laneSource: "inferred", + realizedBy: [], + realizes: [], + dependsOn: [], + }, + ], + ); + + expect(diagnostics).not.toEqual( + expect.arrayContaining([ + expect.objectContaining({ + category: "frontmatter", + message: expect.stringContaining("doc_type"), + }), + ]), + ); + expect(diagnostics).not.toEqual( + expect.arrayContaining([ + expect.objectContaining({ + category: "frontmatter", + message: expect.stringContaining("truth_lane"), + }), + ]), + ); + } finally { + await repo.cleanup(); + } + }); + + it("allows truth_lane frontmatter when it matches truth_kind", async () => { + const repo = await createTempRepo(); + + try { + await repo.writeFile( + "docs/truthmark/product/capabilities/search.md", + `--- +status: active +truth_kind: product-capability +truth_lane: product +last_reviewed: 2026-05-14 +source_of_truth: + - docs/truthmark/routes/areas/repository.md +--- + +# Search + +## Capability + +Product truth. +`, + ); + + const diagnostics = await checkFrontmatter( + repo.rootDir, + config, + ["docs/truthmark/product/capabilities/search.md"], + [ + { + path: "docs/truthmark/product/capabilities/search.md", + kind: "product-capability", + kindSource: "explicit", + lane: "product", + laneSource: "inferred", + realizedBy: [], + realizes: [], + dependsOn: [], + }, + ], + ); + + expect(diagnostics).toEqual([]); + } finally { + await repo.cleanup(); + } + }); + it("emits an error when truth_kind disagrees with the routed kind", async () => { const repo = await createTempRepo(); @@ -16,7 +124,7 @@ describe("checkFrontmatter", () => { `--- status: active doc_type: contract -truth_kind: behavior +truth_kind: engineering-behavior last_reviewed: 2026-05-14 source_of_truth: - docs/truthmark/routes/areas/repository.md @@ -41,8 +149,13 @@ Current contract. [ { path: "docs/truthmark/truth/contracts.md", - kind: "contract", + kind: "engineering-contract", kindSource: "explicit", + lane: "engineering", + laneSource: "explicit", + realizedBy: [], + realizes: [], + dependsOn: [], }, ], ); @@ -60,4 +173,81 @@ Current contract. await repo.cleanup(); } }); -}); \ No newline at end of file + + it("emits errors when relationship metadata appears in truth doc frontmatter", async () => { + const repo = await createTempRepo(); + + try { + await repo.writeFile( + "docs/truthmark/engineering/behaviors/search.md", + `--- +status: active +truth_kind: engineering-behavior +last_reviewed: 2026-05-14 +realized_by: + - docs/truthmark/engineering/behaviors/search.md +realizes: + - docs/truthmark/product/capabilities/search.md +depends_on: + - docs/truthmark/engineering/contracts/api.md +source_of_truth: + - docs/truthmark/routes/areas/repository.md +--- + +# Search Behavior + +## Scope + +Engineering truth. +`, + ); + + const diagnostics = await checkFrontmatter( + repo.rootDir, + config, + ["docs/truthmark/engineering/behaviors/search.md"], + [ + { + path: "docs/truthmark/engineering/behaviors/search.md", + kind: "engineering-behavior", + kindSource: "explicit", + lane: "engineering", + laneSource: "inferred", + realizedBy: [], + realizes: [], + dependsOn: [], + }, + ], + ); + + expect(diagnostics).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + category: "frontmatter", + severity: "error", + file: "docs/truthmark/engineering/behaviors/search.md", + message: expect.stringContaining("realized_by"), + }), + expect.objectContaining({ + category: "frontmatter", + severity: "error", + file: "docs/truthmark/engineering/behaviors/search.md", + message: expect.stringContaining("realizes"), + }), + expect.objectContaining({ + category: "frontmatter", + severity: "error", + file: "docs/truthmark/engineering/behaviors/search.md", + message: expect.stringContaining("depends_on"), + }), + ]), + ); + expect(diagnostics).toHaveLength(3); + for (const diagnostic of diagnostics) { + expect(diagnostic.message).toContain("fenced route YAML"); + } + } finally { + await repo.cleanup(); + } + }); +}); diff --git a/tests/config/config-command.test.ts b/tests/config/config-command.test.ts index 82b709b..354c8bf 100644 --- a/tests/config/config-command.test.ts +++ b/tests/config/config-command.test.ts @@ -20,16 +20,11 @@ describe("runConfig", () => { expect(config.version).toBe(2); expect(config).not.toHaveProperty("docs"); expect(config).not.toHaveProperty("authority"); + expect(config.truthmark).not.toHaveProperty("truth"); + expect(config.truthmark).not.toHaveProperty("routes"); + expect(config.truthmark).not.toHaveProperty("templates"); 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, @@ -40,7 +35,11 @@ describe("runConfig", () => { 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("product_root"); + expect(JSON.stringify(config)).not.toContain("engineering_root"); expect(JSON.stringify(config)).not.toContain("docs/templates"); + expect(configText).not.toContain("routes:"); + expect(configText).not.toContain("templates:"); await expect(fs.stat(`${repo.rootDir}/AGENTS.md`)).rejects.toThrow(); await expect(fs.stat(`${repo.rootDir}/docs/truthmark/routes/areas.md`)).rejects.toThrow(); expect(result.diagnostics).toEqual( diff --git a/tests/config/load.test.ts b/tests/config/load.test.ts index 3c5b72f..8287cd2 100644 --- a/tests/config/load.test.ts +++ b/tests/config/load.test.ts @@ -8,15 +8,6 @@ platforms: - codex 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 @@ -50,7 +41,64 @@ describe("loadConfig", () => { } }); - it("rejects unsafe workspace and child paths", async () => { + it("rejects unsupported truth config blocks", async () => { + const repo = await createTempRepo(); + + try { + await repo.writeFile( + ".truthmark/config.yml", + validConfig().replace( + " generated:\n", + " truth:\n root: truth\n product_root: custom-product\n engineering_root: custom-engineering\n generated:\n", + ), + ); + + const result = await loadConfig(repo.rootDir); + + expect(result.status).toBe("invalid"); + expect(result.config).toBeNull(); + expect(result.diagnostics).toContainEqual( + expect.objectContaining({ + message: expect.stringContaining("additional property truth is not allowed"), + }), + ); + } finally { + await repo.cleanup(); + } + }); + + it("rejects unsupported routes and templates config blocks", async () => { + const repo = await createTempRepo(); + + try { + await repo.writeFile( + ".truthmark/config.yml", + validConfig().replace( + " generated:\n", + " routes:\n index: routes/custom.md\n areas: routes/custom\n default_area: custom\n max_delegation_depth: 1\n templates:\n root: custom-templates\n generated:\n", + ), + ); + + const result = await loadConfig(repo.rootDir); + + expect(result.status).toBe("invalid"); + expect(result.config).toBeNull(); + expect(result.diagnostics).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + message: expect.stringContaining("additional property routes is not allowed"), + }), + expect.objectContaining({ + message: expect.stringContaining("additional property templates is not allowed"), + }), + ]), + ); + } finally { + await repo.cleanup(); + } + }); + + it("rejects unsafe workspace paths", async () => { const repo = await createTempRepo(); try { @@ -117,4 +165,49 @@ describe("loadConfig", () => { await repo.cleanup(); } }); + + it("derives fixed internal paths from a custom workspace", async () => { + const repo = await createTempRepo(); + + try { + await repo.writeFile( + ".truthmark/config.yml", + validConfig().replace("workspace: docs/truthmark", "workspace: docs/custom-truthmark"), + ); + + const result = await loadConfig(repo.rootDir); + + expect(result.status).toBe("loaded"); + expect(result.config?.truthmark.routes).toEqual({ + index: "routes/areas.md", + areas: "routes/areas", + defaultArea: "repository", + maxDelegationDepth: 1, + }); + expect(result.config?.truthmark.truth.productRoot).toBe("product"); + expect(result.config?.truthmark.truth.engineeringRoot).toBe("engineering"); + expect(result.config?.truthmark.templates.root).toBe("templates"); + expect(result.config?.truthmark.paths.routesIndex).toBe( + "docs/custom-truthmark/routes/areas.md", + ); + expect(result.config?.truthmark.paths.routeAreasRoot).toBe( + "docs/custom-truthmark/routes/areas", + ); + expect(result.config?.truthmark.paths.productTruthRoot).toBe("docs/custom-truthmark/product"); + expect(result.config?.truthmark.paths.engineeringTruthRoot).toBe( + "docs/custom-truthmark/engineering", + ); + expect(result.config?.truthmark.paths.templatesRoot).toBe( + "docs/custom-truthmark/templates", + ); + expect(result.config?.truthmark.paths.portalOutput).toBe( + "docs/custom-truthmark/generated/portal", + ); + expect(result.config?.truthmark.paths.portalTemplate).toBe( + "docs/custom-truthmark/templates/portal.html", + ); + } finally { + await repo.cleanup(); + } + }); }); diff --git a/tests/evals/workflow-routing.test.ts b/tests/evals/workflow-routing.test.ts index 8007b1b..9537240 100644 --- a/tests/evals/workflow-routing.test.ts +++ b/tests/evals/workflow-routing.test.ts @@ -56,13 +56,41 @@ const WORKFLOW_CONTRACT_PATH_GROUPS = ( 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`], - [WORKFLOW_COMMAND_PATHS[id]], ]; +const WORKFLOW_ADAPTER_PATHS = (id: TruthmarkWorkflowId): readonly string[] => [ + `.github/prompts/${id}.prompt.md`, + WORKFLOW_COMMAND_PATHS[id], +]; + +const GENERATED_SKILL_SURFACE_PATTERN = /\/SKILL\.md$/u; +const GENERATED_COMMAND_ADAPTER_PATTERN = + /^\.github\/prompts\/truthmark-[^/]+\.prompt\.md$|^\.gemini\/commands\/truthmark\/[^/]+\.toml$/u; +const SURFACE_TOKEN_PATTERN = /\S+/gu; +const ADAPTER_NEXT_STEP_SELF_INVOCATION_PATTERN = + /\b(?:run|invoke|open|use|call|execute|dispatch|start)\s+(?:the\s+)?\/?\$?truthmark[-:\s][a-z-]+\b/iu; + +const surfaceTokenCount = (content: string): number => + content.match(SURFACE_TOKEN_PATTERN)?.length ?? 0; + +const surfaceLineCount = (content: string): number => + content.split(/\r?\n/u).length; + +const nonProhibitionLinesMatching = ( + content: string, + pattern: RegExp, +): string[] => + content + .split(/\r?\n/u) + .map((line) => line.trim()) + .filter((line) => pattern.test(line)) + .filter( + (line) => !/\b(?:do not|must not|never|none|without)\b/iu.test(line), + ); + const SURFACE_CONTRACT_TERMS: Record = { "truthmark-sync": [ - "Skip when changes are documentation-only", + "Skip docs-only", "block and recommend Truth Structure", "verify only truth docs and leased truth routing files changed", "Report completion in this shape:", @@ -82,11 +110,8 @@ const SURFACE_CONTRACT_TERMS: Record = { ], "truthmark-document": [ "document existing implemented behavior", - "may write canonical truth docs", - "must not write functional code", - "Report completion in this shape:", - "Implementation reviewed:", - "Evidence checked:", + "Not for functional-code changes", + "topology repair that needs Structure", ], "truthmark-preview": [ "preview Truthmark routing", @@ -212,11 +237,15 @@ 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])); + 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.equivalenceAxes).toEqual([ + ...NO_CLI_FALLBACK_EQUIVALENCE_AXES, + ]); expect(testCase.expectedCliOutcome).toEqual( expect.objectContaining({ decision: expect.stringMatching(/^(apply|block|structure)$/u), @@ -227,9 +256,11 @@ describe("no-CLI fallback eval corpus", () => { ); } - expect(NO_CLI_FALLBACK_EVAL_CASES.map((testCase) => testCase.scenario).join("\n")).not.toMatch( - /token budget|hard budget/iu, - ); + expect( + NO_CLI_FALLBACK_EVAL_CASES.map((testCase) => testCase.scenario).join( + "\n", + ), + ).not.toMatch(/token budget|hard budget/iu); }); }); @@ -287,6 +318,132 @@ describe("generated workflow surface conformance", () => { } }); + it("keeps prompt and command adapters linked to canonical skill packages", () => { + for (const id of TRUTHMARK_WORKFLOW_IDS) { + const workflow = getTruthmarkWorkflow(id); + + for (const path of WORKFLOW_ADAPTER_PATHS(id)) { + const content = surfaces.get(path); + + expect(content, `${path} is generated`).toBeDefined(); + expect(content).toContain(workflow.description); + expect(content).toContain("entrypoint for"); + expect(content).toContain( + "Do not invoke another Truthmark command from here.", + ); + expect(content).toContain( + "If skill entrypoints are unavailable, use the host's direct evidence-first manual fallback procedure.", + ); + expect(content).toContain(`${id}/SKILL.md`); + expect(content).toContain(`${id}/support/procedure.md`); + expect(content).toContain(`${id}/support/report-template.md`); + } + } + }); + + it("keeps read-only generated surfaces free of write-authorizing guidance", () => { + const readOnlySurfacePaths = Array.from(surfaces.keys()).filter( + (path) => + path.includes("truthmark-preview") || + path.includes("truthmark-check") || + path.includes("route-auditor") || + path.includes("claim-verifier") || + path.includes("doc-reviewer"), + ); + const writeAuthorityPatterns = [ + /\bbefore writing\b/iu, + /\bmay write\b/iu, + /\bwrite canonical truth docs\b/iu, + /\bwrite lease\b/iu, + ]; + + expect(readOnlySurfacePaths.length).toBeGreaterThan(0); + for (const path of readOnlySurfacePaths) { + const content = surfaces.get(path) ?? ""; + + for (const pattern of writeAuthorityPatterns) { + expect(nonProhibitionLinesMatching(content, pattern), path).toEqual([]); + } + } + }); + + it("keeps Truth Realize surfaces from inheriting truth-doc write instructions", () => { + const realizeSurfacePaths = Array.from(surfaces.keys()).filter( + (path) => + path.includes("truthmark-realize") && + (path.endsWith("/SKILL.md") || + path.endsWith("/support/procedure.md") || + path.startsWith(".github/prompts/") || + path.startsWith(".gemini/commands/")), + ); + + expect(realizeSurfacePaths.length).toBeGreaterThan(0); + for (const path of realizeSurfacePaths) { + const content = surfaces.get(path) ?? ""; + + expect( + nonProhibitionLinesMatching( + content, + /\b(?:write|edit|update|patch|create)\b.*\b(?:truth docs?|truth routing|canonical truth docs?)\b/iu, + ), + path, + ).toEqual([]); + if ( + path.endsWith("/SKILL.md") || + path.endsWith("/support/procedure.md") + ) { + expect(content, path).toMatch( + /\b(?:do not|must not|never)\b.*\b(?:edit|write|update)\b.*\b(?:truth docs?|truth routing)\b/iu, + ); + } + } + }); + + it("keeps host command adapters from self-recursive next steps", () => { + for (const id of TRUTHMARK_WORKFLOW_IDS) { + for (const path of WORKFLOW_ADAPTER_PATHS(id)) { + const content = surfaces.get(path); + + expect(content, `${path} is generated`).toBeDefined(); + expect(content, path).not.toMatch( + ADAPTER_NEXT_STEP_SELF_INVOCATION_PATTERN, + ); + } + } + }); + + it("keeps generated skills and command adapters under deterministic size ceilings", () => { + const ceilings = [ + { + pattern: GENERATED_SKILL_SURFACE_PATTERN, + maxLines: 45, + maxTokens: 350, + }, + { + pattern: GENERATED_COMMAND_ADAPTER_PATTERN, + maxLines: 25, + maxTokens: 125, + }, + ]; + + for (const [path, content] of surfaces) { + const ceiling = ceilings.find(({ pattern }) => pattern.test(path)); + + if (ceiling === undefined) { + continue; + } + + expect( + surfaceLineCount(content), + `${path} line count`, + ).toBeLessThanOrEqual(ceiling.maxLines); + expect( + surfaceTokenCount(content), + `${path} token count`, + ).toBeLessThanOrEqual(ceiling.maxTokens); + } + }); + it("keeps write-workflow no-CLI fallback route-first and non-expansive", () => { const writeWorkflowExpectations: Record< | "truthmark-sync" @@ -325,7 +482,9 @@ describe("generated workflow surface conformance", () => { ], }; - for (const [id, expectedTerms] of Object.entries(writeWorkflowExpectations)) { + 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(); diff --git a/tests/evidence/validate.test.ts b/tests/evidence/validate.test.ts index 7f2ad8d..0ba8a11 100644 --- a/tests/evidence/validate.test.ts +++ b/tests/evidence/validate.test.ts @@ -18,7 +18,9 @@ describe("validateEvidenceReferences", () => { "---\nstatus: active\nsource_of_truth:\n - ../../src/missing.ts\n---\n# Sample\n", ); - const diagnostics = await validateEvidenceReferences(repo.rootDir, ["docs/truthmark/truth/sample.md"]); + const diagnostics = await validateEvidenceReferences(repo.rootDir, [ + "docs/truthmark/truth/sample.md", + ]); expect(diagnostics).toContainEqual( expect.objectContaining({ @@ -39,7 +41,9 @@ describe("validateEvidenceReferences", () => { "---\nstatus: active\nsource_of_truth:\n - ../../../src/**/*.ts\n---\n# Sample\n", ); - const diagnostics = await validateEvidenceReferences(repo.rootDir, ["docs/truthmark/truth/sample.md"]); + const diagnostics = await validateEvidenceReferences(repo.rootDir, [ + "docs/truthmark/truth/sample.md", + ]); expect(diagnostics).toEqual([]); }); @@ -54,11 +58,76 @@ describe("validateEvidenceReferences", () => { "---\nstatus: active\nsource_of_truth:\n - overview.md\n---\n# Sample\n", ); - const diagnostics = await validateEvidenceReferences(repo.rootDir, ["docs/truthmark/truth/sample.md"]); + const diagnostics = await validateEvidenceReferences(repo.rootDir, [ + "docs/truthmark/truth/sample.md", + ]); expect(diagnostics).toEqual([]); }); + it("validates final Source References bullets as traceability evidence", 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/valid.md", + `--- +status: active +truth_kind: engineering-behavior +last_reviewed: 2026-06-14 +--- + +# Valid + +## Current Implementation Behavior + +Uses the current source file. + +## Source References + +- ../../../src/index.ts +`, + ); + await repo.writeFile( + "docs/truthmark/truth/missing.md", + `--- +status: active +truth_kind: engineering-behavior +last_reviewed: 2026-06-14 +--- + +# Missing + +## Current Implementation Behavior + +References a missing file. + +## Source References + +- ../../../src/missing.ts +`, + ); + + const diagnostics = await validateEvidenceReferences(repo.rootDir, [ + "docs/truthmark/truth/valid.md", + "docs/truthmark/truth/missing.md", + ]); + + expect(diagnostics).toContainEqual( + expect.objectContaining({ + category: "source-traceability", + severity: "error", + file: "docs/truthmark/truth/missing.md", + }), + ); + expect(diagnostics).not.toContainEqual( + expect.objectContaining({ + file: "docs/truthmark/truth/valid.md", + }), + ); + }); + it("reports evidence line spans outside the file even without a content hash", async () => { const repo = await createTempRepo(); repos.push(repo); @@ -80,7 +149,9 @@ evidence: `, ); - const diagnostics = await validateEvidenceReferences(repo.rootDir, ["docs/truthmark/truth/sample.md"]); + const diagnostics = await validateEvidenceReferences(repo.rootDir, [ + "docs/truthmark/truth/sample.md", + ]); expect(diagnostics).toContainEqual( expect.objectContaining({ diff --git a/tests/fs/paths.test.ts b/tests/fs/paths.test.ts index f0ae97c..ffc964f 100644 --- a/tests/fs/paths.test.ts +++ b/tests/fs/paths.test.ts @@ -11,19 +11,26 @@ describe("repo path writes", () => { const repo = await createTempRepo(); try { - const outsideDir = path.resolve(repo.rootDir, "..", "truthmark-paths-write-outside"); + const outsideDir = path.resolve( + repo.rootDir, + "..", + "truthmark-paths-write-outside", + ); await fs.mkdir(outsideDir, { recursive: true }); await fs.symlink(outsideDir, path.join(repo.rootDir, "docs")); - await expect(writeRepoFile(repo.rootDir, "docs/escaped.md", "# Escaped\n")).rejects.toThrow( - "must stay inside the repository root", - ); + await expect( + writeRepoFile(repo.rootDir, "docs/escaped.md", "# Escaped\n"), + ).rejects.toThrow("must stay inside the repository root"); } finally { - await fs.rm(path.resolve(repo.rootDir, "..", "truthmark-paths-write-outside"), { - force: true, - recursive: true, - }); + await fs.rm( + path.resolve(repo.rootDir, "..", "truthmark-paths-write-outside"), + { + force: true, + recursive: true, + }, + ); await repo.cleanup(); } }); @@ -32,36 +39,57 @@ describe("repo path writes", () => { const repo = await createTempRepo(); try { - const outsideDir = path.resolve(repo.rootDir, "..", "truthmark-paths-ensure-outside"); + const outsideDir = path.resolve( + repo.rootDir, + "..", + "truthmark-paths-ensure-outside", + ); await fs.mkdir(outsideDir, { recursive: true }); await fs.symlink(outsideDir, path.join(repo.rootDir, "docs")); - await expect(ensureRepoFile(repo.rootDir, "docs/escaped.md", "# Escaped\n")).rejects.toThrow( - "must stay inside the repository root", - ); + await expect( + ensureRepoFile(repo.rootDir, "docs/escaped.md", "# Escaped\n"), + ).rejects.toThrow("must stay inside the repository root"); } finally { - await fs.rm(path.resolve(repo.rootDir, "..", "truthmark-paths-ensure-outside"), { - force: true, - recursive: true, - }); + await fs.rm( + path.resolve(repo.rootDir, "..", "truthmark-paths-ensure-outside"), + { + force: true, + recursive: true, + }, + ); await repo.cleanup(); } }); it("rejects ensureRepoFile when the target is a broken symlink outside the repo", async () => { const repo = await createTempRepo(); - const outsidePath = path.resolve(repo.rootDir, "..", "truthmark-paths-broken-link.md"); + const outsidePath = path.resolve( + repo.rootDir, + "..", + "truthmark-paths-broken-link.md", + ); try { await repo.writeFile("docs/truthmark/templates/.keep", ""); await fs.symlink( outsidePath, - path.join(repo.rootDir, "docs", "truthmark", "templates", "behavior-doc.md"), + path.join( + repo.rootDir, + "docs", + "truthmark", + "templates", + "engineering-behavior.md", + ), ); await expect( - ensureRepoFile(repo.rootDir, "docs/truthmark/templates/behavior-doc.md", "# Template\n"), + ensureRepoFile( + repo.rootDir, + "docs/truthmark/templates/engineering-behavior.md", + "# Template\n", + ), ).rejects.toThrow("must stay inside the repository root"); await expect(fs.stat(outsidePath)).rejects.toThrow(); } finally { diff --git a/tests/impact/build.test.ts b/tests/impact/build.test.ts index 045d512..f5ac1b5 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/truthmark/truth/repository/overview.md"; + const truthDocPath = "docs/truthmark/engineering/repository/overview.md"; await repo.writeFile( truthDocPath, `${await repo.readFile(truthDocPath)}\nUpdated direct truth-doc edit.\n`, diff --git a/tests/init/init.test.ts b/tests/init/init.test.ts index 99d3e27..7650660 100644 --- a/tests/init/init.test.ts +++ b/tests/init/init.test.ts @@ -58,15 +58,15 @@ describe("runInit", () => { expect(config.platforms.length).toBeGreaterThan(0); expect(config.truthmark).toMatchObject({ workspace: "docs/truthmark", - routes: { - index: "routes/areas.md", - areas: "routes/areas", - default_area: "repository", - max_delegation_depth: 1, + generated: { + portal: { + enabled: false, + }, }, - truth: { root: "truth" }, - templates: { root: "templates" }, }); + expect(config.truthmark).not.toHaveProperty("routes"); + expect(config.truthmark).not.toHaveProperty("templates"); + expect(config.truthmark).not.toHaveProperty("truth"); await expect( fs.stat(`${repo.rootDir}/.truthmark/local.example.yml`), ).rejects.toThrow(); @@ -87,82 +87,117 @@ describe("runInit", () => { ).toContain("Truth documents:"); expect( await repo.readFile("docs/truthmark/routes/areas/repository.md"), - ).toContain("path: docs/truthmark/truth/repository/overview.md"); + ).toContain("path: docs/truthmark/engineering/repository/overview.md"); expect( await repo.readFile("docs/truthmark/routes/areas/repository.md"), - ).toContain("kind: behavior"); + ).toContain("kind: engineering-behavior"); expect( await repo.readFile("docs/truthmark/routes/areas/repository.md"), - ).not.toContain("- docs/truthmark/truth/repository/overview.md"); + ).not.toContain("- docs/truthmark/engineering/repository/overview.md"); expect( 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/truthmark/truth/README.md")).toContain("index"); - expect(await repo.readFile("docs/truthmark/templates/behavior-doc.md")).toContain( - "# {{title}}", - ); - expect(await repo.readFile("docs/truthmark/templates/behavior-doc.md")).toContain( - "## Current Behavior", - ); - expect(await repo.readFile("docs/truthmark/templates/behavior-doc.md")).toContain( - "## Scope", - ); - expect(await repo.readFile("docs/truthmark/templates/behavior-doc.md")).toContain( - "{{scope}}", - ); - expect(await repo.readFile("docs/truthmark/templates/behavior-doc.md")).toContain( - "## Core Rules", - ); - expect(await repo.readFile("docs/truthmark/templates/behavior-doc.md")).toContain( - "## Flows And States", - ); - expect(await repo.readFile("docs/truthmark/templates/behavior-doc.md")).toContain( - "Split into another leaf doc when content introduces", - ); - expect(await repo.readFile("docs/truthmark/truth/repository/README.md")).toContain( - "Repository Truth Docs", - ); - expect(await repo.readFile("docs/truthmark/truth/repository/README.md")).toContain( - "index", + ).not.toContain("- docs/truthmark/engineering/README.md"); + expect( + await repo.readFile("docs/truthmark/engineering/README.md"), + ).toContain("Truth Docs"); + expect( + await repo.readFile("docs/truthmark/engineering/README.md"), + ).toContain( + "Keep engineering truth in bounded behavior, contract, architecture, workflow, operations, and test docs.", ); expect( - await repo.readFile("docs/truthmark/truth/repository/overview.md"), + await repo.readFile("docs/truthmark/engineering/README.md"), + ).not.toContain("/.md"); + expect( + await repo.readFile("docs/truthmark/product/README.md"), + ).toContain("Keep product truth in bounded capability docs."); + expect( + await repo.readFile("docs/truthmark/product/README.md"), + ).not.toContain("/.md"); + expect( + await repo.readFile("docs/truthmark/engineering/README.md"), + ).toContain("index"); + expect( + await repo.readFile("docs/truthmark/templates/engineering-behavior.md"), + ).toContain("# {{title}}"); + expect( + await repo.readFile("docs/truthmark/templates/engineering-behavior.md"), + ).toContain("## Current Implementation Behavior"); + expect( + await repo.readFile("docs/truthmark/templates/engineering-behavior.md"), + ).toContain("## Scope"); + expect( + await repo.readFile("docs/truthmark/templates/engineering-behavior.md"), + ).toContain("{{scope}}"); + expect( + await repo.readFile("docs/truthmark/templates/engineering-behavior.md"), + ).toContain("## Core Rules"); + expect( + await repo.readFile("docs/truthmark/templates/engineering-behavior.md"), + ).toContain("## Flows And States"); + expect( + await repo.readFile("docs/truthmark/templates/engineering-behavior.md"), + ).toContain("Split into another leaf doc when content introduces"); + expect( + await repo.readFile("docs/truthmark/engineering/repository/README.md"), + ).toContain("Repository Truth Docs"); + expect( + await repo.readFile("docs/truthmark/engineering/repository/README.md"), + ).toContain("index"); + expect( + await repo.readFile( + "docs/truthmark/engineering/repository/overview.md", + ), ).toContain("# Repository Overview"); expect( - await repo.readFile("docs/truthmark/truth/repository/overview.md"), + await repo.readFile( + "docs/truthmark/engineering/repository/overview.md", + ), ).toContain( - "This doc was created from the editable behavior-doc template at docs/truthmark/templates/behavior-doc.md.", + "This doc was created from the editable engineering-behavior template at docs/truthmark/templates/engineering-behavior.md.", ); expect( - await repo.readFile("docs/truthmark/truth/repository/overview.md"), - ).toContain("## Current Behavior"); + await repo.readFile( + "docs/truthmark/engineering/repository/overview.md", + ), + ).toContain("## Current Implementation Behavior"); expect( - await repo.readFile("docs/truthmark/truth/repository/overview.md"), + await repo.readFile( + "docs/truthmark/engineering/repository/overview.md", + ), ).toContain("## Purpose"); expect( - (await repo.readFile("docs/truthmark/truth/repository/overview.md")).match( - /## Scope/g, - ), + ( + await repo.readFile( + "docs/truthmark/engineering/repository/overview.md", + ) + ).match(/## Scope/g), ).toHaveLength(1); expect( - await repo.readFile("docs/truthmark/truth/repository/overview.md"), + await repo.readFile( + "docs/truthmark/engineering/repository/overview.md", + ), ).toContain("## Non-Goals"); expect( - await repo.readFile("docs/truthmark/truth/repository/overview.md"), + await repo.readFile( + "docs/truthmark/engineering/repository/overview.md", + ), ).toContain("## Maintenance Notes"); expect( - await repo.readFile("docs/truthmark/truth/repository/overview.md"), + await repo.readFile( + "docs/truthmark/engineering/repository/overview.md", + ), ).not.toContain("{{"); expect( - await repo.readFile("docs/truthmark/truth/repository/overview.md"), - ).toContain("## Product Decisions"); + await repo.readFile( + "docs/truthmark/engineering/repository/overview.md", + ), + ).toContain("## Engineering Decisions"); expect( - await repo.readFile("docs/truthmark/truth/repository/overview.md"), + await repo.readFile( + "docs/truthmark/engineering/repository/overview.md", + ), ).toContain("## Rationale"); - const agents = await repo.readFile("AGENTS.md"); const structureSkill = await repo.readFile( ".agents/skills/truthmark-structure/SKILL.md", @@ -224,6 +259,9 @@ describe("runInit", () => { const syncCopilotPrompt = await repo.readFile( ".github/prompts/truthmark-sync.prompt.md", ); + const syncCopilotSubagents = await repo.readFile( + ".github/skills/truthmark-sync/support/subagents-and-leases.md", + ); const realizeSkill = await repo.readFile( ".agents/skills/truthmark-realize/SKILL.md", ); @@ -340,7 +378,9 @@ describe("runInit", () => { expect(agents).toContain("Hierarchy hints: config .truthmark/config.yml"); 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( + "Truth docs: docs/truthmark/product/**/*.md and docs/truthmark/engineering/**/*.md", + ); expect(agents).toContain( "Decisions live in the canonical doc they govern", ); @@ -421,14 +461,18 @@ describe("runInit", () => { expect(syncHelperManifest).toContain("- sync-report"); expect(syncHelperManifest).toContain("- "); expect(syncHelperManifest).toContain("- --json"); - expect(syncHelperManifest).not.toContain("cd .agents/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(".agents/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"); @@ -438,7 +482,9 @@ describe("runInit", () => { expect(syncSkill).toContain( "Inspect .truthmark/config.yml and configured route files", ); - expect(syncSkill).toContain("then inspect relevant canonical docs directly"); + expect(syncSkill).toContain( + "then inspect relevant canonical docs directly", + ); expect(syncSkill).not.toContain(".truthmark/local.yml"); expect(syncSkill).not.toContain("truth_sync.sync_agent"); expect(syncSkill).not.toContain( @@ -459,13 +505,26 @@ describe("runInit", () => { expect(syncOpenCodeSubagents).toContain("@truth-claim-verifier"); expect(syncOpenCodeSubagents).toContain("@truth-doc-writer"); expect( - await repo.readFile(".opencode/skills/truthmark-sync/helper-manifest.yml"), + await repo.readFile( + ".opencode/skills/truthmark-sync/helper-manifest.yml", + ), ).toContain("validate-sync-report:"); - expect(syncCopilotPrompt).toContain("Copilot custom-agent mode:"); - expect(syncCopilotPrompt).toContain("@truth-route-auditor"); - expect(syncCopilotPrompt).toContain("@truth-claim-verifier"); - expect(syncCopilotPrompt).toContain("@truth-doc-writer"); - expect(syncCopilotPrompt).not.toContain("scripts/validate-sync-report.mjs"); + expect(syncCopilotPrompt).toContain( + "This prompt is the GitHub Copilot entrypoint for Truthmark Sync.", + ); + expect(syncCopilotPrompt).toContain( + "Do not invoke another Truthmark command from here.", + ); + expect(syncCopilotPrompt).toContain( + ".github/skills/truthmark-sync/support/subagents-and-leases.md", + ); + expect(syncCopilotSubagents).toContain("Copilot custom-agent mode:"); + expect(syncCopilotSubagents).toContain("@truth-route-auditor"); + expect(syncCopilotSubagents).toContain("@truth-claim-verifier"); + expect(syncCopilotSubagents).toContain("@truth-doc-writer"); + expect(syncCopilotPrompt).not.toContain( + "scripts/validate-sync-report.mjs", + ); expect(syncClaudeSkill).toContain("name: truthmark-sync"); expect(syncClaudeSkill).toContain( "Use this skill automatically before finishing", @@ -477,7 +536,9 @@ describe("runInit", () => { expect(syncClaudeSubagents).toContain("truth-claim-verifier subagent"); expect(syncClaudeSubagents).toContain("truth-doc-writer subagent"); expect( - await repo.readFile(".claude/skills/truthmark-sync/helper-manifest.yml"), + await repo.readFile( + ".claude/skills/truthmark-sync/helper-manifest.yml", + ), ).toContain("validate-sync-report:"); expect(realizeSkill).toContain("name: truthmark-realize"); expect(realizeSkill).toContain("user-invocable: true"); @@ -517,8 +578,18 @@ describe("runInit", () => { ); expect(previewOpenCodeSkill).toContain("name: truthmark-preview"); expect(previewClaudeSkill).toContain("name: truthmark-preview"); - expect(previewCopilotPrompt).toContain("Truth Preview: completed"); - expect(previewGeminiCommand).toContain("/truthmark:preview"); + expect(previewCopilotPrompt).toContain( + "This prompt is the GitHub Copilot entrypoint for Truthmark Preview.", + ); + expect(previewCopilotPrompt).toContain( + "Do not invoke another Truthmark command from here.", + ); + expect(previewCopilotPrompt).toContain( + ".github/skills/truthmark-preview/support/report-template.md", + ); + expect(previewGeminiCommand).toContain( + "This command is the Gemini CLI entrypoint for Truthmark Preview.", + ); expect(previewGeminiCommand).not.toContain("helper-manifest.yml"); expect(checkSkill).toContain("name: truthmark-check"); expect(checkSkill).toContain("support/procedure.md"); @@ -553,7 +624,9 @@ describe("runInit", () => { expect(openCodeDocReviewerAgent).toContain("edit: deny"); expect(openCodeDocReviewerAgent).toContain(READ_ONLY_CONTEXT_BOUNDARY); expect(openCodeDocWriterAgent).toContain("mode: subagent"); - expect(openCodeDocWriterAgent).toContain('"docs/truthmark/truth/**": allow'); + expect(openCodeDocWriterAgent).toContain( + '"docs/truthmark/engineering/**": allow', + ); expect(openCodeDocWriterAgent).toContain("@truth-doc-writer"); expect(openCodeDocWriterAgent).not.toContain(READ_ONLY_CONTEXT_BOUNDARY); expect(copilotRouteAuditorAgent).toContain("name: truth-route-auditor"); @@ -584,7 +657,9 @@ describe("runInit", () => { expect(claudeDocReviewerAgent).toContain("name: truth-doc-reviewer"); expect(claudeDocReviewerAgent).toContain("tools: Read, Grep, Glob, LS"); expect(claudeDocReviewerAgent).toContain(READ_ONLY_CONTEXT_BOUNDARY); - expect(claudeDocReviewerAgent).toContain("Rationale"); + expect(claudeDocReviewerAgent).toContain("Product Decisions"); + expect(claudeDocReviewerAgent).toContain("Engineering Decisions"); + expect(claudeDocReviewerAgent).toContain("lane-appropriate decision sections"); expect(claudeDocWriterAgent).toContain("name: truth-doc-writer"); expect(claudeDocWriterAgent).toContain( "tools: Read, Grep, Glob, LS, Edit, MultiEdit", @@ -664,7 +739,10 @@ describe("runInit", () => { ), ).toBe(true); const diagnosticCategoriesByFile = new Map( - result.diagnostics.map((diagnostic) => [diagnostic.file, diagnostic.category]), + result.diagnostics.map((diagnostic) => [ + diagnostic.file, + diagnostic.category, + ]), ); for (const file of [ ".github/prompts/truthmark-realize.prompt.md", @@ -693,56 +771,64 @@ describe("runInit", () => { await runInit(repo.rootDir); const config = parse(await repo.readFile(".truthmark/config.yml")) as { - truthmark: { workspace: string; truth: { root: string } }; + truthmark: { workspace: string }; }; 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/truthmark/truth/repository/README.md")).toContain( - "Repository Truth Docs", - ); - expect(await repo.readFile("docs/truthmark/templates/behavior-doc.md")).toContain( - "truth_kind: behavior", - ); - expect(await repo.readFile("docs/truthmark/templates/behavior-doc.md")).toContain( - "## Current Behavior", - ); - expect(await repo.readFile("docs/truthmark/templates/contract-doc.md")).toContain( - "## Contract Surface", - ); - expect(await repo.readFile("docs/truthmark/templates/contract-doc.md")).toContain( - "{{contract_surface}}", - ); expect( - await repo.readFile("docs/truthmark/templates/architecture-doc.md"), + await repo.readFile("docs/truthmark/engineering/README.md"), + ).toContain("Truth Docs"); + expect( + await repo.readFile("docs/truthmark/engineering/repository/README.md"), + ).toContain("Repository Truth Docs"); + expect( + await repo.readFile("docs/truthmark/templates/engineering-behavior.md"), + ).toContain("truth_kind: engineering-behavior"); + expect( + await repo.readFile("docs/truthmark/templates/engineering-behavior.md"), + ).toContain("## Current Implementation Behavior"); + expect( + await repo.readFile("docs/truthmark/templates/engineering-contract.md"), + ).toContain("## Contract Surface"); + expect( + await repo.readFile("docs/truthmark/templates/engineering-contract.md"), + ).toContain("{{contract_surface}}"); + expect( + await repo.readFile( + "docs/truthmark/templates/engineering-architecture.md", + ), ).toContain("## Boundaries"); - expect(await repo.readFile("docs/truthmark/templates/workflow-doc.md")).toContain( - "## Execution Model", - ); - expect(await repo.readFile("docs/truthmark/templates/operations-doc.md")).toContain( - "## Runtime Topology", - ); expect( - await repo.readFile("docs/truthmark/templates/test-behavior-doc.md"), + await repo.readFile("docs/truthmark/templates/engineering-workflow.md"), + ).toContain("## Execution Model"); + expect( + await repo.readFile( + "docs/truthmark/templates/engineering-operations.md", + ), + ).toContain("## Runtime Topology"); + expect( + await repo.readFile( + "docs/truthmark/templates/engineering-test-behavior.md", + ), ).toContain("## Assertions And Invariants"); expect( - await repo.readFile("docs/truthmark/truth/repository/overview.md"), - ).toContain("doc_type: behavior"); + await repo.readFile( + "docs/truthmark/engineering/repository/overview.md", + ), + ).toContain("truth_kind: engineering-behavior"); expect( - await repo.readFile("docs/truthmark/truth/repository/overview.md"), - ).toContain("truth_kind: behavior"); - expect( - await repo.readFile("docs/truthmark/truth/repository/overview.md"), + await repo.readFile( + "docs/truthmark/engineering/repository/overview.md", + ), ).toContain( "Truth README files are indexes; behavior truth belongs in bounded leaf docs.", ); expect( - await repo.readFile("docs/truthmark/truth/repository/overview.md"), + await repo.readFile( + "docs/truthmark/engineering/repository/overview.md", + ), ).toContain( - "This doc was created from the editable behavior-doc template at docs/truthmark/templates/behavior-doc.md.", + "This doc was created from the editable engineering-behavior template at docs/truthmark/templates/engineering-behavior.md.", ); } finally { await repo.cleanup(); @@ -762,15 +848,6 @@ platforms: - gemini-cli 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 @@ -795,10 +872,10 @@ ignore: [] ).resolves.toBeTruthy(); expect( await repo.readFile(".github/prompts/truthmark-sync.prompt.md"), - ).toContain("GitHub Copilot /truthmark-sync"); + ).toContain("This prompt is the GitHub Copilot entrypoint for Truthmark Sync."); expect( await repo.readFile(".github/prompts/truthmark-document.prompt.md"), - ).toContain("GitHub Copilot /truthmark-document"); + ).toContain("This prompt is the GitHub Copilot entrypoint for Truthmark Document."); await expect( fs.stat(`${repo.rootDir}/.github/skills/truthmark-sync/SKILL.md`), ).resolves.toBeTruthy(); @@ -809,13 +886,19 @@ ignore: [] await repo.readFile(".github/skills/truthmark-sync/SKILL.md"), ).toContain("helper-manifest.yml"); expect( - await repo.readFile(".github/skills/truthmark-sync/support/subagents-and-leases.md"), + await repo.readFile( + ".github/skills/truthmark-sync/support/subagents-and-leases.md", + ), ).toContain("@truth-doc-writer"); expect( - await repo.readFile(".github/skills/truthmark-document/helper-manifest.yml"), + await repo.readFile( + ".github/skills/truthmark-document/helper-manifest.yml", + ), ).toContain("validate-document-report:"); expect( - await repo.readFile(".github/skills/truthmark-document/support/helper-policy.md"), + await repo.readFile( + ".github/skills/truthmark-document/support/helper-policy.md", + ), ).not.toContain("scripts/validate-document-report.mjs"); await expect(fs.stat(`${repo.rootDir}/GEMINI.md`)).resolves.toBeTruthy(); await expect( @@ -840,10 +923,15 @@ ignore: [] ); expect( await repo.readFile(".gemini/commands/truthmark/sync.toml"), - ).toContain("name: truthmark-sync"); + ).toContain("This command is the Gemini CLI entrypoint for Truthmark Sync."); + expect( + await repo.readFile(".gemini/commands/truthmark/sync.toml"), + ).toContain(".gemini/skills/truthmark-sync/SKILL.md"); expect( await repo.readFile(".gemini/commands/truthmark/document.toml"), - ).toContain("name: truthmark-document"); + ).toContain( + `description = "${getTruthmarkWorkflow("truthmark-document").description}"`, + ); expect( await repo.readFile(".gemini/commands/truthmark/realize.toml"), ).toContain( @@ -859,10 +947,14 @@ ignore: [] await repo.readFile(".gemini/skills/truthmark-sync/SKILL.md"), ).toContain("helper-manifest.yml"); expect( - await repo.readFile(".gemini/skills/truthmark-document/helper-manifest.yml"), + await repo.readFile( + ".gemini/skills/truthmark-document/helper-manifest.yml", + ), ).toContain("validate-document-report:"); expect( - await repo.readFile(".gemini/skills/truthmark-sync/support/subagents-and-leases.md"), + await repo.readFile( + ".gemini/skills/truthmark-sync/support/subagents-and-leases.md", + ), ).toContain("@truth-doc-writer"); await expect( fs.stat(`${repo.rootDir}/.gemini/agents/truth-route-auditor.md`), @@ -899,15 +991,6 @@ platforms: - claude-code 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 @@ -972,7 +1055,7 @@ ignore: [] "# System Architecture\n", ); await repo.writeFile( - "docs/truthmark/truth/authentication.md", + "docs/truthmark/engineering/authentication.md", "# Authentication\n", ); await repo.writeFile( @@ -986,9 +1069,9 @@ ignore: [] expect(await repo.readFile("docs/architecture/system.md")).toBe( "# System Architecture\n", ); - expect(await repo.readFile("docs/truthmark/truth/authentication.md")).toBe( - "# Authentication\n", - ); + expect( + await repo.readFile("docs/truthmark/engineering/authentication.md"), + ).toBe("# Authentication\n"); const areas = await repo.readFile("docs/truthmark/routes/areas.md"); @@ -1011,11 +1094,11 @@ ignore: [] try { await runConfig(repo.rootDir, {}); await repo.writeFile( - "docs/truthmark/templates/behavior-doc.md", + "docs/truthmark/templates/engineering-behavior.md", `--- status: active doc_type: behavior - truth_kind: behavior + truth_kind: engineering-behavior last_reviewed: 2026-05-12 source_of_truth: - {{source_of_truth}} @@ -1031,17 +1114,23 @@ Custom template for {{area}}. await runInit(repo.rootDir); - expect(await repo.readFile("docs/truthmark/templates/behavior-doc.md")).toContain( - "## Local Standard", - ); expect( - await repo.readFile("docs/truthmark/truth/repository/overview.md"), + await repo.readFile("docs/truthmark/templates/engineering-behavior.md"), ).toContain("## Local Standard"); expect( - await repo.readFile("docs/truthmark/truth/repository/overview.md"), + await repo.readFile( + "docs/truthmark/engineering/repository/overview.md", + ), + ).toContain("## Local Standard"); + expect( + await repo.readFile( + "docs/truthmark/engineering/repository/overview.md", + ), ).toContain("Custom template for repository."); expect( - await repo.readFile("docs/truthmark/truth/repository/overview.md"), + await repo.readFile( + "docs/truthmark/engineering/repository/overview.md", + ), ).not.toContain("{{"); } finally { await repo.cleanup(); @@ -1054,11 +1143,11 @@ Custom template for {{area}}. try { await runConfig(repo.rootDir, {}); await repo.writeFile( - "docs/truthmark/templates/behavior-doc.md", + "docs/truthmark/templates/engineering-behavior.md", `--- status: active doc_type: behavior -truth_kind: behavior +truth_kind: engineering-behavior last_reviewed: 2026-05-12 owner: local-platform source_of_truth: @@ -1087,7 +1176,7 @@ This fenced heading example should remain part of the custom section. Old local scope copy that should be replaced. -## Current Behavior +## Current Implementation Behavior Old current-behavior copy that should be replaced. @@ -1111,13 +1200,18 @@ Keep this project-specific trailing section. await runInit(repo.rootDir); - const updatedTemplate = await repo.readFile("docs/truthmark/templates/behavior-doc.md"); + const updatedTemplate = await repo.readFile( + "docs/truthmark/templates/engineering-behavior.md", + ); expect(updatedTemplate).toContain( "State the user/system outcome this behavior protects and why it exists.", ); expect(updatedTemplate).toContain("owner: local-platform"); - expect(updatedTemplate).toContain(" - docs/local-source.md"); + expect(updatedTemplate).not.toContain("source_of_truth:"); + expect(updatedTemplate).not.toContain(" - docs/local-source.md"); + expect(updatedTemplate).toContain("## Source References"); + expect(updatedTemplate).toContain("{{source_references}}"); expect(updatedTemplate).toContain("# Custom {{title}} Template"); expect(updatedTemplate).toContain( "Local introduction that should remain before managed sections.", @@ -1142,15 +1236,18 @@ Keep this project-specific trailing section. "## Purpose", "## Team Notes Before Scope", "## Scope", - "## Current Behavior", + "## Current Implementation Behavior", "## Domain Vocabulary", "## Core Rules", "## Maintenance Notes", + "## Source References", "## Local Appendices", ].map((heading) => updatedTemplate.indexOf(heading)); expect(headingOrder.every((index) => index >= 0)).toBe(true); - expect(headingOrder).toEqual([...headingOrder].sort((left, right) => left - right)); + expect(headingOrder).toEqual( + [...headingOrder].sort((left, right) => left - right), + ); } finally { await repo.cleanup(); } @@ -1159,12 +1256,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/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", + "docs/truthmark/templates/engineering-behavior.md", + "docs/truthmark/templates/engineering-contract.md", + "docs/truthmark/templates/engineering-architecture.md", + "docs/truthmark/templates/engineering-workflow.md", + "docs/truthmark/templates/engineering-operations.md", + "docs/truthmark/templates/engineering-test-behavior.md", ]; try { @@ -1196,20 +1293,24 @@ Keep this project-specific trailing section. for (const templatePath of templatePaths) { const updatedTemplate = await repo.readFile(templatePath); expect(updatedTemplate).toContain(`template_path: ${templatePath}`); - expect(updatedTemplate).toContain(`# Local Template For ${templatePath}`); - expect(updatedTemplate).toContain("Repository-specific introductory guidance."); + expect(updatedTemplate).toContain( + `# Local Template For ${templatePath}`, + ); + expect(updatedTemplate).toContain( + "Repository-specific introductory guidance.", + ); } } finally { await repo.cleanup(); } }); - it("rejects a broken behavior-doc template symlink that would write outside the repo", async () => { + it("rejects a broken engineering-behavior template symlink that would write outside the repo", async () => { const repo = await createTempRepo(); const outsideTemplatePath = path.resolve( repo.rootDir, "..", - "truthmark-outside-behavior-doc-template.md", + "truthmark-outside-engineering-behavior-template.md", ); try { @@ -1217,7 +1318,13 @@ Keep this project-specific trailing section. await repo.writeFile("docs/truthmark/templates/.keep", ""); await fs.symlink( outsideTemplatePath, - path.join(repo.rootDir, "docs", "truthmark", "templates", "behavior-doc.md"), + path.join( + repo.rootDir, + "docs", + "truthmark", + "templates", + "engineering-behavior.md", + ), ); await expect(runInit(repo.rootDir)).rejects.toThrow( @@ -1321,13 +1428,15 @@ authority: expect.objectContaining({ category: "config", severity: "error", - message: expect.stringContaining("Unsupported Truthmark config shape"), + message: expect.stringContaining( + "Unsupported Truthmark config shape", + ), }), ]), ); - expect(await repo.readFile("docs/truthmark/truth/README.md")).toContain( - "Truth Docs", - ); + expect( + await repo.readFile("docs/truthmark/engineering/README.md"), + ).toContain("Truth Docs"); } finally { await repo.cleanup(); } @@ -1342,15 +1451,6 @@ authority: `version: 2 truthmark: workspace: docs/product - 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 @@ -1363,8 +1463,10 @@ truthmark: "docs/product/routes/areas/repository.md", ); expect(childRoute).toContain("```yaml"); - expect(childRoute).toContain("path: docs/product/truth/repository/overview.md"); - expect(childRoute).toContain("kind: behavior"); + expect(childRoute).toContain( + "path: docs/product/engineering/repository/overview.md", + ); + expect(childRoute).toContain("kind: engineering-behavior"); expect(childRoute).not.toContain("- docs/product/repository/overview.md"); const result = await runCheck(repo.rootDir); @@ -1392,15 +1494,6 @@ platforms: - opencode truthmark: workspace: product - routes: - index: routes/index.md - areas: routes/areas - default_area: repository - max_delegation_depth: 1 - truth: - root: truth - templates: - root: templates generated: portal: enabled: false @@ -1412,14 +1505,18 @@ truthmark: const openCodeDocWriterAgent = await repo.readFile( ".opencode/agents/truth-doc-writer.md", ); - expect(openCodeDocWriterAgent).toContain('"product/truth/**": allow'); expect(openCodeDocWriterAgent).toContain( - '"product/routes/index.md": allow', + '"product/engineering/**": allow', + ); + expect(openCodeDocWriterAgent).toContain( + '"product/routes/areas.md": allow', ); expect(openCodeDocWriterAgent).toContain( '"product/routes/areas/**/*.md": allow', ); - expect(openCodeDocWriterAgent).not.toContain('"docs/truthmark/truth/**": allow'); + expect(openCodeDocWriterAgent).not.toContain( + '"docs/truthmark/engineering/**": allow', + ); expect(openCodeDocWriterAgent).not.toContain( '"docs/truthmark/routes/areas.md": allow', ); @@ -1485,11 +1582,13 @@ Update truth when: await runInit(repo.rootDir); await expect( - fs.stat(path.join(repo.rootDir, "docs/truthmark/routes/areas/repository.md")), + fs.stat( + path.join(repo.rootDir, "docs/truthmark/routes/areas/repository.md"), + ), ).rejects.toThrow(); - expect(await repo.readFile("docs/truthmark/routes/areas.md")).not.toContain( - "docs/truthmark/routes/areas/repository.md", - ); + expect( + await repo.readFile("docs/truthmark/routes/areas.md"), + ).not.toContain("docs/truthmark/routes/areas/repository.md"); } finally { await repo.cleanup(); } @@ -1523,11 +1622,15 @@ authority: expect.objectContaining({ category: "config", severity: "error", - message: expect.stringContaining("Unsupported Truthmark config shape"), + 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}/docs/truthmark/engineering/README.md`), + ).rejects.toThrow(); await expect(fs.stat(`${repo.rootDir}/AGENTS.md`)).rejects.toThrow(); } finally { await repo.cleanup(); diff --git a/tests/integration/init-check-workflow.test.ts b/tests/integration/init-check-workflow.test.ts index 859fc98..424dc1c 100644 --- a/tests/integration/init-check-workflow.test.ts +++ b/tests/integration/init-check-workflow.test.ts @@ -10,10 +10,14 @@ describe("init and check workflow acceptance", () => { const repo = await createTempRepo(); try { - const configResult = await runCli(["config", "--json"], { cwd: repo.rootDir }); + const configResult = await runCli(["config", "--json"], { + cwd: repo.rootDir, + }); expect(configResult.exitCode).toBe(0); - const initResult = await runCli(["init", "--json"], { cwd: repo.rootDir }); + const initResult = await runCli(["init", "--json"], { + cwd: repo.rootDir, + }); expect(initResult.exitCode).toBe(0); @@ -23,8 +27,63 @@ 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/routes/areas.md`)).resolves.toBeTruthy(); + await expect( + fs.stat(`${repo.rootDir}/.truthmark/config.yml`), + ).resolves.toBeTruthy(); + await expect( + fs.stat(`${repo.rootDir}/docs/truthmark/routes/areas.md`), + ).resolves.toBeTruthy(); + await expect( + fs.stat( + `${repo.rootDir}/docs/truthmark/templates/product-capability.md`, + ), + ).resolves.toBeTruthy(); + await expect( + fs.stat( + `${repo.rootDir}/docs/truthmark/templates/engineering-behavior.md`, + ), + ).resolves.toBeTruthy(); + await expect( + fs.stat( + `${repo.rootDir}/docs/truthmark/templates/engineering-contract.md`, + ), + ).resolves.toBeTruthy(); + await expect( + fs.stat( + `${repo.rootDir}/docs/truthmark/templates/engineering-architecture.md`, + ), + ).resolves.toBeTruthy(); + await expect( + fs.stat( + `${repo.rootDir}/docs/truthmark/templates/engineering-workflow.md`, + ), + ).resolves.toBeTruthy(); + await expect( + fs.stat( + `${repo.rootDir}/docs/truthmark/templates/engineering-operations.md`, + ), + ).resolves.toBeTruthy(); + await expect( + fs.stat( + `${repo.rootDir}/docs/truthmark/templates/engineering-test-behavior.md`, + ), + ).resolves.toBeTruthy(); + const oldBehaviorTemplateName = ["behavior", "doc.md"].join("-"); + const oldProductBoundaryTemplateName = [ + "product", + "boundary", + "doc.md", + ].join("-"); + await expect( + fs.stat( + `${repo.rootDir}/docs/truthmark/templates/${oldBehaviorTemplateName}`, + ), + ).rejects.toThrow(); + await expect( + fs.stat( + `${repo.rootDir}/docs/truthmark/templates/${oldProductBoundaryTemplateName}`, + ), + ).rejects.toThrow(); await expect(fs.stat(`${repo.rootDir}/AGENTS.md`)).resolves.toBeTruthy(); await expect( fs.stat(`${repo.rootDir}/.agents/skills/truthmark-structure/SKILL.md`), @@ -42,7 +101,9 @@ describe("init and check workflow acceptance", () => { fs.stat(`${repo.rootDir}/.claude/skills/truthmark-sync/SKILL.md`), ).resolves.toBeTruthy(); - const checkResult = await runCli(["check", "--json"], { cwd: repo.rootDir }); + const checkResult = await runCli(["check", "--json"], { + cwd: repo.rootDir, + }); expect(checkResult.exitCode).toBe(0); @@ -58,9 +119,11 @@ describe("init and check workflow acceptance", () => { }; expect(checkPayload.command).toBe("check"); - expect(checkPayload.diagnostics.filter((diagnostic) => diagnostic.severity === "error")).toHaveLength( - 0, - ); + expect( + checkPayload.diagnostics.filter( + (diagnostic) => diagnostic.severity === "error", + ), + ).toHaveLength(0); expect(checkPayload.data?.branchScope?.identity).toBe("unborn:main"); expect(checkPayload.data?.branchScope?.worktreePath).toBe(repo.rootDir); } finally { @@ -72,16 +135,20 @@ describe("init and check workflow acceptance", () => { const repo = await createTempRepo(); try { - const configResult = await runCli(["config", "--json"], { cwd: repo.rootDir }); + const configResult = await runCli(["config", "--json"], { + cwd: repo.rootDir, + }); expect(configResult.exitCode).toBe(0); - const initResult = await runCli(["init", "--json"], { cwd: repo.rootDir }); + const initResult = await runCli(["init", "--json"], { + cwd: repo.rootDir, + }); expect(initResult.exitCode).toBe(0); await repo.writeFile( - "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", + "docs/truthmark/engineering/behaviors/authentication.md", + "---\nstatus: active\ndoc_type: behavior\ntruth_kind: engineering-behavior\nlast_reviewed: 2026-05-06\nsource_of_truth:\n - ../../../../src/auth/session.ts\n---\n\n# Authentication\n", ); await repo.writeFile( "docs/truthmark/routes/areas.md", @@ -90,7 +157,7 @@ describe("init and check workflow acceptance", () => { ## Authentication Truth documents: -- docs/truthmark/truth/authentication.md +- docs/truthmark/engineering/behaviors/authentication.md Code surface: - src/auth/** @@ -99,9 +166,14 @@ Update truth when: - authentication behavior changes `, ); - await repo.writeFile("src/auth/session.ts", "export const session = true;\n"); + await repo.writeFile( + "src/auth/session.ts", + "export const session = true;\n", + ); - const checkResult = await runCli(["check", "--json"], { cwd: repo.rootDir }); + const checkResult = await runCli(["check", "--json"], { + cwd: repo.rootDir, + }); expect(checkResult.exitCode).toBe(0); diff --git a/tests/markdown/discovery.test.ts b/tests/markdown/discovery.test.ts deleted file mode 100644 index ce17504..0000000 --- a/tests/markdown/discovery.test.ts +++ /dev/null @@ -1,187 +0,0 @@ -import { parse } from "yaml"; -import { describe, expect, it } from "vitest"; - -import { createTempRepo } from "../helpers/temp-repo.js"; -import { discoverMarkdownDocuments } from "../../src/markdown/discovery.js"; -import { - renderConfigTemplate, - renderAreasTemplate, -} from "../../src/templates/init-files.js"; -import { renderAgentsBlock } from "../../src/templates/agents-block.js"; - -describe("discoverMarkdownDocuments", () => { - it("finds repository markdown docs and ignores common derived directories", async () => { - const repo = await createTempRepo(); - - try { - await repo.writeFile( - "docs/architecture/system.md", - "---\nstatus: active\n---\n# System Architecture\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( - ".agents/skills/truthmark-sync/SKILL.md", - "# Ignore me\n", - ); - await repo.writeFile( - ".agents/skills/truthmark-structure/SKILL.md", - "# Ignore me\n", - ); - await repo.writeFile( - ".agents/skills/truthmark-realize/SKILL.md", - "# Ignore me\n", - ); - await repo.writeFile( - ".agents/skills/truthmark-check/SKILL.md", - "# Ignore me\n", - ); - await repo.writeFile( - ".opencode/skills/truthmark-sync/SKILL.md", - "# Ignore me\n", - ); - await repo.writeFile( - ".claude/skills/truthmark-sync/SKILL.md", - "# Ignore me\n", - ); - await repo.writeFile(".github/copilot-instructions.md", "# Ignore me\n"); - await repo.writeFile( - ".github/prompts/truthmark-sync.prompt.md", - "# Ignore me\n", - ); - await repo.writeFile( - ".github/agents/truth-route-auditor.md", - "# Ignore me\n", - ); - await repo.writeFile("CLAUDE.md", "# Ignore me\n"); - await repo.writeFile("GEMINI.md", "# Ignore me\n"); - await repo.writeFile( - ".gemini/commands/truthmark/sync.toml", - 'description = "Ignore me"\n', - ); - await repo.writeFile("skills/truthmark-sync/SKILL.md", "# Ignore me\n"); - await repo.writeFile( - "skills/truthmark-structure/SKILL.md", - "# Ignore me\n", - ); - await repo.writeFile("skills/truthmark-check/SKILL.md", "# Ignore me\n"); - await repo.writeFile("commands/truthmark-realize.md", "# Ignore me\n"); - await repo.runGit(["add", "README.md", "docs"]); - await repo.runGit(["commit", "-m", "test: add markdown docs"]); - - const documents = await discoverMarkdownDocuments(repo.rootDir); - - expect(documents.map((document) => document.path)).toEqual([ - "README.md", - "docs/architecture/system.md", - "docs/product/authentication.md", - ]); - expect(documents[1]).toMatchObject({ - path: "docs/architecture/system.md", - title: "System Architecture", - hasFrontmatter: true, - }); - } finally { - await repo.cleanup(); - } - }); -}); - -describe("init templates", () => { - it("renders the V2 workspace config template fields", () => { - const config = parse(renderConfigTemplate()) as { - truthmark: Record; - frontmatter: { - required: string[]; - recommended: string[]; - }; - } & Record; - - expect(config).toMatchObject({ - version: 2, - platforms: [ - "codex", - "opencode", - "claude-code", - "github-copilot", - "gemini-cli", - ], - truthmark: expect.any(Object), - instruction_targets: expect.any(Array), - frontmatter: expect.any(Object), - ignore: expect.any(Array), - }); - expect(config.frontmatter).toMatchObject({ - required: [], - recommended: ["status", "doc_type", "last_reviewed", "source_of_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/routes/areas.md from discovered docs without moving them", () => { - const areas = renderAreasTemplate([ - { - path: "docs/truthmark/truth/authentication.md", - title: "Authentication", - hasFrontmatter: false, - }, - { - path: "docs/api/authentication.md", - title: "Authentication API", - hasFrontmatter: false, - }, - ]); - - 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).not.toContain("kind: contract"); - expect(areas).toContain("Code surface:"); - expect(areas).toContain("Update truth when:"); - expect(areas).not.toContain("- docs/truthmark/truth/authentication.md"); - }); - - it("renders a managed AGENTS.md block with stable markers and workflow boundaries", () => { - const agentsBlock = renderAgentsBlock(); - - expect(agentsBlock).toContain(""); - expect(agentsBlock).toContain(""); - expect(agentsBlock.split("\n").length).toBeLessThanOrEqual(20); - expect(agentsBlock).not.toContain("### Manual Truth Realize"); - expect(agentsBlock).not.toContain("### Truth Structure"); - expect(agentsBlock).not.toContain("### Truth Check"); - expect(agentsBlock).toContain( - "Explicit workflows: Truth Structure, Truth Document, Truth Preview, Truth Realize, Truth Check", - ); - expect(agentsBlock).toContain( - "Sync may write truth docs and truth routing files", - ); - expect(agentsBlock).toContain( - "Support new or changed behavior-bearing truth claims with checkout evidence", - ); - expect(agentsBlock).toContain("must not rewrite functional code"); - expect(agentsBlock).toContain( - "If routing cannot map changed code to a bounded truth owner", - ); - expect(agentsBlock).toContain( - "otherwise block and recommend Truth Structure", - ); - expect(agentsBlock).not.toContain("write functional code only"); - expect(agentsBlock).not.toContain("do not edit truth docs or truth routing"); - expect(agentsBlock).not.toContain("Explicit invocation:"); - expect(agentsBlock).not.toContain("/skill truthmark-sync"); - }); - -}); diff --git a/tests/output/render.test.ts b/tests/output/render.test.ts index 75c5c9a..f365fc8 100644 --- a/tests/output/render.test.ts +++ b/tests/output/render.test.ts @@ -98,6 +98,9 @@ describe("output rendering", () => { "truth-sync", "realization", "doc-structure", + "lane-shape", + "lane-drift", + "traceability", "generated-surface", "repo-index", "impact", diff --git a/tests/realize/report.test.ts b/tests/realize/report.test.ts index ceacc51..650983d 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/truthmark/truth/authentication.md"], + truthDocsUsed: ["docs/truthmark/engineering/behaviors/authentication.md"], codeUpdated: ["src/auth/session.ts"], verification: ["npm test -- auth"], }), ).toBe(`Truth Realize: completed Truth docs used: -- docs/truthmark/truth/authentication.md +- docs/truthmark/engineering/behaviors/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 e2e62f4..7d6fefe 100644 --- a/tests/repo-index/build.test.ts +++ b/tests/repo-index/build.test.ts @@ -19,14 +19,21 @@ describe("buildRepoIndex", () => { repos.push(repo); await repo.writeFile( "package.json", - JSON.stringify({ name: "sample", version: "1.0.0", scripts: { test: "vitest" } }, null, 2), + JSON.stringify( + { name: "sample", version: "1.0.0", 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("src/index.ts", "export { add } from './math.js';\n"); - await repo.writeFile("tests/math.test.ts", "import { add } from '../src/math.js';\n"); + await repo.writeFile( + "tests/math.test.ts", + "import { add } from '../src/math.js';\n", + ); await runConfig(repo.rootDir, { force: false, stdout: false }); await runInit(repo.rootDir); @@ -34,18 +41,103 @@ describe("buildRepoIndex", () => { expect(result.schemaVersion).toBe("repo-index/v0"); expect(result.packages).toContainEqual( - expect.objectContaining({ name: "sample", version: "1.0.0", manager: "npm" }), + 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/truthmark/truth/repository/overview.md"); + expect(result.docs.map((doc) => doc.path)).toContain( + "docs/truthmark/engineering/repository/overview.md", + ); expect(result.files).toContainEqual( expect.objectContaining({ path: "AGENTS.md", kind: "generated" }), ); expect(result.docs.map((doc) => doc.path)).not.toContain("AGENTS.md"); - expect(result.tests.map((file) => file.path)).toContain("tests/math.test.ts"); - expect(result.exports).toContainEqual({ path: "src/math.ts", name: "add", kind: "function" }); - expect(result.publicSymbols).toContainEqual({ path: "src/math.ts", name: "add", kind: "function" }); - expect(result.routeMap.routes.some((route) => route.truthDocs.length > 0)).toBe(true); + expect(result.tests.map((file) => file.path)).toContain( + "tests/math.test.ts", + ); + expect(result.exports).toContainEqual({ + path: "src/math.ts", + name: "add", + kind: "function", + }); + expect(result.publicSymbols).toContainEqual({ + path: "src/math.ts", + name: "add", + kind: "function", + }); + expect( + result.routeMap.routes.some((route) => route.truthDocs.length > 0), + ).toBe(true); + }); + + it("derives truth doc lane, doc type, and source references from compact truth docs", async () => { + const repo = await createTempRepo(); + repos.push(repo); + await repo.writeFile( + "docs/truthmark/routes/areas/repository.md", + "# Repository Route\n", + ); + await repo.writeFile( + "docs/truthmark/engineering/contracts/api.md", + `--- +status: active +truth_kind: engineering-contract +last_reviewed: 2026-05-14 +--- + +# API Contract + +## Source References + +- ../../routes/areas/repository.md +`, + ); + + const result = await buildRepoIndex(repo.rootDir); + + expect(result.docs).toContainEqual( + expect.objectContaining({ + path: "docs/truthmark/engineering/contracts/api.md", + docType: "contract", + truthKind: "engineering-contract", + truthLane: "engineering", + sourceOfTruth: ["docs/truthmark/routes/areas/repository.md"], + }), + ); + }); + + it("does not treat relationship frontmatter as canonical repo-index metadata", async () => { + const repo = await createTempRepo(); + repos.push(repo); + await repo.writeFile( + "docs/truthmark/engineering/contracts/api.md", + `--- +status: active +truth_kind: engineering-contract +last_reviewed: 2026-05-14 +realizes: + - docs/truthmark/product/capabilities/api.md +depends_on: + - docs/truthmark/engineering/contracts/shared.md +--- + +# API Contract +`, + ); + + const result = await buildRepoIndex(repo.rootDir); + + expect(result.docs).toContainEqual( + expect.objectContaining({ + path: "docs/truthmark/engineering/contracts/api.md", + realizedBy: [], + realizes: [], + dependsOn: [], + }), + ); }); it("skips tracked files that are deleted from the worktree", async () => { @@ -58,8 +150,12 @@ describe("buildRepoIndex", () => { const result = await buildRepoIndex(repo.rootDir); - expect(result.files.map((file) => file.path)).not.toContain("src/deleted.ts"); - expect(result.exports.map((entry) => entry.path)).not.toContain("src/deleted.ts"); + expect(result.files.map((file) => file.path)).not.toContain( + "src/deleted.ts", + ); + expect(result.exports.map((entry) => entry.path)).not.toContain( + "src/deleted.ts", + ); }); it("excludes files ignored by gitignore", async () => { @@ -73,6 +169,8 @@ describe("buildRepoIndex", () => { const result = await buildRepoIndex(repo.rootDir); - expect(result.files.map((file) => file.path)).not.toContain(".lean-ctx/graph.meta.json"); + expect(result.files.map((file) => file.path)).not.toContain( + ".lean-ctx/graph.meta.json", + ); }); }); diff --git a/tests/repo-index/route-map.test.ts b/tests/repo-index/route-map.test.ts index 7e7b988..d3d9cf2 100644 --- a/tests/repo-index/route-map.test.ts +++ b/tests/repo-index/route-map.test.ts @@ -31,4 +31,67 @@ describe("buildRouteMap", () => { }), ); }); + + it("emits merged relationship metadata for duplicate route entries", async () => { + const repo = await createTempRepo(); + repos.push(repo); + await runConfig(repo.rootDir, { force: false, stdout: false }); + await runInit(repo.rootDir); + await repo.writeFile( + "docs/truthmark/product/payments/checkout.md", + "# Checkout Capability\n", + ); + await repo.writeFile( + "docs/truthmark/product/payments/refunds.md", + "# Refunds Capability\n", + ); + await repo.writeFile( + "docs/truthmark/engineering/behaviors/checkout.md", + "# Checkout Behavior\n", + ); + await repo.writeFile( + "docs/truthmark/routes/areas.md", + `# Truthmark Areas + +## Checkout + +Truth documents: +\`\`\`yaml +truth_documents: + - path: docs/truthmark/product/payments/checkout.md + kind: product-capability + - path: docs/truthmark/product/payments/refunds.md + kind: product-capability + - path: docs/truthmark/engineering/behaviors/checkout.md + kind: engineering-behavior + realizes: + - docs/truthmark/product/payments/refunds.md + - path: docs/truthmark/engineering/behaviors/checkout.md + kind: engineering-behavior + realizes: + - docs/truthmark/product/payments/checkout.md +\`\`\` + +Code surface: +- src/checkout/** + +Update truth when: +- checkout behavior changes +`, + ); + + const routeMap = await buildRouteMap(repo.rootDir); + const checkoutRoute = routeMap.routes.find( + (route) => route.name === "Checkout", + ); + const checkoutEntry = checkoutRoute?.truthDocumentEntries.find( + (entry) => + entry.path === "docs/truthmark/engineering/behaviors/checkout.md", + ); + + expect(checkoutEntry?.realizes).toEqual([ + "docs/truthmark/product/payments/checkout.md", + "docs/truthmark/product/payments/refunds.md", + ]); + }); }); diff --git a/tests/routing/area-resolver.test.ts b/tests/routing/area-resolver.test.ts index 93b2f2e..50d4f38 100644 --- a/tests/routing/area-resolver.test.ts +++ b/tests/routing/area-resolver.test.ts @@ -36,7 +36,7 @@ Update truth when: ## Checkout Truth documents: -- docs/truthmark/truth/payments/checkout.md +- docs/truthmark/engineering/behaviors/payments-checkout.md Code surface: - services/payments/checkout/** @@ -56,7 +56,7 @@ Update truth when: expect(result.areas).toEqual([ expect.objectContaining({ name: "Checkout", - truthDocuments: ["docs/truthmark/truth/payments/checkout.md"], + truthDocuments: ["docs/truthmark/engineering/behaviors/payments-checkout.md"], sourcePath: "docs/truthmark/routes/areas/payments.md", parentName: "Payments", }), diff --git a/tests/routing/areas-markdown-globs.test.ts b/tests/routing/areas-markdown-globs.test.ts index 5e3cb59..f9d08ce 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/truthmark/truth/authentication.md +- docs/truthmark/engineering/behaviors/authentication.md Code surface: - src/auth/\\*\\* diff --git a/tests/routing/areas.test.ts b/tests/routing/areas.test.ts index 064b229..c90a02f 100644 --- a/tests/routing/areas.test.ts +++ b/tests/routing/areas.test.ts @@ -11,10 +11,12 @@ describe("parseAreasMarkdown", () => { Truth documents: ${"```"}yaml truth_documents: - - path: docs/truthmark/truth/authentication.md - kind: behavior + - path: docs/truthmark/engineering/authentication.md + kind: engineering-behavior + lane: engineering - path: docs/api/authentication.md - kind: contract + kind: engineering-contract + lane: engineering ${"```"} Code surface: @@ -33,20 +35,20 @@ Update truth when: name: "Authentication", key: "authentication", truthDocuments: [ - "docs/truthmark/truth/authentication.md", + "docs/truthmark/engineering/authentication.md", "docs/api/authentication.md", ], truthDocumentEntries: [ - { - path: "docs/truthmark/truth/authentication.md", - kind: "behavior", + expect.objectContaining({ + path: "docs/truthmark/engineering/authentication.md", + kind: "engineering-behavior", kindSource: "explicit", - }, - { + }), + expect.objectContaining({ path: "docs/api/authentication.md", - kind: "contract", + kind: "engineering-contract", kindSource: "explicit", - }, + }), ], codeSurface: ["src/auth/**", "src/session/**"], updateTruthWhen: ["authentication behavior changes", "permissions change"], @@ -60,7 +62,7 @@ Update truth when: ## Authentication Truth documents: -- docs/truthmark/truth/authentication.md +- docs/truthmark/engineering/authentication.md `); expect(result.areas).toEqual([]); @@ -81,7 +83,7 @@ Truth documents: " ## Authentication", "", "Truth documents:", - "- docs/truthmark/truth/authentication.md", + "- docs/truthmark/engineering/authentication.md", "", "Code surface:", "- src/auth/**", @@ -132,7 +134,7 @@ Update truth when: ## Payments Truth documents: -- docs/truthmark/truth/payments.md +- docs/truthmark/engineering/payments.md Area files: - docs/truthmark/areas/payments.md @@ -165,10 +167,12 @@ Update truth when: Truth documents: ${"```"}yaml truth_documents: - - path: docs/truthmark/truth/billing/checkout.md - kind: behavior + - path: docs/truthmark/engineering/billing/checkout.md + kind: engineering-behavior + lane: engineering - path: docs/contracts/billing/api.md - kind: contract + kind: engineering-contract + lane: engineering ${"```"} Code surface: @@ -182,20 +186,20 @@ Update truth when: expect(result.areas).toEqual([ expect.objectContaining({ truthDocuments: [ - "docs/truthmark/truth/billing/checkout.md", + "docs/truthmark/engineering/billing/checkout.md", "docs/contracts/billing/api.md", ], truthDocumentEntries: [ - { - path: "docs/truthmark/truth/billing/checkout.md", - kind: "behavior", + expect.objectContaining({ + path: "docs/truthmark/engineering/billing/checkout.md", + kind: "engineering-behavior", kindSource: "explicit", - }, - { + }), + expect.objectContaining({ path: "docs/contracts/billing/api.md", - kind: "contract", + kind: "engineering-contract", kindSource: "explicit", - }, + }), ], }), ]); @@ -207,7 +211,7 @@ Update truth when: ## Repository Truth documents: -- docs/truthmark/truth/repository/overview.md +- docs/truthmark/engineering/repository/overview.md - docs/architecture/module-map.md - docs/api/contracts.md @@ -230,21 +234,21 @@ Update truth when: expect(result.areas).toEqual([ expect.objectContaining({ truthDocumentEntries: [ - { - path: "docs/truthmark/truth/repository/overview.md", - kind: "behavior", + expect.objectContaining({ + path: "docs/truthmark/engineering/repository/overview.md", + kind: "engineering-behavior", kindSource: "inferred", - }, - { + }), + expect.objectContaining({ path: "docs/architecture/module-map.md", - kind: "behavior", + kind: "engineering-behavior", kindSource: "defaulted", - }, - { + }), + expect.objectContaining({ path: "docs/api/contracts.md", - kind: "behavior", + kind: "engineering-behavior", kindSource: "defaulted", - }, + }), ], }), ]); @@ -258,11 +262,12 @@ Update truth when: Truth documents: ${"```"}yaml truth_documents: - - path: docs/truthmark/truth/contracts.md - kind: contract + - path: docs/truthmark/engineering/contracts/routing.md + kind: engineering-contract + lane: engineering ${"```"} -- docs/truthmark/truth/installed-workflows.md +- docs/truthmark/engineering/installed-workflows.md - docs/architecture/overview.md Code surface: @@ -275,13 +280,13 @@ Update truth when: expect(result.diagnostics).toEqual([]); expect(result.areas).toEqual([ expect.objectContaining({ - truthDocuments: ["docs/truthmark/truth/contracts.md"], + truthDocuments: ["docs/truthmark/engineering/contracts/routing.md"], truthDocumentEntries: [ - { - path: "docs/truthmark/truth/contracts.md", - kind: "contract", + expect.objectContaining({ + path: "docs/truthmark/engineering/contracts/routing.md", + kind: "engineering-contract", kindSource: "explicit", - }, + }), ], }), ]); @@ -312,11 +317,11 @@ Update truth when: expect(result.areas).toEqual([ expect.objectContaining({ truthDocumentEntries: [ - { + expect.objectContaining({ path: "docs/README.md", - kind: "behavior", + kind: "engineering-behavior", kindSource: "defaulted", - }, + }), ], }), ]); diff --git a/tests/sync/report.test.ts b/tests/sync/report.test.ts index 75cd876..9eed61e 100644 --- a/tests/sync/report.test.ts +++ b/tests/sync/report.test.ts @@ -12,7 +12,7 @@ describe("Truth Sync reporting", () => { const report = renderTruthSyncCompletedReport({ changedCode: ["src/auth/session.ts"], ownershipReviewed: ["docs/truthmark/routes/areas/repository.md"], - truthDocsUpdated: ["docs/truthmark/truth/authentication.md"], + truthDocsUpdated: ["docs/truthmark/engineering/behaviors/authentication.md"], evidenceChecked: [ { claim: "Session timeout behavior is documented in the authentication truth doc.", @@ -35,7 +35,7 @@ Ownership reviewed: - docs/truthmark/routes/areas/repository.md Truth docs updated: -- docs/truthmark/truth/authentication.md +- docs/truthmark/engineering/behaviors/authentication.md Evidence checked: - Claim: Session timeout behavior is documented in the authentication truth doc. @@ -48,7 +48,7 @@ Notes: status: "completed", changedCode: ["src/auth/session.ts"], ownershipReviewed: ["docs/truthmark/routes/areas/repository.md"], - truthDocsUpdated: ["docs/truthmark/truth/authentication.md"], + truthDocsUpdated: ["docs/truthmark/engineering/behaviors/authentication.md"], evidenceChecked: [ { claim: "Session timeout behavior is documented in the authentication truth doc.", @@ -67,7 +67,7 @@ Notes: const report = renderTruthSyncCompletedReport({ changedCode: ["src/auth/session.ts"], ownershipReviewed: ["docs/truthmark/routes/areas/repository.md"], - truthDocsUpdated: ["docs/truthmark/truth/authentication.md"], + truthDocsUpdated: ["docs/truthmark/engineering/behaviors/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/truthmark/truth/authentication.md"], + manualReviewFiles: ["docs/truthmark/engineering/behaviors/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/truthmark/truth/authentication.md +- docs/truthmark/engineering/behaviors/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/truthmark/truth/authentication.md +- docs/truthmark/engineering/behaviors/authentication.md Evidence checked: - Session timeout behavior was reviewed. @@ -144,7 +144,7 @@ Changed code reviewed: - src/auth/session.ts Truth docs updated: -- docs/truthmark/truth/authentication.md +- docs/truthmark/engineering/behaviors/authentication.md Evidence checked: - Claim:${" "} @@ -162,7 +162,7 @@ Changed code reviewed: - src/auth/session.ts Truth docs updated: -- docs/truthmark/truth/authentication.md +- docs/truthmark/engineering/behaviors/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 aa162bc..0b4bc48 100644 --- a/tests/templates/generated-surfaces.test.ts +++ b/tests/templates/generated-surfaces.test.ts @@ -1,3 +1,6 @@ +import { readFileSync } from "node:fs"; +import { join } from "node:path"; + import { describe, expect, it } from "vitest"; import { createDefaultConfig } from "../../src/config/defaults.js"; @@ -15,7 +18,36 @@ const portalPaths = [ ".gemini/commands/truthmark/portal.toml", ]; +const readOnlyProcedurePaths = [ + ".agents/skills/truthmark-check/support/procedure.md", + ".agents/skills/truthmark-preview/support/procedure.md", + ".claude/skills/truthmark-check/support/procedure.md", + ".claude/skills/truthmark-preview/support/procedure.md", + ".gemini/skills/truthmark-check/support/procedure.md", + ".gemini/skills/truthmark-preview/support/procedure.md", + ".github/skills/truthmark-check/support/procedure.md", + ".github/skills/truthmark-preview/support/procedure.md", + ".opencode/skills/truthmark-check/support/procedure.md", + ".opencode/skills/truthmark-preview/support/procedure.md", +]; + +const staleWriteAuthorizingLaneText = + "before writing canonical truth docs, classify the request or change as product-lane, engineering-lane, both-lane, or ambiguous"; + describe("Truthmark Portal generated surfaces", () => { + it("keeps checked-in read-only procedures free of write-authorizing lane wording", () => { + for (const procedurePath of readOnlyProcedurePaths) { + const content = readFileSync(join(process.cwd(), procedurePath), "utf8"); + + expect(content, procedurePath).not.toContain( + staleWriteAuthorizingLaneText, + ); + expect(content, procedurePath).toContain( + "classify the request or changed surface as product-lane, engineering-lane, both-lane, or ambiguous for reporting only", + ); + } + }); + it("omits generic optional CLI validation from generated user-facing workflow surfaces", () => { const config = createDefaultConfig(); const generatedSurfaces = renderGeneratedSurfaces(config); @@ -51,24 +83,34 @@ describe("Truthmark Portal generated surfaces", () => { ]), ); - const syncSkill = byPath.get(".agents/skills/truthmark-sync/SKILL.md") ?? ""; + 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") ?? ""; + 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(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(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( + "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"); @@ -76,7 +118,9 @@ describe("Truthmark Portal generated surfaces", () => { it("omits Portal surfaces and AGENTS wording when disabled", () => { const config = createDefaultConfig(); - const paths = renderGeneratedSurfaces(config).map((surface) => surface.path); + const paths = renderGeneratedSurfaces(config).map( + (surface) => surface.path, + ); expect(config.truthmark.generated.portal.enabled).toBe(false); for (const portalPath of portalPaths) { @@ -92,20 +136,25 @@ describe("Truthmark Portal generated surfaces", () => { }; const surfaces = renderGeneratedSurfaces(config); - const byPath = new Map(surfaces.map((surface) => [surface.path, surface.content])); + const byPath = new Map( + surfaces.map((surface) => [surface.path, surface.content]), + ); for (const portalPath of portalPaths) { expect(byPath.has(portalPath)).toBe(true); } - const portalSkill = byPath.get(".agents/skills/truthmark-portal/SKILL.md") ?? ""; + const portalSkill = + byPath.get(".agents/skills/truthmark-portal/SKILL.md") ?? ""; const portalProcedure = 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 copilotPrompt = + byPath.get(".github/prompts/truthmark-portal.prompt.md") ?? ""; + const geminiCommand = + byPath.get(".gemini/commands/truthmark/portal.toml") ?? ""; const agentsBlock = renderAgentsBlock(config); - for (const text of [portalSkill, portalProcedure, copilotPrompt, geminiCommand]) { + for (const text of [portalSkill, portalProcedure]) { expect(text).toContain("manual-only"); expect(text).toContain("Markdown remains canonical"); expect(text).toContain("does not require the truthmark CLI"); @@ -117,10 +166,21 @@ describe("Truthmark Portal generated surfaces", () => { expect(text).toContain("generated non-canonical static files"); } + expect(copilotPrompt).toContain( + "This prompt is the GitHub Copilot entrypoint for Truthmark Portal.", + ); + expect(copilotPrompt).toContain(".github/skills/truthmark-portal/SKILL.md"); + expect(geminiCommand).toContain( + "This command is the Gemini CLI entrypoint for Truthmark Portal.", + ); + expect(geminiCommand).toContain(".gemini/skills/truthmark-portal/SKILL.md"); + expect(portalProcedure).toContain("replace the entire output directory"); 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( + "Truthmark Portal is a separate manual-only presentation workflow", + ); expect(agentsBlock).toContain("docs/truthmark/generated/portal/"); expect(agentsBlock).toContain("Markdown remains canonical"); }); diff --git a/tests/templates/init-files.test.ts b/tests/templates/init-files.test.ts new file mode 100644 index 0000000..2e8d60a --- /dev/null +++ b/tests/templates/init-files.test.ts @@ -0,0 +1,53 @@ +import { describe, expect, it } from "vitest"; +import matter from "gray-matter"; + +import { + renderArchitectureDocTemplateFile, + renderBehaviorDocTemplateFile, + renderContractDocTemplateFile, + renderOperationsDocTemplateFile, + renderProductCapabilityDocTemplateFile, + renderTestBehaviorDocTemplateFile, + renderWorkflowDocTemplateFile, +} from "../../src/templates/init-files.js"; + +describe("truth doc templates", () => { + const templateCases = [ + ["product-capability", renderProductCapabilityDocTemplateFile], + ["engineering-behavior", renderBehaviorDocTemplateFile], + ["engineering-contract", renderContractDocTemplateFile], + ["engineering-architecture", renderArchitectureDocTemplateFile], + ["engineering-workflow", renderWorkflowDocTemplateFile], + ["engineering-operations", renderOperationsDocTemplateFile], + ["engineering-test-behavior", renderTestBehaviorDocTemplateFile], + ] as const; + + it("keeps cross-lane relationship authority in route YAML, not frontmatter", () => { + for (const [templateKind, renderTemplate] of templateCases) { + const template = renderTemplate(); + const frontmatter = matter(template).data; + + expect(frontmatter, templateKind).not.toHaveProperty("realized_by"); + expect(frontmatter, templateKind).not.toHaveProperty("realizes"); + expect(frontmatter, templateKind).not.toHaveProperty("depends_on"); + + const relationshipInstructionLines = template + .split(/\r?\n/u) + .filter((line) => + /\b(?:realized_by|canonical realizes|depends_on)\b/u.test(line), + ); + + for (const line of relationshipInstructionLines) { + expect(line, templateKind).toContain("route YAML"); + expect(line, templateKind).toContain("not doc frontmatter"); + } + } + + expect(renderProductCapabilityDocTemplateFile()).toContain( + "author canonical realized_by links in route YAML, not doc frontmatter", + ); + expect(renderBehaviorDocTemplateFile()).toContain( + "author canonical realizes links in route YAML, not doc frontmatter", + ); + }); +}); diff --git a/tests/truth/docs.test.ts b/tests/truth/docs.test.ts index 410b8b1..dbe0c3f 100644 --- a/tests/truth/docs.test.ts +++ b/tests/truth/docs.test.ts @@ -7,6 +7,6 @@ describe("resolveTruthDocsRoot", () => { it("returns the normalized configured truth root", () => { const config = createDefaultConfig(); - expect(resolveTruthDocsRoot(config)).toBe("docs/truthmark/truth"); + expect(resolveTruthDocsRoot(config)).toBe("docs/truthmark/engineering"); }); }); diff --git a/tests/workflow-state/build.test.ts b/tests/workflow-state/build.test.ts index 0b1664f..ff3cce8 100644 --- a/tests/workflow-state/build.test.ts +++ b/tests/workflow-state/build.test.ts @@ -113,14 +113,14 @@ describe("action context", () => { 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"], + truthDocs: ["docs/truthmark/engineering/repository/overview.md"], }); expect(context.mode).toBe("truth-doc-write"); expect(context.allowedWritePaths).toEqual([ + "docs/truthmark/engineering/repository/overview.md", "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); @@ -132,14 +132,14 @@ describe("action context", () => { 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"], + starterTruthDocs: ["docs/truthmark/engineering/new-area.md"], }); expect(context.mode).toBe("route-write"); expect(context.allowedWritePaths).toEqual([ + "docs/truthmark/engineering/new-area.md", "docs/truthmark/routes/areas.md", "docs/truthmark/routes/areas/new-area.md", - "docs/truthmark/truth/new-area.md", ]); expect(context.allowedWritePaths).not.toContain("*"); }); @@ -148,18 +148,18 @@ describe("action context", () => { 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"], + truthRoot: "docs/truthmark/engineering", + truthDocs: ["docs/truthmark/engineering/repository/overview.md"], codeWritePaths: ["src/**/*.ts"], }); expect(context.mode).toBe("code-write"); expect(context.allowedWritePaths).toEqual(["src/**/*.ts"]); expect(context.forbiddenWritePaths).toEqual([ + "docs/truthmark/engineering/**/*.md", + "docs/truthmark/engineering/repository/overview.md", "docs/truthmark/routes/areas.md", "docs/truthmark/routes/areas/repository.md", - "docs/truthmark/truth/**/*.md", - "docs/truthmark/truth/repository/overview.md", ]); }); @@ -293,9 +293,9 @@ describe("buildWorkflowState", () => { 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", + "# Truthmark Areas\n\n## Docs Only\n\nTruth documents:\n- docs/truthmark/engineering/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.writeFile("docs/truthmark/engineering/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");