truthmark 1.2.0 → 1.2.1
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 +21 -7
- package/README.es.md +21 -7
- package/README.md +31 -13
- package/README.ru.md +22 -8
- package/README.zh.md +21 -7
- package/dist/main.js +70 -52
- 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";
|
|
@@ -423,14 +423,26 @@ var createDefaultConfig = () => ({
|
|
|
423
423
|
});
|
|
424
424
|
|
|
425
425
|
// src/version.ts
|
|
426
|
-
|
|
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;
|
|
427
431
|
|
|
428
432
|
// src/templates/init-files.ts
|
|
429
433
|
var renderConfigTemplate = () => {
|
|
430
434
|
return stringify(createDefaultRawConfig());
|
|
431
435
|
};
|
|
432
436
|
var renderTruthmarkTemplate = () => {
|
|
433
|
-
return
|
|
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
|
|
434
446
|
|
|
435
447
|
Markdown in the current checkout is authoritative for this branch.
|
|
436
448
|
|
|
@@ -459,6 +471,14 @@ var renderHierarchicalAreasIndexTemplate = (config) => {
|
|
|
459
471
|
const childPath = `${config.docs.routing.areaFilesRoot}/${defaultArea}.md`;
|
|
460
472
|
const title = titleCase(defaultArea);
|
|
461
473
|
return [
|
|
474
|
+
"---",
|
|
475
|
+
"status: active",
|
|
476
|
+
"doc_type: route-index",
|
|
477
|
+
"last_reviewed: 2026-05-09",
|
|
478
|
+
"source_of_truth:",
|
|
479
|
+
" - ../../.truthmark/config.yml",
|
|
480
|
+
"---",
|
|
481
|
+
"",
|
|
462
482
|
"# Truthmark Areas",
|
|
463
483
|
"",
|
|
464
484
|
`## ${title}`,
|
|
@@ -481,6 +501,14 @@ var renderChildAreaTemplate = (config) => {
|
|
|
481
501
|
const featureRoot = config.docs.roots.features ?? config.docs.roots.features_current ?? "docs/features";
|
|
482
502
|
const leafTruthDoc = `${featureRoot}/${defaultArea}/overview.md`;
|
|
483
503
|
return [
|
|
504
|
+
"---",
|
|
505
|
+
"status: active",
|
|
506
|
+
"doc_type: area-route",
|
|
507
|
+
"last_reviewed: 2026-05-09",
|
|
508
|
+
"source_of_truth:",
|
|
509
|
+
" - ../../../.truthmark/config.yml",
|
|
510
|
+
"---",
|
|
511
|
+
"",
|
|
484
512
|
`# ${title} Areas`,
|
|
485
513
|
"",
|
|
486
514
|
`## ${title}`,
|
|
@@ -575,7 +603,7 @@ var renderFeatureLeafDocTemplate = (config) => {
|
|
|
575
603
|
var CONFIG_PATH = ".truthmark/config.yml";
|
|
576
604
|
var configExists = async (rootDir) => {
|
|
577
605
|
try {
|
|
578
|
-
await
|
|
606
|
+
await fs4.stat(resolveRepoPath(rootDir, CONFIG_PATH));
|
|
579
607
|
return true;
|
|
580
608
|
} catch (error) {
|
|
581
609
|
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
@@ -648,10 +676,10 @@ var runConfig = async (cwd, options = {}) => {
|
|
|
648
676
|
};
|
|
649
677
|
|
|
650
678
|
// src/init/init.ts
|
|
651
|
-
import
|
|
679
|
+
import fs6 from "fs/promises";
|
|
652
680
|
|
|
653
681
|
// src/config/load.ts
|
|
654
|
-
import
|
|
682
|
+
import fs5 from "fs/promises";
|
|
655
683
|
import { Ajv } from "ajv";
|
|
656
684
|
import { parse } from "yaml";
|
|
657
685
|
var ajv = new Ajv({ allErrors: true });
|
|
@@ -700,7 +728,7 @@ var loadConfig = async (rootDir) => {
|
|
|
700
728
|
const absolutePath = resolveRepoPath(rootDir, configPath);
|
|
701
729
|
let source;
|
|
702
730
|
try {
|
|
703
|
-
source = await
|
|
731
|
+
source = await fs5.readFile(absolutePath, "utf8");
|
|
704
732
|
} catch (error) {
|
|
705
733
|
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
706
734
|
return {
|
|
@@ -941,6 +969,8 @@ Truth Structure is agent-native:
|
|
|
941
969
|
- define areas by product or behavior ownership, not by mechanical directory mirroring
|
|
942
970
|
- create or repair docs/truthmark/areas.md
|
|
943
971
|
- create starter truth docs when useful and when they belong in the canonical current-truth surface
|
|
972
|
+
- 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
|
+
- Starter truth docs must include ## Product Decisions and ## Rationale sections.
|
|
944
974
|
- use docs/features/**, docs/architecture/**, or docs/standards/** for current truth destinations
|
|
945
975
|
- use only canonical current-truth destinations for starter truth docs
|
|
946
976
|
- keep active Product Decisions and Rationale in the canonical doc that owns the behavior
|
|
@@ -972,6 +1002,8 @@ Repair rules:
|
|
|
972
1002
|
- keep API endpoint details in the nearest contract truth doc when such a doc exists
|
|
973
1003
|
- update routing so future Truth Sync can target small docs
|
|
974
1004
|
- preserve existing authored docs; move or rewrite only when needed to remove ambiguity
|
|
1005
|
+
- Do not finish topology repair with routed canonical current-truth docs missing Product Decisions or Rationale sections.
|
|
1006
|
+
- 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
1007
|
Portable fallback:
|
|
976
1008
|
- If this skill surface is unavailable, perform the same workflow directly from committed repository files.
|
|
977
1009
|
- Do not require the truthmark CLI.
|
|
@@ -1514,7 +1546,7 @@ ${block}`;
|
|
|
1514
1546
|
var writeManagedAgentsFile = async (rootDir, path4 = "AGENTS.md", block) => {
|
|
1515
1547
|
let existingContent = null;
|
|
1516
1548
|
try {
|
|
1517
|
-
existingContent = await
|
|
1549
|
+
existingContent = await fs6.readFile(resolveRepoPath(rootDir, path4), "utf8");
|
|
1518
1550
|
} catch (error) {
|
|
1519
1551
|
if (!(error instanceof Error) || !("code" in error) || error.code !== "ENOENT") {
|
|
1520
1552
|
throw error;
|
|
@@ -1532,21 +1564,12 @@ var diagnosticCategoryForPath = (filePath) => {
|
|
|
1532
1564
|
if (filePath.startsWith(".codex/skills/truthmark-structure/")) {
|
|
1533
1565
|
return "truth-sync";
|
|
1534
1566
|
}
|
|
1535
|
-
if (filePath.startsWith("skills/truthmark-structure/")) {
|
|
1536
|
-
return "truth-sync";
|
|
1537
|
-
}
|
|
1538
1567
|
if (filePath.startsWith(".codex/skills/truthmark-sync/")) {
|
|
1539
1568
|
return "truth-sync";
|
|
1540
1569
|
}
|
|
1541
|
-
if (filePath.startsWith("skills/truthmark-sync/")) {
|
|
1542
|
-
return "truth-sync";
|
|
1543
|
-
}
|
|
1544
1570
|
if (filePath.startsWith(".codex/skills/truthmark-realize/")) {
|
|
1545
1571
|
return "realization";
|
|
1546
1572
|
}
|
|
1547
|
-
if (filePath.startsWith("skills/truthmark-realize/")) {
|
|
1548
|
-
return "realization";
|
|
1549
|
-
}
|
|
1550
1573
|
if (filePath.startsWith(".gemini/commands/truthmark/realize")) {
|
|
1551
1574
|
return "realization";
|
|
1552
1575
|
}
|
|
@@ -1556,9 +1579,6 @@ var diagnosticCategoryForPath = (filePath) => {
|
|
|
1556
1579
|
if (filePath.startsWith(".codex/skills/truthmark-check/")) {
|
|
1557
1580
|
return "truth-sync";
|
|
1558
1581
|
}
|
|
1559
|
-
if (filePath.startsWith("skills/truthmark-check/")) {
|
|
1560
|
-
return "truth-sync";
|
|
1561
|
-
}
|
|
1562
1582
|
if (filePath === "TRUTHMARK.md" || filePath === "docs/truthmark/areas.md") {
|
|
1563
1583
|
return "authority";
|
|
1564
1584
|
}
|
|
@@ -1640,12 +1660,9 @@ var filesForPlatform = (platform, config, block) => {
|
|
|
1640
1660
|
case "codex":
|
|
1641
1661
|
return codexFiles(config);
|
|
1642
1662
|
case "opencode":
|
|
1643
|
-
return
|
|
1644
|
-
...workflowSkillFiles("skills", config),
|
|
1645
|
-
...workflowSkillFiles(".opencode/skills", config)
|
|
1646
|
-
];
|
|
1663
|
+
return workflowSkillFiles(".opencode/skills", config);
|
|
1647
1664
|
case "claude-code":
|
|
1648
|
-
return instructionBlockFiles([
|
|
1665
|
+
return instructionBlockFiles(["CLAUDE.md"], block);
|
|
1649
1666
|
case "cursor":
|
|
1650
1667
|
return instructionBlockFiles([".cursor/rules/truthmark.mdc"], block);
|
|
1651
1668
|
case "github-copilot":
|
|
@@ -1726,9 +1743,10 @@ var runInit = async (cwd) => {
|
|
|
1726
1743
|
results.push(...await scaffoldHierarchy(rootDir, config));
|
|
1727
1744
|
const migrationDiagnostics = await detectHierarchyMigrationDiagnostics(rootDir, config);
|
|
1728
1745
|
const block = renderAgentsBlock(config);
|
|
1729
|
-
const platformFiles =
|
|
1730
|
-
(
|
|
1731
|
-
|
|
1746
|
+
const platformFiles = [
|
|
1747
|
+
...instructionBlockFiles(config.instructionTargets, block),
|
|
1748
|
+
...config.platforms.flatMap((platform) => filesForPlatform(platform, config, block))
|
|
1749
|
+
];
|
|
1732
1750
|
const uniquePlatformFiles = Array.from(
|
|
1733
1751
|
new Map(platformFiles.map((file) => [file.path, file])).values()
|
|
1734
1752
|
).sort((left, right) => left.path.localeCompare(right.path));
|
|
@@ -1751,7 +1769,7 @@ var runInit = async (cwd) => {
|
|
|
1751
1769
|
};
|
|
1752
1770
|
|
|
1753
1771
|
// src/checks/branch-scope.ts
|
|
1754
|
-
import
|
|
1772
|
+
import fs7 from "fs/promises";
|
|
1755
1773
|
import fg2 from "fast-glob";
|
|
1756
1774
|
|
|
1757
1775
|
// src/markdown/hash.ts
|
|
@@ -1806,7 +1824,7 @@ var getBranchScopeData = async (cwd) => {
|
|
|
1806
1824
|
}
|
|
1807
1825
|
for (const relativePath of [...relevantFiles].sort()) {
|
|
1808
1826
|
try {
|
|
1809
|
-
const source = await
|
|
1827
|
+
const source = await fs7.readFile(resolveWorktreePath(repository, relativePath), "utf8");
|
|
1810
1828
|
relevantFileHashes[relativePath] = hashText(source);
|
|
1811
1829
|
} catch (error) {
|
|
1812
1830
|
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
@@ -1823,14 +1841,14 @@ var getBranchScopeData = async (cwd) => {
|
|
|
1823
1841
|
};
|
|
1824
1842
|
|
|
1825
1843
|
// src/checks/authority.ts
|
|
1826
|
-
import
|
|
1844
|
+
import fs8 from "fs/promises";
|
|
1827
1845
|
import fg3 from "fast-glob";
|
|
1828
1846
|
var looksLikeGlob = (pattern) => {
|
|
1829
1847
|
return /[*?[\]{}()!+@]/u.test(pattern);
|
|
1830
1848
|
};
|
|
1831
1849
|
var pathExists = async (absolutePath) => {
|
|
1832
1850
|
try {
|
|
1833
|
-
await
|
|
1851
|
+
await fs8.stat(absolutePath);
|
|
1834
1852
|
return true;
|
|
1835
1853
|
} catch (error) {
|
|
1836
1854
|
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
@@ -1919,7 +1937,7 @@ var checkAuthority = async (rootDir, config) => {
|
|
|
1919
1937
|
};
|
|
1920
1938
|
|
|
1921
1939
|
// src/checks/frontmatter.ts
|
|
1922
|
-
import
|
|
1940
|
+
import fs9 from "fs/promises";
|
|
1923
1941
|
|
|
1924
1942
|
// src/markdown/parse.ts
|
|
1925
1943
|
import matter from "gray-matter";
|
|
@@ -1967,7 +1985,7 @@ var checkFrontmatter = async (rootDir, config, markdownPaths) => {
|
|
|
1967
1985
|
}
|
|
1968
1986
|
const absolutePath = resolveRepoPath(rootDir, markdownPath);
|
|
1969
1987
|
await assertRepoContainment(rootDir, absolutePath);
|
|
1970
|
-
const source = await
|
|
1988
|
+
const source = await fs9.readFile(absolutePath, "utf8");
|
|
1971
1989
|
let document;
|
|
1972
1990
|
try {
|
|
1973
1991
|
document = parseMarkdownDocument(source);
|
|
@@ -2005,11 +2023,11 @@ var checkFrontmatter = async (rootDir, config, markdownPaths) => {
|
|
|
2005
2023
|
};
|
|
2006
2024
|
|
|
2007
2025
|
// src/checks/links.ts
|
|
2008
|
-
import
|
|
2026
|
+
import fs10 from "fs/promises";
|
|
2009
2027
|
import path3 from "path";
|
|
2010
2028
|
var pathExists2 = async (absolutePath) => {
|
|
2011
2029
|
try {
|
|
2012
|
-
await
|
|
2030
|
+
await fs10.stat(absolutePath);
|
|
2013
2031
|
return true;
|
|
2014
2032
|
} catch (error) {
|
|
2015
2033
|
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
@@ -2025,7 +2043,7 @@ var checkLinks = async (rootDir, markdownPaths) => {
|
|
|
2025
2043
|
continue;
|
|
2026
2044
|
}
|
|
2027
2045
|
const absolutePath = resolveRepoPath(rootDir, markdownPath);
|
|
2028
|
-
const source = await
|
|
2046
|
+
const source = await fs10.readFile(absolutePath, "utf8");
|
|
2029
2047
|
let document;
|
|
2030
2048
|
try {
|
|
2031
2049
|
document = parseMarkdownDocument(source);
|
|
@@ -2067,12 +2085,12 @@ var checkLinks = async (rootDir, markdownPaths) => {
|
|
|
2067
2085
|
};
|
|
2068
2086
|
|
|
2069
2087
|
// src/checks/areas.ts
|
|
2070
|
-
import
|
|
2088
|
+
import fs12 from "fs/promises";
|
|
2071
2089
|
import fg5 from "fast-glob";
|
|
2072
2090
|
import micromatch3 from "micromatch";
|
|
2073
2091
|
|
|
2074
2092
|
// src/routing/area-resolver.ts
|
|
2075
|
-
import
|
|
2093
|
+
import fs11 from "fs/promises";
|
|
2076
2094
|
import fg4 from "fast-glob";
|
|
2077
2095
|
import micromatch from "micromatch";
|
|
2078
2096
|
|
|
@@ -2229,7 +2247,7 @@ var ensureChildPath = async (rootDir, areaFilesRoot, filePath) => {
|
|
|
2229
2247
|
var readRouteFile = async (rootDir, filePath) => {
|
|
2230
2248
|
try {
|
|
2231
2249
|
return {
|
|
2232
|
-
source: await
|
|
2250
|
+
source: await fs11.readFile(resolveRepoPath(rootDir, filePath), "utf8"),
|
|
2233
2251
|
diagnostic: null
|
|
2234
2252
|
};
|
|
2235
2253
|
} catch (error) {
|
|
@@ -2502,7 +2520,7 @@ var classifyPath = (filePath, ignorePatterns) => {
|
|
|
2502
2520
|
if (normalizedPath.startsWith(".truthmark/")) {
|
|
2503
2521
|
return "derived";
|
|
2504
2522
|
}
|
|
2505
|
-
if (normalizedPath.startsWith(".codex/") || normalizedPath.startsWith(".cursor/") || normalizedPath.startsWith(".gemini/commands/") || normalizedPath.startsWith(".opencode/") || normalizedPath === ".github/copilot-instructions.md" || normalizedPath === "AGENTS.md" || normalizedPath === "CLAUDE.md" || normalizedPath === "GEMINI.md" || normalizedPath.startsWith(".gemini/commands/truthmark/")
|
|
2523
|
+
if (normalizedPath.startsWith(".codex/") || normalizedPath.startsWith(".cursor/") || normalizedPath.startsWith(".gemini/commands/") || normalizedPath.startsWith(".opencode/") || normalizedPath === ".github/copilot-instructions.md" || normalizedPath === "AGENTS.md" || normalizedPath === "CLAUDE.md" || normalizedPath === "GEMINI.md" || normalizedPath.startsWith(".gemini/commands/truthmark/")) {
|
|
2506
2524
|
return "derived";
|
|
2507
2525
|
}
|
|
2508
2526
|
if (ignorePatterns.length > 0 && micromatch2.isMatch(normalizedPath, ignorePatterns)) {
|
|
@@ -2529,7 +2547,7 @@ var looksLikeGlob2 = (pattern) => {
|
|
|
2529
2547
|
};
|
|
2530
2548
|
var pathExists3 = async (absolutePath) => {
|
|
2531
2549
|
try {
|
|
2532
|
-
await
|
|
2550
|
+
await fs12.stat(absolutePath);
|
|
2533
2551
|
return true;
|
|
2534
2552
|
} catch (error) {
|
|
2535
2553
|
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
@@ -2798,7 +2816,7 @@ var checkAreas = async (rootDir, config) => {
|
|
|
2798
2816
|
};
|
|
2799
2817
|
|
|
2800
2818
|
// src/checks/decisions.ts
|
|
2801
|
-
import
|
|
2819
|
+
import fs13 from "fs/promises";
|
|
2802
2820
|
import micromatch4 from "micromatch";
|
|
2803
2821
|
var REQUIRED_DECISION_HEADINGS = ["Product Decisions", "Rationale"];
|
|
2804
2822
|
var escapeRegExp2 = (value) => {
|
|
@@ -2821,7 +2839,7 @@ var checkDecisionSections = async (rootDir, config, markdownPaths) => {
|
|
|
2821
2839
|
const diagnostics = [];
|
|
2822
2840
|
const candidatePaths = [...new Set(markdownPaths)].filter((filePath) => isDecisionTruthCandidate(config, filePath)).sort();
|
|
2823
2841
|
for (const filePath of candidatePaths) {
|
|
2824
|
-
const source = await
|
|
2842
|
+
const source = await fs13.readFile(resolveRepoPath(rootDir, filePath), "utf8");
|
|
2825
2843
|
const missingHeadings = REQUIRED_DECISION_HEADINGS.filter((heading) => !hasHeading(source, heading));
|
|
2826
2844
|
if (missingHeadings.length === 0) {
|
|
2827
2845
|
continue;
|
|
@@ -2837,7 +2855,7 @@ var checkDecisionSections = async (rootDir, config, markdownPaths) => {
|
|
|
2837
2855
|
};
|
|
2838
2856
|
|
|
2839
2857
|
// src/checks/generated-surfaces.ts
|
|
2840
|
-
import
|
|
2858
|
+
import fs14 from "fs/promises";
|
|
2841
2859
|
|
|
2842
2860
|
// src/templates/generated-surfaces.ts
|
|
2843
2861
|
var workflowSkillFiles2 = (basePath, config) => {
|
|
@@ -2916,12 +2934,9 @@ var filesForPlatform2 = (platform, config, block) => {
|
|
|
2916
2934
|
case "codex":
|
|
2917
2935
|
return codexFiles2(config);
|
|
2918
2936
|
case "opencode":
|
|
2919
|
-
return
|
|
2920
|
-
...workflowSkillFiles2("skills", config),
|
|
2921
|
-
...workflowSkillFiles2(".opencode/skills", config)
|
|
2922
|
-
];
|
|
2937
|
+
return workflowSkillFiles2(".opencode/skills", config);
|
|
2923
2938
|
case "claude-code":
|
|
2924
|
-
return instructionBlockFiles2([
|
|
2939
|
+
return instructionBlockFiles2(["CLAUDE.md"], block);
|
|
2925
2940
|
case "cursor":
|
|
2926
2941
|
return instructionBlockFiles2([".cursor/rules/truthmark.mdc"], block);
|
|
2927
2942
|
case "github-copilot":
|
|
@@ -2951,7 +2966,10 @@ var filesForPlatform2 = (platform, config, block) => {
|
|
|
2951
2966
|
}
|
|
2952
2967
|
};
|
|
2953
2968
|
var renderGeneratedSurfaces = (config, block = renderAgentsBlock(config)) => {
|
|
2954
|
-
const files =
|
|
2969
|
+
const files = [
|
|
2970
|
+
...instructionBlockFiles2(config.instructionTargets, block),
|
|
2971
|
+
...config.platforms.flatMap((platform) => filesForPlatform2(platform, config, block))
|
|
2972
|
+
];
|
|
2955
2973
|
return Array.from(new Map(files.map((file) => [file.path, file])).values()).sort(
|
|
2956
2974
|
(left, right) => left.path.localeCompare(right.path)
|
|
2957
2975
|
);
|
|
@@ -2960,7 +2978,7 @@ var renderGeneratedSurfaces = (config, block = renderAgentsBlock(config)) => {
|
|
|
2960
2978
|
// src/checks/generated-surfaces.ts
|
|
2961
2979
|
var readOptionalFile = async (rootDir, filePath) => {
|
|
2962
2980
|
try {
|
|
2963
|
-
return await
|
|
2981
|
+
return await fs14.readFile(resolveRepoPath(rootDir, filePath), "utf8");
|
|
2964
2982
|
} catch (error) {
|
|
2965
2983
|
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
2966
2984
|
return null;
|