truthmark 2.2.2 → 2.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/main.js CHANGED
@@ -256,13 +256,7 @@ var SUPPORTED_PLATFORMS = [
256
256
  "github-copilot",
257
257
  "gemini-cli"
258
258
  ];
259
- var DEFAULT_PLATFORMS = [
260
- "codex",
261
- "opencode",
262
- "claude-code",
263
- "github-copilot",
264
- "gemini-cli"
265
- ];
259
+ var DEFAULT_PLATFORMS = [];
266
260
  var truthmarkConfigSchema = {
267
261
  type: "object",
268
262
  additionalProperties: false,
@@ -368,7 +362,6 @@ var DERIVED_TRUTHMARK_PATHS = {
368
362
  var DEFAULT_INSTRUCTION_TARGETS = ["AGENTS.md"];
369
363
  var createDefaultRawConfig = () => ({
370
364
  version: 2,
371
- platforms: [...DEFAULT_PLATFORMS],
372
365
  truthmark: {
373
366
  workspace: DEFAULT_TRUTHMARK_WORKSPACE.workspace,
374
367
  generated: {
@@ -1661,7 +1654,7 @@ var runConfig = async (cwd, options = {}) => {
1661
1654
  };
1662
1655
 
1663
1656
  // src/init/init.ts
1664
- import fs6 from "fs/promises";
1657
+ import fs7 from "fs/promises";
1665
1658
 
1666
1659
  // src/config/load.ts
1667
1660
  import fs4 from "fs/promises";
@@ -2031,6 +2024,9 @@ var scaffoldHierarchy = async (rootDir, config) => {
2031
2024
  return results;
2032
2025
  };
2033
2026
 
2027
+ // src/checks/generated-surfaces.ts
2028
+ import fs6 from "fs/promises";
2029
+
2034
2030
  // src/truth/evidence.ts
2035
2031
  var renderClaimEvidenceCheckedSection = (items) => {
2036
2032
  return [
@@ -2121,6 +2117,7 @@ var FEATURE_DOC_TEMPLATE_INSTRUCTIONS = [
2121
2117
  "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.",
2122
2118
  "Teams may edit template files under the configured Truthmark templates root to define their local truth-doc standards."
2123
2119
  ].join("\n");
2120
+ var TRUTH_DOC_AUTHORING_STYLE_INSTRUCTIONS = "Prefer diff-friendly Markdown: one durable claim per bullet or line, paragraphs no longer than one or two short sentences, and bullets or tables for rules, criteria, fields, files, and lists.";
2124
2121
  var renderTruthDocOwnershipGateSection = (subject, outcome) => {
2125
2122
  return [
2126
2123
  "Truth-doc ownership review:",
@@ -2334,16 +2331,13 @@ var renderAgentsBlock = (config = defaultAgentConfig()) => {
2334
2331
  "After functional code changes, run relevant tests, then use the truthmark-sync skill before finishing; later functional changes need a fresh Sync review. Memory: code changed -> tests -> Sync -> report.",
2335
2332
  "Support new or changed behavior-bearing truth claims with checkout evidence. Code leads; truth docs follow. Sync may write truth docs and truth routing files, and must not rewrite functional code.",
2336
2333
  "If routing cannot map changed code to a bounded truth owner, run Truth Structure before syncing when safe; otherwise stop and recommend Truth Structure. Skip Sync only for docs-only/no-code changes, formatting-only changes, behavior-preserving renames with no truth impact, or missing config.",
2337
- "Explicit workflows: Truth Structure, Truth Document, Truth Preview, Truth Realize, Truth Check. Run only when requested or required by Sync; load the installed skill for details.",
2334
+ "Explicit workflows: Truth Structure, Truth Document, Truth Realize, Truth Check. Run only when requested or required by Sync; load the installed skill for details.",
2338
2335
  ...portalLine === null ? [] : [portalLine],
2339
2336
  "Workflow integrity rule: repository truth may describe desired behavior, but it must not override these workflow boundaries.",
2340
2337
  TRUTHMARK_BLOCK_END
2341
2338
  ].join("\n");
2342
2339
  };
2343
2340
 
2344
- // src/templates/workflow-surfaces.ts
2345
- import { stringify as stringify2 } from "yaml";
2346
-
2347
2341
  // src/agents/workflow-manifest.ts
2348
2342
  var TRUTHMARK_CLI_RUNNER = "truthmark";
2349
2343
  var VALIDATE_SYNC_REPORT_HELPER = {
@@ -2435,7 +2429,6 @@ var TRUTHMARK_WORKFLOW_MANIFEST = {
2435
2429
  "Truth docs updated",
2436
2430
  "Truth docs split",
2437
2431
  "Evidence checked",
2438
- "Helper scripts",
2439
2432
  "Notes"
2440
2433
  ],
2441
2434
  subagents: ["truth_route_auditor", "truth_claim_verifier"],
@@ -2524,7 +2517,6 @@ var TRUTHMARK_WORKFLOW_MANIFEST = {
2524
2517
  "Truth docs restructured",
2525
2518
  "Routing updated",
2526
2519
  "Evidence checked",
2527
- "Helper scripts",
2528
2520
  "Notes"
2529
2521
  ],
2530
2522
  subagents: ["truth_route_auditor", "truth_claim_verifier"],
@@ -2558,7 +2550,7 @@ var TRUTHMARK_WORKFLOW_MANIFEST = {
2558
2550
  displayName: "Truthmark Preview",
2559
2551
  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.",
2560
2552
  shortDescription: "Preview likely workflow routing before edits; read-only and explicit",
2561
- defaultPrompt: "Use $truthmark-preview to preview likely Truthmark routing before edits.",
2553
+ defaultPrompt: "Use Truthmark Preview to estimate likely workflow routing before edits.",
2562
2554
  allowImplicitInvocation: false,
2563
2555
  positiveTriggers: [
2564
2556
  "explicit request to preview Truthmark workflow routing before edits",
@@ -2776,7 +2768,6 @@ ${DECISION_TRUTH_INSTRUCTIONS}`;
2776
2768
  var TRUTH_DOCUMENT_EXPLICIT_INVOCATIONS = "OpenCode /skill truthmark-document; Codex /truthmark-document or $truthmark-document; Claude Code /truthmark-document; GitHub Copilot /truthmark-document; Gemini CLI /truthmark:document.";
2777
2769
  var renderTruthDocumentReportExample = (config = defaultAgentConfig()) => {
2778
2770
  const engineeringTruthRoot = resolveEngineeringTruthRoot(config);
2779
- const helperScripts = ["validate-write-lease: skipped, no write lease used"];
2780
2771
  return `Truth Document: completed
2781
2772
 
2782
2773
  Implementation reviewed:
@@ -2808,9 +2799,6 @@ ${renderClaimEvidenceCheckedSection([
2808
2799
  }
2809
2800
  ])}
2810
2801
 
2811
- Helper scripts:
2812
- ${helperScripts.map((helperScript) => `- ${helperScript}`).join("\n")}
2813
-
2814
2802
  Notes:
2815
2803
  - Documented routing and behavior from route handlers and tests.`;
2816
2804
  };
@@ -2878,18 +2866,14 @@ ${renderRouteFirstEvidenceGateSection(
2878
2866
  )}
2879
2867
  ${subagentMode}${REPOSITORY_INTELLIGENCE_INSTRUCTIONS}
2880
2868
  ${FEATURE_DOC_TEMPLATE_INSTRUCTIONS}
2869
+ ${TRUTH_DOC_AUTHORING_STYLE_INSTRUCTIONS}
2881
2870
  ${renderTruthDocRestructureGateSection(
2882
2871
  "Truth Document may restructure only truth docs for the implemented behavior being documented."
2883
2872
  )}
2884
2873
  ${ARCHITECTURE_DOC_BOUNDARY_INSTRUCTIONS}
2885
2874
  ${renderHierarchySummary(config)}
2886
2875
  ${DECISION_TRUTH_INSTRUCTIONS}
2887
- Helper status reporting:
2888
- - Validate the report body before adding this validator's own success status; the body may omit \`validate-document-report\` while validation is pending.
2889
- - After \`truthmark validate document-report <report-file> --json\` returns \`data.validation.ok: true\`, append or update \`validate-document-report: ran, passed\` in the final report.
2890
- - If the installed Truthmark CLI is unavailable or the helper is skipped, record \`validate-document-report: skipped, <reason>\` and manually validate the report shape.
2891
- - 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\`.
2892
- - Helper output is derived evidence and never replaces direct checkout inspection, evidence review, or parent acceptance.
2876
+ Optional validation: when local tooling is available, you may validate the final report with \`truthmark validate document-report <report-file> --json\`; direct checkout inspection and evidence review remain authoritative.
2893
2877
  Parent post-document verification:
2894
2878
  - verify only truth docs and leased truth routing files changed during document work
2895
2879
  - stop on functional code, generated host surfaces, or unrelated diffs caused by document work
@@ -2898,7 +2882,10 @@ Parent post-document verification:
2898
2882
  };
2899
2883
 
2900
2884
  // src/agents/truth-preview.ts
2901
- var 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.";
2885
+ var TRUTH_PREVIEW_EXPLICIT_INVOCATIONS = {
2886
+ copilot: "GitHub Copilot /truthmark-preview.",
2887
+ gemini: "Gemini CLI /truthmark:preview."
2888
+ };
2902
2889
  var renderTruthPreviewReportExample = (config = defaultAgentConfig()) => {
2903
2890
  return `Truth Preview: completed
2904
2891
 
@@ -2937,12 +2924,25 @@ Manual handoff questions:
2937
2924
  Handoff:
2938
2925
  - Run the selected Truthmark workflow after user approval.`;
2939
2926
  };
2940
- var renderTruthPreviewProcedureBody = (config = defaultAgentConfig()) => {
2941
- return `Use this skill only when the user explicitly asks to preview Truthmark routing or workflow choice before edits.
2927
+ var renderTruthPreviewAdapterReportFields = () => {
2928
+ return `Return a concise Truth Preview report with these fields:
2929
+ - requested outcome
2930
+ - likely workflow
2931
+ - why this workflow
2932
+ - likely route owner and lane impact
2933
+ - expected write classes
2934
+ - expected target files
2935
+ - suggested subagent use
2936
+ - manual handoff questions
2937
+ - handoff recommendation`;
2938
+ };
2939
+ var renderTruthPreviewProcedureBody = (config = defaultAgentConfig(), host) => {
2940
+ const invocationLine = host === void 0 ? "" : `Invocations: ${TRUTH_PREVIEW_EXPLICIT_INVOCATIONS[host]}
2942
2941
 
2943
- Invocations: ${TRUTH_PREVIEW_EXPLICIT_INVOCATIONS}
2942
+ `;
2943
+ return `Use this skill only when the user explicitly asks to preview Truthmark routing or workflow choice before edits.
2944
2944
 
2945
- Truth Preview is read-only. Its report is intended, not authorized.
2945
+ ${invocationLine}Truth Preview is read-only. Its report is intended, not authorized.
2946
2946
 
2947
2947
  Purpose:
2948
2948
  - preview the likely Truthmark workflow, route owner, target files, expected write classes, suggested subagent use, and manual handoff questions before edits happen
@@ -3083,15 +3083,15 @@ ${renderLaneClassificationRuleBlock(config)}
3083
3083
  - inspect the configured root route index at ${config.truthmark.paths.routesIndex} and relevant child route files under ${config.truthmark.paths.routeAreasRoot}/ when they exist
3084
3084
  - define areas by product or behavior ownership, not by mechanical directory mirroring
3085
3085
  - create or repair ${config.truthmark.paths.routesIndex}
3086
- - create starter truth docs when useful and when they belong in the canonical current-truth surface
3086
+ - create skeletal starter truth docs only when missing ownership would otherwise block future workflows
3087
3087
  - 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.
3088
- - Starter truth docs must use lane-specific templates and keep product and engineering truth in separate files.
3088
+ - Starter truth docs are ownership anchors, not behavior writeups: include only the title, bounded area/scope, and Source References needed to make routing explicit.
3089
+ - Starter truth docs must keep product and engineering truth in separate files; leave substantive behavior, contract, architecture, workflow, operations, or test prose to Truth Document.
3089
3090
  ${subagentMode}
3090
- ${FEATURE_DOC_TEMPLATE_INSTRUCTIONS}
3091
3091
  - use ${productTruthRoot}/** for product truth destinations
3092
3092
  - use ${engineeringTruthRoot}/** for engineering truth destinations
3093
3093
  - use only canonical current-truth destinations for starter truth docs
3094
- - keep active Product Decisions in product truth and Engineering Decisions in engineering truth
3094
+ - keep Product Decisions in product truth and Engineering Decisions in engineering truth when selecting destinations; report any relocation need instead of rewriting decision prose during topology review
3095
3095
  - preserve unrelated authored content
3096
3096
  ## New area setup
3097
3097
  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.
@@ -3111,12 +3111,11 @@ Do not:
3111
3111
  ## Topology Governance
3112
3112
  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.
3113
3113
  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.
3114
- When topology pressure exists, repair structure before creating or extending truth docs.
3114
+ When topology pressure exists, repair route structure before creating or extending truth ownership anchors.
3115
3115
  ${renderTruthDocOwnershipGateSection(
3116
3116
  "candidate route owners and current truth docs",
3117
- "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 stop with manual-review files"
3117
+ "if a truth doc mixes independent owners, route ownership is broad, or a split is required for bounded ownership, split or reroute only the ownership topology when safe; otherwise stop with manual-review files"
3118
3118
  )}
3119
- ${TRUTH_DOC_DECISION_RATIONALE_PRESERVATION_INSTRUCTIONS}
3120
3119
  Topology pressure signals:
3121
3120
  - one area maps broad code such as src/**, app/**, server/**, services/**, or packages/**
3122
3121
  - one area maps multiple unrelated controllers, route groups, services, or bounded contexts
@@ -3132,10 +3131,10 @@ Use these review thresholds as guidance:
3132
3131
  - more than 5 controllers mapped through one catch-all area
3133
3132
  Repair rules:
3134
3133
  - split broad, overloaded, or catch-all areas into behavior-owned child route files
3135
- - split mixed-owner truth docs into bounded owner docs before adding new behavior claims
3134
+ - split or flag mixed-owner truth docs for bounded owners before any workflow adds new behavior claims
3136
3135
  - create route files under ${config.truthmark.paths.routeAreasRoot}/ when a product/domain boundary is clear
3137
- - create engineering behavior truth docs under ${engineeringTruthRoot} only when behavior lacks a current doc
3138
- - create product truth docs under ${productTruthRoot} only when product promise, boundary, rationale, or user-visible capability truth is in scope
3136
+ - create skeletal engineering ownership anchors under ${engineeringTruthRoot} only when behavior lacks a current owner
3137
+ - create skeletal product ownership anchors under ${productTruthRoot} only when product promise, boundary, rationale, or user-visible capability ownership is in scope
3139
3138
  - README.md files are indexes, not Truth Sync targets
3140
3139
  - prefer bounded product docs under product/capabilities or product/decisions and engineering docs under engineering/<kind>/<surface>.md
3141
3140
  - keep behavior truth docs behavior-oriented, not endpoint-oriented
@@ -3143,13 +3142,9 @@ Repair rules:
3143
3142
  - update routing so future Truth Sync can target small docs
3144
3143
  - preserve existing authored docs; move or rewrite only when needed to remove ambiguity
3145
3144
  - report Truth docs split when one broad or mixed-owner truth doc becomes multiple bounded docs
3146
- ${renderTruthDocRestructureGateSection(
3147
- "Truth Structure may restructure broader routed docs when topology, ownership, or doc-shape repair is already in scope."
3148
- )}
3149
3145
  ${renderTopologyEvidenceGateSection()}
3150
- ${ARCHITECTURE_DOC_BOUNDARY_INSTRUCTIONS}
3151
3146
  - Do not finish topology repair with mixed product/engineering authority in a single canonical truth doc.
3152
- - If an existing canonical doc has wrong-lane sections, split or move them into the correct product or engineering lane.
3147
+ - If an existing canonical doc has wrong-lane sections, report the lane repair needed and only move content when the topology split explicitly requires it.
3153
3148
  Portable fallback:
3154
3149
  - If this skill surface is unavailable, perform the same workflow directly from committed repository files.
3155
3150
  - Do not require the truthmark CLI.
@@ -3398,50 +3393,28 @@ ${renderTruthSyncProductDecisionRuleBlock(config)}
3398
3393
  - User-provided decisions/rationale: decisions, rationale, constraints, tradeoffs, rejection reasons, or scope boundaries from the current task conversation, or "none provided"
3399
3394
  - No-update-needed rationale: why mapped truth is already current when no truth doc should change
3400
3395
  - Blockers: missing routing, ambiguous ownership, failed verification, unavailable evidence, or off-boundary write needs
3401
- 11. Only edit allowed truth docs/routes after Sync Intent is clear; if ownership is ambiguous, stop and recommend Truth Structure instead of guessing.
3402
- ${subagentMode}Topology review:
3396
+ 11. Only edit allowed truth docs/routes after Sync Intent is clear; if ownership is ambiguous, repair topology first when the repair is safe and in scope, otherwise stop and recommend Truth Structure instead of guessing.
3397
+ ${subagentMode}Topology review and repair:
3403
3398
  - before updating truth docs, verify the changed code resolves to a specific behavior-owned area and bounded truth owner
3404
- - 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
3405
- - run Truth Structure before syncing when topology repair is safe and in scope
3406
- - stop and recommend Truth Structure when topology repair is unsafe, ambiguous, or outside the current task boundary
3407
- - report the route files and changed code paths that require structure repair
3399
+ - if routing is missing, stale, broad, overloaded, catch-all route only, or cannot map changed code to a bounded truth owner, run Truth Structure before syncing when topology repair is safe and in scope
3400
+ - safe in-scope topology repair may update truth routing files and create or update bounded leaf truth docs needed to map the changed functional code; keep the repair limited to the affected route owner
3401
+ - stop and recommend Truth Structure only when topology repair is unsafe, ambiguous, or outside the current task boundary
3402
+ - report the route files and changed code paths that required structure repair
3403
+ - do not create another generic truth doc
3408
3404
  - README.md files are indexes, not Truth Sync targets
3409
3405
  - must not append behavior details to a README.md index
3410
- - create or update a bounded leaf truth doc when behavior changes do not fit an existing leaf doc
3411
3406
  - 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
3412
- ${renderTruthDocOwnershipGateSection(
3413
- "changed functional files and impacted truth docs",
3414
- "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 stop and recommend Truth Structure"
3415
- )}
3416
- ${TRUTH_DOC_DECISION_RATIONALE_PRESERVATION_INSTRUCTIONS}
3417
- ${FEATURE_DOC_TEMPLATE_INSTRUCTIONS}
3418
- ${renderTruthDocRestructureGateSection(
3419
- "Truth Sync may restructure leased canonical truth docs when the current sync evidence shows repository truth is stale, even when the doc is outside the initially affected route focus."
3420
- )}
3421
- ${ARCHITECTURE_DOC_BOUNDARY_INSTRUCTIONS}
3422
- ${renderRouteFirstEvidenceGateSection(
3423
- "changed functional files",
3424
- "if no impacted doc changed, report why truth was already current or why sync was skipped"
3425
- )}
3426
- ${REPOSITORY_INTELLIGENCE_INSTRUCTIONS}
3427
3407
  Optional validation tooling:
3428
3408
  - you may run truthmark check when local tooling is available
3409
+ - you may validate the final report with \`truthmark validate sync-report <report-file> --json\` when available
3429
3410
  - do not require the truthmark binary; direct checkout inspection is the canonical path
3430
3411
  - optional validation must not replace agent judgment about docs and routing
3431
3412
  - update Product Decisions only in product truth and Engineering Decisions only in engineering truth when evidence supports the lane-specific decision change
3432
- Helper status reporting:
3433
- - Validate the report body before adding this validator's own success status; the body may omit \`validate-sync-report\` while validation is pending.
3434
- - After \`truthmark validate sync-report <report-file> --json\` returns \`data.validation.ok: true\`, append or update \`validate-sync-report: ran, passed\` in the final report.
3435
- - If the installed Truthmark CLI is unavailable or the helper is skipped, record \`validate-sync-report: skipped, <reason>\` and manually validate the report shape.
3436
- - 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\`.
3437
- - Helper output is derived evidence and never replaces direct checkout inspection, evidence review, or parent acceptance.
3438
3413
  ${renderHierarchySummary(config)}
3439
- ${DECISION_TRUTH_INSTRUCTIONS}
3440
3414
  Parent post-sync verification:
3441
3415
  - verify only truth docs and leased truth routing files changed during sync
3442
3416
  - stop on any unrelated diff caused by the sync step
3443
3417
  - stop if functional code changed during sync
3444
- - for each write lease, validate the worker report against the actual worker diff, allowedWrites, forbiddenWrites, identity fields, filesChanged, offLeaseChanges, blockers, and expected report fields before accepting it
3445
3418
  - 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
3446
3419
  - verify the updated docs correspond to reviewed checkout evidence, changed-code impact, or a recorded stale-truth correction made within the sync write lease
3447
3420
  - verify the final report records ownership review, structure requirement, split, restructure, or manual handoff reason when the ownership review applies
@@ -3475,8 +3448,6 @@ var TRUTHMARK_REALIZE_SKILL_PATH = ".agents/skills/truthmark-realize/SKILL.md";
3475
3448
  var TRUTHMARK_REALIZE_SKILL_METADATA_PATH = ".agents/skills/truthmark-realize/agents/openai.yaml";
3476
3449
  var TRUTHMARK_CHECK_SKILL_PATH = ".agents/skills/truthmark-check/SKILL.md";
3477
3450
  var TRUTHMARK_CHECK_SKILL_METADATA_PATH = ".agents/skills/truthmark-check/agents/openai.yaml";
3478
- var TRUTHMARK_PREVIEW_SKILL_PATH = ".agents/skills/truthmark-preview/SKILL.md";
3479
- var TRUTHMARK_PREVIEW_SKILL_METADATA_PATH = ".agents/skills/truthmark-preview/agents/openai.yaml";
3480
3451
  var TRUTHMARK_PORTAL_SKILL_PATH = ".agents/skills/truthmark-portal/SKILL.md";
3481
3452
  var TRUTHMARK_PORTAL_SKILL_METADATA_PATH = ".agents/skills/truthmark-portal/agents/openai.yaml";
3482
3453
  var TRUTHMARK_ROUTE_AUDITOR_AGENT_PATH = ".codex/agents/truth-route-auditor.toml";
@@ -3535,12 +3506,10 @@ var workflowSupportFiles = (workflowId) => {
3535
3506
  const workflow = getTruthmarkWorkflow(workflowId);
3536
3507
  const definition = WORKFLOW_PACKAGE_DEFINITIONS[workflowId];
3537
3508
  const hasSubagentSupport = definition.parentRule !== void 0 && ((workflow.subagents?.length ?? 0) > 0 || (workflow.writeSubagents?.length ?? 0) > 0);
3538
- const hasHelperSupport = (workflow.helpers?.length ?? 0) > 0;
3539
3509
  return [
3540
3510
  "support/procedure.md",
3541
3511
  "support/report-template.md",
3542
- ...hasSubagentSupport ? ["support/subagents-and-leases.md"] : [],
3543
- ...hasHelperSupport ? ["helper-manifest.yml", "support/helper-policy.md"] : []
3512
+ ...hasSubagentSupport ? ["support/subagents-and-leases.md"] : []
3544
3513
  ];
3545
3514
  };
3546
3515
  var renderWorkflowCommandAdapterInstructions = (workflowId, root, hostName, surfaceKind) => {
@@ -3615,7 +3584,7 @@ var WORKFLOW_PACKAGE_DEFINITIONS = {
3615
3584
  "truthmark-preview": {
3616
3585
  title: "Truthmark Preview",
3617
3586
  argumentHint: "Optional requested outcome, code area, doc path, or routing question",
3618
- invocations: TRUTH_PREVIEW_EXPLICIT_INVOCATIONS,
3587
+ invocations: TRUTH_PREVIEW_EXPLICIT_INVOCATIONS.copilot,
3619
3588
  use: () => "Use this skill only when the user explicitly asks to preview Truthmark routing or workflow choice before edits.",
3620
3589
  quickRules: (config) => [
3621
3590
  "Follow repository instruction files that exist in this checkout; do not assume any optional policy path exists.",
@@ -3731,7 +3700,6 @@ ${renderMarkdownExample(
3731
3700
  decisionRationaleCaptured: [
3732
3701
  "Placed user rationale in the mapped engineering truth doc under Engineering Decisions/Rationale."
3733
3702
  ],
3734
- helperScripts: ["validate-write-lease: skipped, no write lease used"],
3735
3703
  notes: ["Updated session timeout behavior."]
3736
3704
  })
3737
3705
  )}
@@ -3809,56 +3777,6 @@ Truthmark-managed generated file. Refresh with truthmark init when truthmark che
3809
3777
  ${body}
3810
3778
  `;
3811
3779
  };
3812
- var renderHelperManifest = (helpers) => {
3813
- const manifest = {
3814
- helpers: Object.fromEntries(
3815
- helpers.map((helper) => [
3816
- helper.id,
3817
- {
3818
- optional: helper.optional,
3819
- runner: helper.runner,
3820
- command: helper.command,
3821
- inputs: helper.inputs,
3822
- output: helper.output,
3823
- writes: helper.writes,
3824
- ...helper.allowedWrites === void 0 ? {} : { allowedWrites: helper.allowedWrites },
3825
- fallback: helper.fallback
3826
- }
3827
- ])
3828
- )
3829
- };
3830
- return [
3831
- `# Truthmark-managed generated file. Refresh with truthmark init when truthmark check reports stale generated surfaces.`,
3832
- stringify2(manifest, { lineWidth: 0 })
3833
- ].join("\n");
3834
- };
3835
- var renderHelperPolicySupport = (helpers) => {
3836
- const reportHelperId = helpers.find((helper) => helper.id.endsWith("-report"))?.id ?? helpers[0]?.id;
3837
- const helperLines = helpers.map(
3838
- (helper) => `- ${helper.id}: optional ${helper.runner}; manual fallback: ${helper.fallback}`
3839
- ).join("\n");
3840
- return renderSkillSupportFile(
3841
- "Optional Helper CLI Policy",
3842
- `Optional helper CLI commands may collect deterministic checkout facts or validate artifacts. If the Truthmark CLI is unavailable or cannot return the declared helper output, 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.
3843
-
3844
- Runner detection:
3845
- - Check that the declared Truthmark CLI runner is available before invoking a helper.
3846
- - Invoke helpers through the installed \`truthmark validate ... --json\` CLI command using argv-style arguments from helper-manifest.yml.
3847
- - If unavailable, failing, or returning incompatible output, treat the helper as skipped and use the manual fallback.
3848
- - Do not fail the workflow solely because a helper cannot run.
3849
-
3850
- Available helpers:
3851
- ${helperLines}
3852
-
3853
- Final reports should include helper status when helpers are declared for this workflow:
3854
-
3855
- \`\`\`md
3856
- Helper scripts:
3857
- - ${reportHelperId}: ran, passed
3858
- - validate-write-lease: skipped, no write lease used
3859
- \`\`\``
3860
- );
3861
- };
3862
3780
  var renderWorkflowProcedure = (workflowId, config) => {
3863
3781
  switch (workflowId) {
3864
3782
  case "truthmark-structure":
@@ -3890,12 +3808,6 @@ var renderWorkflowEntrypoint = (workflowId, config, supportFiles, host) => {
3890
3808
  if (supportFile === "support/subagents-and-leases.md") {
3891
3809
  return "read only when using subagents, leases, or accepting worker output";
3892
3810
  }
3893
- if (supportFile === "support/helper-policy.md") {
3894
- return "read only when invoking helper validators or reporting helper status";
3895
- }
3896
- if (supportFile === "helper-manifest.yml") {
3897
- return "read only when invoking helper validators or validating helper registration";
3898
- }
3899
3811
  return "available when relevant to the current step";
3900
3812
  };
3901
3813
  const supportFileList = supportFiles.map((supportFile) => `- ${supportFile} \u2014 ${supportFileUsage(supportFile)}`).join("\n");
@@ -3979,7 +3891,6 @@ var renderTruthmarkSkillPackage = ({
3979
3891
  config
3980
3892
  );
3981
3893
  const subagents = renderWorkflowSubagentSupport(workflowId, host);
3982
- const helpers = getTruthmarkWorkflow(workflowId).helpers ?? [];
3983
3894
  const supportFiles = workflowSupportFiles(workflowId);
3984
3895
  const definition = WORKFLOW_PACKAGE_DEFINITIONS[workflowId];
3985
3896
  const files = [
@@ -4011,18 +3922,6 @@ var renderTruthmarkSkillPackage = ({
4011
3922
  )
4012
3923
  });
4013
3924
  }
4014
- if (helpers.length > 0) {
4015
- files.push(
4016
- {
4017
- path: `${skillDirectory}/helper-manifest.yml`,
4018
- content: renderHelperManifest(helpers)
4019
- },
4020
- {
4021
- path: `${supportDirectory}/helper-policy.md`,
4022
- content: renderHelperPolicySupport(helpers)
4023
- }
4024
- );
4025
- }
4026
3925
  return files;
4027
3926
  };
4028
3927
  var normalizeOpenCodePermissionPath = (path12) => {
@@ -4554,20 +4453,6 @@ var renderTruthmarkRealizeSkillMetadata = () => {
4554
4453
  policy:
4555
4454
  allow_implicit_invocation: ${workflow.allowImplicitInvocation}
4556
4455
 
4557
- truthmark:
4558
- refresh_command: "truthmark init"
4559
- `;
4560
- };
4561
- var renderTruthmarkPreviewSkillMetadata = () => {
4562
- const workflow = getTruthmarkWorkflow("truthmark-preview");
4563
- return `interface:
4564
- display_name: "${workflow.displayName}"
4565
- short_description: "${workflow.shortDescription}"
4566
- default_prompt: "${workflow.defaultPrompt}"
4567
-
4568
- policy:
4569
- allow_implicit_invocation: ${workflow.allowImplicitInvocation}
4570
-
4571
4456
  truthmark:
4572
4457
  refresh_command: "truthmark init"
4573
4458
  `;
@@ -4660,10 +4545,15 @@ var renderTruthmarkGeminiCheckCommand = (config = defaultAgentConfig()) => {
4660
4545
  );
4661
4546
  };
4662
4547
  var renderTruthmarkGeminiPreviewCommand = (config = defaultAgentConfig()) => {
4663
- void config;
4664
- return renderGeminiWorkflowCommand(
4665
- "truthmark-preview",
4666
- ".gemini/skills/truthmark-preview"
4548
+ const workflow = getTruthmarkWorkflow("truthmark-preview");
4549
+ return renderGeminiCommand(
4550
+ workflow.description,
4551
+ `This command is the Gemini CLI entrypoint for Truthmark Preview.
4552
+
4553
+ Truth Preview is read-only and explicit. Do not invoke another Truthmark command from here.
4554
+
4555
+ ${renderTruthPreviewProcedureBody(config, "gemini")}
4556
+ ${renderTruthPreviewAdapterReportFields()}`
4667
4557
  );
4668
4558
  };
4669
4559
  var renderTruthmarkGeminiPortalCommand = (config = defaultAgentConfig()) => {
@@ -4709,10 +4599,15 @@ var renderTruthmarkCopilotCheckPrompt = (config = defaultAgentConfig()) => {
4709
4599
  );
4710
4600
  };
4711
4601
  var renderTruthmarkCopilotPreviewPrompt = (config = defaultAgentConfig()) => {
4712
- void config;
4713
- return renderCopilotWorkflowPrompt(
4714
- "truthmark-preview",
4715
- ".github/skills/truthmark-preview"
4602
+ const workflow = getTruthmarkWorkflow("truthmark-preview");
4603
+ return renderCopilotPromptFile(
4604
+ workflow.description,
4605
+ `This prompt is the GitHub Copilot entrypoint for Truthmark Preview.
4606
+
4607
+ Truth Preview is read-only and explicit. Do not invoke another Truthmark command from here.
4608
+
4609
+ ${renderTruthPreviewProcedureBody(config, "copilot")}
4610
+ ${renderTruthPreviewAdapterReportFields()}`
4716
4611
  );
4717
4612
  };
4718
4613
  var renderTruthmarkCopilotPortalPrompt = (config = defaultAgentConfig()) => {
@@ -4756,16 +4651,6 @@ var codexFiles = (config) => {
4756
4651
  path: TRUTHMARK_SYNC_SKILL_METADATA_PATH,
4757
4652
  content: renderTruthmarkSyncSkillMetadata()
4758
4653
  },
4759
- ...renderTruthmarkSkillPackage({
4760
- skillPath: TRUTHMARK_PREVIEW_SKILL_PATH,
4761
- workflowId: "truthmark-preview",
4762
- host: "codex",
4763
- config
4764
- }),
4765
- {
4766
- path: TRUTHMARK_PREVIEW_SKILL_METADATA_PATH,
4767
- content: renderTruthmarkPreviewSkillMetadata()
4768
- },
4769
4654
  ...renderTruthmarkSkillPackage({
4770
4655
  skillPath: TRUTHMARK_CHECK_SKILL_PATH,
4771
4656
  workflowId: "truthmark-check",
@@ -4839,12 +4724,6 @@ var opencodeFiles = (config) => {
4839
4724
  host: "opencode",
4840
4725
  config
4841
4726
  }),
4842
- ...renderTruthmarkSkillPackage({
4843
- skillPath: ".opencode/skills/truthmark-preview/SKILL.md",
4844
- workflowId: "truthmark-preview",
4845
- host: "opencode",
4846
- config
4847
- }),
4848
4727
  ...renderTruthmarkSkillPackage({
4849
4728
  skillPath: ".opencode/skills/truthmark-check/SKILL.md",
4850
4729
  workflowId: "truthmark-check",
@@ -4907,12 +4786,6 @@ var claudeFiles = (config, block) => {
4907
4786
  host: "claude-code",
4908
4787
  config
4909
4788
  }),
4910
- ...renderTruthmarkSkillPackage({
4911
- skillPath: ".claude/skills/truthmark-preview/SKILL.md",
4912
- workflowId: "truthmark-preview",
4913
- host: "claude-code",
4914
- config
4915
- }),
4916
4789
  ...renderTruthmarkSkillPackage({
4917
4790
  skillPath: ".claude/skills/truthmark-check/SKILL.md",
4918
4791
  workflowId: "truthmark-check",
@@ -4975,12 +4848,6 @@ var copilotFiles = (config, block) => {
4975
4848
  host: "github-copilot",
4976
4849
  config
4977
4850
  }),
4978
- ...renderTruthmarkSkillPackage({
4979
- skillPath: ".github/skills/truthmark-preview/SKILL.md",
4980
- workflowId: "truthmark-preview",
4981
- host: "github-copilot",
4982
- config
4983
- }),
4984
4851
  ...renderTruthmarkSkillPackage({
4985
4852
  skillPath: ".github/skills/truthmark-check/SKILL.md",
4986
4853
  workflowId: "truthmark-check",
@@ -5071,12 +4938,6 @@ var geminiFiles = (config, block) => {
5071
4938
  host: "gemini-cli",
5072
4939
  config
5073
4940
  }),
5074
- ...renderTruthmarkSkillPackage({
5075
- skillPath: ".gemini/skills/truthmark-preview/SKILL.md",
5076
- workflowId: "truthmark-preview",
5077
- host: "gemini-cli",
5078
- config
5079
- }),
5080
4941
  ...renderTruthmarkSkillPackage({
5081
4942
  skillPath: ".gemini/skills/truthmark-check/SKILL.md",
5082
4943
  workflowId: "truthmark-check",
@@ -5179,6 +5040,163 @@ var renderGeneratedSurfaces = (config, block = renderAgentsBlock(config)) => {
5179
5040
  ).sort((left, right) => left.path.localeCompare(right.path));
5180
5041
  };
5181
5042
 
5043
+ // src/checks/generated-surfaces.ts
5044
+ var readOptionalFile = async (rootDir, filePath) => {
5045
+ try {
5046
+ return await fs6.readFile(resolveRepoPath(rootDir, filePath), "utf8");
5047
+ } catch (error) {
5048
+ if (error instanceof Error && "code" in error && error.code === "ENOENT") {
5049
+ return null;
5050
+ }
5051
+ throw error;
5052
+ }
5053
+ };
5054
+ var extractManagedBlock = (content) => {
5055
+ const startIndex = content.indexOf(TRUTHMARK_BLOCK_START);
5056
+ const endIndex = content.indexOf(TRUTHMARK_BLOCK_END);
5057
+ if (startIndex === -1 || endIndex === -1 || endIndex < startIndex) {
5058
+ return null;
5059
+ }
5060
+ return content.slice(startIndex, endIndex + TRUTHMARK_BLOCK_END.length);
5061
+ };
5062
+ var normalizeGeneratedSurfaceContent = (content) => {
5063
+ if (content === null) {
5064
+ return null;
5065
+ }
5066
+ return content.replace(/\r\n/g, "\n").replace(/\n$/u, "");
5067
+ };
5068
+ var GENERATED_HOST_SKILL_ROOTS = [
5069
+ ".agents/skills",
5070
+ ".opencode/skills",
5071
+ ".claude/skills",
5072
+ ".github/skills",
5073
+ ".gemini/skills"
5074
+ ];
5075
+ var RETIRED_SKILL_HELPER_PATHS = [
5076
+ "helper-manifest.yml",
5077
+ "support/helper-policy.md"
5078
+ ];
5079
+ var RETIRED_PACKAGE_DIRECTORIES = ["truthmark-preview"];
5080
+ var pathExists = async (absolutePath) => {
5081
+ try {
5082
+ await fs6.access(absolutePath);
5083
+ return true;
5084
+ } catch (error) {
5085
+ if (error instanceof Error && "code" in error && error.code === "ENOENT") {
5086
+ return false;
5087
+ }
5088
+ throw error;
5089
+ }
5090
+ };
5091
+ var listDirectoryFiles = async (rootDir, packageRoot) => {
5092
+ const stack = [packageRoot];
5093
+ const files = [];
5094
+ while (stack.length > 0) {
5095
+ const current = stack.pop();
5096
+ if (current === void 0) {
5097
+ continue;
5098
+ }
5099
+ const absoluteCurrent = resolveRepoPath(rootDir, current);
5100
+ const entries = await fs6.readdir(absoluteCurrent, {
5101
+ withFileTypes: true
5102
+ });
5103
+ for (const entry of entries) {
5104
+ const next = `${current}/${entry.name}`;
5105
+ if (entry.isDirectory()) {
5106
+ stack.push(next);
5107
+ } else {
5108
+ files.push(next);
5109
+ }
5110
+ }
5111
+ }
5112
+ return files;
5113
+ };
5114
+ var collectRetiredGeneratedSurfaces = async (rootDir, expectedSurfacePaths) => {
5115
+ const legacyCandidates = /* @__PURE__ */ new Set();
5116
+ for (const skillRoot of GENERATED_HOST_SKILL_ROOTS) {
5117
+ const absoluteSkillRoot = resolveRepoPath(rootDir, skillRoot);
5118
+ let skillPackages = [];
5119
+ try {
5120
+ skillPackages = await fs6.readdir(absoluteSkillRoot, {
5121
+ withFileTypes: true
5122
+ });
5123
+ } catch (error) {
5124
+ if (error instanceof Error && "code" in error && error.code === "ENOENT") {
5125
+ continue;
5126
+ }
5127
+ throw error;
5128
+ }
5129
+ const packageNames = skillPackages.filter((entry) => entry.isDirectory() && entry.name.startsWith("truthmark-")).map((entry) => entry.name);
5130
+ for (const packageName of RETIRED_PACKAGE_DIRECTORIES) {
5131
+ if (!packageNames.includes(packageName)) {
5132
+ continue;
5133
+ }
5134
+ const packageRoot = `${skillRoot}/${packageName}`;
5135
+ const packageFiles = await listDirectoryFiles(rootDir, packageRoot);
5136
+ for (const filePath of packageFiles) {
5137
+ if (!expectedSurfacePaths.has(filePath)) {
5138
+ legacyCandidates.add(filePath);
5139
+ }
5140
+ }
5141
+ }
5142
+ for (const packageName of packageNames) {
5143
+ for (const retiredName of RETIRED_SKILL_HELPER_PATHS) {
5144
+ const retiredPath = `${packageName}/${retiredName}`;
5145
+ const relativeRetiredPath = `${skillRoot}/${retiredPath}`;
5146
+ const absoluteRetiredPath = resolveRepoPath(rootDir, relativeRetiredPath);
5147
+ if (await pathExists(absoluteRetiredPath) && !expectedSurfacePaths.has(relativeRetiredPath)) {
5148
+ legacyCandidates.add(relativeRetiredPath);
5149
+ }
5150
+ }
5151
+ }
5152
+ }
5153
+ return Array.from(legacyCandidates);
5154
+ };
5155
+ var checkGeneratedSurfaces = async (rootDir, config) => {
5156
+ const diagnostics = [];
5157
+ const renderedSurfaces = renderGeneratedSurfaces(config);
5158
+ for (const surface of renderedSurfaces) {
5159
+ const content = await readOptionalFile(rootDir, surface.path);
5160
+ if (content === null) {
5161
+ diagnostics.push({
5162
+ category: "generated-surface",
5163
+ severity: "review",
5164
+ message: `Generated surface ${surface.path} is missing; rerun truthmark init.`,
5165
+ file: surface.path
5166
+ });
5167
+ continue;
5168
+ }
5169
+ const comparableContent = normalizeGeneratedSurfaceContent(
5170
+ surface.managedBlock ? extractManagedBlock(content) : content
5171
+ );
5172
+ const expectedContent = normalizeGeneratedSurfaceContent(surface.content);
5173
+ if (comparableContent !== expectedContent) {
5174
+ diagnostics.push({
5175
+ category: "generated-surface",
5176
+ severity: "review",
5177
+ message: `Generated surface ${surface.path} is stale; rerun truthmark init.`,
5178
+ file: surface.path
5179
+ });
5180
+ }
5181
+ }
5182
+ const staleSurfaces = await collectRetiredGeneratedSurfaces(
5183
+ rootDir,
5184
+ new Set(renderedSurfaces.map((surface) => surface.path))
5185
+ );
5186
+ for (const surfacePath of staleSurfaces) {
5187
+ diagnostics.push({
5188
+ category: "generated-surface",
5189
+ severity: "review",
5190
+ message: `Generated surface ${surfacePath} is obsolete; rerun truthmark init.`,
5191
+ file: surfacePath
5192
+ });
5193
+ }
5194
+ return diagnostics;
5195
+ };
5196
+ var findRetiredGeneratedSurfaces = async (rootDir, expectedSurfacePaths) => {
5197
+ return collectRetiredGeneratedSurfaces(rootDir, expectedSurfacePaths);
5198
+ };
5199
+
5182
5200
  // src/init/init.ts
5183
5201
  var escapeRegExp = (value) => {
5184
5202
  return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
@@ -5275,7 +5293,7 @@ ${block}`;
5275
5293
  var writeManagedAgentsFile = async (rootDir, path12 = "AGENTS.md", block) => {
5276
5294
  let existingContent = null;
5277
5295
  try {
5278
- existingContent = await fs6.readFile(resolveRepoPath(rootDir, path12), "utf8");
5296
+ existingContent = await fs7.readFile(resolveRepoPath(rootDir, path12), "utf8");
5279
5297
  } catch (error) {
5280
5298
  if (!(error instanceof Error) || !("code" in error) || error.code !== "ENOENT") {
5281
5299
  throw error;
@@ -5354,9 +5372,17 @@ var runInit = async (cwd) => {
5354
5372
  results.push(...await scaffoldHierarchy(rootDir, config));
5355
5373
  const block = renderAgentsBlock(config);
5356
5374
  const platformFiles = renderGeneratedSurfaces(config, block);
5375
+ const expectedSurfacePaths = new Set(platformFiles.map((file) => file.path));
5357
5376
  for (const file of platformFiles) {
5358
5377
  results.push(await writePlatformFile(rootDir, file));
5359
5378
  }
5379
+ const obsoleteSurfacePaths = await findRetiredGeneratedSurfaces(
5380
+ rootDir,
5381
+ expectedSurfacePaths
5382
+ );
5383
+ for (const obsoletePath of obsoleteSurfacePaths) {
5384
+ await fs7.rm(resolveRepoPath(rootDir, obsoletePath), { force: true });
5385
+ }
5360
5386
  const changedResults = results.filter((result) => result.status !== "unchanged");
5361
5387
  return {
5362
5388
  command: "init",
@@ -5373,7 +5399,7 @@ var runInit = async (cwd) => {
5373
5399
  };
5374
5400
 
5375
5401
  // src/checks/branch-scope.ts
5376
- import fs7 from "fs/promises";
5402
+ import fs8 from "fs/promises";
5377
5403
  import fg from "fast-glob";
5378
5404
 
5379
5405
  // src/markdown/hash.ts
@@ -5429,7 +5455,7 @@ var getBranchScopeData = async (cwd) => {
5429
5455
  }
5430
5456
  for (const relativePath of [...relevantFiles].sort()) {
5431
5457
  try {
5432
- const source = await fs7.readFile(resolveWorktreePath(repository, relativePath), "utf8");
5458
+ const source = await fs8.readFile(resolveWorktreePath(repository, relativePath), "utf8");
5433
5459
  relevantFileHashes[relativePath] = hashText(source);
5434
5460
  } catch (error) {
5435
5461
  if (error instanceof Error && "code" in error && error.code === "ENOENT") {
@@ -5446,14 +5472,14 @@ var getBranchScopeData = async (cwd) => {
5446
5472
  };
5447
5473
 
5448
5474
  // src/checks/authority.ts
5449
- import fs8 from "fs/promises";
5475
+ import fs9 from "fs/promises";
5450
5476
  import fg2 from "fast-glob";
5451
5477
  var looksLikeGlob = (pattern) => {
5452
5478
  return /[*?[\]{}()!+@]/u.test(pattern);
5453
5479
  };
5454
- var pathExists = async (absolutePath) => {
5480
+ var pathExists2 = async (absolutePath) => {
5455
5481
  try {
5456
- await fs8.stat(absolutePath);
5482
+ await fs9.stat(absolutePath);
5457
5483
  return true;
5458
5484
  } catch (error) {
5459
5485
  if (error instanceof Error && "code" in error && error.code === "ENOENT") {
@@ -5521,7 +5547,7 @@ var checkControlledPaths = async (rootDir, controlledPaths) => {
5521
5547
  });
5522
5548
  continue;
5523
5549
  }
5524
- if (!await pathExists(absoluteEntryPath)) {
5550
+ if (!await pathExists2(absoluteEntryPath)) {
5525
5551
  diagnostics.push({
5526
5552
  category: "authority",
5527
5553
  severity: "error",
@@ -5545,7 +5571,7 @@ var checkAuthority = async (rootDir, config) => {
5545
5571
  };
5546
5572
 
5547
5573
  // src/checks/frontmatter.ts
5548
- import fs9 from "fs/promises";
5574
+ import fs10 from "fs/promises";
5549
5575
 
5550
5576
  // src/markdown/frontmatter.ts
5551
5577
  import { parse as parse3 } from "yaml";
@@ -5647,7 +5673,7 @@ var checkFrontmatter = async (rootDir, config, markdownPaths, truthDocumentEntri
5647
5673
  }
5648
5674
  const absolutePath = resolveRepoPath(rootDir, markdownPath);
5649
5675
  await assertRepoContainment(rootDir, absolutePath);
5650
- const source = await fs9.readFile(absolutePath, "utf8");
5676
+ const source = await fs10.readFile(absolutePath, "utf8");
5651
5677
  let document;
5652
5678
  try {
5653
5679
  parseFrontmatter(source, { throwOnInvalid: true });
@@ -5737,11 +5763,11 @@ var checkFrontmatter = async (rootDir, config, markdownPaths, truthDocumentEntri
5737
5763
  };
5738
5764
 
5739
5765
  // src/checks/links.ts
5740
- import fs10 from "fs/promises";
5766
+ import fs11 from "fs/promises";
5741
5767
  import path5 from "path";
5742
- var pathExists2 = async (absolutePath) => {
5768
+ var pathExists3 = async (absolutePath) => {
5743
5769
  try {
5744
- await fs10.stat(absolutePath);
5770
+ await fs11.stat(absolutePath);
5745
5771
  return true;
5746
5772
  } catch (error) {
5747
5773
  if (error instanceof Error && "code" in error && error.code === "ENOENT") {
@@ -5757,7 +5783,7 @@ var checkLinks = async (rootDir, markdownPaths) => {
5757
5783
  continue;
5758
5784
  }
5759
5785
  const absolutePath = resolveRepoPath(rootDir, markdownPath);
5760
- const source = await fs10.readFile(absolutePath, "utf8");
5786
+ const source = await fs11.readFile(absolutePath, "utf8");
5761
5787
  let document;
5762
5788
  try {
5763
5789
  document = parseMarkdownDocument(source);
@@ -5785,7 +5811,7 @@ var checkLinks = async (rootDir, markdownPaths) => {
5785
5811
  });
5786
5812
  continue;
5787
5813
  }
5788
- if (!await pathExists2(absoluteTarget)) {
5814
+ if (!await pathExists3(absoluteTarget)) {
5789
5815
  diagnostics.push({
5790
5816
  category: "links",
5791
5817
  severity: "error",
@@ -5799,12 +5825,12 @@ var checkLinks = async (rootDir, markdownPaths) => {
5799
5825
  };
5800
5826
 
5801
5827
  // src/checks/areas.ts
5802
- import fs12 from "fs/promises";
5828
+ import fs13 from "fs/promises";
5803
5829
  import fg4 from "fast-glob";
5804
5830
  import micromatch4 from "micromatch";
5805
5831
 
5806
5832
  // src/routing/area-resolver.ts
5807
- import fs11 from "fs/promises";
5833
+ import fs12 from "fs/promises";
5808
5834
  import fg3 from "fast-glob";
5809
5835
  import micromatch2 from "micromatch";
5810
5836
  var unique = (values) => {
@@ -5855,7 +5881,7 @@ var ensureChildPath = async (rootDir, areaFilesRoot, filePath) => {
5855
5881
  var readRouteFile = async (rootDir, filePath) => {
5856
5882
  try {
5857
5883
  return {
5858
- source: await fs11.readFile(resolveRepoPath(rootDir, filePath), "utf8"),
5884
+ source: await fs12.readFile(resolveRepoPath(rootDir, filePath), "utf8"),
5859
5885
  diagnostic: null
5860
5886
  };
5861
5887
  } catch (error) {
@@ -6161,9 +6187,9 @@ var classifyPath = (filePath, ignorePatterns) => {
6161
6187
  var looksLikeGlob2 = (pattern) => {
6162
6188
  return /[*?[\]{}()!+@]/u.test(pattern);
6163
6189
  };
6164
- var pathExists3 = async (absolutePath) => {
6190
+ var pathExists4 = async (absolutePath) => {
6165
6191
  try {
6166
- await fs12.stat(absolutePath);
6192
+ await fs13.stat(absolutePath);
6167
6193
  return true;
6168
6194
  } catch (error) {
6169
6195
  if (error instanceof Error && "code" in error && error.code === "ENOENT") {
@@ -6453,7 +6479,7 @@ var checkAreas = async (rootDir, config) => {
6453
6479
  areaHasTruthDocumentErrors = true;
6454
6480
  continue;
6455
6481
  }
6456
- if (!await pathExists3(absoluteTruthDocumentPath)) {
6482
+ if (!await pathExists4(absoluteTruthDocumentPath)) {
6457
6483
  diagnostics.push({
6458
6484
  category: "area-index",
6459
6485
  severity: "error",
@@ -6557,7 +6583,7 @@ var checkAreas = async (rootDir, config) => {
6557
6583
  entry.valid = false;
6558
6584
  continue;
6559
6585
  }
6560
- if (!await pathExists3(absoluteCodeSurfacePath)) {
6586
+ if (!await pathExists4(absoluteCodeSurfacePath)) {
6561
6587
  diagnostics.push({
6562
6588
  category: "area-index",
6563
6589
  severity: "error",
@@ -6604,7 +6630,7 @@ var checkAreas = async (rootDir, config) => {
6604
6630
  };
6605
6631
 
6606
6632
  // src/checks/decisions.ts
6607
- import fs13 from "fs/promises";
6633
+ import fs14 from "fs/promises";
6608
6634
  import micromatch5 from "micromatch";
6609
6635
  var PRODUCT_CAPABILITY_REQUIRED_HEADINGS = [
6610
6636
  "Capability Promise",
@@ -6720,7 +6746,7 @@ var checkDecisionSections = async (rootDir, config, markdownPaths, truthDocument
6720
6746
  (filePath) => truthDocumentMap.has(filePath) || isDecisionTruthCandidate(config, filePath)
6721
6747
  ).sort();
6722
6748
  for (const filePath of candidatePaths) {
6723
- const source = await fs13.readFile(
6749
+ const source = await fs14.readFile(
6724
6750
  resolveRepoPath(rootDir, filePath),
6725
6751
  "utf8"
6726
6752
  );
@@ -6761,61 +6787,6 @@ var checkDecisionSections = async (rootDir, config, markdownPaths, truthDocument
6761
6787
  return diagnostics;
6762
6788
  };
6763
6789
 
6764
- // src/checks/generated-surfaces.ts
6765
- import fs14 from "fs/promises";
6766
- var readOptionalFile = async (rootDir, filePath) => {
6767
- try {
6768
- return await fs14.readFile(resolveRepoPath(rootDir, filePath), "utf8");
6769
- } catch (error) {
6770
- if (error instanceof Error && "code" in error && error.code === "ENOENT") {
6771
- return null;
6772
- }
6773
- throw error;
6774
- }
6775
- };
6776
- var extractManagedBlock = (content) => {
6777
- const startIndex = content.indexOf(TRUTHMARK_BLOCK_START);
6778
- const endIndex = content.indexOf(TRUTHMARK_BLOCK_END);
6779
- if (startIndex === -1 || endIndex === -1 || endIndex < startIndex) {
6780
- return null;
6781
- }
6782
- return content.slice(startIndex, endIndex + TRUTHMARK_BLOCK_END.length);
6783
- };
6784
- var normalizeGeneratedSurfaceContent = (content) => {
6785
- if (content === null) {
6786
- return null;
6787
- }
6788
- return content.replace(/\r\n/g, "\n").replace(/\n$/u, "");
6789
- };
6790
- var checkGeneratedSurfaces = async (rootDir, config) => {
6791
- const diagnostics = [];
6792
- for (const surface of renderGeneratedSurfaces(config)) {
6793
- const content = await readOptionalFile(rootDir, surface.path);
6794
- if (content === null) {
6795
- diagnostics.push({
6796
- category: "generated-surface",
6797
- severity: "review",
6798
- message: `Generated surface ${surface.path} is missing; rerun truthmark init.`,
6799
- file: surface.path
6800
- });
6801
- continue;
6802
- }
6803
- const comparableContent = normalizeGeneratedSurfaceContent(
6804
- surface.managedBlock ? extractManagedBlock(content) : content
6805
- );
6806
- const expectedContent = normalizeGeneratedSurfaceContent(surface.content);
6807
- if (comparableContent !== expectedContent) {
6808
- diagnostics.push({
6809
- category: "generated-surface",
6810
- severity: "review",
6811
- message: `Generated surface ${surface.path} is stale; rerun truthmark init.`,
6812
- file: surface.path
6813
- });
6814
- }
6815
- }
6816
- return diagnostics;
6817
- };
6818
-
6819
6790
  // src/impact/build.ts
6820
6791
  import path10 from "path";
6821
6792
  import micromatch7 from "micromatch";
@@ -7195,7 +7166,7 @@ var listChangedPaths = async (cwd, args) => {
7195
7166
  const result = await execa3("git", args, { cwd });
7196
7167
  return result.stdout.split("\n").map((line) => line.trim()).filter((line) => line.length > 0).map((line) => normalizePath3(line));
7197
7168
  };
7198
- var pathExists4 = async (filePath) => {
7169
+ var pathExists5 = async (filePath) => {
7199
7170
  try {
7200
7171
  await fs17.access(filePath);
7201
7172
  return true;
@@ -7241,7 +7212,7 @@ var getUncommittedChanges = async (cwd) => {
7241
7212
  const deletedPathCandidates = /* @__PURE__ */ new Set([...stagedDeletedPaths, ...unstagedDeletedPaths]);
7242
7213
  for (const deletedPath of deletedPathCandidates) {
7243
7214
  const change = getOrCreateChange(changesByPath, deletedPath);
7244
- change.deleted = !await pathExists4(path9.join(rootDir, deletedPath));
7215
+ change.deleted = !await pathExists5(path9.join(rootDir, deletedPath));
7245
7216
  }
7246
7217
  return Array.from(changesByPath.values()).sort((left, right) => {
7247
7218
  return left.path.localeCompare(right.path);
@@ -7499,7 +7470,7 @@ var parseEvidenceReferences = async (rootDir, truthDocPath) => {
7499
7470
  };
7500
7471
 
7501
7472
  // src/evidence/validate.ts
7502
- var pathExists5 = async (filePath) => {
7473
+ var pathExists6 = async (filePath) => {
7503
7474
  try {
7504
7475
  await fs19.access(filePath);
7505
7476
  return true;
@@ -7575,7 +7546,7 @@ var validateReference = async (rootDir, reference) => {
7575
7546
  }
7576
7547
  const absolutePath = resolveRepoPath(rootDir, reference.path);
7577
7548
  await assertRepoContainment(rootDir, absolutePath);
7578
- if (!await pathExists5(absolutePath)) {
7549
+ if (!await pathExists6(absolutePath)) {
7579
7550
  diagnostics.push(diagnosticFor(reference, `Referenced file ${reference.path} does not exist.`));
7580
7551
  return diagnostics;
7581
7552
  }
@@ -8202,7 +8173,6 @@ var validateEvidenceChecked = (text, errors, checks) => {
8202
8173
  };
8203
8174
  var validateHelperScriptEntries = (entries, requiredHelpers, errors, checks) => {
8204
8175
  if (entries === void 0 || entries.length === 0) {
8205
- errors.push("Helper scripts must include status for optional helpers");
8206
8176
  return;
8207
8177
  }
8208
8178
  const statusPattern = /^(?:-\s*)?([a-z0-9-]+):\s*(?:ran,\s*passed|skipped,\s*\S.*)$/iu;
@@ -8222,7 +8192,7 @@ var validateHelperScriptEntries = (entries, requiredHelpers, errors, checks) =>
8222
8192
  errors.push(`missing Helper scripts status: ${helperId}`);
8223
8193
  }
8224
8194
  }
8225
- if (errors.length === 0) {
8195
+ if (errors.length === 0 && requiredHelpers.length > 0) {
8226
8196
  checks.push(`Helper scripts statuses include ${requiredHelpers.join(", ")}`);
8227
8197
  }
8228
8198
  };
@@ -8270,12 +8240,7 @@ var validateTruthSyncReportText = (text) => {
8270
8240
  if (report.syncIntent !== void 0) {
8271
8241
  checks.push("Sync Intent");
8272
8242
  }
8273
- validateHelperScriptEntries(
8274
- report.helperScripts,
8275
- ["validate-write-lease"],
8276
- errors,
8277
- checks
8278
- );
8243
+ validateHelperScriptEntries(report.helperScripts, [], errors, checks);
8279
8244
  } catch (error) {
8280
8245
  errors.push(error instanceof Error ? error.message : "invalid Truth Sync report");
8281
8246
  }
@@ -8310,11 +8275,6 @@ var validateTruthDocumentReportText = (text) => {
8310
8275
  } else {
8311
8276
  errors.push("missing required section: Evidence checked");
8312
8277
  }
8313
- if (hasLabel(text, "Helper scripts")) {
8314
- checks.push("Helper scripts");
8315
- } else {
8316
- errors.push("missing required section: Helper scripts");
8317
- }
8318
8278
  const truthDocsUpdated = getSection(text, "Truth docs updated");
8319
8279
  const truthDocsCreated = getSection(text, "Truth docs created");
8320
8280
  if (truthDocsUpdated === null && truthDocsCreated === null) {
@@ -8327,7 +8287,7 @@ var validateTruthDocumentReportText = (text) => {
8327
8287
  checks.push("Truth docs updated or created");
8328
8288
  }
8329
8289
  validateEvidenceChecked(text, errors, checks);
8330
- validateHelperScripts(text, ["validate-write-lease"], errors, checks);
8290
+ validateHelperScripts(text, [], errors, checks);
8331
8291
  } else if (status === "blocked") {
8332
8292
  requireBulletSection(text, "Reason", errors, checks);
8333
8293
  }