codehere 0.8.0 → 1.0.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.
Files changed (134) hide show
  1. package/README.md +22 -13
  2. package/dist/application/services/verdict-service.js +154 -0
  3. package/dist/application/use-cases/assess-cross-vendor.js +126 -0
  4. package/dist/application/use-cases/build-cross-vendor-verdict.js +118 -0
  5. package/dist/application/use-cases/export-aat.js +107 -0
  6. package/dist/application/use-cases/generate-acceptance-criteria.js +223 -0
  7. package/dist/application/use-cases/generate-final-report.js +140 -15
  8. package/dist/application/use-cases/generate-narration.js +5 -3
  9. package/dist/application/use-cases/generate-thread-title.js +5 -2
  10. package/dist/application/use-cases/plan-auto-review.js +57 -0
  11. package/dist/application/use-cases/reconcile-audit.js +100 -0
  12. package/dist/application/use-cases/rerun-tests.js +226 -0
  13. package/dist/application/use-cases/search-sessions.js +70 -0
  14. package/dist/application/use-cases/should-auto-review.js +71 -0
  15. package/dist/application/use-cases/thread-export.js +90 -0
  16. package/dist/application/use-cases/verify-claim.js +187 -5
  17. package/dist/domain/audit.js +11 -0
  18. package/dist/domain/services/codebase-detector.js +0 -6
  19. package/dist/domain/task.js +91 -0
  20. package/dist/error-handler.js +3 -115
  21. package/dist/index.js +269 -25
  22. package/dist/infrastructure/completion/bash-completion.js +7 -3
  23. package/dist/infrastructure/completion/fish-completion.js +7 -12
  24. package/dist/infrastructure/completion/zsh-completion.js +7 -12
  25. package/dist/infrastructure/config/config-manager.js +4 -3
  26. package/dist/infrastructure/config/product-context.js +1 -19
  27. package/dist/infrastructure/context/adapters/figma-source.js +37 -2
  28. package/dist/infrastructure/context/adapters/github-issue-source.js +3 -2
  29. package/dist/infrastructure/context/github-api.js +110 -0
  30. package/dist/infrastructure/context/github-device-flow.js +65 -0
  31. package/dist/infrastructure/context/oauth-store.js +5 -2
  32. package/dist/infrastructure/context/registry-bootstrap.js +0 -4
  33. package/dist/infrastructure/cost/budget-config.js +3 -2
  34. package/dist/infrastructure/cost/cost-router.js +16 -23
  35. package/dist/infrastructure/cost/spend-aggregator.js +90 -15
  36. package/dist/infrastructure/cost/team-ledger.js +355 -0
  37. package/dist/infrastructure/discovery/discovery-log.js +85 -0
  38. package/dist/infrastructure/hooks/audit-tip-signature.js +336 -0
  39. package/dist/infrastructure/hooks/claude-sdk-hook.js +133 -3
  40. package/dist/infrastructure/hooks/hook-mode.js +20 -4
  41. package/dist/infrastructure/hooks/mirror-tool-call-to-audit.js +8 -2
  42. package/dist/infrastructure/hooks/pre-prompt-scan.js +3 -3
  43. package/dist/infrastructure/observability/execution-tracer.js +1 -1
  44. package/dist/infrastructure/orchestration/agents-config-seed.js +22 -10
  45. package/dist/infrastructure/orchestration/aider-adapter.js +188 -24
  46. package/dist/infrastructure/orchestration/artifacts-extractor.js +60 -2
  47. package/dist/infrastructure/orchestration/claude-code-adapter.js +117 -3
  48. package/dist/infrastructure/orchestration/codex-adapter.js +52 -16
  49. package/dist/infrastructure/orchestration/conductor-adapter.js +46 -7
  50. package/dist/infrastructure/orchestration/context-handoff.js +32 -14
  51. package/dist/infrastructure/orchestration/detect-ollama.js +75 -0
  52. package/dist/infrastructure/orchestration/failover-config.js +0 -10
  53. package/dist/infrastructure/orchestration/gemini-adapter.js +92 -12
  54. package/dist/infrastructure/orchestration/generic-cli-adapter.js +132 -1
  55. package/dist/infrastructure/orchestration/graphify-context.js +14 -59
  56. package/dist/infrastructure/orchestration/mocks/mock-agent-repl.js +164 -9
  57. package/dist/infrastructure/orchestration/opencode-adapter.js +84 -14
  58. package/dist/infrastructure/orchestration/progress-aggregator.js +238 -21
  59. package/dist/infrastructure/orchestration/session-manager.js +593 -94
  60. package/dist/infrastructure/orchestration/session-persistence.js +177 -41
  61. package/dist/infrastructure/orchestration/thread-key-store.js +1 -1
  62. package/dist/infrastructure/orchestration/write-pass-store.js +0 -8
  63. package/dist/infrastructure/protocols/mcp-helpers.js +1 -1
  64. package/dist/infrastructure/protocols/mcp-server-impl.js +1462 -380
  65. package/dist/infrastructure/protocols/mcp-tools.js +401 -0
  66. package/dist/infrastructure/protocols/ui/app-script-artifacts.js +121 -0
  67. package/dist/infrastructure/protocols/ui/app-script-audit-footer.js +44 -0
  68. package/dist/infrastructure/protocols/ui/app-script-audit-verify.js +56 -0
  69. package/dist/infrastructure/protocols/ui/app-script-composer-cost.js +588 -0
  70. package/dist/infrastructure/protocols/ui/app-script-context-sources.js +168 -0
  71. package/dist/infrastructure/protocols/ui/app-script-conversation.js +67 -0
  72. package/dist/infrastructure/protocols/ui/app-script-drawer.js +115 -0
  73. package/dist/infrastructure/protocols/ui/app-script-failover.js +133 -0
  74. package/dist/infrastructure/protocols/ui/app-script-github.js +113 -0
  75. package/dist/infrastructure/protocols/ui/app-script-observer.js +104 -0
  76. package/dist/infrastructure/protocols/ui/app-script-onboarding.js +80 -0
  77. package/dist/infrastructure/protocols/ui/app-script-overlay.js +203 -0
  78. package/dist/infrastructure/protocols/ui/app-script-recovery.js +136 -0
  79. package/dist/infrastructure/protocols/ui/app-script-render.js +166 -0
  80. package/dist/infrastructure/protocols/ui/app-script-share.js +78 -0
  81. package/dist/infrastructure/protocols/ui/app-script-sidebar.js +194 -0
  82. package/dist/infrastructure/protocols/ui/app-script-tour.js +78 -0
  83. package/dist/infrastructure/protocols/ui/app-script-wpass.js +312 -0
  84. package/dist/infrastructure/protocols/ui/app-script.js +2998 -0
  85. package/dist/infrastructure/protocols/ui/font-faces.js +7 -0
  86. package/dist/infrastructure/protocols/ui/styles.js +2147 -0
  87. package/dist/infrastructure/protocols/ui/tokens.js +96 -0
  88. package/dist/infrastructure/protocols/ui-page-v2.js +116 -4214
  89. package/dist/infrastructure/protocols/verify-page.js +849 -155
  90. package/dist/infrastructure/security/fix-code.js +144 -0
  91. package/dist/infrastructure/security/fix-secret.js +89 -0
  92. package/dist/infrastructure/security/permissions-config.js +3 -2
  93. package/dist/infrastructure/security/scan-types.js +10 -0
  94. package/dist/infrastructure/security/ship-scan.js +195 -0
  95. package/dist/infrastructure/security/trust-scorer.js +70 -3
  96. package/dist/infrastructure/security/vibe-checks.js +99 -0
  97. package/dist/infrastructure/storage/atomic-write.js +86 -0
  98. package/dist/infrastructure/storage/project-thread-mirror.js +150 -3
  99. package/dist/infrastructure/storage/project-thread-reader.js +261 -24
  100. package/dist/monitoring.js +2 -2
  101. package/dist/presentation/cli/commands/audit-command.js +79 -4
  102. package/dist/presentation/cli/commands/budget-command.js +2 -2
  103. package/dist/presentation/cli/commands/check-command.js +96 -0
  104. package/dist/presentation/cli/commands/context-source-command.js +20 -1
  105. package/dist/presentation/cli/commands/help-command.js +5 -5
  106. package/dist/presentation/cli/commands/hook-command.js +5 -5
  107. package/dist/presentation/cli/commands/init-command.js +26 -14
  108. package/dist/presentation/cli/commands/memory-command.js +28 -28
  109. package/dist/presentation/cli/commands/permission-command.js +1 -12
  110. package/dist/presentation/cli/commands/protocols-builder.js +2 -2
  111. package/dist/presentation/cli/commands/protocols-command.js +4 -4
  112. package/dist/presentation/cli/commands/repo-map-builder.js +1 -1
  113. package/dist/presentation/cli/commands/report-command.js +48 -32
  114. package/dist/presentation/cli/commands/scan-command.js +52 -0
  115. package/dist/presentation/cli/commands/scan-tool-command.js +24 -8
  116. package/dist/presentation/cli/commands/search-command.js +51 -0
  117. package/dist/presentation/cli/commands/setup-command.js +31 -8
  118. package/dist/presentation/cli/commands/status-command.js +39 -86
  119. package/dist/presentation/cli/commands/team-command.js +256 -0
  120. package/dist/presentation/cli/commands/thread-command.js +87 -5
  121. package/dist/presentation/cli/commands/trust-command.js +53 -31
  122. package/dist/presentation/cli/commands/verify-command.js +74 -9
  123. package/dist/presentation/cli/error-display.js +0 -8
  124. package/dist/presentation/cli/repl.js +15 -7
  125. package/dist/presentation/cli/task-deliverable.js +36 -10
  126. package/dist/testing/replay-adapter.js +0 -19
  127. package/dist/ui.js +51 -239
  128. package/dist/utils/version.js +0 -6
  129. package/package.json +30 -10
  130. package/dist/domain/entities/task.js +0 -61
  131. package/dist/infrastructure/protocols/ui-page.js +0 -2377
  132. package/dist/infrastructure/security/input-validator.js +0 -152
  133. package/dist/infrastructure/storage/embeddings-path.js +0 -37
  134. package/dist/infrastructure/storage/task-repository.js +0 -206
