@synctek/forgeos 2.0.0

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.
Files changed (143) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +386 -0
  3. package/dist/cli/commands/analyze.d.ts +14 -0
  4. package/dist/cli/commands/analyze.d.ts.map +1 -0
  5. package/dist/cli/commands/analyze.js +94 -0
  6. package/dist/cli/commands/analyze.js.map +1 -0
  7. package/dist/cli/commands/build.d.ts +11 -0
  8. package/dist/cli/commands/build.d.ts.map +1 -0
  9. package/dist/cli/commands/build.js +86 -0
  10. package/dist/cli/commands/build.js.map +1 -0
  11. package/dist/cli/commands/changeset.d.ts +13 -0
  12. package/dist/cli/commands/changeset.d.ts.map +1 -0
  13. package/dist/cli/commands/changeset.js +174 -0
  14. package/dist/cli/commands/changeset.js.map +1 -0
  15. package/dist/cli/commands/evidence.d.ts +12 -0
  16. package/dist/cli/commands/evidence.d.ts.map +1 -0
  17. package/dist/cli/commands/evidence.js +94 -0
  18. package/dist/cli/commands/evidence.js.map +1 -0
  19. package/dist/cli/commands/federation.d.ts +13 -0
  20. package/dist/cli/commands/federation.d.ts.map +1 -0
  21. package/dist/cli/commands/federation.js +127 -0
  22. package/dist/cli/commands/federation.js.map +1 -0
  23. package/dist/cli/commands/gate.d.ts +15 -0
  24. package/dist/cli/commands/gate.d.ts.map +1 -0
  25. package/dist/cli/commands/gate.js +178 -0
  26. package/dist/cli/commands/gate.js.map +1 -0
  27. package/dist/cli/commands/initiative.d.ts +13 -0
  28. package/dist/cli/commands/initiative.d.ts.map +1 -0
  29. package/dist/cli/commands/initiative.js +130 -0
  30. package/dist/cli/commands/initiative.js.map +1 -0
  31. package/dist/cli/commands/mind.d.ts +16 -0
  32. package/dist/cli/commands/mind.d.ts.map +1 -0
  33. package/dist/cli/commands/mind.js +139 -0
  34. package/dist/cli/commands/mind.js.map +1 -0
  35. package/dist/cli/commands/outcome.d.ts +12 -0
  36. package/dist/cli/commands/outcome.d.ts.map +1 -0
  37. package/dist/cli/commands/outcome.js +85 -0
  38. package/dist/cli/commands/outcome.js.map +1 -0
  39. package/dist/cli/commands/project.d.ts +13 -0
  40. package/dist/cli/commands/project.d.ts.map +1 -0
  41. package/dist/cli/commands/project.js +128 -0
  42. package/dist/cli/commands/project.js.map +1 -0
  43. package/dist/cli/commands/review.d.ts +15 -0
  44. package/dist/cli/commands/review.d.ts.map +1 -0
  45. package/dist/cli/commands/review.js +167 -0
  46. package/dist/cli/commands/review.js.map +1 -0
  47. package/dist/cli/commands/score.d.ts +17 -0
  48. package/dist/cli/commands/score.d.ts.map +1 -0
  49. package/dist/cli/commands/score.js +168 -0
  50. package/dist/cli/commands/score.js.map +1 -0
  51. package/dist/cli/commands/session.d.ts +13 -0
  52. package/dist/cli/commands/session.d.ts.map +1 -0
  53. package/dist/cli/commands/session.js +133 -0
  54. package/dist/cli/commands/session.js.map +1 -0
  55. package/dist/cli/commands/trust.d.ts +16 -0
  56. package/dist/cli/commands/trust.d.ts.map +1 -0
  57. package/dist/cli/commands/trust.js +261 -0
  58. package/dist/cli/commands/trust.js.map +1 -0
  59. package/dist/cli/index.d.ts +19 -0
  60. package/dist/cli/index.d.ts.map +1 -0
  61. package/dist/cli/index.js +99 -0
  62. package/dist/cli/index.js.map +1 -0
  63. package/dist/cli/output.d.ts +48 -0
  64. package/dist/cli/output.d.ts.map +1 -0
  65. package/dist/cli/output.js +139 -0
  66. package/dist/cli/output.js.map +1 -0
  67. package/dist/client.d.ts +46 -0
  68. package/dist/client.d.ts.map +1 -0
  69. package/dist/client.js +146 -0
  70. package/dist/client.js.map +1 -0
  71. package/dist/handlers.d.ts +11 -0
  72. package/dist/handlers.d.ts.map +1 -0
  73. package/dist/handlers.js +424 -0
  74. package/dist/handlers.js.map +1 -0
  75. package/dist/http-server.d.ts +25 -0
  76. package/dist/http-server.d.ts.map +1 -0
  77. package/dist/http-server.js +246 -0
  78. package/dist/http-server.js.map +1 -0
  79. package/dist/index.d.ts +3 -0
  80. package/dist/index.d.ts.map +1 -0
  81. package/dist/index.js +40 -0
  82. package/dist/index.js.map +1 -0
  83. package/dist/mcp/handlers.d.ts +11 -0
  84. package/dist/mcp/handlers.d.ts.map +1 -0
  85. package/dist/mcp/handlers.js +553 -0
  86. package/dist/mcp/handlers.js.map +1 -0
  87. package/dist/mcp/http-server.d.ts +25 -0
  88. package/dist/mcp/http-server.d.ts.map +1 -0
  89. package/dist/mcp/http-server.js +246 -0
  90. package/dist/mcp/http-server.js.map +1 -0
  91. package/dist/mcp/index.d.ts +3 -0
  92. package/dist/mcp/index.d.ts.map +1 -0
  93. package/dist/mcp/index.js +40 -0
  94. package/dist/mcp/index.js.map +1 -0
  95. package/dist/mcp/tools.d.ts +944 -0
  96. package/dist/mcp/tools.d.ts.map +1 -0
  97. package/dist/mcp/tools.js +531 -0
  98. package/dist/mcp/tools.js.map +1 -0
  99. package/dist/shared/client.d.ts +59 -0
  100. package/dist/shared/client.d.ts.map +1 -0
  101. package/dist/shared/client.js +171 -0
  102. package/dist/shared/client.js.map +1 -0
  103. package/dist/shared/errors.d.ts +25 -0
  104. package/dist/shared/errors.d.ts.map +1 -0
  105. package/dist/shared/errors.js +44 -0
  106. package/dist/shared/errors.js.map +1 -0
  107. package/dist/shared/types.d.ts +111 -0
  108. package/dist/shared/types.d.ts.map +1 -0
  109. package/dist/shared/types.js +10 -0
  110. package/dist/shared/types.js.map +1 -0
  111. package/dist/tools.d.ts +944 -0
  112. package/dist/tools.d.ts.map +1 -0
  113. package/dist/tools.js +513 -0
  114. package/dist/tools.js.map +1 -0
  115. package/dist/trust/chain.d.ts +86 -0
  116. package/dist/trust/chain.d.ts.map +1 -0
  117. package/dist/trust/chain.js +176 -0
  118. package/dist/trust/chain.js.map +1 -0
  119. package/dist/trust/git-binding.d.ts +61 -0
  120. package/dist/trust/git-binding.d.ts.map +1 -0
  121. package/dist/trust/git-binding.js +133 -0
  122. package/dist/trust/git-binding.js.map +1 -0
  123. package/dist/trust/index.d.ts +20 -0
  124. package/dist/trust/index.d.ts.map +1 -0
  125. package/dist/trust/index.js +17 -0
  126. package/dist/trust/index.js.map +1 -0
  127. package/dist/trust/ledger.d.ts +144 -0
  128. package/dist/trust/ledger.d.ts.map +1 -0
  129. package/dist/trust/ledger.js +351 -0
  130. package/dist/trust/ledger.js.map +1 -0
  131. package/dist/trust/signing.d.ts +134 -0
  132. package/dist/trust/signing.d.ts.map +1 -0
  133. package/dist/trust/signing.js +249 -0
  134. package/dist/trust/signing.js.map +1 -0
  135. package/dist/trust/transmission.d.ts +129 -0
  136. package/dist/trust/transmission.d.ts.map +1 -0
  137. package/dist/trust/transmission.js +390 -0
  138. package/dist/trust/transmission.js.map +1 -0
  139. package/dist/types.d.ts +183 -0
  140. package/dist/types.d.ts.map +1 -0
  141. package/dist/types.js +3 -0
  142. package/dist/types.js.map +1 -0
  143. package/package.json +61 -0
