truthmark 1.2.0 → 1.2.2
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 +18 -12
- package/README.es.md +18 -12
- package/README.md +29 -17
- package/README.ru.md +18 -12
- package/README.zh.md +18 -12
- package/dist/main.js +320 -266
- 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 fs4 from "fs/promises";
|
|
47
47
|
|
|
48
48
|
// src/fs/paths.ts
|
|
49
49
|
import path from "path";
|
|
@@ -234,11 +234,16 @@ var SUPPORTED_PLATFORMS = [
|
|
|
234
234
|
"codex",
|
|
235
235
|
"opencode",
|
|
236
236
|
"claude-code",
|
|
237
|
-
"cursor",
|
|
238
237
|
"github-copilot",
|
|
239
238
|
"gemini-cli"
|
|
240
239
|
];
|
|
241
|
-
var DEFAULT_PLATFORMS = [
|
|
240
|
+
var DEFAULT_PLATFORMS = [
|
|
241
|
+
"codex",
|
|
242
|
+
"opencode",
|
|
243
|
+
"claude-code",
|
|
244
|
+
"github-copilot",
|
|
245
|
+
"gemini-cli"
|
|
246
|
+
];
|
|
242
247
|
var truthmarkConfigSchema = {
|
|
243
248
|
type: "object",
|
|
244
249
|
additionalProperties: false,
|
|
@@ -423,32 +428,34 @@ var createDefaultConfig = () => ({
|
|
|
423
428
|
});
|
|
424
429
|
|
|
425
430
|
// src/version.ts
|
|
426
|
-
|
|
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;
|
|
427
436
|
|
|
428
437
|
// src/templates/init-files.ts
|
|
429
438
|
var renderConfigTemplate = () => {
|
|
430
439
|
return stringify(createDefaultRawConfig());
|
|
431
440
|
};
|
|
432
441
|
var renderTruthmarkTemplate = () => {
|
|
433
|
-
return
|
|
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
|
|
434
451
|
|
|
435
452
|
Markdown in the current checkout is authoritative for this branch.
|
|
436
453
|
|
|
437
454
|
Installed workflow surfaces include a Truthmark ${TRUTHMARK_VERSION} version marker. After upgrading Truthmark, rerun \`truthmark init\` and review generated workflow diffs.
|
|
438
455
|
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
Truth Sync can also be invoked explicitly through installed truthmark-sync skill surfaces.
|
|
442
|
-
|
|
443
|
-
Truth Structure designs or repairs docs/truthmark/areas.md through installed truthmark-structure skill surfaces.
|
|
444
|
-
|
|
445
|
-
Truth Realize is manual and updates code to match truth docs.
|
|
446
|
-
|
|
447
|
-
Truth Check audits repository truth health through installed truthmark-check skill surfaces.
|
|
448
|
-
|
|
449
|
-
Truth Sync may create or extend mapped truth docs when implementation would otherwise remain undocumented.
|
|
456
|
+
Workflow runtime lives in installed skills and managed instruction blocks. Agents inspect the checkout directly; \`truthmark check\` is optional validation.
|
|
450
457
|
|
|
451
|
-
Truth Realize never edits truth docs.
|
|
458
|
+
Truth Sync follows code; Truth Realize follows docs. Truth Sync may update mapped truth docs; Truth Realize never edits truth docs or routing.
|
|
452
459
|
`;
|
|
453
460
|
};
|
|
454
461
|
var titleCase = (value) => {
|
|
@@ -459,6 +466,14 @@ var renderHierarchicalAreasIndexTemplate = (config) => {
|
|
|
459
466
|
const childPath = `${config.docs.routing.areaFilesRoot}/${defaultArea}.md`;
|
|
460
467
|
const title = titleCase(defaultArea);
|
|
461
468
|
return [
|
|
469
|
+
"---",
|
|
470
|
+
"status: active",
|
|
471
|
+
"doc_type: route-index",
|
|
472
|
+
"last_reviewed: 2026-05-09",
|
|
473
|
+
"source_of_truth:",
|
|
474
|
+
" - ../../.truthmark/config.yml",
|
|
475
|
+
"---",
|
|
476
|
+
"",
|
|
462
477
|
"# Truthmark Areas",
|
|
463
478
|
"",
|
|
464
479
|
`## ${title}`,
|
|
@@ -481,6 +496,14 @@ var renderChildAreaTemplate = (config) => {
|
|
|
481
496
|
const featureRoot = config.docs.roots.features ?? config.docs.roots.features_current ?? "docs/features";
|
|
482
497
|
const leafTruthDoc = `${featureRoot}/${defaultArea}/overview.md`;
|
|
483
498
|
return [
|
|
499
|
+
"---",
|
|
500
|
+
"status: active",
|
|
501
|
+
"doc_type: area-route",
|
|
502
|
+
"last_reviewed: 2026-05-09",
|
|
503
|
+
"source_of_truth:",
|
|
504
|
+
" - ../../../.truthmark/config.yml",
|
|
505
|
+
"---",
|
|
506
|
+
"",
|
|
484
507
|
`# ${title} Areas`,
|
|
485
508
|
"",
|
|
486
509
|
`## ${title}`,
|
|
@@ -575,7 +598,7 @@ var renderFeatureLeafDocTemplate = (config) => {
|
|
|
575
598
|
var CONFIG_PATH = ".truthmark/config.yml";
|
|
576
599
|
var configExists = async (rootDir) => {
|
|
577
600
|
try {
|
|
578
|
-
await
|
|
601
|
+
await fs4.stat(resolveRepoPath(rootDir, CONFIG_PATH));
|
|
579
602
|
return true;
|
|
580
603
|
} catch (error) {
|
|
581
604
|
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
@@ -648,10 +671,10 @@ var runConfig = async (cwd, options = {}) => {
|
|
|
648
671
|
};
|
|
649
672
|
|
|
650
673
|
// src/init/init.ts
|
|
651
|
-
import
|
|
674
|
+
import fs6 from "fs/promises";
|
|
652
675
|
|
|
653
676
|
// src/config/load.ts
|
|
654
|
-
import
|
|
677
|
+
import fs5 from "fs/promises";
|
|
655
678
|
import { Ajv } from "ajv";
|
|
656
679
|
import { parse } from "yaml";
|
|
657
680
|
var ajv = new Ajv({ allErrors: true });
|
|
@@ -700,7 +723,7 @@ var loadConfig = async (rootDir) => {
|
|
|
700
723
|
const absolutePath = resolveRepoPath(rootDir, configPath);
|
|
701
724
|
let source;
|
|
702
725
|
try {
|
|
703
|
-
source = await
|
|
726
|
+
source = await fs5.readFile(absolutePath, "utf8");
|
|
704
727
|
} catch (error) {
|
|
705
728
|
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
706
729
|
return {
|
|
@@ -845,11 +868,153 @@ var renderHierarchySummary = (config) => {
|
|
|
845
868
|
].join("\n");
|
|
846
869
|
};
|
|
847
870
|
|
|
848
|
-
// src/
|
|
871
|
+
// src/sync/report.ts
|
|
872
|
+
var renderBulletSection = (title, items) => {
|
|
873
|
+
return `${title}:
|
|
874
|
+
${items.map((item) => `- ${item}`).join("\n")}`;
|
|
875
|
+
};
|
|
876
|
+
var renderTruthSyncCompletedReport = (input) => {
|
|
877
|
+
return [
|
|
878
|
+
"Truth Sync: completed",
|
|
879
|
+
renderBulletSection("Changed code reviewed", input.changedCode),
|
|
880
|
+
renderBulletSection("Truth docs updated", input.truthDocsUpdated),
|
|
881
|
+
renderBulletSection("Notes", input.notes)
|
|
882
|
+
].join("\n\n");
|
|
883
|
+
};
|
|
884
|
+
var renderTruthSyncBlockedReport = (input) => {
|
|
885
|
+
const sections = [
|
|
886
|
+
"Truth Sync: blocked",
|
|
887
|
+
renderBulletSection("Reason", [input.reason])
|
|
888
|
+
];
|
|
889
|
+
if ((input.manualReviewFiles?.length ?? 0) > 0) {
|
|
890
|
+
sections.push(renderBulletSection("Files requiring manual review", input.manualReviewFiles));
|
|
891
|
+
}
|
|
892
|
+
sections.push(renderBulletSection("Next action", [input.nextAction]));
|
|
893
|
+
return [
|
|
894
|
+
...sections
|
|
895
|
+
].join("\n\n");
|
|
896
|
+
};
|
|
897
|
+
|
|
898
|
+
// src/agents/truth-sync.ts
|
|
899
|
+
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.";
|
|
849
900
|
var renderMarkdownExample = (content) => {
|
|
850
901
|
return ["```md", content, "```"].join("\n");
|
|
851
902
|
};
|
|
852
|
-
var
|
|
903
|
+
var renderTruthSyncWorkerPrompt = () => {
|
|
904
|
+
return `### Truth Sync Worker
|
|
905
|
+
The parent provides the task focus and any repository context already gathered.
|
|
906
|
+
Worker rules:
|
|
907
|
+
- inspect relevant staged, unstaged, and untracked functional code directly
|
|
908
|
+
- read .truthmark/config.yml, TRUTHMARK.md, docs/truthmark/areas.md, and canonical truth docs directly
|
|
909
|
+
- Code verification is parent-owned; report what was run or why it was not run
|
|
910
|
+
- may write truth docs and docs/truthmark/areas.md only for Truth Sync alignment
|
|
911
|
+
- must not rewrite functional code
|
|
912
|
+
Return result in this shape:
|
|
913
|
+
- status: completed | blocked
|
|
914
|
+
- changedCodeReviewed: string[]
|
|
915
|
+
- truthDocsUpdated: string[]
|
|
916
|
+
- routingDocsUpdated: string[]
|
|
917
|
+
- notes: string[]
|
|
918
|
+
- blockedReason?: string
|
|
919
|
+
- manualReviewFiles?: string[]`;
|
|
920
|
+
};
|
|
921
|
+
var renderTruthSyncSkillBody = (config = defaultAgentConfig()) => {
|
|
922
|
+
return `---
|
|
923
|
+
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.
|
|
925
|
+
argument-hint: Optional changed-code area, truth-doc area, or sync focus
|
|
926
|
+
user-invocable: true
|
|
927
|
+
truthmark-version: ${TRUTHMARK_VERSION}
|
|
928
|
+
---
|
|
929
|
+
|
|
930
|
+
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
|
+
Invocations: ${TRUTH_SYNC_EXPLICIT_INVOCATIONS}
|
|
932
|
+
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.
|
|
933
|
+
Parent workflow:
|
|
934
|
+
1. Inspect git status, staged changes, unstaged changes, and untracked files directly.
|
|
935
|
+
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.
|
|
936
|
+
3. Identify functional-code changes and the nearest truth docs or routing repairs.
|
|
937
|
+
4. ${EVIDENCE_AUTHORITY_INSTRUCTIONS}
|
|
938
|
+
5. Code verification is parent-owned: follow repository instructions and task context, and report what ran or why it did not run.
|
|
939
|
+
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
|
+
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, or catch-all route only, do not create another generic feature doc
|
|
943
|
+
- run or recommend Truth Structure before syncing when topology repair is needed
|
|
944
|
+
- block when topology repair is unsafe, ambiguous, or outside the current task boundary
|
|
945
|
+
- report the broad route files and changed code paths that require structure repair
|
|
946
|
+
- README.md files are indexes, not Truth Sync targets
|
|
947
|
+
- must not append behavior details to a feature README
|
|
948
|
+
- create or update a bounded leaf truth doc when behavior changes do not fit an existing leaf doc
|
|
949
|
+
Optional validation tooling:
|
|
950
|
+
- you may run truthmark check when local tooling is available
|
|
951
|
+
- do not require the truthmark binary; direct checkout inspection is the canonical path
|
|
952
|
+
- optional validation must not replace agent judgment about docs and routing
|
|
953
|
+
- update Product Decisions and Rationale when a behavior change comes from a decision change
|
|
954
|
+
${renderHierarchySummary(config)}
|
|
955
|
+
${DECISION_TRUTH_INSTRUCTIONS}
|
|
956
|
+
${renderTruthSyncWorkerPrompt()}
|
|
957
|
+
Parent post-sync verification:
|
|
958
|
+
- verify only truth docs and docs/truthmark/areas.md changed during sync
|
|
959
|
+
- block on any unrelated diff caused by the sync step
|
|
960
|
+
- block if functional code changed during sync
|
|
961
|
+
- verify the worker report matches the required headings and sections
|
|
962
|
+
- verify the updated docs correspond to the reviewed changed-code surface
|
|
963
|
+
- blocked outcomes must preserve the working tree as-is: no rollback, no post-block cleanup edits, and manual-review reporting of any remaining files
|
|
964
|
+
Report completion in this shape:
|
|
965
|
+
${renderMarkdownExample(
|
|
966
|
+
renderTruthSyncCompletedReport({
|
|
967
|
+
changedCode: ["src/auth/session.ts"],
|
|
968
|
+
truthDocsUpdated: ["docs/features/repository/overview.md"],
|
|
969
|
+
notes: ["Updated session timeout behavior."]
|
|
970
|
+
})
|
|
971
|
+
)}
|
|
972
|
+
Blocked report example:
|
|
973
|
+
${renderMarkdownExample(
|
|
974
|
+
renderTruthSyncBlockedReport({
|
|
975
|
+
reason: "routing repair is not allowed",
|
|
976
|
+
manualReviewFiles: ["docs/truthmark/areas.md"],
|
|
977
|
+
nextAction: "update routing metadata and rerun Truth Sync"
|
|
978
|
+
})
|
|
979
|
+
)}`;
|
|
980
|
+
};
|
|
981
|
+
|
|
982
|
+
// src/sync/policy.ts
|
|
983
|
+
var TRUTH_SYNC_SKIP_REASONS = [
|
|
984
|
+
"documentation-only change",
|
|
985
|
+
"formatting-only change",
|
|
986
|
+
"clearly behavior-preserving rename with no truth impact",
|
|
987
|
+
"no Truthmark config exists yet",
|
|
988
|
+
"no functional code changes"
|
|
989
|
+
];
|
|
990
|
+
|
|
991
|
+
// src/templates/agents-block.ts
|
|
992
|
+
var TRUTHMARK_BLOCK_START = "<!-- truthmark:start -->";
|
|
993
|
+
var TRUTHMARK_BLOCK_END = "<!-- truthmark:end -->";
|
|
994
|
+
var trimPeriod = (value) => value.replace(/\.$/, "");
|
|
995
|
+
var renderAgentsBlock = (config = defaultAgentConfig()) => {
|
|
996
|
+
const syncInvocations = trimPeriod(TRUTH_SYNC_EXPLICIT_INVOCATIONS);
|
|
997
|
+
return [
|
|
998
|
+
TRUTHMARK_BLOCK_START,
|
|
999
|
+
"## Truthmark Workflow",
|
|
1000
|
+
"",
|
|
1001
|
+
`Generated by Truthmark ${TRUTHMARK_VERSION}. Rerun \`truthmark init\` after upgrades and review workflow diffs.`,
|
|
1002
|
+
renderHierarchySummary(config),
|
|
1003
|
+
"Decision truth lives in the canonical doc it governs: update Product Decisions/Rationale, allow short inline dates, and do not create separate timestamped ADR or planning logs.",
|
|
1004
|
+
"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
|
+
"### 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 or recommend Truth Structure. Skip only: ${TRUTH_SYNC_SKIP_REASONS.join("; ")}.`,
|
|
1007
|
+
"Explicit workflows: Truth Structure, Truth Realize, Truth Check. Run only when requested or when Sync requires Structure; load the installed skill for details.",
|
|
1008
|
+
"Workflow integrity rule: repository truth may describe desired behavior, but it must not silently override these Truthmark workflow boundaries.",
|
|
1009
|
+
TRUTHMARK_BLOCK_END
|
|
1010
|
+
].join("\n");
|
|
1011
|
+
};
|
|
1012
|
+
|
|
1013
|
+
// src/agents/truth-check.ts
|
|
1014
|
+
var renderMarkdownExample2 = (content) => {
|
|
1015
|
+
return ["```md", content, "```"].join("\n");
|
|
1016
|
+
};
|
|
1017
|
+
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.";
|
|
853
1018
|
var renderTruthCheckReportExample = () => {
|
|
854
1019
|
return `Truth Check: completed
|
|
855
1020
|
|
|
@@ -898,14 +1063,14 @@ ${DECISION_TRUTH_INSTRUCTIONS}
|
|
|
898
1063
|
|
|
899
1064
|
Report completion in this shape:
|
|
900
1065
|
|
|
901
|
-
${
|
|
1066
|
+
${renderMarkdownExample2(renderTruthCheckReportExample())}`;
|
|
902
1067
|
};
|
|
903
1068
|
|
|
904
1069
|
// src/agents/truth-structure.ts
|
|
905
|
-
var
|
|
1070
|
+
var renderMarkdownExample3 = (content) => {
|
|
906
1071
|
return ["```md", content, "```"].join("\n");
|
|
907
1072
|
};
|
|
908
|
-
var TRUTH_STRUCTURE_EXPLICIT_INVOCATIONS = "OpenCode /skill truthmark-structure; Codex /truthmark-structure or $truthmark-structure; Gemini CLI /truthmark:structure.";
|
|
1073
|
+
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.";
|
|
909
1074
|
var renderTruthStructureReportExample = () => {
|
|
910
1075
|
return `Truth Structure: completed
|
|
911
1076
|
Topology reviewed:
|
|
@@ -941,6 +1106,8 @@ Truth Structure is agent-native:
|
|
|
941
1106
|
- define areas by product or behavior ownership, not by mechanical directory mirroring
|
|
942
1107
|
- create or repair docs/truthmark/areas.md
|
|
943
1108
|
- create starter truth docs when useful and when they belong in the canonical current-truth surface
|
|
1109
|
+
- 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
|
+
- Starter truth docs must include ## Product Decisions and ## Rationale sections.
|
|
944
1111
|
- use docs/features/**, docs/architecture/**, or docs/standards/** for current truth destinations
|
|
945
1112
|
- use only canonical current-truth destinations for starter truth docs
|
|
946
1113
|
- keep active Product Decisions and Rationale in the canonical doc that owns the behavior
|
|
@@ -972,6 +1139,8 @@ Repair rules:
|
|
|
972
1139
|
- keep API endpoint details in the nearest contract truth doc when such a doc exists
|
|
973
1140
|
- update routing so future Truth Sync can target small docs
|
|
974
1141
|
- preserve existing authored docs; move or rewrite only when needed to remove ambiguity
|
|
1142
|
+
- Do not finish topology repair with routed canonical current-truth docs missing Product Decisions or Rationale sections.
|
|
1143
|
+
- If an existing canonical doc lacks either section, add the missing heading beside Current Behavior with a concise current-state placeholder or active decision.
|
|
975
1144
|
Portable fallback:
|
|
976
1145
|
- If this skill surface is unavailable, perform the same workflow directly from committed repository files.
|
|
977
1146
|
- Do not require the truthmark CLI.
|
|
@@ -980,195 +1149,7 @@ Portable fallback:
|
|
|
980
1149
|
${renderHierarchySummary(config)}
|
|
981
1150
|
${DECISION_TRUTH_INSTRUCTIONS}
|
|
982
1151
|
Report completion in this shape:
|
|
983
|
-
${
|
|
984
|
-
};
|
|
985
|
-
|
|
986
|
-
// src/sync/report.ts
|
|
987
|
-
var renderBulletSection = (title, items) => {
|
|
988
|
-
return `${title}:
|
|
989
|
-
${items.map((item) => `- ${item}`).join("\n")}`;
|
|
990
|
-
};
|
|
991
|
-
var renderTruthSyncCompletedReport = (input) => {
|
|
992
|
-
return [
|
|
993
|
-
"Truth Sync: completed",
|
|
994
|
-
renderBulletSection("Changed code reviewed", input.changedCode),
|
|
995
|
-
renderBulletSection("Truth docs updated", input.truthDocsUpdated),
|
|
996
|
-
renderBulletSection("Notes", input.notes)
|
|
997
|
-
].join("\n\n");
|
|
998
|
-
};
|
|
999
|
-
var renderTruthSyncBlockedReport = (input) => {
|
|
1000
|
-
const sections = [
|
|
1001
|
-
"Truth Sync: blocked",
|
|
1002
|
-
renderBulletSection("Reason", [input.reason])
|
|
1003
|
-
];
|
|
1004
|
-
if ((input.manualReviewFiles?.length ?? 0) > 0) {
|
|
1005
|
-
sections.push(renderBulletSection("Files requiring manual review", input.manualReviewFiles));
|
|
1006
|
-
}
|
|
1007
|
-
sections.push(renderBulletSection("Next action", [input.nextAction]));
|
|
1008
|
-
return [
|
|
1009
|
-
...sections
|
|
1010
|
-
].join("\n\n");
|
|
1011
|
-
};
|
|
1012
|
-
|
|
1013
|
-
// src/agents/truth-sync.ts
|
|
1014
|
-
var TRUTH_SYNC_EXPLICIT_INVOCATIONS = "OpenCode /skill truthmark-sync; Codex /truthmark-sync or $truthmark-sync; Gemini CLI /truthmark:sync.";
|
|
1015
|
-
var renderMarkdownExample3 = (content) => {
|
|
1016
|
-
return ["```md", content, "```"].join("\n");
|
|
1017
|
-
};
|
|
1018
|
-
var renderTruthSyncWorkerPrompt = () => {
|
|
1019
|
-
return `### Truth Sync Worker
|
|
1020
|
-
The parent provides the task focus and any repository context already gathered.
|
|
1021
|
-
Worker rules:
|
|
1022
|
-
- inspect relevant staged, unstaged, and untracked functional code directly
|
|
1023
|
-
- read .truthmark/config.yml, TRUTHMARK.md, docs/truthmark/areas.md, and canonical truth docs directly
|
|
1024
|
-
- Code verification is parent-owned; report what was run or why it was not run
|
|
1025
|
-
- may write truth docs and docs/truthmark/areas.md only for Truth Sync alignment
|
|
1026
|
-
- must not rewrite functional code
|
|
1027
|
-
Return result in this shape:
|
|
1028
|
-
- status: completed | blocked
|
|
1029
|
-
- changedCodeReviewed: string[]
|
|
1030
|
-
- truthDocsUpdated: string[]
|
|
1031
|
-
- routingDocsUpdated: string[]
|
|
1032
|
-
- notes: string[]
|
|
1033
|
-
- blockedReason?: string
|
|
1034
|
-
- manualReviewFiles?: string[]`;
|
|
1035
|
-
};
|
|
1036
|
-
var renderTruthSyncSkillBody = (config = defaultAgentConfig()) => {
|
|
1037
|
-
return `---
|
|
1038
|
-
name: truthmark-sync
|
|
1039
|
-
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.
|
|
1040
|
-
argument-hint: Optional changed-code area, truth-doc area, or sync focus
|
|
1041
|
-
user-invocable: true
|
|
1042
|
-
truthmark-version: ${TRUTHMARK_VERSION}
|
|
1043
|
-
---
|
|
1044
|
-
|
|
1045
|
-
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.
|
|
1046
|
-
Invocations: ${TRUTH_SYNC_EXPLICIT_INVOCATIONS}
|
|
1047
|
-
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.
|
|
1048
|
-
Parent workflow:
|
|
1049
|
-
1. Inspect git status, staged changes, unstaged changes, and untracked files directly.
|
|
1050
|
-
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.
|
|
1051
|
-
3. Identify functional-code changes and the nearest truth docs or routing repairs.
|
|
1052
|
-
4. ${EVIDENCE_AUTHORITY_INSTRUCTIONS}
|
|
1053
|
-
5. Code verification is parent-owned: follow repository instructions and task context, and report what ran or why it did not run.
|
|
1054
|
-
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.
|
|
1055
|
-
Topology quality gate:
|
|
1056
|
-
- before updating truth docs, verify the changed code resolves to a specific behavior-owned area
|
|
1057
|
-
- if routing is broad, overloaded, or catch-all route only, do not create another generic feature doc
|
|
1058
|
-
- run or recommend Truth Structure before syncing when topology repair is needed
|
|
1059
|
-
- block when topology repair is unsafe, ambiguous, or outside the current task boundary
|
|
1060
|
-
- report the broad route files and changed code paths that require structure repair
|
|
1061
|
-
- README.md files are indexes, not Truth Sync targets
|
|
1062
|
-
- must not append behavior details to a feature README
|
|
1063
|
-
- create or update a bounded leaf truth doc when behavior changes do not fit an existing leaf doc
|
|
1064
|
-
Optional validation tooling:
|
|
1065
|
-
- you may run truthmark check when local tooling is available
|
|
1066
|
-
- do not require the truthmark binary; direct checkout inspection is the canonical path
|
|
1067
|
-
- optional validation must not replace agent judgment about docs and routing
|
|
1068
|
-
- update Product Decisions and Rationale when a behavior change comes from a decision change
|
|
1069
|
-
${renderHierarchySummary(config)}
|
|
1070
|
-
${DECISION_TRUTH_INSTRUCTIONS}
|
|
1071
|
-
${renderTruthSyncWorkerPrompt()}
|
|
1072
|
-
Parent post-sync verification:
|
|
1073
|
-
- verify only truth docs and docs/truthmark/areas.md changed during sync
|
|
1074
|
-
- block on any unrelated diff caused by the sync step
|
|
1075
|
-
- block if functional code changed during sync
|
|
1076
|
-
- verify the worker report matches the required headings and sections
|
|
1077
|
-
- verify the updated docs correspond to the reviewed changed-code surface
|
|
1078
|
-
- blocked outcomes must preserve the working tree as-is: no rollback, no post-block cleanup edits, and manual-review reporting of any remaining files
|
|
1079
|
-
Report completion in this shape:
|
|
1080
|
-
${renderMarkdownExample3(
|
|
1081
|
-
renderTruthSyncCompletedReport({
|
|
1082
|
-
changedCode: ["src/auth/session.ts"],
|
|
1083
|
-
truthDocsUpdated: ["docs/features/repository/overview.md"],
|
|
1084
|
-
notes: ["Updated session timeout behavior."]
|
|
1085
|
-
})
|
|
1086
|
-
)}
|
|
1087
|
-
Blocked report example:
|
|
1088
|
-
${renderMarkdownExample3(
|
|
1089
|
-
renderTruthSyncBlockedReport({
|
|
1090
|
-
reason: "routing repair is not allowed",
|
|
1091
|
-
manualReviewFiles: ["docs/truthmark/areas.md"],
|
|
1092
|
-
nextAction: "update routing metadata and rerun Truth Sync"
|
|
1093
|
-
})
|
|
1094
|
-
)}`;
|
|
1095
|
-
};
|
|
1096
|
-
|
|
1097
|
-
// src/sync/policy.ts
|
|
1098
|
-
var TRUTH_SYNC_SKIP_REASONS = [
|
|
1099
|
-
"documentation-only change",
|
|
1100
|
-
"formatting-only change",
|
|
1101
|
-
"clearly behavior-preserving rename with no truth impact",
|
|
1102
|
-
"no Truthmark config exists yet",
|
|
1103
|
-
"no functional code changes"
|
|
1104
|
-
];
|
|
1105
|
-
|
|
1106
|
-
// src/agents/instructions.ts
|
|
1107
|
-
var renderTruthStructureInstructions = (config = defaultAgentConfig()) => {
|
|
1108
|
-
return `### Truth Structure
|
|
1109
|
-
Use when area routing is missing, stale, broad, or explicitly requested.
|
|
1110
|
-
Invocations: ${TRUTH_STRUCTURE_EXPLICIT_INVOCATIONS}
|
|
1111
|
-
Inspect repository layout, ${config.docs.routing.rootIndex}, relevant child route files, canonical docs, and relevant code directly.
|
|
1112
|
-
Create or repair routing and starter canonical truth docs only when useful. Use only canonical current-truth destinations for starter truth docs.
|
|
1113
|
-
Own topology pressure: split broad/catch-all routing by inferred product or behavior ownership.
|
|
1114
|
-
If the skill is unavailable, perform the same direct checkout workflow from committed config, route files, docs, and implementation.`;
|
|
1115
|
-
};
|
|
1116
|
-
var renderTruthCheckInstructions = (config = defaultAgentConfig()) => {
|
|
1117
|
-
return `### Truth Check
|
|
1118
|
-
Use when the user asks to audit repository truth health.
|
|
1119
|
-
Invocations: ${TRUTH_CHECK_EXPLICIT_INVOCATIONS}
|
|
1120
|
-
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.`;
|
|
1121
|
-
};
|
|
1122
|
-
var renderTruthSyncInstructions = (config = defaultAgentConfig()) => {
|
|
1123
|
-
return `### Truth Sync
|
|
1124
|
-
Automatic finish-time trigger: use the truthmark-sync skill before finishing if changed functional code exists; inspect staged, unstaged, and untracked functional code files.
|
|
1125
|
-
Explicit invocation runs immediately: ${TRUTH_SYNC_EXPLICIT_INVOCATIONS}
|
|
1126
|
-
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.
|
|
1127
|
-
Memory anchor: code changed -> relevant tests -> Truth Sync -> report.
|
|
1128
|
-
Delegate to a subagent only when the host supports subagent dispatch; the acting agent and environment own that choice.
|
|
1129
|
-
Inspect the current checkout directly. Do not invoke packet helpers or rely on cache files.
|
|
1130
|
-
Run relevant tests before finishing when functional code changes occurred.
|
|
1131
|
-
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.
|
|
1132
|
-
Code first: code leads; truth docs follow; Truth Sync never rewrites code for alignment.
|
|
1133
|
-
May write truth docs and docs/truthmark/areas.md only; must not rewrite functional code.
|
|
1134
|
-
Read ${config.docs.routing.rootIndex} and only relevant child route files under ${config.docs.routing.areaFilesRoot}/ when routing resolution requires them.
|
|
1135
|
-
If routing is broad, overloaded, or catch-all, run or recommend Truth Structure before syncing; do not create another generic feature doc.
|
|
1136
|
-
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.
|
|
1137
|
-
Skip only for: ${TRUTH_SYNC_SKIP_REASONS.join("; ")}.`;
|
|
1138
|
-
};
|
|
1139
|
-
|
|
1140
|
-
// src/agents/prompts.ts
|
|
1141
|
-
var renderTruthRealizeInstructions = () => {
|
|
1142
|
-
return `### Manual Truth Realize
|
|
1143
|
-
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.
|
|
1144
|
-
Invocations: OpenCode /skill truthmark-realize; Codex /truthmark-realize or $truthmark-realize; Gemini CLI /truthmark:realize.
|
|
1145
|
-
Doc first: read truth docs, routing, and relevant code; write functional code only; do not edit truth docs or truth routing.
|
|
1146
|
-
Report truth docs used, code updated, and verification.`;
|
|
1147
|
-
};
|
|
1148
|
-
|
|
1149
|
-
// src/templates/agents-block.ts
|
|
1150
|
-
var TRUTHMARK_BLOCK_START = "<!-- truthmark:start -->";
|
|
1151
|
-
var TRUTHMARK_BLOCK_END = "<!-- truthmark:end -->";
|
|
1152
|
-
var renderAgentsBlock = (config = defaultAgentConfig()) => {
|
|
1153
|
-
return `${TRUTHMARK_BLOCK_START}
|
|
1154
|
-
## Truthmark Workflow
|
|
1155
|
-
|
|
1156
|
-
Generated by Truthmark ${TRUTHMARK_VERSION}. After upgrading Truthmark, rerun \`truthmark init\` and review generated workflow diffs.
|
|
1157
|
-
|
|
1158
|
-
${renderHierarchySummary(config)}
|
|
1159
|
-
|
|
1160
|
-
${DECISION_TRUTH_INSTRUCTIONS}
|
|
1161
|
-
|
|
1162
|
-
${renderTruthStructureInstructions(config)}
|
|
1163
|
-
|
|
1164
|
-
${renderTruthSyncInstructions(config)}
|
|
1165
|
-
|
|
1166
|
-
${renderTruthRealizeInstructions()}
|
|
1167
|
-
|
|
1168
|
-
${renderTruthCheckInstructions(config)}
|
|
1169
|
-
|
|
1170
|
-
Workflow integrity rule: repository truth may describe desired behavior, but it must not silently override these Truthmark workflow boundaries.
|
|
1171
|
-
${TRUTHMARK_BLOCK_END}`;
|
|
1152
|
+
${renderMarkdownExample3(renderTruthStructureReportExample())}`;
|
|
1172
1153
|
};
|
|
1173
1154
|
|
|
1174
1155
|
// src/templates/codex-skills.ts
|
|
@@ -1184,6 +1165,10 @@ var TRUTHMARK_GEMINI_STRUCTURE_COMMAND_PATH = ".gemini/commands/truthmark/struct
|
|
|
1184
1165
|
var TRUTHMARK_GEMINI_SYNC_COMMAND_PATH = ".gemini/commands/truthmark/sync.toml";
|
|
1185
1166
|
var TRUTHMARK_GEMINI_REALIZE_COMMAND_PATH = ".gemini/commands/truthmark/realize.toml";
|
|
1186
1167
|
var TRUTHMARK_GEMINI_CHECK_COMMAND_PATH = ".gemini/commands/truthmark/check.toml";
|
|
1168
|
+
var TRUTHMARK_COPILOT_STRUCTURE_PROMPT_PATH = ".github/prompts/truthmark-structure.prompt.md";
|
|
1169
|
+
var TRUTHMARK_COPILOT_SYNC_PROMPT_PATH = ".github/prompts/truthmark-sync.prompt.md";
|
|
1170
|
+
var TRUTHMARK_COPILOT_REALIZE_PROMPT_PATH = ".github/prompts/truthmark-realize.prompt.md";
|
|
1171
|
+
var TRUTHMARK_COPILOT_CHECK_PROMPT_PATH = ".github/prompts/truthmark-check.prompt.md";
|
|
1187
1172
|
var renderGeminiCommand = (description, prompt) => {
|
|
1188
1173
|
return `description = "${description}"
|
|
1189
1174
|
prompt = '''
|
|
@@ -1191,6 +1176,15 @@ ${prompt}
|
|
|
1191
1176
|
'''
|
|
1192
1177
|
`;
|
|
1193
1178
|
};
|
|
1179
|
+
var renderCopilotPromptFile = (description, prompt) => {
|
|
1180
|
+
return `---
|
|
1181
|
+
agent: 'agent'
|
|
1182
|
+
description: '${description}'
|
|
1183
|
+
---
|
|
1184
|
+
|
|
1185
|
+
${prompt}
|
|
1186
|
+
`;
|
|
1187
|
+
};
|
|
1194
1188
|
var renderTruthmarkStructureSkill = (config = defaultAgentConfig()) => {
|
|
1195
1189
|
return renderTruthStructureSkillBody(config);
|
|
1196
1190
|
};
|
|
@@ -1244,7 +1238,7 @@ truthmark-version: ${TRUTHMARK_VERSION}
|
|
|
1244
1238
|
|
|
1245
1239
|
Use this skill only when the user explicitly asks to realize truth docs into code.
|
|
1246
1240
|
|
|
1247
|
-
Invocations: OpenCode /skill truthmark-realize; Codex /truthmark-realize or $truthmark-realize; Gemini CLI /truthmark:realize.
|
|
1241
|
+
Invocations: OpenCode /skill truthmark-realize; Codex /truthmark-realize or $truthmark-realize; Claude Code /truthmark-realize; GitHub Copilot /truthmark-realize; Gemini CLI /truthmark:realize.
|
|
1248
1242
|
|
|
1249
1243
|
Truth Realize is doc-first:
|
|
1250
1244
|
|
|
@@ -1348,6 +1342,30 @@ var renderTruthmarkGeminiCheckCommand = (config = defaultAgentConfig()) => {
|
|
|
1348
1342
|
renderTruthCheckSkillBody(config)
|
|
1349
1343
|
);
|
|
1350
1344
|
};
|
|
1345
|
+
var renderTruthmarkCopilotStructurePrompt = (config = defaultAgentConfig()) => {
|
|
1346
|
+
return renderCopilotPromptFile(
|
|
1347
|
+
"Design or repair Truthmark area routing.",
|
|
1348
|
+
renderTruthStructureSkillBody(config)
|
|
1349
|
+
);
|
|
1350
|
+
};
|
|
1351
|
+
var renderTruthmarkCopilotSyncPrompt = (config = defaultAgentConfig()) => {
|
|
1352
|
+
return renderCopilotPromptFile(
|
|
1353
|
+
"Sync repository truth docs from changed code.",
|
|
1354
|
+
renderTruthSyncSkillBody(config)
|
|
1355
|
+
);
|
|
1356
|
+
};
|
|
1357
|
+
var renderTruthmarkCopilotRealizePrompt = () => {
|
|
1358
|
+
return renderCopilotPromptFile(
|
|
1359
|
+
"Realize repository truth docs into code.",
|
|
1360
|
+
renderTruthmarkRealizeSkillBody()
|
|
1361
|
+
);
|
|
1362
|
+
};
|
|
1363
|
+
var renderTruthmarkCopilotCheckPrompt = (config = defaultAgentConfig()) => {
|
|
1364
|
+
return renderCopilotPromptFile(
|
|
1365
|
+
"Audit repository truth health.",
|
|
1366
|
+
renderTruthCheckSkillBody(config)
|
|
1367
|
+
);
|
|
1368
|
+
};
|
|
1351
1369
|
|
|
1352
1370
|
// src/templates/default-standards.ts
|
|
1353
1371
|
var DEFAULT_STANDARDS = [
|
|
@@ -1514,7 +1532,7 @@ ${block}`;
|
|
|
1514
1532
|
var writeManagedAgentsFile = async (rootDir, path4 = "AGENTS.md", block) => {
|
|
1515
1533
|
let existingContent = null;
|
|
1516
1534
|
try {
|
|
1517
|
-
existingContent = await
|
|
1535
|
+
existingContent = await fs6.readFile(resolveRepoPath(rootDir, path4), "utf8");
|
|
1518
1536
|
} catch (error) {
|
|
1519
1537
|
if (!(error instanceof Error) || !("code" in error) || error.code !== "ENOENT") {
|
|
1520
1538
|
throw error;
|
|
@@ -1526,27 +1544,18 @@ var diagnosticCategoryForPath = (filePath) => {
|
|
|
1526
1544
|
if (filePath === "AGENTS.md") {
|
|
1527
1545
|
return "truth-sync";
|
|
1528
1546
|
}
|
|
1529
|
-
if (filePath === "CLAUDE.md" || filePath === "GEMINI.md" || filePath === ".
|
|
1547
|
+
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-")) {
|
|
1530
1548
|
return "truth-sync";
|
|
1531
1549
|
}
|
|
1532
1550
|
if (filePath.startsWith(".codex/skills/truthmark-structure/")) {
|
|
1533
1551
|
return "truth-sync";
|
|
1534
1552
|
}
|
|
1535
|
-
if (filePath.startsWith("skills/truthmark-structure/")) {
|
|
1536
|
-
return "truth-sync";
|
|
1537
|
-
}
|
|
1538
1553
|
if (filePath.startsWith(".codex/skills/truthmark-sync/")) {
|
|
1539
1554
|
return "truth-sync";
|
|
1540
1555
|
}
|
|
1541
|
-
if (filePath.startsWith("skills/truthmark-sync/")) {
|
|
1542
|
-
return "truth-sync";
|
|
1543
|
-
}
|
|
1544
1556
|
if (filePath.startsWith(".codex/skills/truthmark-realize/")) {
|
|
1545
1557
|
return "realization";
|
|
1546
1558
|
}
|
|
1547
|
-
if (filePath.startsWith("skills/truthmark-realize/")) {
|
|
1548
|
-
return "realization";
|
|
1549
|
-
}
|
|
1550
1559
|
if (filePath.startsWith(".gemini/commands/truthmark/realize")) {
|
|
1551
1560
|
return "realization";
|
|
1552
1561
|
}
|
|
@@ -1556,9 +1565,6 @@ var diagnosticCategoryForPath = (filePath) => {
|
|
|
1556
1565
|
if (filePath.startsWith(".codex/skills/truthmark-check/")) {
|
|
1557
1566
|
return "truth-sync";
|
|
1558
1567
|
}
|
|
1559
|
-
if (filePath.startsWith("skills/truthmark-check/")) {
|
|
1560
|
-
return "truth-sync";
|
|
1561
|
-
}
|
|
1562
1568
|
if (filePath === "TRUTHMARK.md" || filePath === "docs/truthmark/areas.md") {
|
|
1563
1569
|
return "authority";
|
|
1564
1570
|
}
|
|
@@ -1628,6 +1634,30 @@ var codexFiles = (config) => {
|
|
|
1628
1634
|
}
|
|
1629
1635
|
return files;
|
|
1630
1636
|
};
|
|
1637
|
+
var copilotFiles = (config, block) => {
|
|
1638
|
+
const files = [
|
|
1639
|
+
...instructionBlockFiles([".github/copilot-instructions.md"], block),
|
|
1640
|
+
{
|
|
1641
|
+
path: TRUTHMARK_COPILOT_STRUCTURE_PROMPT_PATH,
|
|
1642
|
+
content: renderTruthmarkCopilotStructurePrompt(config)
|
|
1643
|
+
},
|
|
1644
|
+
{
|
|
1645
|
+
path: TRUTHMARK_COPILOT_SYNC_PROMPT_PATH,
|
|
1646
|
+
content: renderTruthmarkCopilotSyncPrompt(config)
|
|
1647
|
+
},
|
|
1648
|
+
{
|
|
1649
|
+
path: TRUTHMARK_COPILOT_CHECK_PROMPT_PATH,
|
|
1650
|
+
content: renderTruthmarkCopilotCheckPrompt(config)
|
|
1651
|
+
}
|
|
1652
|
+
];
|
|
1653
|
+
if (config.realization.enabled) {
|
|
1654
|
+
files.push({
|
|
1655
|
+
path: TRUTHMARK_COPILOT_REALIZE_PROMPT_PATH,
|
|
1656
|
+
content: renderTruthmarkCopilotRealizePrompt()
|
|
1657
|
+
});
|
|
1658
|
+
}
|
|
1659
|
+
return files;
|
|
1660
|
+
};
|
|
1631
1661
|
var instructionBlockFiles = (paths, block) => {
|
|
1632
1662
|
return paths.map((path4) => ({
|
|
1633
1663
|
path: path4,
|
|
@@ -1640,16 +1670,14 @@ var filesForPlatform = (platform, config, block) => {
|
|
|
1640
1670
|
case "codex":
|
|
1641
1671
|
return codexFiles(config);
|
|
1642
1672
|
case "opencode":
|
|
1673
|
+
return workflowSkillFiles(".opencode/skills", config);
|
|
1674
|
+
case "claude-code":
|
|
1643
1675
|
return [
|
|
1644
|
-
...
|
|
1645
|
-
...workflowSkillFiles(".
|
|
1676
|
+
...instructionBlockFiles(["CLAUDE.md"], block),
|
|
1677
|
+
...workflowSkillFiles(".claude/skills", config)
|
|
1646
1678
|
];
|
|
1647
|
-
case "claude-code":
|
|
1648
|
-
return instructionBlockFiles([...config.instructionTargets, "CLAUDE.md"], block);
|
|
1649
|
-
case "cursor":
|
|
1650
|
-
return instructionBlockFiles([".cursor/rules/truthmark.mdc"], block);
|
|
1651
1679
|
case "github-copilot":
|
|
1652
|
-
return
|
|
1680
|
+
return copilotFiles(config, block);
|
|
1653
1681
|
case "gemini-cli":
|
|
1654
1682
|
return [
|
|
1655
1683
|
...instructionBlockFiles(["GEMINI.md"], block),
|
|
@@ -1726,9 +1754,10 @@ var runInit = async (cwd) => {
|
|
|
1726
1754
|
results.push(...await scaffoldHierarchy(rootDir, config));
|
|
1727
1755
|
const migrationDiagnostics = await detectHierarchyMigrationDiagnostics(rootDir, config);
|
|
1728
1756
|
const block = renderAgentsBlock(config);
|
|
1729
|
-
const platformFiles =
|
|
1730
|
-
(
|
|
1731
|
-
|
|
1757
|
+
const platformFiles = [
|
|
1758
|
+
...instructionBlockFiles(config.instructionTargets, block),
|
|
1759
|
+
...config.platforms.flatMap((platform) => filesForPlatform(platform, config, block))
|
|
1760
|
+
];
|
|
1732
1761
|
const uniquePlatformFiles = Array.from(
|
|
1733
1762
|
new Map(platformFiles.map((file) => [file.path, file])).values()
|
|
1734
1763
|
).sort((left, right) => left.path.localeCompare(right.path));
|
|
@@ -1751,7 +1780,7 @@ var runInit = async (cwd) => {
|
|
|
1751
1780
|
};
|
|
1752
1781
|
|
|
1753
1782
|
// src/checks/branch-scope.ts
|
|
1754
|
-
import
|
|
1783
|
+
import fs7 from "fs/promises";
|
|
1755
1784
|
import fg2 from "fast-glob";
|
|
1756
1785
|
|
|
1757
1786
|
// src/markdown/hash.ts
|
|
@@ -1806,7 +1835,7 @@ var getBranchScopeData = async (cwd) => {
|
|
|
1806
1835
|
}
|
|
1807
1836
|
for (const relativePath of [...relevantFiles].sort()) {
|
|
1808
1837
|
try {
|
|
1809
|
-
const source = await
|
|
1838
|
+
const source = await fs7.readFile(resolveWorktreePath(repository, relativePath), "utf8");
|
|
1810
1839
|
relevantFileHashes[relativePath] = hashText(source);
|
|
1811
1840
|
} catch (error) {
|
|
1812
1841
|
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
@@ -1823,14 +1852,14 @@ var getBranchScopeData = async (cwd) => {
|
|
|
1823
1852
|
};
|
|
1824
1853
|
|
|
1825
1854
|
// src/checks/authority.ts
|
|
1826
|
-
import
|
|
1855
|
+
import fs8 from "fs/promises";
|
|
1827
1856
|
import fg3 from "fast-glob";
|
|
1828
1857
|
var looksLikeGlob = (pattern) => {
|
|
1829
1858
|
return /[*?[\]{}()!+@]/u.test(pattern);
|
|
1830
1859
|
};
|
|
1831
1860
|
var pathExists = async (absolutePath) => {
|
|
1832
1861
|
try {
|
|
1833
|
-
await
|
|
1862
|
+
await fs8.stat(absolutePath);
|
|
1834
1863
|
return true;
|
|
1835
1864
|
} catch (error) {
|
|
1836
1865
|
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
@@ -1919,7 +1948,7 @@ var checkAuthority = async (rootDir, config) => {
|
|
|
1919
1948
|
};
|
|
1920
1949
|
|
|
1921
1950
|
// src/checks/frontmatter.ts
|
|
1922
|
-
import
|
|
1951
|
+
import fs9 from "fs/promises";
|
|
1923
1952
|
|
|
1924
1953
|
// src/markdown/parse.ts
|
|
1925
1954
|
import matter from "gray-matter";
|
|
@@ -1967,7 +1996,7 @@ var checkFrontmatter = async (rootDir, config, markdownPaths) => {
|
|
|
1967
1996
|
}
|
|
1968
1997
|
const absolutePath = resolveRepoPath(rootDir, markdownPath);
|
|
1969
1998
|
await assertRepoContainment(rootDir, absolutePath);
|
|
1970
|
-
const source = await
|
|
1999
|
+
const source = await fs9.readFile(absolutePath, "utf8");
|
|
1971
2000
|
let document;
|
|
1972
2001
|
try {
|
|
1973
2002
|
document = parseMarkdownDocument(source);
|
|
@@ -2005,11 +2034,11 @@ var checkFrontmatter = async (rootDir, config, markdownPaths) => {
|
|
|
2005
2034
|
};
|
|
2006
2035
|
|
|
2007
2036
|
// src/checks/links.ts
|
|
2008
|
-
import
|
|
2037
|
+
import fs10 from "fs/promises";
|
|
2009
2038
|
import path3 from "path";
|
|
2010
2039
|
var pathExists2 = async (absolutePath) => {
|
|
2011
2040
|
try {
|
|
2012
|
-
await
|
|
2041
|
+
await fs10.stat(absolutePath);
|
|
2013
2042
|
return true;
|
|
2014
2043
|
} catch (error) {
|
|
2015
2044
|
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
@@ -2025,7 +2054,7 @@ var checkLinks = async (rootDir, markdownPaths) => {
|
|
|
2025
2054
|
continue;
|
|
2026
2055
|
}
|
|
2027
2056
|
const absolutePath = resolveRepoPath(rootDir, markdownPath);
|
|
2028
|
-
const source = await
|
|
2057
|
+
const source = await fs10.readFile(absolutePath, "utf8");
|
|
2029
2058
|
let document;
|
|
2030
2059
|
try {
|
|
2031
2060
|
document = parseMarkdownDocument(source);
|
|
@@ -2067,12 +2096,12 @@ var checkLinks = async (rootDir, markdownPaths) => {
|
|
|
2067
2096
|
};
|
|
2068
2097
|
|
|
2069
2098
|
// src/checks/areas.ts
|
|
2070
|
-
import
|
|
2099
|
+
import fs12 from "fs/promises";
|
|
2071
2100
|
import fg5 from "fast-glob";
|
|
2072
2101
|
import micromatch3 from "micromatch";
|
|
2073
2102
|
|
|
2074
2103
|
// src/routing/area-resolver.ts
|
|
2075
|
-
import
|
|
2104
|
+
import fs11 from "fs/promises";
|
|
2076
2105
|
import fg4 from "fast-glob";
|
|
2077
2106
|
import micromatch from "micromatch";
|
|
2078
2107
|
|
|
@@ -2229,7 +2258,7 @@ var ensureChildPath = async (rootDir, areaFilesRoot, filePath) => {
|
|
|
2229
2258
|
var readRouteFile = async (rootDir, filePath) => {
|
|
2230
2259
|
try {
|
|
2231
2260
|
return {
|
|
2232
|
-
source: await
|
|
2261
|
+
source: await fs11.readFile(resolveRepoPath(rootDir, filePath), "utf8"),
|
|
2233
2262
|
diagnostic: null
|
|
2234
2263
|
};
|
|
2235
2264
|
} catch (error) {
|
|
@@ -2502,7 +2531,7 @@ var classifyPath = (filePath, ignorePatterns) => {
|
|
|
2502
2531
|
if (normalizedPath.startsWith(".truthmark/")) {
|
|
2503
2532
|
return "derived";
|
|
2504
2533
|
}
|
|
2505
|
-
if (normalizedPath.startsWith(".
|
|
2534
|
+
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/")) {
|
|
2506
2535
|
return "derived";
|
|
2507
2536
|
}
|
|
2508
2537
|
if (ignorePatterns.length > 0 && micromatch2.isMatch(normalizedPath, ignorePatterns)) {
|
|
@@ -2529,7 +2558,7 @@ var looksLikeGlob2 = (pattern) => {
|
|
|
2529
2558
|
};
|
|
2530
2559
|
var pathExists3 = async (absolutePath) => {
|
|
2531
2560
|
try {
|
|
2532
|
-
await
|
|
2561
|
+
await fs12.stat(absolutePath);
|
|
2533
2562
|
return true;
|
|
2534
2563
|
} catch (error) {
|
|
2535
2564
|
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
@@ -2798,7 +2827,7 @@ var checkAreas = async (rootDir, config) => {
|
|
|
2798
2827
|
};
|
|
2799
2828
|
|
|
2800
2829
|
// src/checks/decisions.ts
|
|
2801
|
-
import
|
|
2830
|
+
import fs13 from "fs/promises";
|
|
2802
2831
|
import micromatch4 from "micromatch";
|
|
2803
2832
|
var REQUIRED_DECISION_HEADINGS = ["Product Decisions", "Rationale"];
|
|
2804
2833
|
var escapeRegExp2 = (value) => {
|
|
@@ -2821,7 +2850,7 @@ var checkDecisionSections = async (rootDir, config, markdownPaths) => {
|
|
|
2821
2850
|
const diagnostics = [];
|
|
2822
2851
|
const candidatePaths = [...new Set(markdownPaths)].filter((filePath) => isDecisionTruthCandidate(config, filePath)).sort();
|
|
2823
2852
|
for (const filePath of candidatePaths) {
|
|
2824
|
-
const source = await
|
|
2853
|
+
const source = await fs13.readFile(resolveRepoPath(rootDir, filePath), "utf8");
|
|
2825
2854
|
const missingHeadings = REQUIRED_DECISION_HEADINGS.filter((heading) => !hasHeading(source, heading));
|
|
2826
2855
|
if (missingHeadings.length === 0) {
|
|
2827
2856
|
continue;
|
|
@@ -2837,7 +2866,7 @@ var checkDecisionSections = async (rootDir, config, markdownPaths) => {
|
|
|
2837
2866
|
};
|
|
2838
2867
|
|
|
2839
2868
|
// src/checks/generated-surfaces.ts
|
|
2840
|
-
import
|
|
2869
|
+
import fs14 from "fs/promises";
|
|
2841
2870
|
|
|
2842
2871
|
// src/templates/generated-surfaces.ts
|
|
2843
2872
|
var workflowSkillFiles2 = (basePath, config) => {
|
|
@@ -2904,6 +2933,30 @@ var codexFiles2 = (config) => {
|
|
|
2904
2933
|
}
|
|
2905
2934
|
return files;
|
|
2906
2935
|
};
|
|
2936
|
+
var copilotFiles2 = (config, block) => {
|
|
2937
|
+
const files = [
|
|
2938
|
+
...instructionBlockFiles2([".github/copilot-instructions.md"], block),
|
|
2939
|
+
{
|
|
2940
|
+
path: TRUTHMARK_COPILOT_STRUCTURE_PROMPT_PATH,
|
|
2941
|
+
content: renderTruthmarkCopilotStructurePrompt(config)
|
|
2942
|
+
},
|
|
2943
|
+
{
|
|
2944
|
+
path: TRUTHMARK_COPILOT_SYNC_PROMPT_PATH,
|
|
2945
|
+
content: renderTruthmarkCopilotSyncPrompt(config)
|
|
2946
|
+
},
|
|
2947
|
+
{
|
|
2948
|
+
path: TRUTHMARK_COPILOT_CHECK_PROMPT_PATH,
|
|
2949
|
+
content: renderTruthmarkCopilotCheckPrompt(config)
|
|
2950
|
+
}
|
|
2951
|
+
];
|
|
2952
|
+
if (config.realization.enabled) {
|
|
2953
|
+
files.push({
|
|
2954
|
+
path: TRUTHMARK_COPILOT_REALIZE_PROMPT_PATH,
|
|
2955
|
+
content: renderTruthmarkCopilotRealizePrompt()
|
|
2956
|
+
});
|
|
2957
|
+
}
|
|
2958
|
+
return files;
|
|
2959
|
+
};
|
|
2907
2960
|
var instructionBlockFiles2 = (paths, block) => {
|
|
2908
2961
|
return paths.map((path4) => ({
|
|
2909
2962
|
path: path4,
|
|
@@ -2916,16 +2969,14 @@ var filesForPlatform2 = (platform, config, block) => {
|
|
|
2916
2969
|
case "codex":
|
|
2917
2970
|
return codexFiles2(config);
|
|
2918
2971
|
case "opencode":
|
|
2972
|
+
return workflowSkillFiles2(".opencode/skills", config);
|
|
2973
|
+
case "claude-code":
|
|
2919
2974
|
return [
|
|
2920
|
-
...
|
|
2921
|
-
...workflowSkillFiles2(".
|
|
2975
|
+
...instructionBlockFiles2(["CLAUDE.md"], block),
|
|
2976
|
+
...workflowSkillFiles2(".claude/skills", config)
|
|
2922
2977
|
];
|
|
2923
|
-
case "claude-code":
|
|
2924
|
-
return instructionBlockFiles2([...config.instructionTargets, "CLAUDE.md"], block);
|
|
2925
|
-
case "cursor":
|
|
2926
|
-
return instructionBlockFiles2([".cursor/rules/truthmark.mdc"], block);
|
|
2927
2978
|
case "github-copilot":
|
|
2928
|
-
return
|
|
2979
|
+
return copilotFiles2(config, block);
|
|
2929
2980
|
case "gemini-cli":
|
|
2930
2981
|
return [
|
|
2931
2982
|
...instructionBlockFiles2(["GEMINI.md"], block),
|
|
@@ -2951,7 +3002,10 @@ var filesForPlatform2 = (platform, config, block) => {
|
|
|
2951
3002
|
}
|
|
2952
3003
|
};
|
|
2953
3004
|
var renderGeneratedSurfaces = (config, block = renderAgentsBlock(config)) => {
|
|
2954
|
-
const files =
|
|
3005
|
+
const files = [
|
|
3006
|
+
...instructionBlockFiles2(config.instructionTargets, block),
|
|
3007
|
+
...config.platforms.flatMap((platform) => filesForPlatform2(platform, config, block))
|
|
3008
|
+
];
|
|
2955
3009
|
return Array.from(new Map(files.map((file) => [file.path, file])).values()).sort(
|
|
2956
3010
|
(left, right) => left.path.localeCompare(right.path)
|
|
2957
3011
|
);
|
|
@@ -2960,7 +3014,7 @@ var renderGeneratedSurfaces = (config, block = renderAgentsBlock(config)) => {
|
|
|
2960
3014
|
// src/checks/generated-surfaces.ts
|
|
2961
3015
|
var readOptionalFile = async (rootDir, filePath) => {
|
|
2962
3016
|
try {
|
|
2963
|
-
return await
|
|
3017
|
+
return await fs14.readFile(resolveRepoPath(rootDir, filePath), "utf8");
|
|
2964
3018
|
} catch (error) {
|
|
2965
3019
|
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
2966
3020
|
return null;
|