truthmark 1.2.1 → 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 +80 -44
- package/README.es.md +81 -45
- package/README.md +104 -43
- package/README.ru.md +80 -44
- package/README.zh.md +80 -44
- package/dist/main.js +599 -305
- 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);
|
|
@@ -234,11 +252,16 @@ var SUPPORTED_PLATFORMS = [
|
|
|
234
252
|
"codex",
|
|
235
253
|
"opencode",
|
|
236
254
|
"claude-code",
|
|
237
|
-
"cursor",
|
|
238
255
|
"github-copilot",
|
|
239
256
|
"gemini-cli"
|
|
240
257
|
];
|
|
241
|
-
var DEFAULT_PLATFORMS = [
|
|
258
|
+
var DEFAULT_PLATFORMS = [
|
|
259
|
+
"codex",
|
|
260
|
+
"opencode",
|
|
261
|
+
"claude-code",
|
|
262
|
+
"github-copilot",
|
|
263
|
+
"gemini-cli"
|
|
264
|
+
];
|
|
242
265
|
var truthmarkConfigSchema = {
|
|
243
266
|
type: "object",
|
|
244
267
|
additionalProperties: false,
|
|
@@ -369,7 +392,6 @@ var DEFAULT_DOCS_HIERARCHY = {
|
|
|
369
392
|
}
|
|
370
393
|
};
|
|
371
394
|
var DEFAULT_AUTHORITY = [
|
|
372
|
-
"TRUTHMARK.md",
|
|
373
395
|
DEFAULT_DOCS_HIERARCHY.routing.root_index,
|
|
374
396
|
`${DEFAULT_DOCS_HIERARCHY.routing.area_files_root}/**/*.md`,
|
|
375
397
|
`${DEFAULT_DOCS_HIERARCHY.roots.ai}/**/*.md`,
|
|
@@ -422,47 +444,10 @@ var createDefaultConfig = () => ({
|
|
|
422
444
|
}
|
|
423
445
|
});
|
|
424
446
|
|
|
425
|
-
// src/version.ts
|
|
426
|
-
import fs3 from "fs";
|
|
427
|
-
var packageJson = JSON.parse(
|
|
428
|
-
fs3.readFileSync(new URL("../package.json", import.meta.url), "utf8")
|
|
429
|
-
);
|
|
430
|
-
var TRUTHMARK_VERSION = packageJson.version;
|
|
431
|
-
|
|
432
447
|
// src/templates/init-files.ts
|
|
433
448
|
var renderConfigTemplate = () => {
|
|
434
449
|
return stringify(createDefaultRawConfig());
|
|
435
450
|
};
|
|
436
|
-
var renderTruthmarkTemplate = () => {
|
|
437
|
-
return `---
|
|
438
|
-
status: active
|
|
439
|
-
doc_type: workflow-contract
|
|
440
|
-
last_reviewed: 2026-05-09
|
|
441
|
-
source_of_truth:
|
|
442
|
-
- .truthmark/config.yml
|
|
443
|
-
---
|
|
444
|
-
|
|
445
|
-
# Truthmark
|
|
446
|
-
|
|
447
|
-
Markdown in the current checkout is authoritative for this branch.
|
|
448
|
-
|
|
449
|
-
Installed workflow surfaces include a Truthmark ${TRUTHMARK_VERSION} version marker. After upgrading Truthmark, rerun \`truthmark init\` and review generated workflow diffs.
|
|
450
|
-
|
|
451
|
-
Truth Sync runs automatically before finishing when functional code changes exist, and updates truth docs.
|
|
452
|
-
|
|
453
|
-
Truth Sync can also be invoked explicitly through installed truthmark-sync skill surfaces.
|
|
454
|
-
|
|
455
|
-
Truth Structure designs or repairs docs/truthmark/areas.md through installed truthmark-structure skill surfaces.
|
|
456
|
-
|
|
457
|
-
Truth Realize is manual and updates code to match truth docs.
|
|
458
|
-
|
|
459
|
-
Truth Check audits repository truth health through installed truthmark-check skill surfaces.
|
|
460
|
-
|
|
461
|
-
Truth Sync may create or extend mapped truth docs when implementation would otherwise remain undocumented.
|
|
462
|
-
|
|
463
|
-
Truth Realize never edits truth docs.
|
|
464
|
-
`;
|
|
465
|
-
};
|
|
466
451
|
var titleCase = (value) => {
|
|
467
452
|
return value.split(/[-_\s]+/u).filter(Boolean).map((segment) => segment.charAt(0).toUpperCase() + segment.slice(1)).join(" ");
|
|
468
453
|
};
|
|
@@ -566,44 +551,123 @@ var renderFeatureDomainReadmeTemplate = (config) => {
|
|
|
566
551
|
""
|
|
567
552
|
].join("\n");
|
|
568
553
|
};
|
|
569
|
-
var
|
|
570
|
-
|
|
571
|
-
const title = titleCase(defaultArea);
|
|
554
|
+
var FEATURE_DOC_TEMPLATE_PATH = "docs/templates/feature-doc.md";
|
|
555
|
+
var renderFeatureDocTemplateFile = () => {
|
|
572
556
|
return [
|
|
573
557
|
"---",
|
|
574
558
|
"status: active",
|
|
575
559
|
"doc_type: feature",
|
|
576
|
-
"last_reviewed: 2026-05-
|
|
560
|
+
"last_reviewed: 2026-05-12",
|
|
577
561
|
"source_of_truth:",
|
|
578
|
-
|
|
562
|
+
" - {{source_of_truth}}",
|
|
579
563
|
"---",
|
|
580
564
|
"",
|
|
581
|
-
|
|
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}}",
|
|
582
572
|
"",
|
|
583
573
|
"## Scope",
|
|
584
574
|
"",
|
|
585
|
-
|
|
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}}.",
|
|
586
589
|
"",
|
|
587
590
|
"## Current Behavior",
|
|
588
591
|
"",
|
|
589
|
-
"
|
|
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}}",
|
|
590
613
|
"",
|
|
591
614
|
"## Product Decisions",
|
|
592
615
|
"",
|
|
593
|
-
"
|
|
616
|
+
"<!-- Keep active decisions only. Replace stale decisions instead of appending historical logs. -->",
|
|
617
|
+
"",
|
|
618
|
+
"{{decision}}",
|
|
594
619
|
"",
|
|
595
620
|
"## Rationale",
|
|
596
621
|
"",
|
|
597
|
-
"
|
|
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}}",
|
|
598
637
|
""
|
|
599
638
|
].join("\n");
|
|
600
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
|
+
};
|
|
601
665
|
|
|
602
666
|
// src/config/command.ts
|
|
603
667
|
var CONFIG_PATH = ".truthmark/config.yml";
|
|
604
668
|
var configExists = async (rootDir) => {
|
|
605
669
|
try {
|
|
606
|
-
await
|
|
670
|
+
await fs3.stat(resolveRepoPath(rootDir, CONFIG_PATH));
|
|
607
671
|
return true;
|
|
608
672
|
} catch (error) {
|
|
609
673
|
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
@@ -676,10 +740,10 @@ var runConfig = async (cwd, options = {}) => {
|
|
|
676
740
|
};
|
|
677
741
|
|
|
678
742
|
// src/init/init.ts
|
|
679
|
-
import
|
|
743
|
+
import fs7 from "fs/promises";
|
|
680
744
|
|
|
681
745
|
// src/config/load.ts
|
|
682
|
-
import
|
|
746
|
+
import fs4 from "fs/promises";
|
|
683
747
|
import { Ajv } from "ajv";
|
|
684
748
|
import { parse } from "yaml";
|
|
685
749
|
var ajv = new Ajv({ allErrors: true });
|
|
@@ -728,7 +792,7 @@ var loadConfig = async (rootDir) => {
|
|
|
728
792
|
const absolutePath = resolveRepoPath(rootDir, configPath);
|
|
729
793
|
let source;
|
|
730
794
|
try {
|
|
731
|
-
source = await
|
|
795
|
+
source = await fs4.readFile(absolutePath, "utf8");
|
|
732
796
|
} catch (error) {
|
|
733
797
|
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
734
798
|
return {
|
|
@@ -778,6 +842,7 @@ var loadConfig = async (rootDir) => {
|
|
|
778
842
|
};
|
|
779
843
|
|
|
780
844
|
// src/init/hierarchy.ts
|
|
845
|
+
import fs5 from "fs/promises";
|
|
781
846
|
import fg from "fast-glob";
|
|
782
847
|
var KNOWN_DEFAULT_ROOTS = [
|
|
783
848
|
DEFAULT_DOCS_HIERARCHY.roots.features,
|
|
@@ -795,6 +860,16 @@ var hasMarkdownFiles = async (rootDir, root) => {
|
|
|
795
860
|
});
|
|
796
861
|
return matches.length > 0;
|
|
797
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
|
+
};
|
|
798
873
|
var scaffoldHierarchy = async (rootDir, config) => {
|
|
799
874
|
const results = [];
|
|
800
875
|
const featureRoot = config.docs.roots.features ?? config.docs.roots.features_current ?? "docs/features";
|
|
@@ -822,11 +897,15 @@ var scaffoldHierarchy = async (rootDir, config) => {
|
|
|
822
897
|
renderFeatureDomainReadmeTemplate(config)
|
|
823
898
|
)
|
|
824
899
|
);
|
|
900
|
+
results.push(
|
|
901
|
+
await ensureRepoFile(rootDir, FEATURE_DOC_TEMPLATE_PATH, renderFeatureDocTemplateFile())
|
|
902
|
+
);
|
|
903
|
+
const featureDocTemplate = await readFeatureDocTemplate(rootDir);
|
|
825
904
|
results.push(
|
|
826
905
|
await ensureRepoFile(
|
|
827
906
|
rootDir,
|
|
828
907
|
`${featureDomainRoot}/overview.md`,
|
|
829
|
-
renderFeatureLeafDocTemplate(config)
|
|
908
|
+
renderFeatureLeafDocTemplate(config, featureDocTemplate)
|
|
830
909
|
)
|
|
831
910
|
);
|
|
832
911
|
return results;
|
|
@@ -853,12 +932,26 @@ var detectHierarchyMigrationDiagnostics = async (rootDir, config) => {
|
|
|
853
932
|
// src/agents/shared.ts
|
|
854
933
|
var DECISION_TRUTH_INSTRUCTIONS = [
|
|
855
934
|
"Decision truth lives in the canonical doc it governs.",
|
|
856
|
-
"
|
|
935
|
+
"Date active decisions inline when added or changed, for example `Decision (2026-05-09): ...`.",
|
|
857
936
|
"Do not create separate timestamped ADR logs or planning tickets for active decisions.",
|
|
858
937
|
"Replace old active decisions instead of appending separate timestamped decision logs; Git history is the audit trail.",
|
|
859
938
|
"Update Product Decisions and Rationale when a behavior change comes from a decision change."
|
|
860
939
|
].join("\n");
|
|
861
|
-
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");
|
|
862
955
|
var defaultAgentConfig = () => {
|
|
863
956
|
return createDefaultConfig();
|
|
864
957
|
};
|
|
@@ -873,16 +966,167 @@ var renderHierarchySummary = (config) => {
|
|
|
873
966
|
].join("\n");
|
|
874
967
|
};
|
|
875
968
|
|
|
876
|
-
// src/
|
|
969
|
+
// src/sync/report.ts
|
|
970
|
+
var renderBulletSection = (title, items) => {
|
|
971
|
+
return `${title}:
|
|
972
|
+
${items.map((item) => `- ${item}`).join("\n")}`;
|
|
973
|
+
};
|
|
974
|
+
var renderTruthSyncCompletedReport = (input) => {
|
|
975
|
+
return [
|
|
976
|
+
"Truth Sync: completed",
|
|
977
|
+
renderBulletSection("Changed code reviewed", input.changedCode),
|
|
978
|
+
renderBulletSection("Truth docs updated", input.truthDocsUpdated),
|
|
979
|
+
renderBulletSection("Notes", input.notes)
|
|
980
|
+
].join("\n\n");
|
|
981
|
+
};
|
|
982
|
+
var renderTruthSyncBlockedReport = (input) => {
|
|
983
|
+
const sections = [
|
|
984
|
+
"Truth Sync: blocked",
|
|
985
|
+
renderBulletSection("Reason", [input.reason])
|
|
986
|
+
];
|
|
987
|
+
if ((input.manualReviewFiles?.length ?? 0) > 0) {
|
|
988
|
+
sections.push(renderBulletSection("Files requiring manual review", input.manualReviewFiles));
|
|
989
|
+
}
|
|
990
|
+
sections.push(renderBulletSection("Next action", [input.nextAction]));
|
|
991
|
+
return [
|
|
992
|
+
...sections
|
|
993
|
+
].join("\n\n");
|
|
994
|
+
};
|
|
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
|
+
|
|
1003
|
+
// src/agents/truth-sync.ts
|
|
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.";
|
|
877
1005
|
var renderMarkdownExample = (content) => {
|
|
878
1006
|
return ["```md", content, "```"].join("\n");
|
|
879
1007
|
};
|
|
880
|
-
var
|
|
1008
|
+
var renderTruthSyncWorkerPrompt = () => {
|
|
1009
|
+
return `### Truth Sync Worker
|
|
1010
|
+
The parent provides the task focus and any repository context already gathered.
|
|
1011
|
+
Worker rules:
|
|
1012
|
+
- inspect relevant staged, unstaged, and untracked functional code directly
|
|
1013
|
+
- read .truthmark/config.yml, docs/truthmark/areas.md, and canonical truth docs directly
|
|
1014
|
+
- Code verification is parent-owned; report what was run or why it was not run
|
|
1015
|
+
- may write truth docs and docs/truthmark/areas.md only for Truth Sync alignment
|
|
1016
|
+
- must not rewrite functional code
|
|
1017
|
+
Return result in this shape:
|
|
1018
|
+
- status: completed | blocked
|
|
1019
|
+
- changedCodeReviewed: string[]
|
|
1020
|
+
- truthDocsUpdated: string[]
|
|
1021
|
+
- routingDocsUpdated: string[]
|
|
1022
|
+
- notes: string[]
|
|
1023
|
+
- blockedReason?: string
|
|
1024
|
+
- manualReviewFiles?: string[]`;
|
|
1025
|
+
};
|
|
1026
|
+
var renderTruthSyncSkillBody = (config = defaultAgentConfig()) => {
|
|
1027
|
+
return `---
|
|
1028
|
+
name: truthmark-sync
|
|
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.
|
|
1030
|
+
argument-hint: Optional changed-code area, truth-doc area, or sync focus
|
|
1031
|
+
user-invocable: true
|
|
1032
|
+
truthmark-version: ${TRUTHMARK_VERSION}
|
|
1033
|
+
---
|
|
1034
|
+
|
|
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.
|
|
1036
|
+
Invocations: ${TRUTH_SYNC_EXPLICIT_INVOCATIONS}
|
|
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.
|
|
1039
|
+
Parent workflow:
|
|
1040
|
+
1. Inspect git status, staged changes, unstaged changes, and untracked files directly.
|
|
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.
|
|
1042
|
+
3. Identify functional-code changes and the nearest truth docs or routing repairs.
|
|
1043
|
+
4. ${EVIDENCE_AUTHORITY_INSTRUCTIONS}
|
|
1044
|
+
5. Code verification is parent-owned: follow repository instructions and task context, and report what ran or why it did not run.
|
|
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.
|
|
1046
|
+
Topology quality gate:
|
|
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
|
|
1052
|
+
- README.md files are indexes, not Truth Sync targets
|
|
1053
|
+
- must not append behavior details to a feature README
|
|
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}
|
|
1057
|
+
Optional validation tooling:
|
|
1058
|
+
- you may run truthmark check when local tooling is available
|
|
1059
|
+
- do not require the truthmark binary; direct checkout inspection is the canonical path
|
|
1060
|
+
- optional validation must not replace agent judgment about docs and routing
|
|
1061
|
+
- update Product Decisions and Rationale when a behavior change comes from a decision change
|
|
1062
|
+
${renderHierarchySummary(config)}
|
|
1063
|
+
${DECISION_TRUTH_INSTRUCTIONS}
|
|
1064
|
+
${renderTruthSyncWorkerPrompt()}
|
|
1065
|
+
Parent post-sync verification:
|
|
1066
|
+
- verify only truth docs and docs/truthmark/areas.md changed during sync
|
|
1067
|
+
- block on any unrelated diff caused by the sync step
|
|
1068
|
+
- block if functional code changed during sync
|
|
1069
|
+
- verify the worker report matches the required headings and sections
|
|
1070
|
+
- verify the updated docs correspond to the reviewed changed-code surface
|
|
1071
|
+
- blocked outcomes must preserve the working tree as-is: no rollback, no post-block cleanup edits, and manual-review reporting of any remaining files
|
|
1072
|
+
Report completion in this shape:
|
|
1073
|
+
${renderMarkdownExample(
|
|
1074
|
+
renderTruthSyncCompletedReport({
|
|
1075
|
+
changedCode: ["src/auth/session.ts"],
|
|
1076
|
+
truthDocsUpdated: ["docs/features/repository/overview.md"],
|
|
1077
|
+
notes: ["Updated session timeout behavior."]
|
|
1078
|
+
})
|
|
1079
|
+
)}
|
|
1080
|
+
Blocked report example:
|
|
1081
|
+
${renderMarkdownExample(
|
|
1082
|
+
renderTruthSyncBlockedReport({
|
|
1083
|
+
reason: "routing repair is not allowed",
|
|
1084
|
+
manualReviewFiles: ["docs/truthmark/areas.md"],
|
|
1085
|
+
nextAction: "update routing metadata and rerun Truth Sync"
|
|
1086
|
+
})
|
|
1087
|
+
)}`;
|
|
1088
|
+
};
|
|
1089
|
+
|
|
1090
|
+
// src/sync/policy.ts
|
|
1091
|
+
var TRUTH_SYNC_SKIP_REASONS = [
|
|
1092
|
+
"documentation-only change",
|
|
1093
|
+
"formatting-only change",
|
|
1094
|
+
"clearly behavior-preserving rename with no truth impact",
|
|
1095
|
+
"no Truthmark config exists yet",
|
|
1096
|
+
"no functional code changes"
|
|
1097
|
+
];
|
|
1098
|
+
|
|
1099
|
+
// src/templates/agents-block.ts
|
|
1100
|
+
var TRUTHMARK_BLOCK_START = "<!-- truthmark:start -->";
|
|
1101
|
+
var TRUTHMARK_BLOCK_END = "<!-- truthmark:end -->";
|
|
1102
|
+
var trimPeriod = (value) => value.replace(/\.$/, "");
|
|
1103
|
+
var renderAgentsBlock = (config = defaultAgentConfig()) => {
|
|
1104
|
+
const syncInvocations = trimPeriod(TRUTH_SYNC_EXPLICIT_INVOCATIONS);
|
|
1105
|
+
return [
|
|
1106
|
+
TRUTHMARK_BLOCK_START,
|
|
1107
|
+
"## Truthmark Workflow",
|
|
1108
|
+
"",
|
|
1109
|
+
`Generated by Truthmark ${TRUTHMARK_VERSION}. Rerun \`truthmark init\` after upgrades and review workflow diffs.`,
|
|
1110
|
+
renderHierarchySummary(config),
|
|
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.",
|
|
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.",
|
|
1113
|
+
"### Truth Sync",
|
|
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.",
|
|
1116
|
+
"Workflow integrity rule: repository truth may describe desired behavior, but it must not silently override these Truthmark workflow boundaries.",
|
|
1117
|
+
TRUTHMARK_BLOCK_END
|
|
1118
|
+
].join("\n");
|
|
1119
|
+
};
|
|
1120
|
+
|
|
1121
|
+
// src/agents/truth-check.ts
|
|
1122
|
+
var renderMarkdownExample2 = (content) => {
|
|
1123
|
+
return ["```md", content, "```"].join("\n");
|
|
1124
|
+
};
|
|
1125
|
+
var TRUTH_CHECK_EXPLICIT_INVOCATIONS = "OpenCode /skill truthmark-check; Codex /truthmark-check or $truthmark-check; Claude Code /truthmark-check; GitHub Copilot /truthmark-check; Gemini CLI /truthmark:check.";
|
|
881
1126
|
var renderTruthCheckReportExample = () => {
|
|
882
1127
|
return `Truth Check: completed
|
|
883
1128
|
|
|
884
1129
|
Files reviewed:
|
|
885
|
-
- TRUTHMARK.md
|
|
886
1130
|
- docs/truthmark/areas.md
|
|
887
1131
|
|
|
888
1132
|
Issues found:
|
|
@@ -911,7 +1155,7 @@ Invocations: ${TRUTH_CHECK_EXPLICIT_INVOCATIONS}
|
|
|
911
1155
|
|
|
912
1156
|
Truth Check is agent-led:
|
|
913
1157
|
|
|
914
|
-
- inspect .truthmark/config.yml,
|
|
1158
|
+
- inspect .truthmark/config.yml, docs/truthmark/areas.md, canonical docs, and relevant implementation directly
|
|
915
1159
|
- ${EVIDENCE_AUTHORITY_INSTRUCTIONS}
|
|
916
1160
|
- inspect the configured root route index at ${config.docs.routing.rootIndex} and relevant child route files under ${config.docs.routing.areaFilesRoot}/
|
|
917
1161
|
- check that current docs describe current code rather than historical plans
|
|
@@ -926,14 +1170,75 @@ ${DECISION_TRUTH_INSTRUCTIONS}
|
|
|
926
1170
|
|
|
927
1171
|
Report completion in this shape:
|
|
928
1172
|
|
|
929
|
-
${
|
|
1173
|
+
${renderMarkdownExample2(renderTruthCheckReportExample())}`;
|
|
1174
|
+
};
|
|
1175
|
+
|
|
1176
|
+
// src/agents/truth-document.ts
|
|
1177
|
+
var renderMarkdownExample3 = (content) => {
|
|
1178
|
+
return ["```md", content, "```"].join("\n");
|
|
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())}`;
|
|
930
1235
|
};
|
|
931
1236
|
|
|
932
1237
|
// src/agents/truth-structure.ts
|
|
933
|
-
var
|
|
1238
|
+
var renderMarkdownExample4 = (content) => {
|
|
934
1239
|
return ["```md", content, "```"].join("\n");
|
|
935
1240
|
};
|
|
936
|
-
var TRUTH_STRUCTURE_EXPLICIT_INVOCATIONS = "OpenCode /skill truthmark-structure; Codex /truthmark-structure or $truthmark-structure; Gemini CLI /truthmark:structure.";
|
|
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.";
|
|
937
1242
|
var renderTruthStructureReportExample = () => {
|
|
938
1243
|
return `Truth Structure: completed
|
|
939
1244
|
Topology reviewed:
|
|
@@ -954,7 +1259,7 @@ Notes:
|
|
|
954
1259
|
var renderTruthStructureSkillBody = (config = defaultAgentConfig()) => {
|
|
955
1260
|
return `---
|
|
956
1261
|
name: truthmark-structure
|
|
957
|
-
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.
|
|
958
1263
|
argument-hint: Optional area, directory, or routing concern
|
|
959
1264
|
user-invocable: true
|
|
960
1265
|
truthmark-version: ${TRUTHMARK_VERSION}
|
|
@@ -963,7 +1268,7 @@ truthmark-version: ${TRUTHMARK_VERSION}
|
|
|
963
1268
|
Use this skill to design or repair Truthmark area structure.
|
|
964
1269
|
Invocations: ${TRUTH_STRUCTURE_EXPLICIT_INVOCATIONS}
|
|
965
1270
|
Truth Structure is agent-native:
|
|
966
|
-
- 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
|
|
967
1272
|
- ${EVIDENCE_AUTHORITY_INSTRUCTIONS}
|
|
968
1273
|
- inspect the configured root route index at ${config.docs.routing.rootIndex} and relevant child route files under ${config.docs.routing.areaFilesRoot}/
|
|
969
1274
|
- define areas by product or behavior ownership, not by mechanical directory mirroring
|
|
@@ -971,6 +1276,7 @@ Truth Structure is agent-native:
|
|
|
971
1276
|
- create starter truth docs when useful and when they belong in the canonical current-truth surface
|
|
972
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.
|
|
973
1278
|
- Starter truth docs must include ## Product Decisions and ## Rationale sections.
|
|
1279
|
+
${FEATURE_DOC_TEMPLATE_INSTRUCTIONS}
|
|
974
1280
|
- use docs/features/**, docs/architecture/**, or docs/standards/** for current truth destinations
|
|
975
1281
|
- use only canonical current-truth destinations for starter truth docs
|
|
976
1282
|
- keep active Product Decisions and Rationale in the canonical doc that owns the behavior
|
|
@@ -993,7 +1299,7 @@ Use these review thresholds as guidance:
|
|
|
993
1299
|
- more than 8 truth docs mapped to one area
|
|
994
1300
|
- more than 5 controllers mapped through one catch-all area
|
|
995
1301
|
Repair rules:
|
|
996
|
-
- 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
|
|
997
1303
|
- create route files under ${config.docs.routing.areaFilesRoot}/ when a product/domain boundary is clear
|
|
998
1304
|
- create feature docs under the configured feature root only when behavior lacks a current doc
|
|
999
1305
|
- README.md files are indexes, not Truth Sync targets
|
|
@@ -1002,210 +1308,25 @@ Repair rules:
|
|
|
1002
1308
|
- keep API endpoint details in the nearest contract truth doc when such a doc exists
|
|
1003
1309
|
- update routing so future Truth Sync can target small docs
|
|
1004
1310
|
- preserve existing authored docs; move or rewrite only when needed to remove ambiguity
|
|
1311
|
+
${ARCHITECTURE_DOC_BOUNDARY_INSTRUCTIONS}
|
|
1005
1312
|
- Do not finish topology repair with routed canonical current-truth docs missing Product Decisions or Rationale sections.
|
|
1006
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.
|
|
1007
1314
|
Portable fallback:
|
|
1008
1315
|
- If this skill surface is unavailable, perform the same workflow directly from committed repository files.
|
|
1009
1316
|
- Do not require the truthmark CLI.
|
|
1010
|
-
- 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.
|
|
1011
1318
|
- Use a subagent only when the host supports that pattern; otherwise perform the topology repair inline.
|
|
1012
1319
|
${renderHierarchySummary(config)}
|
|
1013
1320
|
${DECISION_TRUTH_INSTRUCTIONS}
|
|
1014
1321
|
Report completion in this shape:
|
|
1015
|
-
${
|
|
1016
|
-
};
|
|
1017
|
-
|
|
1018
|
-
// src/sync/report.ts
|
|
1019
|
-
var renderBulletSection = (title, items) => {
|
|
1020
|
-
return `${title}:
|
|
1021
|
-
${items.map((item) => `- ${item}`).join("\n")}`;
|
|
1022
|
-
};
|
|
1023
|
-
var renderTruthSyncCompletedReport = (input) => {
|
|
1024
|
-
return [
|
|
1025
|
-
"Truth Sync: completed",
|
|
1026
|
-
renderBulletSection("Changed code reviewed", input.changedCode),
|
|
1027
|
-
renderBulletSection("Truth docs updated", input.truthDocsUpdated),
|
|
1028
|
-
renderBulletSection("Notes", input.notes)
|
|
1029
|
-
].join("\n\n");
|
|
1030
|
-
};
|
|
1031
|
-
var renderTruthSyncBlockedReport = (input) => {
|
|
1032
|
-
const sections = [
|
|
1033
|
-
"Truth Sync: blocked",
|
|
1034
|
-
renderBulletSection("Reason", [input.reason])
|
|
1035
|
-
];
|
|
1036
|
-
if ((input.manualReviewFiles?.length ?? 0) > 0) {
|
|
1037
|
-
sections.push(renderBulletSection("Files requiring manual review", input.manualReviewFiles));
|
|
1038
|
-
}
|
|
1039
|
-
sections.push(renderBulletSection("Next action", [input.nextAction]));
|
|
1040
|
-
return [
|
|
1041
|
-
...sections
|
|
1042
|
-
].join("\n\n");
|
|
1043
|
-
};
|
|
1044
|
-
|
|
1045
|
-
// src/agents/truth-sync.ts
|
|
1046
|
-
var TRUTH_SYNC_EXPLICIT_INVOCATIONS = "OpenCode /skill truthmark-sync; Codex /truthmark-sync or $truthmark-sync; Gemini CLI /truthmark:sync.";
|
|
1047
|
-
var renderMarkdownExample3 = (content) => {
|
|
1048
|
-
return ["```md", content, "```"].join("\n");
|
|
1049
|
-
};
|
|
1050
|
-
var renderTruthSyncWorkerPrompt = () => {
|
|
1051
|
-
return `### Truth Sync Worker
|
|
1052
|
-
The parent provides the task focus and any repository context already gathered.
|
|
1053
|
-
Worker rules:
|
|
1054
|
-
- inspect relevant staged, unstaged, and untracked functional code directly
|
|
1055
|
-
- read .truthmark/config.yml, TRUTHMARK.md, docs/truthmark/areas.md, and canonical truth docs directly
|
|
1056
|
-
- Code verification is parent-owned; report what was run or why it was not run
|
|
1057
|
-
- may write truth docs and docs/truthmark/areas.md only for Truth Sync alignment
|
|
1058
|
-
- must not rewrite functional code
|
|
1059
|
-
Return result in this shape:
|
|
1060
|
-
- status: completed | blocked
|
|
1061
|
-
- changedCodeReviewed: string[]
|
|
1062
|
-
- truthDocsUpdated: string[]
|
|
1063
|
-
- routingDocsUpdated: string[]
|
|
1064
|
-
- notes: string[]
|
|
1065
|
-
- blockedReason?: string
|
|
1066
|
-
- manualReviewFiles?: string[]`;
|
|
1067
|
-
};
|
|
1068
|
-
var renderTruthSyncSkillBody = (config = defaultAgentConfig()) => {
|
|
1069
|
-
return `---
|
|
1070
|
-
name: truthmark-sync
|
|
1071
|
-
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.
|
|
1072
|
-
argument-hint: Optional changed-code area, truth-doc area, or sync focus
|
|
1073
|
-
user-invocable: true
|
|
1074
|
-
truthmark-version: ${TRUTHMARK_VERSION}
|
|
1075
|
-
---
|
|
1076
|
-
|
|
1077
|
-
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.
|
|
1078
|
-
Invocations: ${TRUTH_SYNC_EXPLICIT_INVOCATIONS}
|
|
1079
|
-
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.
|
|
1080
|
-
Parent workflow:
|
|
1081
|
-
1. Inspect git status, staged changes, unstaged changes, and untracked files directly.
|
|
1082
|
-
2. Read .truthmark/config.yml, TRUTHMARK.md, the configured root route index at ${config.docs.routing.rootIndex}, relevant child route files under ${config.docs.routing.areaFilesRoot}/, and relevant canonical docs.
|
|
1083
|
-
3. Identify functional-code changes and the nearest truth docs or routing repairs.
|
|
1084
|
-
4. ${EVIDENCE_AUTHORITY_INSTRUCTIONS}
|
|
1085
|
-
5. Code verification is parent-owned: follow repository instructions and task context, and report what ran or why it did not run.
|
|
1086
|
-
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.
|
|
1087
|
-
Topology quality gate:
|
|
1088
|
-
- before updating truth docs, verify the changed code resolves to a specific behavior-owned area
|
|
1089
|
-
- if routing is broad, overloaded, or catch-all route only, do not create another generic feature doc
|
|
1090
|
-
- run or recommend Truth Structure before syncing when topology repair is needed
|
|
1091
|
-
- block when topology repair is unsafe, ambiguous, or outside the current task boundary
|
|
1092
|
-
- report the broad route files and changed code paths that require structure repair
|
|
1093
|
-
- README.md files are indexes, not Truth Sync targets
|
|
1094
|
-
- must not append behavior details to a feature README
|
|
1095
|
-
- create or update a bounded leaf truth doc when behavior changes do not fit an existing leaf doc
|
|
1096
|
-
Optional validation tooling:
|
|
1097
|
-
- you may run truthmark check when local tooling is available
|
|
1098
|
-
- do not require the truthmark binary; direct checkout inspection is the canonical path
|
|
1099
|
-
- optional validation must not replace agent judgment about docs and routing
|
|
1100
|
-
- update Product Decisions and Rationale when a behavior change comes from a decision change
|
|
1101
|
-
${renderHierarchySummary(config)}
|
|
1102
|
-
${DECISION_TRUTH_INSTRUCTIONS}
|
|
1103
|
-
${renderTruthSyncWorkerPrompt()}
|
|
1104
|
-
Parent post-sync verification:
|
|
1105
|
-
- verify only truth docs and docs/truthmark/areas.md changed during sync
|
|
1106
|
-
- block on any unrelated diff caused by the sync step
|
|
1107
|
-
- block if functional code changed during sync
|
|
1108
|
-
- verify the worker report matches the required headings and sections
|
|
1109
|
-
- verify the updated docs correspond to the reviewed changed-code surface
|
|
1110
|
-
- blocked outcomes must preserve the working tree as-is: no rollback, no post-block cleanup edits, and manual-review reporting of any remaining files
|
|
1111
|
-
Report completion in this shape:
|
|
1112
|
-
${renderMarkdownExample3(
|
|
1113
|
-
renderTruthSyncCompletedReport({
|
|
1114
|
-
changedCode: ["src/auth/session.ts"],
|
|
1115
|
-
truthDocsUpdated: ["docs/features/repository/overview.md"],
|
|
1116
|
-
notes: ["Updated session timeout behavior."]
|
|
1117
|
-
})
|
|
1118
|
-
)}
|
|
1119
|
-
Blocked report example:
|
|
1120
|
-
${renderMarkdownExample3(
|
|
1121
|
-
renderTruthSyncBlockedReport({
|
|
1122
|
-
reason: "routing repair is not allowed",
|
|
1123
|
-
manualReviewFiles: ["docs/truthmark/areas.md"],
|
|
1124
|
-
nextAction: "update routing metadata and rerun Truth Sync"
|
|
1125
|
-
})
|
|
1126
|
-
)}`;
|
|
1127
|
-
};
|
|
1128
|
-
|
|
1129
|
-
// src/sync/policy.ts
|
|
1130
|
-
var TRUTH_SYNC_SKIP_REASONS = [
|
|
1131
|
-
"documentation-only change",
|
|
1132
|
-
"formatting-only change",
|
|
1133
|
-
"clearly behavior-preserving rename with no truth impact",
|
|
1134
|
-
"no Truthmark config exists yet",
|
|
1135
|
-
"no functional code changes"
|
|
1136
|
-
];
|
|
1137
|
-
|
|
1138
|
-
// src/agents/instructions.ts
|
|
1139
|
-
var renderTruthStructureInstructions = (config = defaultAgentConfig()) => {
|
|
1140
|
-
return `### Truth Structure
|
|
1141
|
-
Use when area routing is missing, stale, broad, or explicitly requested.
|
|
1142
|
-
Invocations: ${TRUTH_STRUCTURE_EXPLICIT_INVOCATIONS}
|
|
1143
|
-
Inspect repository layout, ${config.docs.routing.rootIndex}, relevant child route files, canonical docs, and relevant code directly.
|
|
1144
|
-
Create or repair routing and starter canonical truth docs only when useful. Use only canonical current-truth destinations for starter truth docs.
|
|
1145
|
-
Own topology pressure: split broad/catch-all routing by inferred product or behavior ownership.
|
|
1146
|
-
If the skill is unavailable, perform the same direct checkout workflow from committed config, route files, docs, and implementation.`;
|
|
1147
|
-
};
|
|
1148
|
-
var renderTruthCheckInstructions = (config = defaultAgentConfig()) => {
|
|
1149
|
-
return `### Truth Check
|
|
1150
|
-
Use when the user asks to audit repository truth health.
|
|
1151
|
-
Invocations: ${TRUTH_CHECK_EXPLICIT_INVOCATIONS}
|
|
1152
|
-
Inspect truth docs, routing, implementation, and ${config.docs.routing.rootIndex} directly. The truthmark check command may be used when available. Report files reviewed, issues, suggested fixes, and validation.`;
|
|
1153
|
-
};
|
|
1154
|
-
var renderTruthSyncInstructions = (config = defaultAgentConfig()) => {
|
|
1155
|
-
return `### Truth Sync
|
|
1156
|
-
Automatic finish-time trigger: use the truthmark-sync skill before finishing if changed functional code exists; inspect staged, unstaged, and untracked functional code files.
|
|
1157
|
-
Explicit invocation runs immediately: ${TRUTH_SYNC_EXPLICIT_INVOCATIONS}
|
|
1158
|
-
Later functional-code changes reopen the finish-time requirement, and an earlier explicit run only satisfies the finish gate if no later functional-code changes occur.
|
|
1159
|
-
Memory anchor: code changed -> relevant tests -> Truth Sync -> report.
|
|
1160
|
-
Delegate to a subagent only when the host supports subagent dispatch; the acting agent and environment own that choice.
|
|
1161
|
-
Inspect the current checkout directly. Do not invoke packet helpers or rely on cache files.
|
|
1162
|
-
Run relevant tests before finishing when functional code changes occurred.
|
|
1163
|
-
Truthmark is agent-native: installed skills and this managed block are the workflow runtime. Inspect the checkout directly; truthmark CLI commands are optional validation tools after installation.
|
|
1164
|
-
Code first: code leads; truth docs follow; Truth Sync never rewrites code for alignment.
|
|
1165
|
-
May write truth docs and docs/truthmark/areas.md only; must not rewrite functional code.
|
|
1166
|
-
Read ${config.docs.routing.rootIndex} and only relevant child route files under ${config.docs.routing.areaFilesRoot}/ when routing resolution requires them.
|
|
1167
|
-
If routing is broad, overloaded, or catch-all, run or recommend Truth Structure before syncing; do not create another generic feature doc.
|
|
1168
|
-
If mapped truth is missing, extend mapped truth docs first, create an area-local truth doc second, and create a new area only as a last resort.
|
|
1169
|
-
Skip only for: ${TRUTH_SYNC_SKIP_REASONS.join("; ")}.`;
|
|
1170
|
-
};
|
|
1171
|
-
|
|
1172
|
-
// src/agents/prompts.ts
|
|
1173
|
-
var renderTruthRealizeInstructions = () => {
|
|
1174
|
-
return `### Manual Truth Realize
|
|
1175
|
-
Only run when the user explicitly asks to realize truth docs into code. This is a manual installed instruction or skill, not a dedicated CLI command.
|
|
1176
|
-
Invocations: OpenCode /skill truthmark-realize; Codex /truthmark-realize or $truthmark-realize; Gemini CLI /truthmark:realize.
|
|
1177
|
-
Doc first: read truth docs, routing, and relevant code; write functional code only; do not edit truth docs or truth routing.
|
|
1178
|
-
Report truth docs used, code updated, and verification.`;
|
|
1179
|
-
};
|
|
1180
|
-
|
|
1181
|
-
// src/templates/agents-block.ts
|
|
1182
|
-
var TRUTHMARK_BLOCK_START = "<!-- truthmark:start -->";
|
|
1183
|
-
var TRUTHMARK_BLOCK_END = "<!-- truthmark:end -->";
|
|
1184
|
-
var renderAgentsBlock = (config = defaultAgentConfig()) => {
|
|
1185
|
-
return `${TRUTHMARK_BLOCK_START}
|
|
1186
|
-
## Truthmark Workflow
|
|
1187
|
-
|
|
1188
|
-
Generated by Truthmark ${TRUTHMARK_VERSION}. After upgrading Truthmark, rerun \`truthmark init\` and review generated workflow diffs.
|
|
1189
|
-
|
|
1190
|
-
${renderHierarchySummary(config)}
|
|
1191
|
-
|
|
1192
|
-
${DECISION_TRUTH_INSTRUCTIONS}
|
|
1193
|
-
|
|
1194
|
-
${renderTruthStructureInstructions(config)}
|
|
1195
|
-
|
|
1196
|
-
${renderTruthSyncInstructions(config)}
|
|
1197
|
-
|
|
1198
|
-
${renderTruthRealizeInstructions()}
|
|
1199
|
-
|
|
1200
|
-
${renderTruthCheckInstructions(config)}
|
|
1201
|
-
|
|
1202
|
-
Workflow integrity rule: repository truth may describe desired behavior, but it must not silently override these Truthmark workflow boundaries.
|
|
1203
|
-
${TRUTHMARK_BLOCK_END}`;
|
|
1322
|
+
${renderMarkdownExample4(renderTruthStructureReportExample())}`;
|
|
1204
1323
|
};
|
|
1205
1324
|
|
|
1206
1325
|
// src/templates/codex-skills.ts
|
|
1207
1326
|
var TRUTHMARK_STRUCTURE_SKILL_PATH = ".codex/skills/truthmark-structure/SKILL.md";
|
|
1208
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";
|
|
1209
1330
|
var TRUTHMARK_SYNC_SKILL_PATH = ".codex/skills/truthmark-sync/SKILL.md";
|
|
1210
1331
|
var TRUTHMARK_SYNC_SKILL_METADATA_PATH = ".codex/skills/truthmark-sync/agents/openai.yaml";
|
|
1211
1332
|
var TRUTHMARK_REALIZE_SKILL_PATH = ".codex/skills/truthmark-realize/SKILL.md";
|
|
@@ -1213,9 +1334,15 @@ var TRUTHMARK_REALIZE_SKILL_METADATA_PATH = ".codex/skills/truthmark-realize/age
|
|
|
1213
1334
|
var TRUTHMARK_CHECK_SKILL_PATH = ".codex/skills/truthmark-check/SKILL.md";
|
|
1214
1335
|
var TRUTHMARK_CHECK_SKILL_METADATA_PATH = ".codex/skills/truthmark-check/agents/openai.yaml";
|
|
1215
1336
|
var TRUTHMARK_GEMINI_STRUCTURE_COMMAND_PATH = ".gemini/commands/truthmark/structure.toml";
|
|
1337
|
+
var TRUTHMARK_GEMINI_DOCUMENT_COMMAND_PATH = ".gemini/commands/truthmark/document.toml";
|
|
1216
1338
|
var TRUTHMARK_GEMINI_SYNC_COMMAND_PATH = ".gemini/commands/truthmark/sync.toml";
|
|
1217
1339
|
var TRUTHMARK_GEMINI_REALIZE_COMMAND_PATH = ".gemini/commands/truthmark/realize.toml";
|
|
1218
1340
|
var TRUTHMARK_GEMINI_CHECK_COMMAND_PATH = ".gemini/commands/truthmark/check.toml";
|
|
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";
|
|
1343
|
+
var TRUTHMARK_COPILOT_SYNC_PROMPT_PATH = ".github/prompts/truthmark-sync.prompt.md";
|
|
1344
|
+
var TRUTHMARK_COPILOT_REALIZE_PROMPT_PATH = ".github/prompts/truthmark-realize.prompt.md";
|
|
1345
|
+
var TRUTHMARK_COPILOT_CHECK_PROMPT_PATH = ".github/prompts/truthmark-check.prompt.md";
|
|
1219
1346
|
var renderGeminiCommand = (description, prompt) => {
|
|
1220
1347
|
return `description = "${description}"
|
|
1221
1348
|
prompt = '''
|
|
@@ -1223,6 +1350,15 @@ ${prompt}
|
|
|
1223
1350
|
'''
|
|
1224
1351
|
`;
|
|
1225
1352
|
};
|
|
1353
|
+
var renderCopilotPromptFile = (description, prompt) => {
|
|
1354
|
+
return `---
|
|
1355
|
+
agent: 'agent'
|
|
1356
|
+
description: '${description}'
|
|
1357
|
+
---
|
|
1358
|
+
|
|
1359
|
+
${prompt}
|
|
1360
|
+
`;
|
|
1361
|
+
};
|
|
1226
1362
|
var renderTruthmarkStructureSkill = (config = defaultAgentConfig()) => {
|
|
1227
1363
|
return renderTruthStructureSkillBody(config);
|
|
1228
1364
|
};
|
|
@@ -1238,6 +1374,26 @@ var renderTruthmarkStructureSkillMetadata = () => {
|
|
|
1238
1374
|
policy:
|
|
1239
1375
|
allow_implicit_invocation: false
|
|
1240
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
|
+
|
|
1241
1397
|
truthmark:
|
|
1242
1398
|
version: "${TRUTHMARK_VERSION}"
|
|
1243
1399
|
refresh_command: "truthmark init"
|
|
@@ -1252,8 +1408,8 @@ var renderTruthmarkSyncLocalSkill = (config = defaultAgentConfig()) => {
|
|
|
1252
1408
|
var renderTruthmarkSyncSkillMetadata = () => {
|
|
1253
1409
|
return `interface:
|
|
1254
1410
|
display_name: "Truthmark Sync"
|
|
1255
|
-
short_description: "Sync truth docs from
|
|
1256
|
-
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."
|
|
1257
1413
|
|
|
1258
1414
|
policy:
|
|
1259
1415
|
allow_implicit_invocation: true
|
|
@@ -1276,7 +1432,7 @@ truthmark-version: ${TRUTHMARK_VERSION}
|
|
|
1276
1432
|
|
|
1277
1433
|
Use this skill only when the user explicitly asks to realize truth docs into code.
|
|
1278
1434
|
|
|
1279
|
-
Invocations: OpenCode /skill truthmark-realize; Codex /truthmark-realize or $truthmark-realize; Gemini CLI /truthmark:realize.
|
|
1435
|
+
Invocations: OpenCode /skill truthmark-realize; Codex /truthmark-realize or $truthmark-realize; Claude Code /truthmark-realize; GitHub Copilot /truthmark-realize; Gemini CLI /truthmark:realize.
|
|
1280
1436
|
|
|
1281
1437
|
Truth Realize is doc-first:
|
|
1282
1438
|
|
|
@@ -1287,7 +1443,7 @@ Truth Realize is doc-first:
|
|
|
1287
1443
|
Workflow:
|
|
1288
1444
|
|
|
1289
1445
|
1. Read the updated truth docs named by the user, or infer the relevant docs from docs/truthmark/areas.md.
|
|
1290
|
-
2. Read .truthmark/config.yml,
|
|
1446
|
+
2. Read .truthmark/config.yml, docs/truthmark/areas.md, and the relevant functional code.
|
|
1291
1447
|
3. ${EVIDENCE_AUTHORITY_INSTRUCTIONS}
|
|
1292
1448
|
4. Update functional code only so implementation matches the truth docs.
|
|
1293
1449
|
5. Do not edit truth docs or truth routing while realizing those docs.
|
|
@@ -1362,9 +1518,15 @@ var renderTruthmarkGeminiStructureCommand = (config = defaultAgentConfig()) => {
|
|
|
1362
1518
|
renderTruthStructureSkillBody(config)
|
|
1363
1519
|
);
|
|
1364
1520
|
};
|
|
1521
|
+
var renderTruthmarkGeminiDocumentCommand = (config = defaultAgentConfig()) => {
|
|
1522
|
+
return renderGeminiCommand(
|
|
1523
|
+
"Document existing implemented behavior.",
|
|
1524
|
+
renderTruthDocumentSkillBody(config)
|
|
1525
|
+
);
|
|
1526
|
+
};
|
|
1365
1527
|
var renderTruthmarkGeminiSyncCommand = (config = defaultAgentConfig()) => {
|
|
1366
1528
|
return renderGeminiCommand(
|
|
1367
|
-
"Sync repository truth docs from
|
|
1529
|
+
"Sync repository truth docs from functional code changes; skip docs-only/no-code changes.",
|
|
1368
1530
|
renderTruthSyncSkillBody(config)
|
|
1369
1531
|
);
|
|
1370
1532
|
};
|
|
@@ -1380,6 +1542,36 @@ var renderTruthmarkGeminiCheckCommand = (config = defaultAgentConfig()) => {
|
|
|
1380
1542
|
renderTruthCheckSkillBody(config)
|
|
1381
1543
|
);
|
|
1382
1544
|
};
|
|
1545
|
+
var renderTruthmarkCopilotStructurePrompt = (config = defaultAgentConfig()) => {
|
|
1546
|
+
return renderCopilotPromptFile(
|
|
1547
|
+
"Design or repair Truthmark area routing.",
|
|
1548
|
+
renderTruthStructureSkillBody(config)
|
|
1549
|
+
);
|
|
1550
|
+
};
|
|
1551
|
+
var renderTruthmarkCopilotDocumentPrompt = (config = defaultAgentConfig()) => {
|
|
1552
|
+
return renderCopilotPromptFile(
|
|
1553
|
+
"Document existing implemented behavior.",
|
|
1554
|
+
renderTruthDocumentSkillBody(config)
|
|
1555
|
+
);
|
|
1556
|
+
};
|
|
1557
|
+
var renderTruthmarkCopilotSyncPrompt = (config = defaultAgentConfig()) => {
|
|
1558
|
+
return renderCopilotPromptFile(
|
|
1559
|
+
"Sync repository truth docs from functional code changes; skip docs-only/no-code changes.",
|
|
1560
|
+
renderTruthSyncSkillBody(config)
|
|
1561
|
+
);
|
|
1562
|
+
};
|
|
1563
|
+
var renderTruthmarkCopilotRealizePrompt = () => {
|
|
1564
|
+
return renderCopilotPromptFile(
|
|
1565
|
+
"Realize repository truth docs into code.",
|
|
1566
|
+
renderTruthmarkRealizeSkillBody()
|
|
1567
|
+
);
|
|
1568
|
+
};
|
|
1569
|
+
var renderTruthmarkCopilotCheckPrompt = (config = defaultAgentConfig()) => {
|
|
1570
|
+
return renderCopilotPromptFile(
|
|
1571
|
+
"Audit repository truth health.",
|
|
1572
|
+
renderTruthCheckSkillBody(config)
|
|
1573
|
+
);
|
|
1574
|
+
};
|
|
1383
1575
|
|
|
1384
1576
|
// src/templates/default-standards.ts
|
|
1385
1577
|
var DEFAULT_STANDARDS = [
|
|
@@ -1405,8 +1597,10 @@ This is a bootstrap standards baseline for repositories that adopt Truthmark.
|
|
|
1405
1597
|
- Committed repository artifacts are the durable source of truth.
|
|
1406
1598
|
- Each document should have one primary responsibility.
|
|
1407
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.
|
|
1408
1602
|
- Verification should be explicit, and skipped checks should state why.
|
|
1409
|
-
-
|
|
1603
|
+
- Missing, stale, broad, overloaded, or unrouteable documentation topology should be repaired through AI-native structure workflow before agents create more generic truth docs.
|
|
1410
1604
|
- Installed repository workflows should remain usable from committed files even when the Truthmark CLI is unavailable.
|
|
1411
1605
|
`
|
|
1412
1606
|
},
|
|
@@ -1428,12 +1622,13 @@ source_of_truth:
|
|
|
1428
1622
|
- Each class of fact should have one canonical source.
|
|
1429
1623
|
- Current implementation, reusable standards, and future proposals should be stored separately.
|
|
1430
1624
|
- Generated helper output is never canonical truth.
|
|
1625
|
+
- Architecture docs describe structure and ownership; feature docs describe current product behavior.
|
|
1431
1626
|
|
|
1432
1627
|
## Truthmark Implications
|
|
1433
1628
|
|
|
1434
1629
|
- Truth Sync should extend mapped docs first, create an area-local doc second, and create a new area only as a last resort.
|
|
1435
1630
|
- Weak routing produces weak truth maintenance.
|
|
1436
|
-
-
|
|
1631
|
+
- Missing, stale, broad, overloaded, or unrouteable routing should trigger Truth Structure before more generic feature docs are created.
|
|
1437
1632
|
`
|
|
1438
1633
|
}
|
|
1439
1634
|
];
|
|
@@ -1486,26 +1681,33 @@ var removeTrailingManagedChunk = (preservedLines) => {
|
|
|
1486
1681
|
preservedLines.splice(startIndex);
|
|
1487
1682
|
}
|
|
1488
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
|
+
};
|
|
1489
1690
|
var upsertManagedBlock = (existingContent, block) => {
|
|
1490
1691
|
if (!existingContent || existingContent.trim().length === 0) {
|
|
1491
1692
|
return block;
|
|
1492
1693
|
}
|
|
1694
|
+
const normalizedExistingContent = normalizeLegacyInstructionPreamble(existingContent);
|
|
1493
1695
|
const startMarkerPattern = new RegExp(escapeRegExp(TRUTHMARK_BLOCK_START), "g");
|
|
1494
1696
|
const endMarkerPattern = new RegExp(escapeRegExp(TRUTHMARK_BLOCK_END), "g");
|
|
1495
1697
|
const managedBlockPattern = new RegExp(
|
|
1496
1698
|
`${escapeRegExp(TRUTHMARK_BLOCK_START)}[\\s\\S]*?${escapeRegExp(TRUTHMARK_BLOCK_END)}`,
|
|
1497
1699
|
"g"
|
|
1498
1700
|
);
|
|
1499
|
-
const completeBlocks =
|
|
1500
|
-
const startCount =
|
|
1501
|
-
const endCount =
|
|
1701
|
+
const completeBlocks = normalizedExistingContent.match(managedBlockPattern) ?? [];
|
|
1702
|
+
const startCount = normalizedExistingContent.match(startMarkerPattern)?.length ?? 0;
|
|
1703
|
+
const endCount = normalizedExistingContent.match(endMarkerPattern)?.length ?? 0;
|
|
1502
1704
|
if (startCount === 1 && endCount === 1 && completeBlocks.length === 1) {
|
|
1503
|
-
return
|
|
1705
|
+
return normalizedExistingContent.replace(managedBlockPattern, block);
|
|
1504
1706
|
}
|
|
1505
1707
|
const preservedLines = [];
|
|
1506
1708
|
let insideManagedBlock = false;
|
|
1507
1709
|
let managedLines = [];
|
|
1508
|
-
for (const line of
|
|
1710
|
+
for (const line of normalizedExistingContent.split("\n")) {
|
|
1509
1711
|
const trimmedLine = line.trim();
|
|
1510
1712
|
if (trimmedLine === TRUTHMARK_BLOCK_START) {
|
|
1511
1713
|
if (insideManagedBlock && !isManagedChunk(managedLines, 2)) {
|
|
@@ -1546,7 +1748,7 @@ ${block}`;
|
|
|
1546
1748
|
var writeManagedAgentsFile = async (rootDir, path4 = "AGENTS.md", block) => {
|
|
1547
1749
|
let existingContent = null;
|
|
1548
1750
|
try {
|
|
1549
|
-
existingContent = await
|
|
1751
|
+
existingContent = await fs7.readFile(resolveRepoPath(rootDir, path4), "utf8");
|
|
1550
1752
|
} catch (error) {
|
|
1551
1753
|
if (!(error instanceof Error) || !("code" in error) || error.code !== "ENOENT") {
|
|
1552
1754
|
throw error;
|
|
@@ -1558,12 +1760,15 @@ var diagnosticCategoryForPath = (filePath) => {
|
|
|
1558
1760
|
if (filePath === "AGENTS.md") {
|
|
1559
1761
|
return "truth-sync";
|
|
1560
1762
|
}
|
|
1561
|
-
if (filePath === "CLAUDE.md" || filePath === "GEMINI.md" || filePath === ".
|
|
1763
|
+
if (filePath === "CLAUDE.md" || filePath === "GEMINI.md" || filePath === ".github/copilot-instructions.md" || filePath.startsWith(".github/prompts/truthmark-") || filePath.startsWith(".claude/skills/truthmark-") || filePath.startsWith(".opencode/skills/truthmark-")) {
|
|
1562
1764
|
return "truth-sync";
|
|
1563
1765
|
}
|
|
1564
1766
|
if (filePath.startsWith(".codex/skills/truthmark-structure/")) {
|
|
1565
1767
|
return "truth-sync";
|
|
1566
1768
|
}
|
|
1769
|
+
if (filePath.startsWith(".codex/skills/truthmark-document/")) {
|
|
1770
|
+
return "truth-sync";
|
|
1771
|
+
}
|
|
1567
1772
|
if (filePath.startsWith(".codex/skills/truthmark-sync/")) {
|
|
1568
1773
|
return "truth-sync";
|
|
1569
1774
|
}
|
|
@@ -1579,7 +1784,7 @@ var diagnosticCategoryForPath = (filePath) => {
|
|
|
1579
1784
|
if (filePath.startsWith(".codex/skills/truthmark-check/")) {
|
|
1580
1785
|
return "truth-sync";
|
|
1581
1786
|
}
|
|
1582
|
-
if (filePath === "
|
|
1787
|
+
if (filePath === "docs/truthmark/areas.md") {
|
|
1583
1788
|
return "authority";
|
|
1584
1789
|
}
|
|
1585
1790
|
return "config";
|
|
@@ -1590,6 +1795,10 @@ var workflowSkillFiles = (basePath, config) => {
|
|
|
1590
1795
|
path: `${basePath}/truthmark-structure/SKILL.md`,
|
|
1591
1796
|
content: renderTruthmarkStructureLocalSkill(config)
|
|
1592
1797
|
},
|
|
1798
|
+
{
|
|
1799
|
+
path: `${basePath}/truthmark-document/SKILL.md`,
|
|
1800
|
+
content: renderTruthmarkDocumentLocalSkill(config)
|
|
1801
|
+
},
|
|
1593
1802
|
{
|
|
1594
1803
|
path: `${basePath}/truthmark-sync/SKILL.md`,
|
|
1595
1804
|
content: renderTruthmarkSyncLocalSkill(config)
|
|
@@ -1617,6 +1826,14 @@ var codexFiles = (config) => {
|
|
|
1617
1826
|
path: TRUTHMARK_STRUCTURE_SKILL_METADATA_PATH,
|
|
1618
1827
|
content: renderTruthmarkStructureSkillMetadata()
|
|
1619
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
|
+
},
|
|
1620
1837
|
{
|
|
1621
1838
|
path: TRUTHMARK_SYNC_SKILL_PATH,
|
|
1622
1839
|
content: renderTruthmarkSyncSkill(config)
|
|
@@ -1648,6 +1865,34 @@ var codexFiles = (config) => {
|
|
|
1648
1865
|
}
|
|
1649
1866
|
return files;
|
|
1650
1867
|
};
|
|
1868
|
+
var copilotFiles = (config, block) => {
|
|
1869
|
+
const files = [
|
|
1870
|
+
...instructionBlockFiles([".github/copilot-instructions.md"], block),
|
|
1871
|
+
{
|
|
1872
|
+
path: TRUTHMARK_COPILOT_STRUCTURE_PROMPT_PATH,
|
|
1873
|
+
content: renderTruthmarkCopilotStructurePrompt(config)
|
|
1874
|
+
},
|
|
1875
|
+
{
|
|
1876
|
+
path: TRUTHMARK_COPILOT_DOCUMENT_PROMPT_PATH,
|
|
1877
|
+
content: renderTruthmarkCopilotDocumentPrompt(config)
|
|
1878
|
+
},
|
|
1879
|
+
{
|
|
1880
|
+
path: TRUTHMARK_COPILOT_SYNC_PROMPT_PATH,
|
|
1881
|
+
content: renderTruthmarkCopilotSyncPrompt(config)
|
|
1882
|
+
},
|
|
1883
|
+
{
|
|
1884
|
+
path: TRUTHMARK_COPILOT_CHECK_PROMPT_PATH,
|
|
1885
|
+
content: renderTruthmarkCopilotCheckPrompt(config)
|
|
1886
|
+
}
|
|
1887
|
+
];
|
|
1888
|
+
if (config.realization.enabled) {
|
|
1889
|
+
files.push({
|
|
1890
|
+
path: TRUTHMARK_COPILOT_REALIZE_PROMPT_PATH,
|
|
1891
|
+
content: renderTruthmarkCopilotRealizePrompt()
|
|
1892
|
+
});
|
|
1893
|
+
}
|
|
1894
|
+
return files;
|
|
1895
|
+
};
|
|
1651
1896
|
var instructionBlockFiles = (paths, block) => {
|
|
1652
1897
|
return paths.map((path4) => ({
|
|
1653
1898
|
path: path4,
|
|
@@ -1662,11 +1907,12 @@ var filesForPlatform = (platform, config, block) => {
|
|
|
1662
1907
|
case "opencode":
|
|
1663
1908
|
return workflowSkillFiles(".opencode/skills", config);
|
|
1664
1909
|
case "claude-code":
|
|
1665
|
-
return
|
|
1666
|
-
|
|
1667
|
-
|
|
1910
|
+
return [
|
|
1911
|
+
...instructionBlockFiles(["CLAUDE.md"], block),
|
|
1912
|
+
...workflowSkillFiles(".claude/skills", config)
|
|
1913
|
+
];
|
|
1668
1914
|
case "github-copilot":
|
|
1669
|
-
return
|
|
1915
|
+
return copilotFiles(config, block);
|
|
1670
1916
|
case "gemini-cli":
|
|
1671
1917
|
return [
|
|
1672
1918
|
...instructionBlockFiles(["GEMINI.md"], block),
|
|
@@ -1674,6 +1920,10 @@ var filesForPlatform = (platform, config, block) => {
|
|
|
1674
1920
|
path: TRUTHMARK_GEMINI_STRUCTURE_COMMAND_PATH,
|
|
1675
1921
|
content: renderTruthmarkGeminiStructureCommand(config)
|
|
1676
1922
|
},
|
|
1923
|
+
{
|
|
1924
|
+
path: TRUTHMARK_GEMINI_DOCUMENT_COMMAND_PATH,
|
|
1925
|
+
content: renderTruthmarkGeminiDocumentCommand(config)
|
|
1926
|
+
},
|
|
1677
1927
|
{
|
|
1678
1928
|
path: TRUTHMARK_GEMINI_SYNC_COMMAND_PATH,
|
|
1679
1929
|
content: renderTruthmarkGeminiSyncCommand(config)
|
|
@@ -1738,7 +1988,6 @@ var runInit = async (cwd) => {
|
|
|
1738
1988
|
for (const template of defaultStandards) {
|
|
1739
1989
|
results.push(await ensureRepoFile(rootDir, template.path, template.content));
|
|
1740
1990
|
}
|
|
1741
|
-
results.push(await ensureRepoFile(rootDir, "TRUTHMARK.md", renderTruthmarkTemplate()));
|
|
1742
1991
|
const config = loadedConfig.config;
|
|
1743
1992
|
results.push(...await scaffoldHierarchy(rootDir, config));
|
|
1744
1993
|
const migrationDiagnostics = await detectHierarchyMigrationDiagnostics(rootDir, config);
|
|
@@ -1769,7 +2018,7 @@ var runInit = async (cwd) => {
|
|
|
1769
2018
|
};
|
|
1770
2019
|
|
|
1771
2020
|
// src/checks/branch-scope.ts
|
|
1772
|
-
import
|
|
2021
|
+
import fs8 from "fs/promises";
|
|
1773
2022
|
import fg2 from "fast-glob";
|
|
1774
2023
|
|
|
1775
2024
|
// src/markdown/hash.ts
|
|
@@ -1787,7 +2036,7 @@ var BranchScopeFileError = class extends Error {
|
|
|
1787
2036
|
this.file = file;
|
|
1788
2037
|
}
|
|
1789
2038
|
};
|
|
1790
|
-
var RELEVANT_BRANCH_SCOPE_FILES = [".truthmark/config.yml"
|
|
2039
|
+
var RELEVANT_BRANCH_SCOPE_FILES = [".truthmark/config.yml"];
|
|
1791
2040
|
var toBranchIdentity = (branchName, headSha) => {
|
|
1792
2041
|
if (branchName && headSha) {
|
|
1793
2042
|
return `${branchName}@${headSha}`;
|
|
@@ -1824,7 +2073,7 @@ var getBranchScopeData = async (cwd) => {
|
|
|
1824
2073
|
}
|
|
1825
2074
|
for (const relativePath of [...relevantFiles].sort()) {
|
|
1826
2075
|
try {
|
|
1827
|
-
const source = await
|
|
2076
|
+
const source = await fs8.readFile(resolveWorktreePath(repository, relativePath), "utf8");
|
|
1828
2077
|
relevantFileHashes[relativePath] = hashText(source);
|
|
1829
2078
|
} catch (error) {
|
|
1830
2079
|
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
@@ -1841,14 +2090,14 @@ var getBranchScopeData = async (cwd) => {
|
|
|
1841
2090
|
};
|
|
1842
2091
|
|
|
1843
2092
|
// src/checks/authority.ts
|
|
1844
|
-
import
|
|
2093
|
+
import fs9 from "fs/promises";
|
|
1845
2094
|
import fg3 from "fast-glob";
|
|
1846
2095
|
var looksLikeGlob = (pattern) => {
|
|
1847
2096
|
return /[*?[\]{}()!+@]/u.test(pattern);
|
|
1848
2097
|
};
|
|
1849
2098
|
var pathExists = async (absolutePath) => {
|
|
1850
2099
|
try {
|
|
1851
|
-
await
|
|
2100
|
+
await fs9.stat(absolutePath);
|
|
1852
2101
|
return true;
|
|
1853
2102
|
} catch (error) {
|
|
1854
2103
|
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
@@ -1937,7 +2186,7 @@ var checkAuthority = async (rootDir, config) => {
|
|
|
1937
2186
|
};
|
|
1938
2187
|
|
|
1939
2188
|
// src/checks/frontmatter.ts
|
|
1940
|
-
import
|
|
2189
|
+
import fs10 from "fs/promises";
|
|
1941
2190
|
|
|
1942
2191
|
// src/markdown/parse.ts
|
|
1943
2192
|
import matter from "gray-matter";
|
|
@@ -1985,7 +2234,7 @@ var checkFrontmatter = async (rootDir, config, markdownPaths) => {
|
|
|
1985
2234
|
}
|
|
1986
2235
|
const absolutePath = resolveRepoPath(rootDir, markdownPath);
|
|
1987
2236
|
await assertRepoContainment(rootDir, absolutePath);
|
|
1988
|
-
const source = await
|
|
2237
|
+
const source = await fs10.readFile(absolutePath, "utf8");
|
|
1989
2238
|
let document;
|
|
1990
2239
|
try {
|
|
1991
2240
|
document = parseMarkdownDocument(source);
|
|
@@ -2023,11 +2272,11 @@ var checkFrontmatter = async (rootDir, config, markdownPaths) => {
|
|
|
2023
2272
|
};
|
|
2024
2273
|
|
|
2025
2274
|
// src/checks/links.ts
|
|
2026
|
-
import
|
|
2275
|
+
import fs11 from "fs/promises";
|
|
2027
2276
|
import path3 from "path";
|
|
2028
2277
|
var pathExists2 = async (absolutePath) => {
|
|
2029
2278
|
try {
|
|
2030
|
-
await
|
|
2279
|
+
await fs11.stat(absolutePath);
|
|
2031
2280
|
return true;
|
|
2032
2281
|
} catch (error) {
|
|
2033
2282
|
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
@@ -2043,7 +2292,7 @@ var checkLinks = async (rootDir, markdownPaths) => {
|
|
|
2043
2292
|
continue;
|
|
2044
2293
|
}
|
|
2045
2294
|
const absolutePath = resolveRepoPath(rootDir, markdownPath);
|
|
2046
|
-
const source = await
|
|
2295
|
+
const source = await fs11.readFile(absolutePath, "utf8");
|
|
2047
2296
|
let document;
|
|
2048
2297
|
try {
|
|
2049
2298
|
document = parseMarkdownDocument(source);
|
|
@@ -2085,12 +2334,12 @@ var checkLinks = async (rootDir, markdownPaths) => {
|
|
|
2085
2334
|
};
|
|
2086
2335
|
|
|
2087
2336
|
// src/checks/areas.ts
|
|
2088
|
-
import
|
|
2337
|
+
import fs13 from "fs/promises";
|
|
2089
2338
|
import fg5 from "fast-glob";
|
|
2090
2339
|
import micromatch3 from "micromatch";
|
|
2091
2340
|
|
|
2092
2341
|
// src/routing/area-resolver.ts
|
|
2093
|
-
import
|
|
2342
|
+
import fs12 from "fs/promises";
|
|
2094
2343
|
import fg4 from "fast-glob";
|
|
2095
2344
|
import micromatch from "micromatch";
|
|
2096
2345
|
|
|
@@ -2247,7 +2496,7 @@ var ensureChildPath = async (rootDir, areaFilesRoot, filePath) => {
|
|
|
2247
2496
|
var readRouteFile = async (rootDir, filePath) => {
|
|
2248
2497
|
try {
|
|
2249
2498
|
return {
|
|
2250
|
-
source: await
|
|
2499
|
+
source: await fs12.readFile(resolveRepoPath(rootDir, filePath), "utf8"),
|
|
2251
2500
|
diagnostic: null
|
|
2252
2501
|
};
|
|
2253
2502
|
} catch (error) {
|
|
@@ -2520,7 +2769,7 @@ var classifyPath = (filePath, ignorePatterns) => {
|
|
|
2520
2769
|
if (normalizedPath.startsWith(".truthmark/")) {
|
|
2521
2770
|
return "derived";
|
|
2522
2771
|
}
|
|
2523
|
-
if (normalizedPath.startsWith(".
|
|
2772
|
+
if (normalizedPath.startsWith(".claude/") || normalizedPath.startsWith(".codex/") || normalizedPath.startsWith(".gemini/commands/") || normalizedPath.startsWith(".opencode/") || normalizedPath === ".github/copilot-instructions.md" || normalizedPath.startsWith(".github/prompts/truthmark-") || normalizedPath === "AGENTS.md" || normalizedPath === "CLAUDE.md" || normalizedPath === "GEMINI.md" || normalizedPath.startsWith(".gemini/commands/truthmark/")) {
|
|
2524
2773
|
return "derived";
|
|
2525
2774
|
}
|
|
2526
2775
|
if (ignorePatterns.length > 0 && micromatch2.isMatch(normalizedPath, ignorePatterns)) {
|
|
@@ -2547,7 +2796,7 @@ var looksLikeGlob2 = (pattern) => {
|
|
|
2547
2796
|
};
|
|
2548
2797
|
var pathExists3 = async (absolutePath) => {
|
|
2549
2798
|
try {
|
|
2550
|
-
await
|
|
2799
|
+
await fs13.stat(absolutePath);
|
|
2551
2800
|
return true;
|
|
2552
2801
|
} catch (error) {
|
|
2553
2802
|
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
@@ -2816,7 +3065,7 @@ var checkAreas = async (rootDir, config) => {
|
|
|
2816
3065
|
};
|
|
2817
3066
|
|
|
2818
3067
|
// src/checks/decisions.ts
|
|
2819
|
-
import
|
|
3068
|
+
import fs14 from "fs/promises";
|
|
2820
3069
|
import micromatch4 from "micromatch";
|
|
2821
3070
|
var REQUIRED_DECISION_HEADINGS = ["Product Decisions", "Rationale"];
|
|
2822
3071
|
var escapeRegExp2 = (value) => {
|
|
@@ -2839,7 +3088,7 @@ var checkDecisionSections = async (rootDir, config, markdownPaths) => {
|
|
|
2839
3088
|
const diagnostics = [];
|
|
2840
3089
|
const candidatePaths = [...new Set(markdownPaths)].filter((filePath) => isDecisionTruthCandidate(config, filePath)).sort();
|
|
2841
3090
|
for (const filePath of candidatePaths) {
|
|
2842
|
-
const source = await
|
|
3091
|
+
const source = await fs14.readFile(resolveRepoPath(rootDir, filePath), "utf8");
|
|
2843
3092
|
const missingHeadings = REQUIRED_DECISION_HEADINGS.filter((heading) => !hasHeading(source, heading));
|
|
2844
3093
|
if (missingHeadings.length === 0) {
|
|
2845
3094
|
continue;
|
|
@@ -2855,7 +3104,7 @@ var checkDecisionSections = async (rootDir, config, markdownPaths) => {
|
|
|
2855
3104
|
};
|
|
2856
3105
|
|
|
2857
3106
|
// src/checks/generated-surfaces.ts
|
|
2858
|
-
import
|
|
3107
|
+
import fs15 from "fs/promises";
|
|
2859
3108
|
|
|
2860
3109
|
// src/templates/generated-surfaces.ts
|
|
2861
3110
|
var workflowSkillFiles2 = (basePath, config) => {
|
|
@@ -2864,6 +3113,10 @@ var workflowSkillFiles2 = (basePath, config) => {
|
|
|
2864
3113
|
path: `${basePath}/truthmark-structure/SKILL.md`,
|
|
2865
3114
|
content: renderTruthmarkStructureLocalSkill(config)
|
|
2866
3115
|
},
|
|
3116
|
+
{
|
|
3117
|
+
path: `${basePath}/truthmark-document/SKILL.md`,
|
|
3118
|
+
content: renderTruthmarkDocumentLocalSkill(config)
|
|
3119
|
+
},
|
|
2867
3120
|
{
|
|
2868
3121
|
path: `${basePath}/truthmark-sync/SKILL.md`,
|
|
2869
3122
|
content: renderTruthmarkSyncLocalSkill(config)
|
|
@@ -2891,6 +3144,14 @@ var codexFiles2 = (config) => {
|
|
|
2891
3144
|
path: TRUTHMARK_STRUCTURE_SKILL_METADATA_PATH,
|
|
2892
3145
|
content: renderTruthmarkStructureSkillMetadata()
|
|
2893
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
|
+
},
|
|
2894
3155
|
{
|
|
2895
3156
|
path: TRUTHMARK_SYNC_SKILL_PATH,
|
|
2896
3157
|
content: renderTruthmarkSyncSkill(config)
|
|
@@ -2922,6 +3183,34 @@ var codexFiles2 = (config) => {
|
|
|
2922
3183
|
}
|
|
2923
3184
|
return files;
|
|
2924
3185
|
};
|
|
3186
|
+
var copilotFiles2 = (config, block) => {
|
|
3187
|
+
const files = [
|
|
3188
|
+
...instructionBlockFiles2([".github/copilot-instructions.md"], block),
|
|
3189
|
+
{
|
|
3190
|
+
path: TRUTHMARK_COPILOT_STRUCTURE_PROMPT_PATH,
|
|
3191
|
+
content: renderTruthmarkCopilotStructurePrompt(config)
|
|
3192
|
+
},
|
|
3193
|
+
{
|
|
3194
|
+
path: TRUTHMARK_COPILOT_DOCUMENT_PROMPT_PATH,
|
|
3195
|
+
content: renderTruthmarkCopilotDocumentPrompt(config)
|
|
3196
|
+
},
|
|
3197
|
+
{
|
|
3198
|
+
path: TRUTHMARK_COPILOT_SYNC_PROMPT_PATH,
|
|
3199
|
+
content: renderTruthmarkCopilotSyncPrompt(config)
|
|
3200
|
+
},
|
|
3201
|
+
{
|
|
3202
|
+
path: TRUTHMARK_COPILOT_CHECK_PROMPT_PATH,
|
|
3203
|
+
content: renderTruthmarkCopilotCheckPrompt(config)
|
|
3204
|
+
}
|
|
3205
|
+
];
|
|
3206
|
+
if (config.realization.enabled) {
|
|
3207
|
+
files.push({
|
|
3208
|
+
path: TRUTHMARK_COPILOT_REALIZE_PROMPT_PATH,
|
|
3209
|
+
content: renderTruthmarkCopilotRealizePrompt()
|
|
3210
|
+
});
|
|
3211
|
+
}
|
|
3212
|
+
return files;
|
|
3213
|
+
};
|
|
2925
3214
|
var instructionBlockFiles2 = (paths, block) => {
|
|
2926
3215
|
return paths.map((path4) => ({
|
|
2927
3216
|
path: path4,
|
|
@@ -2936,11 +3225,12 @@ var filesForPlatform2 = (platform, config, block) => {
|
|
|
2936
3225
|
case "opencode":
|
|
2937
3226
|
return workflowSkillFiles2(".opencode/skills", config);
|
|
2938
3227
|
case "claude-code":
|
|
2939
|
-
return
|
|
2940
|
-
|
|
2941
|
-
|
|
3228
|
+
return [
|
|
3229
|
+
...instructionBlockFiles2(["CLAUDE.md"], block),
|
|
3230
|
+
...workflowSkillFiles2(".claude/skills", config)
|
|
3231
|
+
];
|
|
2942
3232
|
case "github-copilot":
|
|
2943
|
-
return
|
|
3233
|
+
return copilotFiles2(config, block);
|
|
2944
3234
|
case "gemini-cli":
|
|
2945
3235
|
return [
|
|
2946
3236
|
...instructionBlockFiles2(["GEMINI.md"], block),
|
|
@@ -2948,6 +3238,10 @@ var filesForPlatform2 = (platform, config, block) => {
|
|
|
2948
3238
|
path: TRUTHMARK_GEMINI_STRUCTURE_COMMAND_PATH,
|
|
2949
3239
|
content: renderTruthmarkGeminiStructureCommand(config)
|
|
2950
3240
|
},
|
|
3241
|
+
{
|
|
3242
|
+
path: TRUTHMARK_GEMINI_DOCUMENT_COMMAND_PATH,
|
|
3243
|
+
content: renderTruthmarkGeminiDocumentCommand(config)
|
|
3244
|
+
},
|
|
2951
3245
|
{
|
|
2952
3246
|
path: TRUTHMARK_GEMINI_SYNC_COMMAND_PATH,
|
|
2953
3247
|
content: renderTruthmarkGeminiSyncCommand(config)
|
|
@@ -2978,7 +3272,7 @@ var renderGeneratedSurfaces = (config, block = renderAgentsBlock(config)) => {
|
|
|
2978
3272
|
// src/checks/generated-surfaces.ts
|
|
2979
3273
|
var readOptionalFile = async (rootDir, filePath) => {
|
|
2980
3274
|
try {
|
|
2981
|
-
return await
|
|
3275
|
+
return await fs15.readFile(resolveRepoPath(rootDir, filePath), "utf8");
|
|
2982
3276
|
} catch (error) {
|
|
2983
3277
|
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
2984
3278
|
return null;
|