@@ -0,0 +1,176 @@
1
+ /**
2
+ * Hash-chain primitives for the ForgeOS Trust Ledger.
3
+ *
4
+ * Binary-compatible with the Python ledger.py implementation.
5
+ *
6
+ * Chain hash formula (matches Python _compute_chain_hash):
7
+ * chain_hash = SHA-256("{seq}:{prev_hash}:{payload_hash}:{timestamp}")
8
+ *
9
+ * Payload hash formula (matches Python _sha256_dict):
10
+ * payload_hash = SHA-256(JSON.stringify(payload, sortedKeys))
11
+ * where JSON uses ensure_ascii=false equivalent (UTF-8) and sort_keys=True.
12
+ *
13
+ * The genesis sentinel is "GENESIS" (matches Python GENESIS_SENTINEL),
14
+ * NOT a zero-filled hex string.
15
+ */
16
+ import { createHash } from 'crypto';
17
+ /** Genesis sentinel value — used as prev_hash for the first entry. */
18
+ export const GENESIS_SENTINEL = 'GENESIS';
19
+ /** Schema version constant matching the Python implementation. */
20
+ export const SCHEMA_VERSION = '1.0';
21
+ /** Valid entry types — must match Python ENTRY_TYPES (§5.3 of architecture spec). */
22
+ export const ENTRY_TYPES = new Set([
23
+ 'analysis_snapshot',
24
+ 'job_record',
25
+ 'review_received',
26
+ 'improvement_applied',
27
+ 'capability_declared',
28
+ 'metric_change',
29
+ 'decay_checkpoint',
30
+ ]);
31
+ /**
32
+ * Compute the chain hash for a ledger entry.
33
+ *
34
+ * Formula: SHA-256("{seq}:{prev_hash}:{payload_hash}:{timestamp}")
35
+ *
36
+ * This exactly replicates Python's:
37
+ * material = f"{seq}:{prev_hash}:{payload_hash}:{timestamp}"
38
+ * return hashlib.sha256(material.encode("utf-8")).hexdigest()
39
+ *
40
+ * @param seq - Zero-based integer sequence number of the entry.
41
+ * @param prevHash - chain_hash of the previous entry, or GENESIS_SENTINEL for seq 0.
42
+ * @param payloadHash - SHA-256 hex digest of the payload dict.
43
+ * @param timestamp - ISO 8601 UTC timestamp string.
44
+ * @returns 64-character hex SHA-256 digest.
45
+ */
46
+ export function computeChainHash(seq, prevHash, payloadHash, timestamp) {
47
+ const material = `${seq}:${prevHash}:${payloadHash}:${timestamp}`;
48
+ return createHash('sha256').update(material, 'utf8').digest('hex');
49
+ }
50
+ /**
51
+ * Compute the payload hash for a ledger entry.
52
+ *
53
+ * Replicates Python's _sha256_dict:
54
+ * canonical = json.dumps(d, ensure_ascii=False, sort_keys=True)
55
+ * return hashlib.sha256(canonical.encode("utf-8")).hexdigest()
56
+ *
57
+ * Keys are sorted recursively at the top level only (matching Python's
58
+ * sort_keys=True which sorts only the top-level dict keys in standard
59
+ * json.dumps — nested dicts are sorted too since Python json.dumps
60
+ * sort_keys=True applies recursively).
61
+ *
62
+ * IMPORTANT: JSON.stringify with a replacer that sorts keys at every
63
+ * level is required for full binary compatibility with Python's
64
+ * json.dumps(..., sort_keys=True) which sorts ALL nested dict keys.
65
+ *
66
+ * @param payload - The payload dict to hash.
67
+ * @returns 64-character hex SHA-256 digest.
68
+ */
69
+ export function computePayloadHash(payload) {
70
+ const canonical = sortedJsonStringify(payload);
71
+ return createHash('sha256').update(canonical, 'utf8').digest('hex');
72
+ }
73
+ /**
74
+ * JSON serialization matching Python's json.dumps(d, ensure_ascii=False, sort_keys=True).
75
+ *
76
+ * CRITICAL compatibility requirement:
77
+ * Python's json.dumps uses ": " (space after colon) and ", " (space after comma)
78
+ * as default separators. JavaScript's JSON.stringify uses ":" and "," (no spaces).
79
+ * For binary hash compatibility, we must reproduce Python's exact output.
80
+ *
81
+ * Python also sorts ALL dict keys recursively (sort_keys=True applies at every
82
+ * nesting level). JavaScript's JSON.stringify does not sort keys.
83
+ *
84
+ * Python's ensure_ascii=False means non-ASCII chars pass through unescaped.
85
+ * JavaScript's JSON.stringify also does not escape non-ASCII chars by default.
86
+ *
87
+ * This function produces output IDENTICAL to Python's json.dumps with those
88
+ * settings, enabling cross-language hash chain verification.
89
+ *
90
+ * @param value - Value to stringify.
91
+ * @returns JSON string matching Python's json.dumps output exactly.
92
+ */
93
+ export function sortedJsonStringify(value) {
94
+ return pythonJsonDumps(value);
95
+ }
96
+ /**
97
+ * Serialize value to JSON matching Python's json.dumps(ensure_ascii=False, sort_keys=True).
98
+ *
99
+ * Uses ": " after colons and ", " after commas — exactly Python's default separators.
100
+ * Sorts all object keys recursively. Does not escape non-ASCII characters.
101
+ */
102
+ export function pythonJsonDumps(value) {
103
+ if (value === null)
104
+ return 'null';
105
+ if (value === true)
106
+ return 'true';
107
+ if (value === false)
108
+ return 'false';
109
+ if (typeof value === 'number') {
110
+ // Match Python's number serialization
111
+ if (!isFinite(value))
112
+ throw new Error('Cannot serialize non-finite number to JSON');
113
+ return String(value);
114
+ }
115
+ if (typeof value === 'string') {
116
+ return jsonEncodeString(value);
117
+ }
118
+ if (Array.isArray(value)) {
119
+ if (value.length === 0)
120
+ return '[]';
121
+ const items = value.map(pythonJsonDumps);
122
+ return '[' + items.join(', ') + ']';
123
+ }
124
+ if (typeof value === 'object') {
125
+ const obj = value;
126
+ const keys = Object.keys(obj).sort();
127
+ if (keys.length === 0)
128
+ return '{}';
129
+ const pairs = keys.map(k => `${jsonEncodeString(k)}: ${pythonJsonDumps(obj[k])}`);
130
+ return '{' + pairs.join(', ') + '}';
131
+ }
132
+ throw new Error(`Cannot serialize value of type ${typeof value} to JSON`);
133
+ }
134
+ /**
135
+ * Encode a string as a JSON string literal.
136
+ *
137
+ * Matches Python's json.dumps string encoding with ensure_ascii=False:
138
+ * - Escapes: \", \\, \n, \r, \t, \b, \f
139
+ * - Control characters (U+0000–U+001F, U+007F) are \uXXXX escaped
140
+ * - Non-ASCII characters are NOT escaped (ensure_ascii=False)
141
+ * - Unicode characters above U+FFFF use surrogate pairs in Python too
142
+ *
143
+ * This matches the subset of JSON string encoding Python uses.
144
+ */
145
+ function jsonEncodeString(s) {
146
+ let result = '"';
147
+ for (let i = 0; i < s.length; i++) {
148
+ const ch = s[i];
149
+ const code = s.charCodeAt(i);
150
+ if (ch === '"')
151
+ result += '\\"';
152
+ else if (ch === '\\')
153
+ result += '\\\\';
154
+ else if (ch === '\n')
155
+ result += '\\n';
156
+ else if (ch === '\r')
157
+ result += '\\r';
158
+ else if (ch === '\t')
159
+ result += '\\t';
160
+ else if (ch === '\b')
161
+ result += '\\b';
162
+ else if (ch === '\f')
163
+ result += '\\f';
164
+ else if (code < 0x20 || code === 0x7f) {
165
+ // Control characters — escape as \uXXXX
166
+ result += '\\u' + code.toString(16).padStart(4, '0');
167
+ }
168
+ else {
169
+ // All other characters (including non-ASCII) pass through unescaped
170
+ result += ch;
171
+ }
172
+ }
173
+ result += '"';
174
+ return result;
175
+ }
176
+ //# sourceMappingURL=chain.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chain.js","sourceRoot":"","sources":["../../src/trust/chain.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Git state binding for Trust Ledger entries.
3
+ *
4
+ * Binary-compatible with the Python git_binding.py implementation.
5
+ *
6
+ * The source_tree_hash field is the output of `git rev-parse HEAD`,
7
+ * with a "-dirty" suffix if the working tree has uncommitted changes
8
+ * (staged or unstaged, or untracked files that affect reproducibility).
9
+ *
10
+ * Security note (architecture §C-02):
11
+ * All functions return null / false rather than throwing on git errors.
12
+ * Callers treat null as "unverifiable" and annotate accordingly.
13
+ * Actual tampering is detected by the chain hash, not git binding.
14
+ */
15
+ export declare class GitBindingError extends Error {
16
+ constructor(message: string);
17
+ }
18
+ export interface GitMetadata {
19
+ commit: string | null;
20
+ branch: string | null;
21
+ dirty: boolean;
22
+ sourceTreeHash: string | null;
23
+ }
24
+ /**
25
+ * Compute a deterministic hash of the current git tree state.
26
+ *
27
+ * Returns the full commit SHA-1 from `git rev-parse HEAD`, appending
28
+ * the "-dirty" suffix if there are any uncommitted changes or untracked
29
+ * files (matching Python's _is_dirty which checks both `git diff --stat HEAD`
30
+ * and `git status --porcelain`).
31
+ *
32
+ * @param repoPath - Absolute path to the git repository root.
33
+ * @returns "<sha1>", "<sha1>-dirty", or null if not a git repo / git unavailable.
34
+ */
35
+ export declare function computeSourceTreeHash(repoPath: string): string | null;
36
+ /**
37
+ * Verify that the current git state matches the entry's recorded hash.
38
+ *
39
+ * Per architecture §C-02, returns false on any unverifiable condition.
40
+ *
41
+ * An entry is considered verified if ALL of the following hold:
42
+ * 1. The entry contains a non-null, non-empty source_tree_hash.
43
+ * 2. The stored hash does not end in "-dirty".
44
+ * 3. The current `git rev-parse HEAD` matches the stored hash.
45
+ *
46
+ * @param entry - A ledger entry dict.
47
+ * @param repoPath - Path to the git repository root.
48
+ * @returns true if verified, false in all other cases.
49
+ */
50
+ export declare function verifyGitBinding(entry: Record<string, unknown>, repoPath: string): boolean;
51
+ /**
52
+ * Return a dict of current git state metadata for ledger payloads.
53
+ *
54
+ * Matches Python's get_git_metadata() exactly — same field names,
55
+ * same dirty detection logic, same null-on-error behavior.
56
+ *
57
+ * @param repoPath - Path to the git repository root.
58
+ * @returns Git metadata dict, or null fields on any failure.
59
+ */
60
+ export declare function getGitMetadata(repoPath: string): GitMetadata;
61
+ //# sourceMappingURL=git-binding.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git-binding.d.ts","sourceRoot":"","sources":["../../src/trust/git-binding.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAIH,qBAAa,eAAgB,SAAQ,KAAK;gBAC5B,OAAO,EAAE,MAAM;CAI5B;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,KAAK,EAAE,OAAO,CAAC;IACf,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAWrE;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,QAAQ,EAAE,MAAM,GACf,OAAO,CAiBT;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,WAAW,CAW5D"}
@@ -0,0 +1,133 @@
1
+ /**
2
+ * Git state binding for Trust Ledger entries.
3
+ *
4
+ * Binary-compatible with the Python git_binding.py implementation.
5
+ *
6
+ * The source_tree_hash field is the output of `git rev-parse HEAD`,
7
+ * with a "-dirty" suffix if the working tree has uncommitted changes
8
+ * (staged or unstaged, or untracked files that affect reproducibility).
9
+ *
10
+ * Security note (architecture §C-02):
11
+ * All functions return null / false rather than throwing on git errors.
12
+ * Callers treat null as "unverifiable" and annotate accordingly.
13
+ * Actual tampering is detected by the chain hash, not git binding.
14
+ */
15
+ import { execFileSync } from 'child_process';
16
+ export class GitBindingError extends Error {
17
+ constructor(message) {
18
+ super(message);
19
+ this.name = 'GitBindingError';
20
+ }
21
+ }
22
+ /**
23
+ * Compute a deterministic hash of the current git tree state.
24
+ *
25
+ * Returns the full commit SHA-1 from `git rev-parse HEAD`, appending
26
+ * the "-dirty" suffix if there are any uncommitted changes or untracked
27
+ * files (matching Python's _is_dirty which checks both `git diff --stat HEAD`
28
+ * and `git status --porcelain`).
29
+ *
30
+ * @param repoPath - Absolute path to the git repository root.
31
+ * @returns "<sha1>", "<sha1>-dirty", or null if not a git repo / git unavailable.
32
+ */
33
+ export function computeSourceTreeHash(repoPath) {
34
+ const commitHash = getCommitHash(repoPath);
35
+ if (commitHash === null) {
36
+ return null;
37
+ }
38
+ if (isDirty(repoPath)) {
39
+ return `${commitHash}-dirty`;
40
+ }
41
+ return commitHash;
42
+ }
43
+ /**
44
+ * Verify that the current git state matches the entry's recorded hash.
45
+ *
46
+ * Per architecture §C-02, returns false on any unverifiable condition.
47
+ *
48
+ * An entry is considered verified if ALL of the following hold:
49
+ * 1. The entry contains a non-null, non-empty source_tree_hash.
50
+ * 2. The stored hash does not end in "-dirty".
51
+ * 3. The current `git rev-parse HEAD` matches the stored hash.
52
+ *
53
+ * @param entry - A ledger entry dict.
54
+ * @param repoPath - Path to the git repository root.
55
+ * @returns true if verified, false in all other cases.
56
+ */
57
+ export function verifyGitBinding(entry, repoPath) {
58
+ const storedHash = entry['source_tree_hash'];
59
+ if (!storedHash || typeof storedHash !== 'string') {
60
+ return false;
61
+ }
62
+ if (storedHash.endsWith('-dirty')) {
63
+ return false;
64
+ }
65
+ const currentHash = getCommitHash(repoPath);
66
+ if (currentHash === null) {
67
+ return false;
68
+ }
69
+ return currentHash === storedHash;
70
+ }
71
+ /**
72
+ * Return a dict of current git state metadata for ledger payloads.
73
+ *
74
+ * Matches Python's get_git_metadata() exactly — same field names,
75
+ * same dirty detection logic, same null-on-error behavior.
76
+ *
77
+ * @param repoPath - Path to the git repository root.
78
+ * @returns Git metadata dict, or null fields on any failure.
79
+ */
80
+ export function getGitMetadata(repoPath) {
81
+ const commit = getCommitHash(repoPath);
82
+ const branch = getBranchName(repoPath);
83
+ const dirty = commit !== null ? isDirty(repoPath) : false;
84
+ let sourceTreeHash = null;
85
+ if (commit !== null) {
86
+ sourceTreeHash = dirty ? `${commit}-dirty` : commit;
87
+ }
88
+ return { commit, branch, dirty, sourceTreeHash };
89
+ }
90
+ // ------------------------------------------------------------------
91
+ // Internal helpers — each wraps a single git subprocess call
92
+ // ------------------------------------------------------------------
93
+ /**
94
+ * Run a git command and return stdout, or null on failure.
95
+ *
96
+ * Never throws — all errors are swallowed and null is returned.
97
+ * This keeps all git binding failures soft (unverifiable, not broken).
98
+ */
99
+ function runGit(args, cwd) {
100
+ try {
101
+ const output = execFileSync('git', args, {
102
+ cwd,
103
+ encoding: 'utf8',
104
+ timeout: 10_000,
105
+ stdio: ['ignore', 'pipe', 'ignore'],
106
+ });
107
+ const trimmed = output.trim();
108
+ return trimmed.length > 0 ? trimmed : null;
109
+ }
110
+ catch {
111
+ return null;
112
+ }
113
+ }
114
+ function getCommitHash(repoPath) {
115
+ return runGit(['rev-parse', 'HEAD'], repoPath);
116
+ }
117
+ function getBranchName(repoPath) {
118
+ // `git symbolic-ref --short HEAD` fails in detached HEAD state
119
+ const branch = runGit(['symbolic-ref', '--short', 'HEAD'], repoPath);
120
+ if (branch !== null) {
121
+ return branch;
122
+ }
123
+ // Detached HEAD — return abbreviated commit hash as a label
124
+ return runGit(['rev-parse', '--short', 'HEAD'], repoPath);
125
+ }
126
+ function isDirty(repoPath) {
127
+ // `git diff --stat HEAD` includes both staged and unstaged changes
128
+ const diffOutput = runGit(['diff', '--stat', 'HEAD'], repoPath);
129
+ // Also check for untracked new files that affect reproducibility
130
+ const statusOutput = runGit(['status', '--porcelain'], repoPath);
131
+ return diffOutput !== null || statusOutput !== null;
132
+ }
133
+ //# sourceMappingURL=git-binding.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git-binding.js","sourceRoot":"","sources":["../../src/trust/git-binding.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * ForgeOS Trust Ledger — TypeScript port of the Python trust module.
3
+ *
4
+ * Provides a fully local, tamper-evident, Ed25519-signed, hash-chained
5
+ * audit trail for code quality tracking. No engine dependency.
6
+ *
7
+ * Binary-compatible with the Python forgeos-cli trust module.
8
+ *
9
+ * Usage:
10
+ * import { TrustLedger, KeyManager, computeChainHash } from '@synctek/forgeos-mcp/trust';
11
+ */
12
+ export { GENESIS_SENTINEL, SCHEMA_VERSION, ENTRY_TYPES, computeChainHash, computePayloadHash, sortedJsonStringify, } from './chain.js';
13
+ export { KeyManager, SigningError, KeyNotFoundError, KeyPermissionError, } from './signing.js';
14
+ export { computeSourceTreeHash, verifyGitBinding, getGitMetadata, GitBindingError, } from './git-binding.js';
15
+ export { TrustLedger, LedgerError, ChainIntegrityError, } from './ledger.js';
16
+ export type { LedgerEntry, VerifyResult, ChainStats, } from './ledger.js';
17
+ export type { GitMetadata } from './git-binding.js';
18
+ export { TRANSMITTABLE_FIELDS, LOCAL_ONLY_FIELDS, TransmissionError, PrivacyViolationError, prepareTransmission, detectSensitiveContent, generateManifest, generatePlainManifest, logTransmission, loadAllowedEndpoints, sendTransmission, } from './transmission.js';
19
+ export type { TransmissionPayload, TransmissionResult, TransmissionLogRecord, } from './transmission.js';
20
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/trust/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EACL,gBAAgB,EAChB,cAAc,EACd,WAAW,EACX,gBAAgB,EAChB,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,UAAU,EACV,YAAY,EACZ,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,qBAAqB,EACrB,gBAAgB,EAChB,cAAc,EACd,eAAe,GAChB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EACL,WAAW,EACX,WAAW,EACX,mBAAmB,GACpB,MAAM,aAAa,CAAC;AAErB,YAAY,EACV,WAAW,EACX,YAAY,EACZ,UAAU,GACX,MAAM,aAAa,CAAC;AAErB,YAAY,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEpD,OAAO,EACL,oBAAoB,EACpB,iBAAiB,EACjB,iBAAiB,EACjB,qBAAqB,EACrB,mBAAmB,EACnB,sBAAsB,EACtB,gBAAgB,EAChB,qBAAqB,EACrB,eAAe,EACf,oBAAoB,EACpB,gBAAgB,GACjB,MAAM,mBAAmB,CAAC;AAE3B,YAAY,EACV,mBAAmB,EACnB,kBAAkB,EAClB,qBAAqB,GACtB,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * ForgeOS Trust Ledger — TypeScript port of the Python trust module.
3
+ *
4
+ * Provides a fully local, tamper-evident, Ed25519-signed, hash-chained
5
+ * audit trail for code quality tracking. No engine dependency.
6
+ *
7
+ * Binary-compatible with the Python forgeos-cli trust module.
8
+ *
9
+ * Usage:
10
+ * import { TrustLedger, KeyManager, computeChainHash } from '@synctek/forgeos-mcp/trust';
11
+ */
12
+ export { GENESIS_SENTINEL, SCHEMA_VERSION, ENTRY_TYPES, computeChainHash, computePayloadHash, sortedJsonStringify, } from './chain.js';
13
+ export { KeyManager, SigningError, KeyNotFoundError, KeyPermissionError, } from './signing.js';
14
+ export { computeSourceTreeHash, verifyGitBinding, getGitMetadata, GitBindingError, } from './git-binding.js';
15
+ export { TrustLedger, LedgerError, ChainIntegrityError, } from './ledger.js';
16
+ export { TRANSMITTABLE_FIELDS, LOCAL_ONLY_FIELDS, TransmissionError, PrivacyViolationError, prepareTransmission, detectSensitiveContent, generateManifest, generatePlainManifest, logTransmission, loadAllowedEndpoints, sendTransmission, } from './transmission.js';
17
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/trust/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EACL,gBAAgB,EAChB,cAAc,EACd,WAAW,EACX,gBAAgB,EAChB,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,UAAU,EACV,YAAY,EACZ,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,qBAAqB,EACrB,gBAAgB,EAChB,cAAc,EACd,eAAe,GAChB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EACL,WAAW,EACX,WAAW,EACX,mBAAmB,GACpB,MAAM,aAAa,CAAC;AAUrB,OAAO,EACL,oBAAoB,EACpB,iBAAiB,EACjB,iBAAiB,EACjB,qBAAqB,EACrB,mBAAmB,EACnB,sBAAsB,EACtB,gBAAgB,EAChB,qBAAqB,EACrB,eAAe,EACf,oBAAoB,EACpB,gBAAgB,GACjB,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,144 @@
1
+ /**
2
+ * Local Trust Ledger — hash-chained JSONL audit trail for code intelligence.
3
+ *
4
+ * Binary-compatible with the Python ledger.py implementation.
5
+ *
6
+ * Each ForgeOS project maintains a local append-only ledger at
7
+ * `.forgeos/ledger.jsonl`. Entries are hash-chained using SHA-256 over
8
+ * the canonical fields "seq:prev_hash:payload_hash:timestamp", producing
9
+ * a tamper-evident record of every analysis run, review, and metric change.
10
+ *
11
+ * Chain hash formula:
12
+ * chain_hash = SHA-256("{seq}:{prev_hash}:{payload_hash}:{timestamp}")
13
+ *
14
+ * JSONL format: one JSON object per line, keys sorted (sort_keys=True),
15
+ * written with appendFileSync. Matches Python's json.dumps(..., sort_keys=True).
16
+ *
17
+ * File locking: Node.js single-threaded event loop provides safe sequential
18
+ * writes within one process. For cross-process safety, a .ledger.lock file
19
+ * is created (advisory lock, best-effort) — same approach as Python's
20
+ * fcntl.LOCK_EX. Full POSIX flock is not available in pure Node stdlib;
21
+ * the lock file is written atomically and removed after use.
22
+ *
23
+ * Entry field order in JSONL (matches Python's sort_keys=True output):
24
+ * chain_hash, entry_type, payload, payload_hash, prev_hash, schema_version,
25
+ * seq, signature, source_tree_hash, timestamp
26
+ */
27
+ /**
28
+ * A single entry in the trust ledger.
29
+ *
30
+ * Field names and types match the Python ledger schema exactly.
31
+ * The JSONL serialization sorts these keys alphabetically (sort_keys=True).
32
+ */
33
+ export interface LedgerEntry {
34
+ schema_version: string;
35
+ seq: number;
36
+ timestamp: string;
37
+ entry_type: string;
38
+ payload: Record<string, unknown>;
39
+ payload_hash: string;
40
+ prev_hash: string;
41
+ chain_hash: string;
42
+ source_tree_hash: string | null;
43
+ signature: string | null;
44
+ }
45
+ export interface VerifyResult {
46
+ valid: boolean;
47
+ total_entries: number;
48
+ first_break_at: number | null;
49
+ message: string;
50
+ }
51
+ export interface ChainStats {
52
+ entry_count: number;
53
+ first_timestamp: string | null;
54
+ last_timestamp: string | null;
55
+ chain_valid: boolean;
56
+ by_type: Record<string, number>;
57
+ shareable_chain_hash: string | null;
58
+ }
59
+ export declare class LedgerError extends Error {
60
+ constructor(message: string);
61
+ }
62
+ export declare class ChainIntegrityError extends LedgerError {
63
+ seq: number;
64
+ constructor(seq: number, message: string);
65
+ }
66
+ /**
67
+ * Append-only, hash-chained ledger for local code intelligence data.
68
+ *
69
+ * The ledger lives at {projectPath}/.forgeos/ledger.jsonl.
70
+ *
71
+ * Example:
72
+ * const ledger = new TrustLedger('/my/project');
73
+ * const entry = ledger.append('analysis_snapshot', { quality_score: 82.4 });
74
+ * const result = ledger.verifyChain();
75
+ * const stats = ledger.getChainStats();
76
+ */
77
+ export declare class TrustLedger {
78
+ private ledgerPath;
79
+ private lockPath;
80
+ private keyManager;
81
+ constructor(projectPath: string);
82
+ /**
83
+ * Append a new entry to the ledger and return the complete record.
84
+ *
85
+ * Optionally binds to git state (sourceTreeHash) and signs the entry
86
+ * (signature) if keys are available.
87
+ *
88
+ * @param entryType - One of the 7 canonical entry types.
89
+ * @param payload - Arbitrary JSON-serializable payload dict.
90
+ * @param repoPath - Optional repo path for git binding.
91
+ * @param signature - Optional pre-computed Ed25519 signature (base64).
92
+ * If null, the ledger will attempt to self-sign if keys exist.
93
+ * @returns The complete ledger entry.
94
+ * @throws LedgerError if the ledger directory does not exist.
95
+ * @throws Error if entryType is not in ENTRY_TYPES.
96
+ */
97
+ append(entryType: string, payload: Record<string, unknown>, repoPath?: string, signature?: string | null): LedgerEntry;
98
+ /**
99
+ * Verify the integrity of the entire hash chain.
100
+ *
101
+ * Walks every entry in order, recomputing each chain_hash and checking
102
+ * that it matches the stored value, and that prev_hash matches the
103
+ * chain_hash of the preceding entry.
104
+ *
105
+ * @returns VerifyResult with validity, entry count, and first break location.
106
+ */
107
+ verifyChain(): VerifyResult;
108
+ /**
109
+ * Read entries from the ledger with optional filtering.
110
+ *
111
+ * @param entryType - If set, only return entries of this type.
112
+ * @param since - If set, only return entries with timestamp >= this ISO string.
113
+ * @param limit - Maximum number of entries to return.
114
+ * @returns Array of entry dicts in chronological order.
115
+ */
116
+ readEntries(entryType?: string, since?: string, limit?: number): LedgerEntry[];
117
+ /**
118
+ * Return the most recent ledger entry, or null if empty.
119
+ */
120
+ getLatest(): LedgerEntry | null;
121
+ /**
122
+ * Return aggregate statistics about the ledger chain.
123
+ *
124
+ * Matches Python's get_chain_stats() return structure exactly.
125
+ */
126
+ getChainStats(): ChainStats;
127
+ /**
128
+ * Write a new entry.
129
+ *
130
+ * Advisory file locking via .ledger.lock is used for cross-process safety.
131
+ * Node.js is single-threaded so within one process this is sequential.
132
+ */
133
+ private appendLocked;
134
+ /** Read all non-empty lines from the ledger file. */
135
+ private readRawLines;
136
+ /**
137
+ * Acquire advisory lock by creating .ledger.lock.
138
+ * Returns true if lock was created (should be released), false if lock
139
+ * already existed (proceeding anyway — this is advisory only).
140
+ */
141
+ private acquireLock;
142
+ private releaseLock;
143
+ }
144
+ //# sourceMappingURL=ledger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ledger.d.ts","sourceRoot":"","sources":["../../src/trust/ledger.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AA0BH;;;;;GAKG;AACH,MAAM,WAAW,WAAW;IAC1B,cAAc,EAAE,MAAM,CAAC;IACvB,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,OAAO,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,UAAU;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,WAAW,EAAE,OAAO,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAC;CACrC;AAED,qBAAa,WAAY,SAAQ,KAAK;gBACxB,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,mBAAoB,SAAQ,WAAW;IAClD,GAAG,EAAE,MAAM,CAAC;gBACA,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;CAKzC;AAMD;;;;;;;;;;GAUG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,UAAU,CAAoB;gBAE1B,WAAW,EAAE,MAAM;IAY/B;;;;;;;;;;;;;;OAcG;IACH,MAAM,CACJ,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,QAAQ,CAAC,EAAE,MAAM,EACjB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,GACxB,WAAW;IAoBd;;;;;;;;OAQG;IACH,WAAW,IAAI,YAAY;IA4E3B;;;;;;;OAOG;IACH,WAAW,CACT,SAAS,CAAC,EAAE,MAAM,EAClB,KAAK,CAAC,EAAE,MAAM,EACd,KAAK,CAAC,EAAE,MAAM,GACb,WAAW,EAAE;IAyBhB;;OAEG;IACH,SAAS,IAAI,WAAW,GAAG,IAAI;IAW/B;;;;OAIG;IACH,aAAa,IAAI,UAAU;IAkD3B;;;;;OAKG;IACH,OAAO,CAAC,YAAY;IA6DpB,qDAAqD;IACrD,OAAO,CAAC,YAAY;IAKpB;;;;OAIG;IACH,OAAO,CAAC,WAAW;IASnB,OAAO,CAAC,WAAW;CAOpB"}