truthmark 1.2.2 → 1.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/README.de.md +75 -31
- package/README.es.md +76 -32
- package/README.md +97 -30
- package/README.ru.md +75 -31
- package/README.zh.md +75 -31
- package/dist/main.js +360 -102
- package/dist/main.js.map +1 -1
- package/package.json +1 -1
package/dist/main.js
CHANGED
|
@@ -43,7 +43,7 @@ var renderJson = (result) => {
|
|
|
43
43
|
};
|
|
44
44
|
|
|
45
45
|
// src/config/command.ts
|
|
46
|
-
import
|
|
46
|
+
import fs3 from "fs/promises";
|
|
47
47
|
|
|
48
48
|
// src/fs/paths.ts
|
|
49
49
|
import path from "path";
|
|
@@ -51,19 +51,37 @@ import fs from "fs/promises";
|
|
|
51
51
|
var isPathInsideRoot = (rootDir, targetPath) => {
|
|
52
52
|
return targetPath === rootDir || targetPath.startsWith(`${rootDir}${path.sep}`);
|
|
53
53
|
};
|
|
54
|
+
var isNodeErrorWithCode = (error, code) => {
|
|
55
|
+
return error instanceof Error && "code" in error && error.code === code;
|
|
56
|
+
};
|
|
57
|
+
var joinMissingSegments = (resolvedPath, missingSegments) => {
|
|
58
|
+
return missingSegments.reduce((currentResolvedPath, segment) => {
|
|
59
|
+
return path.join(currentResolvedPath, segment);
|
|
60
|
+
}, resolvedPath);
|
|
61
|
+
};
|
|
54
62
|
var resolveThroughExistingAncestor = async (targetPath) => {
|
|
55
63
|
let currentPath = path.resolve(targetPath);
|
|
56
64
|
const missingSegments = [];
|
|
57
65
|
while (true) {
|
|
58
66
|
try {
|
|
59
67
|
const resolvedExistingPath = await fs.realpath(currentPath);
|
|
60
|
-
return
|
|
61
|
-
return path.join(resolvedPath, segment);
|
|
62
|
-
}, resolvedExistingPath);
|
|
68
|
+
return joinMissingSegments(resolvedExistingPath, missingSegments);
|
|
63
69
|
} catch (error) {
|
|
64
|
-
if (!(error
|
|
70
|
+
if (!isNodeErrorWithCode(error, "ENOENT")) {
|
|
65
71
|
throw error;
|
|
66
72
|
}
|
|
73
|
+
try {
|
|
74
|
+
const currentStat = await fs.lstat(currentPath);
|
|
75
|
+
if (currentStat.isSymbolicLink()) {
|
|
76
|
+
const linkTarget = await fs.readlink(currentPath);
|
|
77
|
+
const resolvedLinkTarget = path.resolve(path.dirname(currentPath), linkTarget);
|
|
78
|
+
return joinMissingSegments(resolvedLinkTarget, missingSegments);
|
|
79
|
+
}
|
|
80
|
+
} catch (lstatError) {
|
|
81
|
+
if (!isNodeErrorWithCode(lstatError, "ENOENT")) {
|
|
82
|
+
throw lstatError;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
67
85
|
const parentPath = path.dirname(currentPath);
|
|
68
86
|
if (parentPath === currentPath) {
|
|
69
87
|
return path.resolve(targetPath);
|
|
@@ -374,7 +392,6 @@ var DEFAULT_DOCS_HIERARCHY = {
|
|
|
374
392
|
}
|
|
375
393
|
};
|
|
376
394
|
var DEFAULT_AUTHORITY = [
|
|
377
|
-
"TRUTHMARK.md",
|
|
378
395
|
DEFAULT_DOCS_HIERARCHY.routing.root_index,
|
|
379
396
|
`${DEFAULT_DOCS_HIERARCHY.routing.area_files_root}/**/*.md`,
|
|
380
397
|
`${DEFAULT_DOCS_HIERARCHY.roots.ai}/**/*.md`,
|
|
@@ -427,37 +444,10 @@ var createDefaultConfig = () => ({
|
|
|
427
444
|
}
|
|
428
445
|
});
|
|
429
446
|
|
|
430
|
-
// src/version.ts
|
|
431
|
-
import fs3 from "fs";
|
|
432
|
-
var packageJson = JSON.parse(
|
|
433
|
-
fs3.readFileSync(new URL("../package.json", import.meta.url), "utf8")
|
|
434
|
-
);
|
|
435
|
-
var TRUTHMARK_VERSION = packageJson.version;
|
|
436
|
-
|
|
437
447
|
// src/templates/init-files.ts
|
|
438
448
|
var renderConfigTemplate = () => {
|
|
439
449
|
return stringify(createDefaultRawConfig());
|
|
440
450
|
};
|
|
441
|
-
var renderTruthmarkTemplate = () => {
|
|
442
|
-
return `---
|
|
443
|
-
status: active
|
|
444
|
-
doc_type: workflow-contract
|
|
445
|
-
last_reviewed: 2026-05-10
|
|
446
|
-
source_of_truth:
|
|
447
|
-
- .truthmark/config.yml
|
|
448
|
-
---
|
|
449
|
-
|
|
450
|
-
# Truthmark
|
|
451
|
-
|
|
452
|
-
Markdown in the current checkout is authoritative for this branch.
|
|
453
|
-
|
|
454
|
-
Installed workflow surfaces include a Truthmark ${TRUTHMARK_VERSION} version marker. After upgrading Truthmark, rerun \`truthmark init\` and review generated workflow diffs.
|
|
455
|
-
|
|
456
|
-
Workflow runtime lives in installed skills and managed instruction blocks. Agents inspect the checkout directly; \`truthmark check\` is optional validation.
|
|
457
|
-
|
|
458
|
-
Truth Sync follows code; Truth Realize follows docs. Truth Sync may update mapped truth docs; Truth Realize never edits truth docs or routing.
|
|
459
|
-
`;
|
|
460
|
-
};
|
|
461
451
|
var titleCase = (value) => {
|
|
462
452
|
return value.split(/[-_\s]+/u).filter(Boolean).map((segment) => segment.charAt(0).toUpperCase() + segment.slice(1)).join(" ");
|
|
463
453
|
};
|
|
@@ -561,44 +551,123 @@ var renderFeatureDomainReadmeTemplate = (config) => {
|
|
|
561
551
|
""
|
|
562
552
|
].join("\n");
|
|
563
553
|
};
|
|
564
|
-
var
|
|
565
|
-
|
|
566
|
-
const title = titleCase(defaultArea);
|
|
554
|
+
var FEATURE_DOC_TEMPLATE_PATH = "docs/templates/feature-doc.md";
|
|
555
|
+
var renderFeatureDocTemplateFile = () => {
|
|
567
556
|
return [
|
|
568
557
|
"---",
|
|
569
558
|
"status: active",
|
|
570
559
|
"doc_type: feature",
|
|
571
|
-
"last_reviewed: 2026-05-
|
|
560
|
+
"last_reviewed: 2026-05-12",
|
|
572
561
|
"source_of_truth:",
|
|
573
|
-
|
|
562
|
+
" - {{source_of_truth}}",
|
|
574
563
|
"---",
|
|
575
564
|
"",
|
|
576
|
-
|
|
565
|
+
"# {{title}}",
|
|
566
|
+
"",
|
|
567
|
+
"## Purpose",
|
|
568
|
+
"",
|
|
569
|
+
"<!-- State why this feature exists, the user or system outcome it protects, and the problem it solves. Keep roadmap or implementation plans out of this section. -->",
|
|
570
|
+
"",
|
|
571
|
+
"{{purpose}}",
|
|
577
572
|
"",
|
|
578
573
|
"## Scope",
|
|
579
574
|
"",
|
|
580
|
-
|
|
575
|
+
"{{scope}}",
|
|
576
|
+
"",
|
|
577
|
+
"<!--",
|
|
578
|
+
"This doc must own one coherent behavior surface.",
|
|
579
|
+
"Split into another leaf doc when content introduces:",
|
|
580
|
+
"- a distinct user or system outcome",
|
|
581
|
+
"- a separate lifecycle or state machine",
|
|
582
|
+
"- an unrelated rule family",
|
|
583
|
+
"- a different external contract",
|
|
584
|
+
"- code that should route through a different owner",
|
|
585
|
+
"Keep README.md files as indexes only.",
|
|
586
|
+
"-->",
|
|
587
|
+
"",
|
|
588
|
+
"This doc was created from the editable feature-doc template at {{template_path}}.",
|
|
581
589
|
"",
|
|
582
590
|
"## Current Behavior",
|
|
583
591
|
"",
|
|
584
|
-
"
|
|
592
|
+
"<!-- Describe implemented behavior in present tense. Do not include desired future behavior. -->",
|
|
593
|
+
"",
|
|
594
|
+
"{{current_behavior}}",
|
|
595
|
+
"",
|
|
596
|
+
"## Core Rules",
|
|
597
|
+
"",
|
|
598
|
+
"<!-- Capture stable business rules, invariants, precedence rules, validation rules, and must-never constraints. Omit incidental implementation details. -->",
|
|
599
|
+
"",
|
|
600
|
+
"{{core_rules}}",
|
|
601
|
+
"",
|
|
602
|
+
"## Flows And States",
|
|
603
|
+
"",
|
|
604
|
+
"<!-- Use for route switches, state transitions, lifecycle stages, retries, fallbacks, and important error paths. Write 'None beyond current behavior.' when no distinct flow or state model exists. -->",
|
|
605
|
+
"",
|
|
606
|
+
"{{flows_and_states}}",
|
|
607
|
+
"",
|
|
608
|
+
"## Contracts",
|
|
609
|
+
"",
|
|
610
|
+
"<!-- Capture user-visible or integration contracts: CLI/API shape, inputs, outputs, diagnostics, files, events, permissions, or links to canonical contract docs. Avoid duplicating a separate canonical contract doc. -->",
|
|
611
|
+
"",
|
|
612
|
+
"{{contracts}}",
|
|
585
613
|
"",
|
|
586
614
|
"## Product Decisions",
|
|
587
615
|
"",
|
|
588
|
-
"
|
|
616
|
+
"<!-- Keep active decisions only. Replace stale decisions instead of appending historical logs. -->",
|
|
617
|
+
"",
|
|
618
|
+
"{{decision}}",
|
|
589
619
|
"",
|
|
590
620
|
"## Rationale",
|
|
591
621
|
"",
|
|
592
|
-
"
|
|
622
|
+
"<!-- Explain why the current behavior and active decisions are this way, including tradeoffs. -->",
|
|
623
|
+
"",
|
|
624
|
+
"{{rationale}}",
|
|
625
|
+
"",
|
|
626
|
+
"## Non-Goals",
|
|
627
|
+
"",
|
|
628
|
+
"<!-- Name adjacent behavior this doc intentionally does not own, especially tempting future expansions. -->",
|
|
629
|
+
"",
|
|
630
|
+
"{{non_goals}}",
|
|
631
|
+
"",
|
|
632
|
+
"## Maintenance Notes",
|
|
633
|
+
"",
|
|
634
|
+
"<!-- List related tests, routing cautions, migration notes, and common drift risks for future agents. Keep this operational, not historical. -->",
|
|
635
|
+
"",
|
|
636
|
+
"{{maintenance_notes}}",
|
|
593
637
|
""
|
|
594
638
|
].join("\n");
|
|
595
639
|
};
|
|
640
|
+
var renderTemplate = (template, values) => {
|
|
641
|
+
return Object.entries(values).reduce((rendered, [key, value]) => {
|
|
642
|
+
return rendered.split(`{{${key}}}`).join(value);
|
|
643
|
+
}, template);
|
|
644
|
+
};
|
|
645
|
+
var renderFeatureLeafDocTemplate = (config, template = renderFeatureDocTemplateFile()) => {
|
|
646
|
+
const defaultArea = config.docs.routing.defaultArea;
|
|
647
|
+
const title = titleCase(defaultArea);
|
|
648
|
+
return renderTemplate(template, {
|
|
649
|
+
area: defaultArea,
|
|
650
|
+
contracts: "- External contracts should link to the nearest canonical contract doc when one exists.",
|
|
651
|
+
core_rules: "- Feature README files are indexes; behavior truth belongs in bounded leaf docs.",
|
|
652
|
+
current_behavior: "- Document current behavior here when implementation changes make repository truth incomplete.",
|
|
653
|
+
decision: "- Decision (2026-05-09): Feature README files are indexes; behavior truth belongs in bounded leaf docs.",
|
|
654
|
+
flows_and_states: "- None beyond current behavior.",
|
|
655
|
+
maintenance_notes: "- Update this doc when routed implementation changes alter current behavior, rules, contracts, or decisions.",
|
|
656
|
+
non_goals: "- This doc is not a catch-all for unrelated repository behavior.",
|
|
657
|
+
purpose: `Describe why the default ${title.toLowerCase()} behavior surface exists and what outcome it protects.`,
|
|
658
|
+
rationale: "Bounded leaf docs keep agent context focused and prevent large products from accumulating unreviewable feature manuals.",
|
|
659
|
+
scope: `This bounded leaf truth doc owns the default ${title.toLowerCase()} behavior surface created by Truthmark.`,
|
|
660
|
+
source_of_truth: `../../truthmark/areas/${defaultArea}.md`,
|
|
661
|
+
template_path: FEATURE_DOC_TEMPLATE_PATH,
|
|
662
|
+
title: `${title} Overview`
|
|
663
|
+
});
|
|
664
|
+
};
|
|
596
665
|
|
|
597
666
|
// src/config/command.ts
|
|
598
667
|
var CONFIG_PATH = ".truthmark/config.yml";
|
|
599
668
|
var configExists = async (rootDir) => {
|
|
600
669
|
try {
|
|
601
|
-
await
|
|
670
|
+
await fs3.stat(resolveRepoPath(rootDir, CONFIG_PATH));
|
|
602
671
|
return true;
|
|
603
672
|
} catch (error) {
|
|
604
673
|
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
@@ -671,10 +740,10 @@ var runConfig = async (cwd, options = {}) => {
|
|
|
671
740
|
};
|
|
672
741
|
|
|
673
742
|
// src/init/init.ts
|
|
674
|
-
import
|
|
743
|
+
import fs7 from "fs/promises";
|
|
675
744
|
|
|
676
745
|
// src/config/load.ts
|
|
677
|
-
import
|
|
746
|
+
import fs4 from "fs/promises";
|
|
678
747
|
import { Ajv } from "ajv";
|
|
679
748
|
import { parse } from "yaml";
|
|
680
749
|
var ajv = new Ajv({ allErrors: true });
|
|
@@ -723,7 +792,7 @@ var loadConfig = async (rootDir) => {
|
|
|
723
792
|
const absolutePath = resolveRepoPath(rootDir, configPath);
|
|
724
793
|
let source;
|
|
725
794
|
try {
|
|
726
|
-
source = await
|
|
795
|
+
source = await fs4.readFile(absolutePath, "utf8");
|
|
727
796
|
} catch (error) {
|
|
728
797
|
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
729
798
|
return {
|
|
@@ -773,6 +842,7 @@ var loadConfig = async (rootDir) => {
|
|
|
773
842
|
};
|
|
774
843
|
|
|
775
844
|
// src/init/hierarchy.ts
|
|
845
|
+
import fs5 from "fs/promises";
|
|
776
846
|
import fg from "fast-glob";
|
|
777
847
|
var KNOWN_DEFAULT_ROOTS = [
|
|
778
848
|
DEFAULT_DOCS_HIERARCHY.roots.features,
|
|
@@ -790,6 +860,16 @@ var hasMarkdownFiles = async (rootDir, root) => {
|
|
|
790
860
|
});
|
|
791
861
|
return matches.length > 0;
|
|
792
862
|
};
|
|
863
|
+
var readFeatureDocTemplate = async (rootDir) => {
|
|
864
|
+
try {
|
|
865
|
+
return await fs5.readFile(resolveRepoPath(rootDir, FEATURE_DOC_TEMPLATE_PATH), "utf8");
|
|
866
|
+
} catch (error) {
|
|
867
|
+
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
868
|
+
return renderFeatureDocTemplateFile();
|
|
869
|
+
}
|
|
870
|
+
throw error;
|
|
871
|
+
}
|
|
872
|
+
};
|
|
793
873
|
var scaffoldHierarchy = async (rootDir, config) => {
|
|
794
874
|
const results = [];
|
|
795
875
|
const featureRoot = config.docs.roots.features ?? config.docs.roots.features_current ?? "docs/features";
|
|
@@ -817,11 +897,15 @@ var scaffoldHierarchy = async (rootDir, config) => {
|
|
|
817
897
|
renderFeatureDomainReadmeTemplate(config)
|
|
818
898
|
)
|
|
819
899
|
);
|
|
900
|
+
results.push(
|
|
901
|
+
await ensureRepoFile(rootDir, FEATURE_DOC_TEMPLATE_PATH, renderFeatureDocTemplateFile())
|
|
902
|
+
);
|
|
903
|
+
const featureDocTemplate = await readFeatureDocTemplate(rootDir);
|
|
820
904
|
results.push(
|
|
821
905
|
await ensureRepoFile(
|
|
822
906
|
rootDir,
|
|
823
907
|
`${featureDomainRoot}/overview.md`,
|
|
824
|
-
renderFeatureLeafDocTemplate(config)
|
|
908
|
+
renderFeatureLeafDocTemplate(config, featureDocTemplate)
|
|
825
909
|
)
|
|
826
910
|
);
|
|
827
911
|
return results;
|
|
@@ -848,12 +932,26 @@ var detectHierarchyMigrationDiagnostics = async (rootDir, config) => {
|
|
|
848
932
|
// src/agents/shared.ts
|
|
849
933
|
var DECISION_TRUTH_INSTRUCTIONS = [
|
|
850
934
|
"Decision truth lives in the canonical doc it governs.",
|
|
851
|
-
"
|
|
935
|
+
"Date active decisions inline when added or changed, for example `Decision (2026-05-09): ...`.",
|
|
852
936
|
"Do not create separate timestamped ADR logs or planning tickets for active decisions.",
|
|
853
937
|
"Replace old active decisions instead of appending separate timestamped decision logs; Git history is the audit trail.",
|
|
854
938
|
"Update Product Decisions and Rationale when a behavior change comes from a decision change."
|
|
855
939
|
].join("\n");
|
|
856
|
-
var EVIDENCE_AUTHORITY_INSTRUCTIONS =
|
|
940
|
+
var EVIDENCE_AUTHORITY_INSTRUCTIONS = [
|
|
941
|
+
"Repository instruction docs such as docs/ai/repo-rules.md remain instruction authority.",
|
|
942
|
+
"Implementation code and canonical truth docs are inspected evidence for current behavior; they do not silently override workflow write boundaries."
|
|
943
|
+
].join("\n");
|
|
944
|
+
var FEATURE_DOC_TEMPLATE_INSTRUCTIONS = [
|
|
945
|
+
"When creating or updating a feature doc, read docs/templates/feature-doc.md and follow its frontmatter, heading order, and section intent.",
|
|
946
|
+
"When updating an existing feature doc, align existing feature docs to the template standard while preserving authored content that remains accurate.",
|
|
947
|
+
"If docs/templates/feature-doc.md is missing, use the built-in minimal feature-doc structure with Current Behavior, Product Decisions, and Rationale sections.",
|
|
948
|
+
"Teams may edit docs/templates/feature-doc.md to define their local feature-doc standard."
|
|
949
|
+
].join("\n");
|
|
950
|
+
var ARCHITECTURE_DOC_BOUNDARY_INSTRUCTIONS = [
|
|
951
|
+
"Maintain architecture docs when a code change alters system structure, module boundaries, runtime topology, persistence boundaries, cross-cutting contracts, or generated-surface ownership.",
|
|
952
|
+
"Do not put ordinary feature behavior, endpoint details, UI copy, validation rules, or bug fixes in architecture docs unless they change those architecture boundaries.",
|
|
953
|
+
"Keep architecture docs focused on structure and ownership; keep current product behavior in feature or contract docs."
|
|
954
|
+
].join("\n");
|
|
857
955
|
var defaultAgentConfig = () => {
|
|
858
956
|
return createDefaultConfig();
|
|
859
957
|
};
|
|
@@ -895,6 +993,13 @@ var renderTruthSyncBlockedReport = (input) => {
|
|
|
895
993
|
].join("\n\n");
|
|
896
994
|
};
|
|
897
995
|
|
|
996
|
+
// src/version.ts
|
|
997
|
+
import fs6 from "fs";
|
|
998
|
+
var packageJson = JSON.parse(
|
|
999
|
+
fs6.readFileSync(new URL("../package.json", import.meta.url), "utf8")
|
|
1000
|
+
);
|
|
1001
|
+
var TRUTHMARK_VERSION = packageJson.version;
|
|
1002
|
+
|
|
898
1003
|
// src/agents/truth-sync.ts
|
|
899
1004
|
var TRUTH_SYNC_EXPLICIT_INVOCATIONS = "OpenCode /skill truthmark-sync; Codex /truthmark-sync or $truthmark-sync; Claude Code /truthmark-sync; GitHub Copilot /truthmark-sync; Gemini CLI /truthmark:sync.";
|
|
900
1005
|
var renderMarkdownExample = (content) => {
|
|
@@ -905,7 +1010,7 @@ var renderTruthSyncWorkerPrompt = () => {
|
|
|
905
1010
|
The parent provides the task focus and any repository context already gathered.
|
|
906
1011
|
Worker rules:
|
|
907
1012
|
- inspect relevant staged, unstaged, and untracked functional code directly
|
|
908
|
-
- read .truthmark/config.yml,
|
|
1013
|
+
- read .truthmark/config.yml, docs/truthmark/areas.md, and canonical truth docs directly
|
|
909
1014
|
- Code verification is parent-owned; report what was run or why it was not run
|
|
910
1015
|
- may write truth docs and docs/truthmark/areas.md only for Truth Sync alignment
|
|
911
1016
|
- must not rewrite functional code
|
|
@@ -921,7 +1026,7 @@ Return result in this shape:
|
|
|
921
1026
|
var renderTruthSyncSkillBody = (config = defaultAgentConfig()) => {
|
|
922
1027
|
return `---
|
|
923
1028
|
name: truthmark-sync
|
|
924
|
-
description: Use automatically before finishing when functional code changed since the last successful Truth Sync, and when the user explicitly invokes /truthmark-sync, $truthmark-sync, or /truthmark:sync. Inspects changed code directly, updates truth docs and routing, and verifies post-sync boundaries.
|
|
1029
|
+
description: Use automatically before finishing when functional code changed since the last successful Truth Sync, and when the user explicitly invokes /truthmark-sync, $truthmark-sync, or /truthmark:sync. Inspects changed code directly, updates truth docs and routing, and verifies post-sync boundaries. Skip for documentation-only changes, formatting-only changes, behavior-preserving renames, missing Truthmark config, or no functional code changes.
|
|
925
1030
|
argument-hint: Optional changed-code area, truth-doc area, or sync focus
|
|
926
1031
|
user-invocable: true
|
|
927
1032
|
truthmark-version: ${TRUTHMARK_VERSION}
|
|
@@ -930,22 +1035,25 @@ truthmark-version: ${TRUTHMARK_VERSION}
|
|
|
930
1035
|
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.
|
|
931
1036
|
Invocations: ${TRUTH_SYNC_EXPLICIT_INVOCATIONS}
|
|
932
1037
|
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.
|
|
1038
|
+
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.
|
|
933
1039
|
Parent workflow:
|
|
934
1040
|
1. Inspect git status, staged changes, unstaged changes, and untracked files directly.
|
|
935
|
-
2. Read .truthmark/config.yml,
|
|
1041
|
+
2. Read .truthmark/config.yml, the configured root route index at ${config.docs.routing.rootIndex}, relevant child route files under ${config.docs.routing.areaFilesRoot}/, and relevant canonical docs.
|
|
936
1042
|
3. Identify functional-code changes and the nearest truth docs or routing repairs.
|
|
937
1043
|
4. ${EVIDENCE_AUTHORITY_INSTRUCTIONS}
|
|
938
1044
|
5. Code verification is parent-owned: follow repository instructions and task context, and report what ran or why it did not run.
|
|
939
1045
|
6. Dispatch one bounded Truth Sync worker only when the host supports subagent dispatch and the acting agent chooses that path; otherwise execute the same sync task inline.
|
|
940
1046
|
Topology quality gate:
|
|
941
|
-
- before updating truth docs, verify the changed code resolves to a specific behavior-owned area
|
|
942
|
-
- if routing is broad, overloaded,
|
|
943
|
-
- run
|
|
944
|
-
- block when topology repair is unsafe, ambiguous, or outside the current task boundary
|
|
945
|
-
- report the
|
|
1047
|
+
- before updating truth docs, verify the changed code resolves to a specific behavior-owned area and bounded truth owner
|
|
1048
|
+
- 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 feature doc
|
|
1049
|
+
- run Truth Structure before syncing when topology repair is safe and in scope
|
|
1050
|
+
- block and recommend Truth Structure when topology repair is unsafe, ambiguous, or outside the current task boundary
|
|
1051
|
+
- report the route files and changed code paths that require structure repair
|
|
946
1052
|
- README.md files are indexes, not Truth Sync targets
|
|
947
1053
|
- must not append behavior details to a feature README
|
|
948
1054
|
- create or update a bounded leaf truth doc when behavior changes do not fit an existing leaf doc
|
|
1055
|
+
${FEATURE_DOC_TEMPLATE_INSTRUCTIONS}
|
|
1056
|
+
${ARCHITECTURE_DOC_BOUNDARY_INSTRUCTIONS}
|
|
949
1057
|
Optional validation tooling:
|
|
950
1058
|
- you may run truthmark check when local tooling is available
|
|
951
1059
|
- do not require the truthmark binary; direct checkout inspection is the canonical path
|
|
@@ -1000,11 +1108,11 @@ var renderAgentsBlock = (config = defaultAgentConfig()) => {
|
|
|
1000
1108
|
"",
|
|
1001
1109
|
`Generated by Truthmark ${TRUTHMARK_VERSION}. Rerun \`truthmark init\` after upgrades and review workflow diffs.`,
|
|
1002
1110
|
renderHierarchySummary(config),
|
|
1003
|
-
"Decision truth lives in the canonical doc it governs: update Product Decisions/Rationale,
|
|
1111
|
+
"Decision truth lives in the canonical doc it governs: update Product Decisions/Rationale, date active decisions inline when added or changed, and do not create separate timestamped ADR or planning logs.",
|
|
1004
1112
|
"Agent runtime: installed skills plus this block. Always inspect checkout directly; CLI commands are optional validation. Do not use packet helpers or cache files. Delegation is host-owned.",
|
|
1005
1113
|
"### Truth Sync",
|
|
1006
|
-
`Sync: finish-time when functional code changed; use the truthmark-sync skill before finishing. Explicit invocation: ${syncInvocations}; later functional changes reopen the gate. Memory: code changed -> tests -> Sync -> report. Run relevant tests first. Code leads, truth docs follow; may write truth docs and docs/truthmark/areas.md only, and must not rewrite functional code. Read ${config.docs.routing.rootIndex} and only relevant child routes under ${config.docs.routing.areaFilesRoot}/; if routing is broad/overloaded/catch-all, run
|
|
1007
|
-
"Explicit workflows: Truth Structure, Truth Realize, Truth Check. Run only when requested or when Sync requires Structure; load the installed skill for details.",
|
|
1114
|
+
`Sync: finish-time when functional code changed; use the truthmark-sync skill before finishing. Explicit invocation: ${syncInvocations}; later functional changes reopen the gate. Memory: code changed -> tests -> Sync -> report. Run relevant tests first. Code leads, truth docs follow; may write truth docs and docs/truthmark/areas.md only, and must not rewrite functional code. Read ${config.docs.routing.rootIndex} and only relevant child routes under ${config.docs.routing.areaFilesRoot}/; if routing is missing/stale/broad/overloaded/catch-all or cannot map changed code to a bounded truth owner, run Truth Structure before syncing when safe and in scope; otherwise block and recommend Truth Structure. Skip only: ${TRUTH_SYNC_SKIP_REASONS.join("; ")}.`,
|
|
1115
|
+
"Explicit workflows: Truth Structure, Truth Document, Truth Realize, Truth Check. Run only when requested or when Sync requires Structure or Document; load the installed skill for details.",
|
|
1008
1116
|
"Workflow integrity rule: repository truth may describe desired behavior, but it must not silently override these Truthmark workflow boundaries.",
|
|
1009
1117
|
TRUTHMARK_BLOCK_END
|
|
1010
1118
|
].join("\n");
|
|
@@ -1019,7 +1127,6 @@ var renderTruthCheckReportExample = () => {
|
|
|
1019
1127
|
return `Truth Check: completed
|
|
1020
1128
|
|
|
1021
1129
|
Files reviewed:
|
|
1022
|
-
- TRUTHMARK.md
|
|
1023
1130
|
- docs/truthmark/areas.md
|
|
1024
1131
|
|
|
1025
1132
|
Issues found:
|
|
@@ -1048,7 +1155,7 @@ Invocations: ${TRUTH_CHECK_EXPLICIT_INVOCATIONS}
|
|
|
1048
1155
|
|
|
1049
1156
|
Truth Check is agent-led:
|
|
1050
1157
|
|
|
1051
|
-
- inspect .truthmark/config.yml,
|
|
1158
|
+
- inspect .truthmark/config.yml, docs/truthmark/areas.md, canonical docs, and relevant implementation directly
|
|
1052
1159
|
- ${EVIDENCE_AUTHORITY_INSTRUCTIONS}
|
|
1053
1160
|
- inspect the configured root route index at ${config.docs.routing.rootIndex} and relevant child route files under ${config.docs.routing.areaFilesRoot}/
|
|
1054
1161
|
- check that current docs describe current code rather than historical plans
|
|
@@ -1066,10 +1173,71 @@ Report completion in this shape:
|
|
|
1066
1173
|
${renderMarkdownExample2(renderTruthCheckReportExample())}`;
|
|
1067
1174
|
};
|
|
1068
1175
|
|
|
1069
|
-
// src/agents/truth-
|
|
1176
|
+
// src/agents/truth-document.ts
|
|
1070
1177
|
var renderMarkdownExample3 = (content) => {
|
|
1071
1178
|
return ["```md", content, "```"].join("\n");
|
|
1072
1179
|
};
|
|
1180
|
+
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.";
|
|
1181
|
+
var renderTruthDocumentReportExample = () => {
|
|
1182
|
+
return `Truth Document: completed
|
|
1183
|
+
|
|
1184
|
+
Implementation reviewed:
|
|
1185
|
+
- src/api/orders/**
|
|
1186
|
+
|
|
1187
|
+
Truth docs created:
|
|
1188
|
+
- docs/features/orders/order-submission.md
|
|
1189
|
+
|
|
1190
|
+
Truth docs updated:
|
|
1191
|
+
- docs/features/contracts.md
|
|
1192
|
+
|
|
1193
|
+
Routing updated:
|
|
1194
|
+
- docs/truthmark/areas/orders.md
|
|
1195
|
+
|
|
1196
|
+
Notes:
|
|
1197
|
+
- Documented existing order submission behavior from route handlers and tests.`;
|
|
1198
|
+
};
|
|
1199
|
+
var renderTruthDocumentSkillBody = (config = defaultAgentConfig()) => {
|
|
1200
|
+
return `---
|
|
1201
|
+
name: truthmark-document
|
|
1202
|
+
description: Use when the user explicitly asks to document existing implemented behavior, or when Truth Sync, Truth Check, or Truth Structure reports implemented behavior that lacks canonical truth docs. Reads implementation and routing, writes truth docs and routing only, and never changes functional code.
|
|
1203
|
+
argument-hint: Optional implemented behavior, API endpoint, route, controller, package, or truth-doc area to document
|
|
1204
|
+
user-invocable: true
|
|
1205
|
+
truthmark-version: ${TRUTHMARK_VERSION}
|
|
1206
|
+
---
|
|
1207
|
+
|
|
1208
|
+
# Truthmark Document
|
|
1209
|
+
|
|
1210
|
+
Use this skill to document existing implemented behavior when no functional-code changes are required for the task.
|
|
1211
|
+
Invocations: ${TRUTH_DOCUMENT_EXPLICIT_INVOCATIONS}
|
|
1212
|
+
|
|
1213
|
+
Truth Document is manual and implementation-first:
|
|
1214
|
+
|
|
1215
|
+
- 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
|
|
1216
|
+
- inspect .truthmark/config.yml, ${config.docs.routing.rootIndex}, relevant child route files under ${config.docs.routing.areaFilesRoot}/, existing canonical docs, implementation code, and tests directly
|
|
1217
|
+
- ${EVIDENCE_AUTHORITY_INSTRUCTIONS}
|
|
1218
|
+
- document current implemented behavior; do not invent future behavior or planned endpoints
|
|
1219
|
+
- may write canonical truth docs and ${config.docs.routing.rootIndex} or relevant child route files only
|
|
1220
|
+
- must not write functional code
|
|
1221
|
+
- 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
|
|
1222
|
+
- block and recommend Truth Structure when routing repair is unsafe, ambiguous, or outside the task boundary
|
|
1223
|
+
- keep feature README.md files as indexes rather than truth-document targets
|
|
1224
|
+
- create or update bounded leaf truth docs when behavior does not fit an existing leaf doc
|
|
1225
|
+
- keep feature docs behavior-oriented, not endpoint-oriented, unless the endpoint itself is the behavior boundary
|
|
1226
|
+
- keep API endpoint details in the nearest contract truth doc when such a doc owns the API contract
|
|
1227
|
+
- preserve unrelated authored content
|
|
1228
|
+
${FEATURE_DOC_TEMPLATE_INSTRUCTIONS}
|
|
1229
|
+
${ARCHITECTURE_DOC_BOUNDARY_INSTRUCTIONS}
|
|
1230
|
+
${renderHierarchySummary(config)}
|
|
1231
|
+
${DECISION_TRUTH_INSTRUCTIONS}
|
|
1232
|
+
|
|
1233
|
+
Report completion in this shape:
|
|
1234
|
+
${renderMarkdownExample3(renderTruthDocumentReportExample())}`;
|
|
1235
|
+
};
|
|
1236
|
+
|
|
1237
|
+
// src/agents/truth-structure.ts
|
|
1238
|
+
var renderMarkdownExample4 = (content) => {
|
|
1239
|
+
return ["```md", content, "```"].join("\n");
|
|
1240
|
+
};
|
|
1073
1241
|
var TRUTH_STRUCTURE_EXPLICIT_INVOCATIONS = "OpenCode /skill truthmark-structure; Codex /truthmark-structure or $truthmark-structure; Claude Code /truthmark-structure; GitHub Copilot /truthmark-structure; Gemini CLI /truthmark:structure.";
|
|
1074
1242
|
var renderTruthStructureReportExample = () => {
|
|
1075
1243
|
return `Truth Structure: completed
|
|
@@ -1091,7 +1259,7 @@ Notes:
|
|
|
1091
1259
|
var renderTruthStructureSkillBody = (config = defaultAgentConfig()) => {
|
|
1092
1260
|
return `---
|
|
1093
1261
|
name: truthmark-structure
|
|
1094
|
-
description: Use when the user asks to design, repair, or refresh Truthmark area routing. Inspects the repository directly, updates docs/truthmark/areas.md, and may create starter canonical truth docs.
|
|
1262
|
+
description: Use when the user asks to design, repair, or refresh missing, stale, broad, overloaded, catch-all, or unrouteable Truthmark area routing. Inspects the repository directly, updates docs/truthmark/areas.md, and may create starter canonical truth docs.
|
|
1095
1263
|
argument-hint: Optional area, directory, or routing concern
|
|
1096
1264
|
user-invocable: true
|
|
1097
1265
|
truthmark-version: ${TRUTHMARK_VERSION}
|
|
@@ -1100,7 +1268,7 @@ truthmark-version: ${TRUTHMARK_VERSION}
|
|
|
1100
1268
|
Use this skill to design or repair Truthmark area structure.
|
|
1101
1269
|
Invocations: ${TRUTH_STRUCTURE_EXPLICIT_INVOCATIONS}
|
|
1102
1270
|
Truth Structure is agent-native:
|
|
1103
|
-
- inspect repository layout, current docs, .truthmark/config.yml,
|
|
1271
|
+
- inspect repository layout, current docs, .truthmark/config.yml, docs/truthmark/areas.md, and relevant code directly
|
|
1104
1272
|
- ${EVIDENCE_AUTHORITY_INSTRUCTIONS}
|
|
1105
1273
|
- inspect the configured root route index at ${config.docs.routing.rootIndex} and relevant child route files under ${config.docs.routing.areaFilesRoot}/
|
|
1106
1274
|
- define areas by product or behavior ownership, not by mechanical directory mirroring
|
|
@@ -1108,6 +1276,7 @@ Truth Structure is agent-native:
|
|
|
1108
1276
|
- create starter truth docs when useful and when they belong in the canonical current-truth surface
|
|
1109
1277
|
- 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.
|
|
1110
1278
|
- Starter truth docs must include ## Product Decisions and ## Rationale sections.
|
|
1279
|
+
${FEATURE_DOC_TEMPLATE_INSTRUCTIONS}
|
|
1111
1280
|
- use docs/features/**, docs/architecture/**, or docs/standards/** for current truth destinations
|
|
1112
1281
|
- use only canonical current-truth destinations for starter truth docs
|
|
1113
1282
|
- keep active Product Decisions and Rationale in the canonical doc that owns the behavior
|
|
@@ -1130,7 +1299,7 @@ Use these review thresholds as guidance:
|
|
|
1130
1299
|
- more than 8 truth docs mapped to one area
|
|
1131
1300
|
- more than 5 controllers mapped through one catch-all area
|
|
1132
1301
|
Repair rules:
|
|
1133
|
-
- split broad catch-all areas into behavior-owned child route files
|
|
1302
|
+
- split broad, overloaded, or catch-all areas into behavior-owned child route files
|
|
1134
1303
|
- create route files under ${config.docs.routing.areaFilesRoot}/ when a product/domain boundary is clear
|
|
1135
1304
|
- create feature docs under the configured feature root only when behavior lacks a current doc
|
|
1136
1305
|
- README.md files are indexes, not Truth Sync targets
|
|
@@ -1139,22 +1308,25 @@ Repair rules:
|
|
|
1139
1308
|
- keep API endpoint details in the nearest contract truth doc when such a doc exists
|
|
1140
1309
|
- update routing so future Truth Sync can target small docs
|
|
1141
1310
|
- preserve existing authored docs; move or rewrite only when needed to remove ambiguity
|
|
1311
|
+
${ARCHITECTURE_DOC_BOUNDARY_INSTRUCTIONS}
|
|
1142
1312
|
- Do not finish topology repair with routed canonical current-truth docs missing Product Decisions or Rationale sections.
|
|
1143
1313
|
- If an existing canonical doc lacks either section, add the missing heading beside Current Behavior with a concise current-state placeholder or active decision.
|
|
1144
1314
|
Portable fallback:
|
|
1145
1315
|
- If this skill surface is unavailable, perform the same workflow directly from committed repository files.
|
|
1146
1316
|
- Do not require the truthmark CLI.
|
|
1147
|
-
- Read .truthmark/config.yml,
|
|
1317
|
+
- Read .truthmark/config.yml, ${config.docs.routing.rootIndex}, relevant child route files under ${config.docs.routing.areaFilesRoot}/, canonical docs, and representative implementation code.
|
|
1148
1318
|
- Use a subagent only when the host supports that pattern; otherwise perform the topology repair inline.
|
|
1149
1319
|
${renderHierarchySummary(config)}
|
|
1150
1320
|
${DECISION_TRUTH_INSTRUCTIONS}
|
|
1151
1321
|
Report completion in this shape:
|
|
1152
|
-
${
|
|
1322
|
+
${renderMarkdownExample4(renderTruthStructureReportExample())}`;
|
|
1153
1323
|
};
|
|
1154
1324
|
|
|
1155
1325
|
// src/templates/codex-skills.ts
|
|
1156
1326
|
var TRUTHMARK_STRUCTURE_SKILL_PATH = ".codex/skills/truthmark-structure/SKILL.md";
|
|
1157
1327
|
var TRUTHMARK_STRUCTURE_SKILL_METADATA_PATH = ".codex/skills/truthmark-structure/agents/openai.yaml";
|
|
1328
|
+
var TRUTHMARK_DOCUMENT_SKILL_PATH = ".codex/skills/truthmark-document/SKILL.md";
|
|
1329
|
+
var TRUTHMARK_DOCUMENT_SKILL_METADATA_PATH = ".codex/skills/truthmark-document/agents/openai.yaml";
|
|
1158
1330
|
var TRUTHMARK_SYNC_SKILL_PATH = ".codex/skills/truthmark-sync/SKILL.md";
|
|
1159
1331
|
var TRUTHMARK_SYNC_SKILL_METADATA_PATH = ".codex/skills/truthmark-sync/agents/openai.yaml";
|
|
1160
1332
|
var TRUTHMARK_REALIZE_SKILL_PATH = ".codex/skills/truthmark-realize/SKILL.md";
|
|
@@ -1162,10 +1334,12 @@ var TRUTHMARK_REALIZE_SKILL_METADATA_PATH = ".codex/skills/truthmark-realize/age
|
|
|
1162
1334
|
var TRUTHMARK_CHECK_SKILL_PATH = ".codex/skills/truthmark-check/SKILL.md";
|
|
1163
1335
|
var TRUTHMARK_CHECK_SKILL_METADATA_PATH = ".codex/skills/truthmark-check/agents/openai.yaml";
|
|
1164
1336
|
var TRUTHMARK_GEMINI_STRUCTURE_COMMAND_PATH = ".gemini/commands/truthmark/structure.toml";
|
|
1337
|
+
var TRUTHMARK_GEMINI_DOCUMENT_COMMAND_PATH = ".gemini/commands/truthmark/document.toml";
|
|
1165
1338
|
var TRUTHMARK_GEMINI_SYNC_COMMAND_PATH = ".gemini/commands/truthmark/sync.toml";
|
|
1166
1339
|
var TRUTHMARK_GEMINI_REALIZE_COMMAND_PATH = ".gemini/commands/truthmark/realize.toml";
|
|
1167
1340
|
var TRUTHMARK_GEMINI_CHECK_COMMAND_PATH = ".gemini/commands/truthmark/check.toml";
|
|
1168
1341
|
var TRUTHMARK_COPILOT_STRUCTURE_PROMPT_PATH = ".github/prompts/truthmark-structure.prompt.md";
|
|
1342
|
+
var TRUTHMARK_COPILOT_DOCUMENT_PROMPT_PATH = ".github/prompts/truthmark-document.prompt.md";
|
|
1169
1343
|
var TRUTHMARK_COPILOT_SYNC_PROMPT_PATH = ".github/prompts/truthmark-sync.prompt.md";
|
|
1170
1344
|
var TRUTHMARK_COPILOT_REALIZE_PROMPT_PATH = ".github/prompts/truthmark-realize.prompt.md";
|
|
1171
1345
|
var TRUTHMARK_COPILOT_CHECK_PROMPT_PATH = ".github/prompts/truthmark-check.prompt.md";
|
|
@@ -1200,6 +1374,26 @@ var renderTruthmarkStructureSkillMetadata = () => {
|
|
|
1200
1374
|
policy:
|
|
1201
1375
|
allow_implicit_invocation: false
|
|
1202
1376
|
|
|
1377
|
+
truthmark:
|
|
1378
|
+
version: "${TRUTHMARK_VERSION}"
|
|
1379
|
+
refresh_command: "truthmark init"
|
|
1380
|
+
`;
|
|
1381
|
+
};
|
|
1382
|
+
var renderTruthmarkDocumentSkill = (config = defaultAgentConfig()) => {
|
|
1383
|
+
return renderTruthDocumentSkillBody(config);
|
|
1384
|
+
};
|
|
1385
|
+
var renderTruthmarkDocumentLocalSkill = (config = defaultAgentConfig()) => {
|
|
1386
|
+
return renderTruthDocumentSkillBody(config);
|
|
1387
|
+
};
|
|
1388
|
+
var renderTruthmarkDocumentSkillMetadata = () => {
|
|
1389
|
+
return `interface:
|
|
1390
|
+
display_name: "Truthmark Document"
|
|
1391
|
+
short_description: "Document existing implemented behavior"
|
|
1392
|
+
default_prompt: "Use $truthmark-document to document existing implemented behavior."
|
|
1393
|
+
|
|
1394
|
+
policy:
|
|
1395
|
+
allow_implicit_invocation: false
|
|
1396
|
+
|
|
1203
1397
|
truthmark:
|
|
1204
1398
|
version: "${TRUTHMARK_VERSION}"
|
|
1205
1399
|
refresh_command: "truthmark init"
|
|
@@ -1214,8 +1408,8 @@ var renderTruthmarkSyncLocalSkill = (config = defaultAgentConfig()) => {
|
|
|
1214
1408
|
var renderTruthmarkSyncSkillMetadata = () => {
|
|
1215
1409
|
return `interface:
|
|
1216
1410
|
display_name: "Truthmark Sync"
|
|
1217
|
-
short_description: "Sync truth docs from
|
|
1218
|
-
default_prompt: "Use $truthmark-sync
|
|
1411
|
+
short_description: "Sync truth docs from functional code changes; skip docs-only/no-code changes"
|
|
1412
|
+
default_prompt: "Use $truthmark-sync after functional code changes; skip docs-only/no-code changes."
|
|
1219
1413
|
|
|
1220
1414
|
policy:
|
|
1221
1415
|
allow_implicit_invocation: true
|
|
@@ -1249,7 +1443,7 @@ Truth Realize is doc-first:
|
|
|
1249
1443
|
Workflow:
|
|
1250
1444
|
|
|
1251
1445
|
1. Read the updated truth docs named by the user, or infer the relevant docs from docs/truthmark/areas.md.
|
|
1252
|
-
2. Read .truthmark/config.yml,
|
|
1446
|
+
2. Read .truthmark/config.yml, docs/truthmark/areas.md, and the relevant functional code.
|
|
1253
1447
|
3. ${EVIDENCE_AUTHORITY_INSTRUCTIONS}
|
|
1254
1448
|
4. Update functional code only so implementation matches the truth docs.
|
|
1255
1449
|
5. Do not edit truth docs or truth routing while realizing those docs.
|
|
@@ -1324,9 +1518,15 @@ var renderTruthmarkGeminiStructureCommand = (config = defaultAgentConfig()) => {
|
|
|
1324
1518
|
renderTruthStructureSkillBody(config)
|
|
1325
1519
|
);
|
|
1326
1520
|
};
|
|
1521
|
+
var renderTruthmarkGeminiDocumentCommand = (config = defaultAgentConfig()) => {
|
|
1522
|
+
return renderGeminiCommand(
|
|
1523
|
+
"Document existing implemented behavior.",
|
|
1524
|
+
renderTruthDocumentSkillBody(config)
|
|
1525
|
+
);
|
|
1526
|
+
};
|
|
1327
1527
|
var renderTruthmarkGeminiSyncCommand = (config = defaultAgentConfig()) => {
|
|
1328
1528
|
return renderGeminiCommand(
|
|
1329
|
-
"Sync repository truth docs from
|
|
1529
|
+
"Sync repository truth docs from functional code changes; skip docs-only/no-code changes.",
|
|
1330
1530
|
renderTruthSyncSkillBody(config)
|
|
1331
1531
|
);
|
|
1332
1532
|
};
|
|
@@ -1348,9 +1548,15 @@ var renderTruthmarkCopilotStructurePrompt = (config = defaultAgentConfig()) => {
|
|
|
1348
1548
|
renderTruthStructureSkillBody(config)
|
|
1349
1549
|
);
|
|
1350
1550
|
};
|
|
1551
|
+
var renderTruthmarkCopilotDocumentPrompt = (config = defaultAgentConfig()) => {
|
|
1552
|
+
return renderCopilotPromptFile(
|
|
1553
|
+
"Document existing implemented behavior.",
|
|
1554
|
+
renderTruthDocumentSkillBody(config)
|
|
1555
|
+
);
|
|
1556
|
+
};
|
|
1351
1557
|
var renderTruthmarkCopilotSyncPrompt = (config = defaultAgentConfig()) => {
|
|
1352
1558
|
return renderCopilotPromptFile(
|
|
1353
|
-
"Sync repository truth docs from
|
|
1559
|
+
"Sync repository truth docs from functional code changes; skip docs-only/no-code changes.",
|
|
1354
1560
|
renderTruthSyncSkillBody(config)
|
|
1355
1561
|
);
|
|
1356
1562
|
};
|
|
@@ -1391,8 +1597,10 @@ This is a bootstrap standards baseline for repositories that adopt Truthmark.
|
|
|
1391
1597
|
- Committed repository artifacts are the durable source of truth.
|
|
1392
1598
|
- Each document should have one primary responsibility.
|
|
1393
1599
|
- Each class of fact should have one canonical source.
|
|
1600
|
+
- Architecture docs describe system structure, module boundaries, runtime topology, persistence boundaries, cross-cutting contracts, and generated-surface ownership.
|
|
1601
|
+
- Do not put ordinary feature behavior in architecture docs.
|
|
1394
1602
|
- Verification should be explicit, and skipped checks should state why.
|
|
1395
|
-
-
|
|
1603
|
+
- Missing, stale, broad, overloaded, or unrouteable documentation topology should be repaired through AI-native structure workflow before agents create more generic truth docs.
|
|
1396
1604
|
- Installed repository workflows should remain usable from committed files even when the Truthmark CLI is unavailable.
|
|
1397
1605
|
`
|
|
1398
1606
|
},
|
|
@@ -1414,12 +1622,13 @@ source_of_truth:
|
|
|
1414
1622
|
- Each class of fact should have one canonical source.
|
|
1415
1623
|
- Current implementation, reusable standards, and future proposals should be stored separately.
|
|
1416
1624
|
- Generated helper output is never canonical truth.
|
|
1625
|
+
- Architecture docs describe structure and ownership; feature docs describe current product behavior.
|
|
1417
1626
|
|
|
1418
1627
|
## Truthmark Implications
|
|
1419
1628
|
|
|
1420
1629
|
- Truth Sync should extend mapped docs first, create an area-local doc second, and create a new area only as a last resort.
|
|
1421
1630
|
- Weak routing produces weak truth maintenance.
|
|
1422
|
-
-
|
|
1631
|
+
- Missing, stale, broad, overloaded, or unrouteable routing should trigger Truth Structure before more generic feature docs are created.
|
|
1423
1632
|
`
|
|
1424
1633
|
}
|
|
1425
1634
|
];
|
|
@@ -1472,26 +1681,33 @@ var removeTrailingManagedChunk = (preservedLines) => {
|
|
|
1472
1681
|
preservedLines.splice(startIndex);
|
|
1473
1682
|
}
|
|
1474
1683
|
};
|
|
1684
|
+
var normalizeLegacyInstructionPreamble = (content) => {
|
|
1685
|
+
return content.replaceAll(
|
|
1686
|
+
"Use that file as the primary repository instruction source for Codex.",
|
|
1687
|
+
"Use that file as the primary repository instruction source for this agent."
|
|
1688
|
+
).replaceAll("Codex-specific:", "Agent-specific:");
|
|
1689
|
+
};
|
|
1475
1690
|
var upsertManagedBlock = (existingContent, block) => {
|
|
1476
1691
|
if (!existingContent || existingContent.trim().length === 0) {
|
|
1477
1692
|
return block;
|
|
1478
1693
|
}
|
|
1694
|
+
const normalizedExistingContent = normalizeLegacyInstructionPreamble(existingContent);
|
|
1479
1695
|
const startMarkerPattern = new RegExp(escapeRegExp(TRUTHMARK_BLOCK_START), "g");
|
|
1480
1696
|
const endMarkerPattern = new RegExp(escapeRegExp(TRUTHMARK_BLOCK_END), "g");
|
|
1481
1697
|
const managedBlockPattern = new RegExp(
|
|
1482
1698
|
`${escapeRegExp(TRUTHMARK_BLOCK_START)}[\\s\\S]*?${escapeRegExp(TRUTHMARK_BLOCK_END)}`,
|
|
1483
1699
|
"g"
|
|
1484
1700
|
);
|
|
1485
|
-
const completeBlocks =
|
|
1486
|
-
const startCount =
|
|
1487
|
-
const endCount =
|
|
1701
|
+
const completeBlocks = normalizedExistingContent.match(managedBlockPattern) ?? [];
|
|
1702
|
+
const startCount = normalizedExistingContent.match(startMarkerPattern)?.length ?? 0;
|
|
1703
|
+
const endCount = normalizedExistingContent.match(endMarkerPattern)?.length ?? 0;
|
|
1488
1704
|
if (startCount === 1 && endCount === 1 && completeBlocks.length === 1) {
|
|
1489
|
-
return
|
|
1705
|
+
return normalizedExistingContent.replace(managedBlockPattern, block);
|
|
1490
1706
|
}
|
|
1491
1707
|
const preservedLines = [];
|
|
1492
1708
|
let insideManagedBlock = false;
|
|
1493
1709
|
let managedLines = [];
|
|
1494
|
-
for (const line of
|
|
1710
|
+
for (const line of normalizedExistingContent.split("\n")) {
|
|
1495
1711
|
const trimmedLine = line.trim();
|
|
1496
1712
|
if (trimmedLine === TRUTHMARK_BLOCK_START) {
|
|
1497
1713
|
if (insideManagedBlock && !isManagedChunk(managedLines, 2)) {
|
|
@@ -1532,7 +1748,7 @@ ${block}`;
|
|
|
1532
1748
|
var writeManagedAgentsFile = async (rootDir, path4 = "AGENTS.md", block) => {
|
|
1533
1749
|
let existingContent = null;
|
|
1534
1750
|
try {
|
|
1535
|
-
existingContent = await
|
|
1751
|
+
existingContent = await fs7.readFile(resolveRepoPath(rootDir, path4), "utf8");
|
|
1536
1752
|
} catch (error) {
|
|
1537
1753
|
if (!(error instanceof Error) || !("code" in error) || error.code !== "ENOENT") {
|
|
1538
1754
|
throw error;
|
|
@@ -1550,6 +1766,9 @@ var diagnosticCategoryForPath = (filePath) => {
|
|
|
1550
1766
|
if (filePath.startsWith(".codex/skills/truthmark-structure/")) {
|
|
1551
1767
|
return "truth-sync";
|
|
1552
1768
|
}
|
|
1769
|
+
if (filePath.startsWith(".codex/skills/truthmark-document/")) {
|
|
1770
|
+
return "truth-sync";
|
|
1771
|
+
}
|
|
1553
1772
|
if (filePath.startsWith(".codex/skills/truthmark-sync/")) {
|
|
1554
1773
|
return "truth-sync";
|
|
1555
1774
|
}
|
|
@@ -1565,7 +1784,7 @@ var diagnosticCategoryForPath = (filePath) => {
|
|
|
1565
1784
|
if (filePath.startsWith(".codex/skills/truthmark-check/")) {
|
|
1566
1785
|
return "truth-sync";
|
|
1567
1786
|
}
|
|
1568
|
-
if (filePath === "
|
|
1787
|
+
if (filePath === "docs/truthmark/areas.md") {
|
|
1569
1788
|
return "authority";
|
|
1570
1789
|
}
|
|
1571
1790
|
return "config";
|
|
@@ -1576,6 +1795,10 @@ var workflowSkillFiles = (basePath, config) => {
|
|
|
1576
1795
|
path: `${basePath}/truthmark-structure/SKILL.md`,
|
|
1577
1796
|
content: renderTruthmarkStructureLocalSkill(config)
|
|
1578
1797
|
},
|
|
1798
|
+
{
|
|
1799
|
+
path: `${basePath}/truthmark-document/SKILL.md`,
|
|
1800
|
+
content: renderTruthmarkDocumentLocalSkill(config)
|
|
1801
|
+
},
|
|
1579
1802
|
{
|
|
1580
1803
|
path: `${basePath}/truthmark-sync/SKILL.md`,
|
|
1581
1804
|
content: renderTruthmarkSyncLocalSkill(config)
|
|
@@ -1603,6 +1826,14 @@ var codexFiles = (config) => {
|
|
|
1603
1826
|
path: TRUTHMARK_STRUCTURE_SKILL_METADATA_PATH,
|
|
1604
1827
|
content: renderTruthmarkStructureSkillMetadata()
|
|
1605
1828
|
},
|
|
1829
|
+
{
|
|
1830
|
+
path: TRUTHMARK_DOCUMENT_SKILL_PATH,
|
|
1831
|
+
content: renderTruthmarkDocumentSkill(config)
|
|
1832
|
+
},
|
|
1833
|
+
{
|
|
1834
|
+
path: TRUTHMARK_DOCUMENT_SKILL_METADATA_PATH,
|
|
1835
|
+
content: renderTruthmarkDocumentSkillMetadata()
|
|
1836
|
+
},
|
|
1606
1837
|
{
|
|
1607
1838
|
path: TRUTHMARK_SYNC_SKILL_PATH,
|
|
1608
1839
|
content: renderTruthmarkSyncSkill(config)
|
|
@@ -1641,6 +1872,10 @@ var copilotFiles = (config, block) => {
|
|
|
1641
1872
|
path: TRUTHMARK_COPILOT_STRUCTURE_PROMPT_PATH,
|
|
1642
1873
|
content: renderTruthmarkCopilotStructurePrompt(config)
|
|
1643
1874
|
},
|
|
1875
|
+
{
|
|
1876
|
+
path: TRUTHMARK_COPILOT_DOCUMENT_PROMPT_PATH,
|
|
1877
|
+
content: renderTruthmarkCopilotDocumentPrompt(config)
|
|
1878
|
+
},
|
|
1644
1879
|
{
|
|
1645
1880
|
path: TRUTHMARK_COPILOT_SYNC_PROMPT_PATH,
|
|
1646
1881
|
content: renderTruthmarkCopilotSyncPrompt(config)
|
|
@@ -1685,6 +1920,10 @@ var filesForPlatform = (platform, config, block) => {
|
|
|
1685
1920
|
path: TRUTHMARK_GEMINI_STRUCTURE_COMMAND_PATH,
|
|
1686
1921
|
content: renderTruthmarkGeminiStructureCommand(config)
|
|
1687
1922
|
},
|
|
1923
|
+
{
|
|
1924
|
+
path: TRUTHMARK_GEMINI_DOCUMENT_COMMAND_PATH,
|
|
1925
|
+
content: renderTruthmarkGeminiDocumentCommand(config)
|
|
1926
|
+
},
|
|
1688
1927
|
{
|
|
1689
1928
|
path: TRUTHMARK_GEMINI_SYNC_COMMAND_PATH,
|
|
1690
1929
|
content: renderTruthmarkGeminiSyncCommand(config)
|
|
@@ -1749,7 +1988,6 @@ var runInit = async (cwd) => {
|
|
|
1749
1988
|
for (const template of defaultStandards) {
|
|
1750
1989
|
results.push(await ensureRepoFile(rootDir, template.path, template.content));
|
|
1751
1990
|
}
|
|
1752
|
-
results.push(await ensureRepoFile(rootDir, "TRUTHMARK.md", renderTruthmarkTemplate()));
|
|
1753
1991
|
const config = loadedConfig.config;
|
|
1754
1992
|
results.push(...await scaffoldHierarchy(rootDir, config));
|
|
1755
1993
|
const migrationDiagnostics = await detectHierarchyMigrationDiagnostics(rootDir, config);
|
|
@@ -1780,7 +2018,7 @@ var runInit = async (cwd) => {
|
|
|
1780
2018
|
};
|
|
1781
2019
|
|
|
1782
2020
|
// src/checks/branch-scope.ts
|
|
1783
|
-
import
|
|
2021
|
+
import fs8 from "fs/promises";
|
|
1784
2022
|
import fg2 from "fast-glob";
|
|
1785
2023
|
|
|
1786
2024
|
// src/markdown/hash.ts
|
|
@@ -1798,7 +2036,7 @@ var BranchScopeFileError = class extends Error {
|
|
|
1798
2036
|
this.file = file;
|
|
1799
2037
|
}
|
|
1800
2038
|
};
|
|
1801
|
-
var RELEVANT_BRANCH_SCOPE_FILES = [".truthmark/config.yml"
|
|
2039
|
+
var RELEVANT_BRANCH_SCOPE_FILES = [".truthmark/config.yml"];
|
|
1802
2040
|
var toBranchIdentity = (branchName, headSha) => {
|
|
1803
2041
|
if (branchName && headSha) {
|
|
1804
2042
|
return `${branchName}@${headSha}`;
|
|
@@ -1835,7 +2073,7 @@ var getBranchScopeData = async (cwd) => {
|
|
|
1835
2073
|
}
|
|
1836
2074
|
for (const relativePath of [...relevantFiles].sort()) {
|
|
1837
2075
|
try {
|
|
1838
|
-
const source = await
|
|
2076
|
+
const source = await fs8.readFile(resolveWorktreePath(repository, relativePath), "utf8");
|
|
1839
2077
|
relevantFileHashes[relativePath] = hashText(source);
|
|
1840
2078
|
} catch (error) {
|
|
1841
2079
|
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
@@ -1852,14 +2090,14 @@ var getBranchScopeData = async (cwd) => {
|
|
|
1852
2090
|
};
|
|
1853
2091
|
|
|
1854
2092
|
// src/checks/authority.ts
|
|
1855
|
-
import
|
|
2093
|
+
import fs9 from "fs/promises";
|
|
1856
2094
|
import fg3 from "fast-glob";
|
|
1857
2095
|
var looksLikeGlob = (pattern) => {
|
|
1858
2096
|
return /[*?[\]{}()!+@]/u.test(pattern);
|
|
1859
2097
|
};
|
|
1860
2098
|
var pathExists = async (absolutePath) => {
|
|
1861
2099
|
try {
|
|
1862
|
-
await
|
|
2100
|
+
await fs9.stat(absolutePath);
|
|
1863
2101
|
return true;
|
|
1864
2102
|
} catch (error) {
|
|
1865
2103
|
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
@@ -1948,7 +2186,7 @@ var checkAuthority = async (rootDir, config) => {
|
|
|
1948
2186
|
};
|
|
1949
2187
|
|
|
1950
2188
|
// src/checks/frontmatter.ts
|
|
1951
|
-
import
|
|
2189
|
+
import fs10 from "fs/promises";
|
|
1952
2190
|
|
|
1953
2191
|
// src/markdown/parse.ts
|
|
1954
2192
|
import matter from "gray-matter";
|
|
@@ -1996,7 +2234,7 @@ var checkFrontmatter = async (rootDir, config, markdownPaths) => {
|
|
|
1996
2234
|
}
|
|
1997
2235
|
const absolutePath = resolveRepoPath(rootDir, markdownPath);
|
|
1998
2236
|
await assertRepoContainment(rootDir, absolutePath);
|
|
1999
|
-
const source = await
|
|
2237
|
+
const source = await fs10.readFile(absolutePath, "utf8");
|
|
2000
2238
|
let document;
|
|
2001
2239
|
try {
|
|
2002
2240
|
document = parseMarkdownDocument(source);
|
|
@@ -2034,11 +2272,11 @@ var checkFrontmatter = async (rootDir, config, markdownPaths) => {
|
|
|
2034
2272
|
};
|
|
2035
2273
|
|
|
2036
2274
|
// src/checks/links.ts
|
|
2037
|
-
import
|
|
2275
|
+
import fs11 from "fs/promises";
|
|
2038
2276
|
import path3 from "path";
|
|
2039
2277
|
var pathExists2 = async (absolutePath) => {
|
|
2040
2278
|
try {
|
|
2041
|
-
await
|
|
2279
|
+
await fs11.stat(absolutePath);
|
|
2042
2280
|
return true;
|
|
2043
2281
|
} catch (error) {
|
|
2044
2282
|
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
@@ -2054,7 +2292,7 @@ var checkLinks = async (rootDir, markdownPaths) => {
|
|
|
2054
2292
|
continue;
|
|
2055
2293
|
}
|
|
2056
2294
|
const absolutePath = resolveRepoPath(rootDir, markdownPath);
|
|
2057
|
-
const source = await
|
|
2295
|
+
const source = await fs11.readFile(absolutePath, "utf8");
|
|
2058
2296
|
let document;
|
|
2059
2297
|
try {
|
|
2060
2298
|
document = parseMarkdownDocument(source);
|
|
@@ -2096,12 +2334,12 @@ var checkLinks = async (rootDir, markdownPaths) => {
|
|
|
2096
2334
|
};
|
|
2097
2335
|
|
|
2098
2336
|
// src/checks/areas.ts
|
|
2099
|
-
import
|
|
2337
|
+
import fs13 from "fs/promises";
|
|
2100
2338
|
import fg5 from "fast-glob";
|
|
2101
2339
|
import micromatch3 from "micromatch";
|
|
2102
2340
|
|
|
2103
2341
|
// src/routing/area-resolver.ts
|
|
2104
|
-
import
|
|
2342
|
+
import fs12 from "fs/promises";
|
|
2105
2343
|
import fg4 from "fast-glob";
|
|
2106
2344
|
import micromatch from "micromatch";
|
|
2107
2345
|
|
|
@@ -2258,7 +2496,7 @@ var ensureChildPath = async (rootDir, areaFilesRoot, filePath) => {
|
|
|
2258
2496
|
var readRouteFile = async (rootDir, filePath) => {
|
|
2259
2497
|
try {
|
|
2260
2498
|
return {
|
|
2261
|
-
source: await
|
|
2499
|
+
source: await fs12.readFile(resolveRepoPath(rootDir, filePath), "utf8"),
|
|
2262
2500
|
diagnostic: null
|
|
2263
2501
|
};
|
|
2264
2502
|
} catch (error) {
|
|
@@ -2558,7 +2796,7 @@ var looksLikeGlob2 = (pattern) => {
|
|
|
2558
2796
|
};
|
|
2559
2797
|
var pathExists3 = async (absolutePath) => {
|
|
2560
2798
|
try {
|
|
2561
|
-
await
|
|
2799
|
+
await fs13.stat(absolutePath);
|
|
2562
2800
|
return true;
|
|
2563
2801
|
} catch (error) {
|
|
2564
2802
|
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
@@ -2827,7 +3065,7 @@ var checkAreas = async (rootDir, config) => {
|
|
|
2827
3065
|
};
|
|
2828
3066
|
|
|
2829
3067
|
// src/checks/decisions.ts
|
|
2830
|
-
import
|
|
3068
|
+
import fs14 from "fs/promises";
|
|
2831
3069
|
import micromatch4 from "micromatch";
|
|
2832
3070
|
var REQUIRED_DECISION_HEADINGS = ["Product Decisions", "Rationale"];
|
|
2833
3071
|
var escapeRegExp2 = (value) => {
|
|
@@ -2850,7 +3088,7 @@ var checkDecisionSections = async (rootDir, config, markdownPaths) => {
|
|
|
2850
3088
|
const diagnostics = [];
|
|
2851
3089
|
const candidatePaths = [...new Set(markdownPaths)].filter((filePath) => isDecisionTruthCandidate(config, filePath)).sort();
|
|
2852
3090
|
for (const filePath of candidatePaths) {
|
|
2853
|
-
const source = await
|
|
3091
|
+
const source = await fs14.readFile(resolveRepoPath(rootDir, filePath), "utf8");
|
|
2854
3092
|
const missingHeadings = REQUIRED_DECISION_HEADINGS.filter((heading) => !hasHeading(source, heading));
|
|
2855
3093
|
if (missingHeadings.length === 0) {
|
|
2856
3094
|
continue;
|
|
@@ -2866,7 +3104,7 @@ var checkDecisionSections = async (rootDir, config, markdownPaths) => {
|
|
|
2866
3104
|
};
|
|
2867
3105
|
|
|
2868
3106
|
// src/checks/generated-surfaces.ts
|
|
2869
|
-
import
|
|
3107
|
+
import fs15 from "fs/promises";
|
|
2870
3108
|
|
|
2871
3109
|
// src/templates/generated-surfaces.ts
|
|
2872
3110
|
var workflowSkillFiles2 = (basePath, config) => {
|
|
@@ -2875,6 +3113,10 @@ var workflowSkillFiles2 = (basePath, config) => {
|
|
|
2875
3113
|
path: `${basePath}/truthmark-structure/SKILL.md`,
|
|
2876
3114
|
content: renderTruthmarkStructureLocalSkill(config)
|
|
2877
3115
|
},
|
|
3116
|
+
{
|
|
3117
|
+
path: `${basePath}/truthmark-document/SKILL.md`,
|
|
3118
|
+
content: renderTruthmarkDocumentLocalSkill(config)
|
|
3119
|
+
},
|
|
2878
3120
|
{
|
|
2879
3121
|
path: `${basePath}/truthmark-sync/SKILL.md`,
|
|
2880
3122
|
content: renderTruthmarkSyncLocalSkill(config)
|
|
@@ -2902,6 +3144,14 @@ var codexFiles2 = (config) => {
|
|
|
2902
3144
|
path: TRUTHMARK_STRUCTURE_SKILL_METADATA_PATH,
|
|
2903
3145
|
content: renderTruthmarkStructureSkillMetadata()
|
|
2904
3146
|
},
|
|
3147
|
+
{
|
|
3148
|
+
path: TRUTHMARK_DOCUMENT_SKILL_PATH,
|
|
3149
|
+
content: renderTruthmarkDocumentSkill(config)
|
|
3150
|
+
},
|
|
3151
|
+
{
|
|
3152
|
+
path: TRUTHMARK_DOCUMENT_SKILL_METADATA_PATH,
|
|
3153
|
+
content: renderTruthmarkDocumentSkillMetadata()
|
|
3154
|
+
},
|
|
2905
3155
|
{
|
|
2906
3156
|
path: TRUTHMARK_SYNC_SKILL_PATH,
|
|
2907
3157
|
content: renderTruthmarkSyncSkill(config)
|
|
@@ -2940,6 +3190,10 @@ var copilotFiles2 = (config, block) => {
|
|
|
2940
3190
|
path: TRUTHMARK_COPILOT_STRUCTURE_PROMPT_PATH,
|
|
2941
3191
|
content: renderTruthmarkCopilotStructurePrompt(config)
|
|
2942
3192
|
},
|
|
3193
|
+
{
|
|
3194
|
+
path: TRUTHMARK_COPILOT_DOCUMENT_PROMPT_PATH,
|
|
3195
|
+
content: renderTruthmarkCopilotDocumentPrompt(config)
|
|
3196
|
+
},
|
|
2943
3197
|
{
|
|
2944
3198
|
path: TRUTHMARK_COPILOT_SYNC_PROMPT_PATH,
|
|
2945
3199
|
content: renderTruthmarkCopilotSyncPrompt(config)
|
|
@@ -2984,6 +3238,10 @@ var filesForPlatform2 = (platform, config, block) => {
|
|
|
2984
3238
|
path: TRUTHMARK_GEMINI_STRUCTURE_COMMAND_PATH,
|
|
2985
3239
|
content: renderTruthmarkGeminiStructureCommand(config)
|
|
2986
3240
|
},
|
|
3241
|
+
{
|
|
3242
|
+
path: TRUTHMARK_GEMINI_DOCUMENT_COMMAND_PATH,
|
|
3243
|
+
content: renderTruthmarkGeminiDocumentCommand(config)
|
|
3244
|
+
},
|
|
2987
3245
|
{
|
|
2988
3246
|
path: TRUTHMARK_GEMINI_SYNC_COMMAND_PATH,
|
|
2989
3247
|
content: renderTruthmarkGeminiSyncCommand(config)
|
|
@@ -3014,7 +3272,7 @@ var renderGeneratedSurfaces = (config, block = renderAgentsBlock(config)) => {
|
|
|
3014
3272
|
// src/checks/generated-surfaces.ts
|
|
3015
3273
|
var readOptionalFile = async (rootDir, filePath) => {
|
|
3016
3274
|
try {
|
|
3017
|
-
return await
|
|
3275
|
+
return await fs15.readFile(resolveRepoPath(rootDir, filePath), "utf8");
|
|
3018
3276
|
} catch (error) {
|
|
3019
3277
|
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
3020
3278
|
return null;
|