@@ -27,15 +27,48 @@ function sessionsFile() {
27
27
  // so a scratch home isolates sessions for dogfooding / the mock harness.
28
28
  return join(process.env.CODEHERE_HOME || homedir(), '.codehere', 'sessions.jsonl');
29
29
  }
30
- function ensureDir() {
31
- const dir = dirname(sessionsFile());
30
+ /**
31
+ * A session's records must all land in the SAME file: the one resolved when it
32
+ * was spawned. sessionsFile() reads env per-call, so a write that fires after
33
+ * the environment moved on (async exit handlers; test suites that swap
34
+ * CODEHERE_HOME per test) would otherwise scatter a session across homes —
35
+ * the failover-skip flake forensics caught exactly this shape (a slow
36
+ * real-claude exit record from another test's home, spawned-record absent —
37
+ * full record in commit message). Spawn binds the
38
+ * path; completed/finalReport reuse it. FIFO-capped — eviction only means a
39
+ * later write falls back to the env-resolved path (prod-identical: the
40
+ * daemon's home never changes mid-run).
41
+ */
42
+ const sessionFileById = new Map();
43
+ const SESSION_FILE_CAP = 500;
44
+ function bindSessionFile(id) {
45
+ const file = sessionsFile();
46
+ if (sessionFileById.size >= SESSION_FILE_CAP) {
47
+ const oldest = sessionFileById.keys().next().value;
48
+ if (oldest !== undefined)
49
+ sessionFileById.delete(oldest);
50
+ }
51
+ sessionFileById.set(id, file);
52
+ return file;
53
+ }
54
+ function fileForSession(id) {
55
+ return sessionFileById.get(id) ?? sessionsFile();
56
+ }
57
+ function ensureDirFor(file) {
58
+ const dir = dirname(file);
32
59
  if (!existsSync(dir))
33
60
  mkdirSync(dir, { recursive: true });
34
61
  }
35
62
  export function appendSpawned(rec) {
36
63
  try {
37
- ensureDir();
38
- appendFileSync(sessionsFile(), JSON.stringify({ t: 'spawned', ...rec }) + '\n', 'utf-8');
64
+ const file = bindSessionFile(rec.id);
65
+ ensureDirFor(file);
66
+ // S18 · practice is a property of the RUN, stamped once on the durable
67
+ // record at spawn — never re-derived from a later daemon's env. Seeded
68
+ // demo-* showcases keep their FEATURED meaning even if seeded under mock.
69
+ const mockDaemon = process.env.CODEHERE_MOCK === '1' || process.env.CODEHERE_MOCK === 'true';
70
+ const mockRun = mockDaemon && !rec.id.startsWith('demo-');
71
+ appendFileSync(file, JSON.stringify({ t: 'spawned', ...rec, mockRun }) + '\n', 'utf-8');
39
72
  }
40
73
  catch {
41
74
  /* persistence is best-effort; never break the spawn path */
@@ -43,8 +76,9 @@ export function appendSpawned(rec) {
43
76
  }
44
77
  export function appendCompleted(rec) {
45
78
  try {
46
- ensureDir();
47
- appendFileSync(sessionsFile(), JSON.stringify({ t: 'completed', ...rec }) + '\n', 'utf-8');
79
+ const file = fileForSession(rec.id);
80
+ ensureDirFor(file);
81
+ appendFileSync(file, JSON.stringify({ t: 'completed', ...rec }) + '\n', 'utf-8');
48
82
  }
49
83
  catch {
50
84
  /* best-effort */
@@ -62,10 +96,35 @@ export function appendCompleted(rec) {
62
96
  * Append-only: Final Report fires AFTER the CompletedRecord (generateFinalReport
63
97
  * is async post-exit), so it gets its own record type. Reader merges by id.
64
98
  */
99
+ /** S3 · persist the human's "mark resolved" ack so it sticks across reload.
100
+ * Append-only like every other record; reader merges by id (last wins). */
101
+ export function appendResolved(rec) {
102
+ try {
103
+ const file = fileForSession(rec.id);
104
+ ensureDirFor(file);
105
+ appendFileSync(file, JSON.stringify({ t: 'resolved', ...rec }) + '\n', 'utf-8');
106
+ }
107
+ catch {
108
+ /* best-effort */
109
+ }
110
+ }
65
111
  export function appendFinalReport(rec) {
66
112
  try {
67
- ensureDir();
68
- appendFileSync(sessionsFile(), JSON.stringify({ t: 'finalReport', ...rec }) + '\n', 'utf-8');
113
+ const file = fileForSession(rec.id);
114
+ ensureDirFor(file);
115
+ appendFileSync(file, JSON.stringify({ t: 'finalReport', ...rec }) + '\n', 'utf-8');
116
+ }
117
+ catch {
118
+ /* best-effort */
119
+ }
120
+ }
121
+ /** Tier 2.2 · persist the audit↔disk reconciliation so the OBSERVED signal
122
+ * survives a daemon restart (mirrors appendFinalReport's async-post-exit shape). */
123
+ export function appendAuditRecon(id, recon) {
124
+ try {
125
+ const file = fileForSession(id);
126
+ ensureDirFor(file);
127
+ appendFileSync(file, JSON.stringify({ t: 'audit-recon', id, recon }) + '\n', 'utf-8');
69
128
  }
70
129
  catch {
71
130
  /* best-effort */
@@ -95,6 +154,27 @@ export function appendFinalReport(rec) {
95
154
  * the CLI · git's `--abbrev-commit` collisions are very rare in practice
96
155
  * for our id space.
97
156
  */
157
+ /** S18 · classification for the joined record. The run-time stamp wins. For
158
+ * LEGACY records written before the stamp existed, the mock adapter leaves
159
+ * two durable on-record signals, and either proves the run was practice:
160
+ * (1) it mints its own resume tokens "mock-…" (mock-agent-repl.ts) — a real
161
+ * vendor CLI never does; (2) its ONLY edit artifact is the hardcoded,
162
+ * gitignored `codehere-mock-change.md` (MOCK_EDIT_FILE) — conductor practice
163
+ * runs carry no resume token but their steps touched it. Classified on read
164
+ * so pre-stamp practice never renders as the founder's real work. demo-*
165
+ * showcases keep their FEATURED meaning. Records with neither stamp nor
166
+ * signal stay undefined (the reader's env fallback — genuinely no signal). */
167
+ function recordedMockRun(s, c) {
168
+ if (s.mockRun !== undefined)
169
+ return s.mockRun;
170
+ if (s.id.startsWith('demo-'))
171
+ return undefined;
172
+ if (c.nativeSessionId?.startsWith('mock-'))
173
+ return true;
174
+ if (c.steps?.some((st) => st.label?.includes('codehere-mock-change.md')))
175
+ return true;
176
+ return undefined;
177
+ }
98
178
  export function loadSessionById(idOrPrefix) {
99
179
  const file = sessionsFile();
100
180
  if (!existsSync(file))
@@ -109,6 +189,8 @@ export function loadSessionById(idOrPrefix) {
109
189
  const spawned = new Map();
110
190
  const completed = [];
111
191
  const finalReports = new Map();
192
+ const resolved = new Map();
193
+ const auditRecons = new Map();
112
194
  for (const line of content.split('\n')) {
113
195
  const trimmed = line.trim();
114
196
  if (!trimmed)
@@ -126,6 +208,10 @@ export function loadSessionById(idOrPrefix) {
126
208
  completed.push(rec);
127
209
  else if (rec.t === 'finalReport')
128
210
  finalReports.set(rec.id, rec);
211
+ else if (rec.t === 'resolved')
212
+ resolved.set(rec.id, rec.resolvedAt);
213
+ else if (rec.t === 'audit-recon')
214
+ auditRecons.set(rec.id, rec.recon);
129
215
  }
130
216
  // Newest-first to break prefix-collision ties toward the most recent
131
217
  for (let i = completed.length - 1; i >= 0; i--) {
@@ -136,6 +222,7 @@ export function loadSessionById(idOrPrefix) {
136
222
  if (!s)
137
223
  continue;
138
224
  const fr = finalReports.get(c.id);
225
+ const mockRun = recordedMockRun(s, c);
139
226
  const failoverFrom = c.failoverFrom ?? s.failoverFrom;
140
227
  const failoverTo = c.failoverTo ?? s.failoverTo;
141
228
  const failoverReason = c.failoverReason ?? s.failoverReason;
@@ -151,12 +238,32 @@ export function loadSessionById(idOrPrefix) {
151
238
  steps: c.steps,
152
239
  artifacts: c.artifacts,
153
240
  ...(c.turns ? { turns: c.turns } : {}),
154
- ...(fr ? { finalReport: { summary: fr.summary, generatedAt: fr.generatedAt, durationMs: fr.durationMs, source: fr.source } } : {}),
241
+ ...(fr
242
+ ? {
243
+ finalReport: {
244
+ summary: fr.summary,
245
+ generatedAt: fr.generatedAt,
246
+ durationMs: fr.durationMs,
247
+ source: fr.source,
248
+ },
249
+ }
250
+ : {}),
155
251
  ...(failoverFrom ? { failoverFrom } : {}),
156
252
  ...(failoverTo ? { failoverTo } : {}),
157
253
  ...(failoverReason ? { failoverReason } : {}),
158
254
  ...(s.failoverAt ? { failoverAt: s.failoverAt } : {}),
159
255
  ...(c.stalledReason ? { stalledReason: c.stalledReason } : {}),
256
+ ...(s.batchId ? { batchId: s.batchId } : {}),
257
+ ...(c.delegatedTo ? { delegatedTo: c.delegatedTo } : {}),
258
+ ...(c.nativeSessionId ? { nativeSessionId: c.nativeSessionId } : {}),
259
+ ...(c.delegateSessionId ? { delegateSessionId: c.delegateSessionId } : {}),
260
+ ...(auditRecons.get(c.id) ? { auditRecon: auditRecons.get(c.id) } : {}),
261
+ ...(s.importedFrom ? { importedFrom: s.importedFrom } : {}),
262
+ ...(s.importAudit ? { importAudit: s.importAudit } : {}),
263
+ ...(s.parentSessionId ? { parentSessionId: s.parentSessionId } : {}),
264
+ ...(s.isReview ? { isReview: true } : {}),
265
+ ...(resolved.has(c.id) ? { resolvedAt: resolved.get(c.id) } : {}),
266
+ ...(mockRun !== undefined ? { mockRun } : {}),
160
267
  provenance: 'persisted',
161
268
  };
162
269
  }
@@ -178,6 +285,8 @@ export function loadRecent(limit = 20) {
178
285
  /** v0.6.x — Final Reports keyed by sessionId. Last write wins
179
286
  * (rare in practice; reports fire once per session). */
180
287
  const finalReports = new Map();
288
+ const resolved = new Map();
289
+ const auditRecons = new Map();
181
290
  for (const line of content.split('\n')) {
182
291
  const trimmed = line.trim();
183
292
  if (!trimmed)
@@ -195,41 +304,68 @@ export function loadRecent(limit = 20) {
195
304
  completed.push(rec);
196
305
  else if (rec.t === 'finalReport')
197
306
  finalReports.set(rec.id, rec);
307
+ else if (rec.t === 'resolved')
308
+ resolved.set(rec.id, rec.resolvedAt);
309
+ else if (rec.t === 'audit-recon')
310
+ auditRecons.set(rec.id, rec.recon);
198
311
  }
199
312
  const merged = [];
200
313
  const includedIds = new Set();
201
- const build = (c, s, fr) => ({
202
- sessionId: s.id,
203
- agent: s.agent,
204
- prompt: s.prompt,
205
- cwd: s.cwd,
206
- startedAt: s.startedAt,
207
- // BUG 2 (May 1 2026) — defensive normalization for zombie records.
208
- // Pre-fix sessions persisted before commit <THIS> were written with
209
- // status='running' even when their completed-record carried real
210
- // durationMs/completedAt — the conductor adapter mirrored its status
211
- // AFTER emitting the exit event. The fix at the source (conductor-
212
- // adapter.ts) prevents new zombies; this normalization repairs old
213
- // records on read so the UI doesn't show a "running" badge on a
214
- // session that obviously finished. We have no ground truth on what
215
- // the actual exit code WAS for these old records, so 'completed' is
216
- // the safest default — they'd been displayed as completed in the UI
217
- // had this been a session-manager.ts bug. Mark explicitly via a
218
- // synthetic note so debug viewers can tell normalization happened.
219
- status: c.status === 'running' && c.completedAt > 0 ? 'completed' : c.status,
220
- durationMs: c.durationMs,
221
- completedAt: c.completedAt,
222
- steps: c.steps,
223
- artifacts: c.artifacts,
224
- ...(c.turns ? { turns: c.turns } : {}),
225
- ...(fr ? { finalReport: { summary: fr.summary, generatedAt: fr.generatedAt, durationMs: fr.durationMs, source: fr.source } } : {}),
226
- ...((c.failoverFrom ?? s.failoverFrom) ? { failoverFrom: c.failoverFrom ?? s.failoverFrom } : {}),
227
- ...((c.failoverTo ?? s.failoverTo) ? { failoverTo: c.failoverTo ?? s.failoverTo } : {}),
228
- ...((c.failoverReason ?? s.failoverReason) ? { failoverReason: c.failoverReason ?? s.failoverReason } : {}),
229
- ...(s.failoverAt ? { failoverAt: s.failoverAt } : {}),
230
- ...(c.stalledReason ? { stalledReason: c.stalledReason } : {}),
231
- provenance: 'persisted',
232
- });
314
+ const build = (c, s, fr) => {
315
+ const mockRun = recordedMockRun(s, c);
316
+ return {
317
+ sessionId: s.id,
318
+ agent: s.agent,
319
+ prompt: s.prompt,
320
+ cwd: s.cwd,
321
+ startedAt: s.startedAt,
322
+ // BUG 2 (May 1 2026) — defensive normalization for zombie records.
323
+ // Pre-fix sessions persisted before commit <THIS> were written with
324
+ // status='running' even when their completed-record carried real
325
+ // durationMs/completedAt — the conductor adapter mirrored its status
326
+ // AFTER emitting the exit event. The fix at the source (conductor-
327
+ // adapter.ts) prevents new zombies; this normalization repairs old
328
+ // records on read so the UI doesn't show a "running" badge on a
329
+ // session that obviously finished. We have no ground truth on what
330
+ // the actual exit code WAS for these old records, so 'completed' is
331
+ // the safest default — they'd been displayed as completed in the UI
332
+ // had this been a session-manager.ts bug. Mark explicitly via a
333
+ // synthetic note so debug viewers can tell normalization happened.
334
+ status: c.status === 'running' && c.completedAt > 0 ? 'completed' : c.status,
335
+ durationMs: c.durationMs,
336
+ completedAt: c.completedAt,
337
+ steps: c.steps,
338
+ artifacts: c.artifacts,
339
+ ...(c.turns ? { turns: c.turns } : {}),
340
+ ...(fr
341
+ ? {
342
+ finalReport: {
343
+ summary: fr.summary,
344
+ generatedAt: fr.generatedAt,
345
+ durationMs: fr.durationMs,
346
+ source: fr.source,
347
+ },
348
+ }
349
+ : {}),
350
+ ...((c.failoverFrom ?? s.failoverFrom) ? { failoverFrom: c.failoverFrom ?? s.failoverFrom } : {}),
351
+ ...((c.failoverTo ?? s.failoverTo) ? { failoverTo: c.failoverTo ?? s.failoverTo } : {}),
352
+ ...((c.failoverReason ?? s.failoverReason) ? { failoverReason: c.failoverReason ?? s.failoverReason } : {}),
353
+ ...(s.failoverAt ? { failoverAt: s.failoverAt } : {}),
354
+ ...(c.stalledReason ? { stalledReason: c.stalledReason } : {}),
355
+ ...(s.batchId ? { batchId: s.batchId } : {}),
356
+ ...(c.delegatedTo ? { delegatedTo: c.delegatedTo } : {}),
357
+ ...(c.nativeSessionId ? { nativeSessionId: c.nativeSessionId } : {}),
358
+ ...(c.delegateSessionId ? { delegateSessionId: c.delegateSessionId } : {}),
359
+ ...(auditRecons.get(c.id) ? { auditRecon: auditRecons.get(c.id) } : {}),
360
+ ...(s.importedFrom ? { importedFrom: s.importedFrom } : {}),
361
+ ...(s.importAudit ? { importAudit: s.importAudit } : {}),
362
+ ...(s.parentSessionId ? { parentSessionId: s.parentSessionId } : {}),
363
+ ...(s.isReview ? { isReview: true } : {}),
364
+ ...(resolved.has(c.id) ? { resolvedAt: resolved.get(c.id) } : {}),
365
+ ...(mockRun !== undefined ? { mockRun } : {}),
366
+ provenance: 'persisted',
367
+ };
368
+ };
233
369
  // Walk completed in reverse so we return newest-first, up to `limit`.
234
370
  for (let i = completed.length - 1; i >= 0 && merged.length < limit; i--) {
235
371
  const c = completed[i];
@@ -18,7 +18,7 @@ import { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from 'f
18
18
  import { homedir } from 'os';
19
19
  import { join } from 'path';
20
20
  import { generateKeypair, exportPrivatePem, exportPublicPem, importPrivatePem, importPublicPem, publicKeyToBase64, } from '../../application/use-cases/thread-export.js';
21
- function keysDir() {
21
+ export function keysDir() {
22
22
  const home = process.env.CODEHERE_HOME || homedir();
23
23
  return join(home, '.codehere', 'keys');
24
24
  }
@@ -35,12 +35,4 @@ export function listForSession(sessionId) {
35
35
  .filter((s) => s.intent.sessionId === sessionId)
36
36
  .sort((a, b) => a.intent.emittedAt - b.intent.emittedAt);
37
37
  }
38
- /** Drop a pass · for tests + the "discard" admin action. */
39
- export function discard(passId) {
40
- return store.delete(passId);
41
- }
42
- /** Test-only · clear the store between cases. */
43
- export function _resetForTests() {
44
- store.clear();
45
- }
46
38
  //# sourceMappingURL=write-pass-store.js.map
@@ -21,5 +21,5 @@ export function collectFilesForMCP(target) {
21
21
  }
22
22
  // ── Scoring ──────────────────────────────────────────────────────────────────
23
23
  // Re-export score function using the shared scorer
24
- export { scoreFile as scoreFileForMCP } from '../security/trust-scorer.js';
24
+ export { scoreFile as scoreFileForMCP, aggregateTrust } from '../security/trust-scorer.js';
25
25
  //# sourceMappingURL=mcp-helpers.js.map