codehere 1.0.1 → 1.0.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.
Files changed (163) hide show
  1. package/README.md +36 -192
  2. package/dist/application/use-cases/check-claimed-tests.js +81 -0
  3. package/dist/application/use-cases/detect-test-weakening.js +237 -0
  4. package/dist/application/use-cases/rerun-tests.js +110 -7
  5. package/dist/index.js +38 -1212
  6. package/dist/infrastructure/orchestration/artifacts-extractor.js +2 -323
  7. package/dist/presentation/cli/commands/check-command.js +178 -23
  8. package/dist/presentation/cli/commands/help-command.js +21 -285
  9. package/dist/ui.js +5 -236
  10. package/dist/utils/version.js +0 -6
  11. package/package.json +9 -38
  12. package/dist/application/services/verdict-service.js +0 -154
  13. package/dist/application/use-cases/assess-cross-vendor.js +0 -126
  14. package/dist/application/use-cases/build-cross-vendor-verdict.js +0 -118
  15. package/dist/application/use-cases/domain-trust.js +0 -110
  16. package/dist/application/use-cases/export-aat.js +0 -107
  17. package/dist/application/use-cases/generate-acceptance-criteria.js +0 -223
  18. package/dist/application/use-cases/generate-final-report.js +0 -259
  19. package/dist/application/use-cases/generate-narration.js +0 -130
  20. package/dist/application/use-cases/generate-thread-title.js +0 -181
  21. package/dist/application/use-cases/narrator-prompt-template.js +0 -158
  22. package/dist/application/use-cases/plan-auto-review.js +0 -57
  23. package/dist/application/use-cases/reconcile-audit.js +0 -100
  24. package/dist/application/use-cases/search-sessions.js +0 -70
  25. package/dist/application/use-cases/should-auto-review.js +0 -71
  26. package/dist/application/use-cases/thread-export.js +0 -245
  27. package/dist/application/use-cases/verify-claim.js +0 -456
  28. package/dist/application/use-cases/write-pass.js +0 -277
  29. package/dist/domain/audit.js +0 -11
  30. package/dist/domain/services/codebase-detector.js +0 -85
  31. package/dist/domain/task.js +0 -91
  32. package/dist/error-handler.js +0 -139
  33. package/dist/infrastructure/completion/bash-completion.js +0 -29
  34. package/dist/infrastructure/completion/fish-completion.js +0 -17
  35. package/dist/infrastructure/completion/zsh-completion.js +0 -25
  36. package/dist/infrastructure/config/config-manager.js +0 -174
  37. package/dist/infrastructure/config/product-context.js +0 -49
  38. package/dist/infrastructure/context/adapters/drawio-source.js +0 -157
  39. package/dist/infrastructure/context/adapters/figma-source.js +0 -198
  40. package/dist/infrastructure/context/adapters/github-issue-source.js +0 -160
  41. package/dist/infrastructure/context/adapters/linear-source.js +0 -190
  42. package/dist/infrastructure/context/context-resolver.js +0 -144
  43. package/dist/infrastructure/context/context-source.js +0 -114
  44. package/dist/infrastructure/context/github-api.js +0 -110
  45. package/dist/infrastructure/context/github-device-flow.js +0 -65
  46. package/dist/infrastructure/context/oauth-flow.js +0 -207
  47. package/dist/infrastructure/context/oauth-store.js +0 -122
  48. package/dist/infrastructure/context/registry-bootstrap.js +0 -95
  49. package/dist/infrastructure/context/write-pass-resolver.js +0 -106
  50. package/dist/infrastructure/cost/budget-config.js +0 -114
  51. package/dist/infrastructure/cost/cost-router.js +0 -97
  52. package/dist/infrastructure/cost/spend-aggregator.js +0 -222
  53. package/dist/infrastructure/cost/team-ledger.js +0 -355
  54. package/dist/infrastructure/discovery/discovery-log.js +0 -85
  55. package/dist/infrastructure/hooks/audit-tip-signature.js +0 -336
  56. package/dist/infrastructure/hooks/claude-sdk-hook.js +0 -1018
  57. package/dist/infrastructure/hooks/hook-mode.js +0 -87
  58. package/dist/infrastructure/hooks/mirror-tool-call-to-audit.js +0 -49
  59. package/dist/infrastructure/hooks/pre-prompt-scan.js +0 -122
  60. package/dist/infrastructure/hooks/session-analyzer.js +0 -177
  61. package/dist/infrastructure/observability/execution-tracer.js +0 -227
  62. package/dist/infrastructure/orchestration/agent-adapter.js +0 -13
  63. package/dist/infrastructure/orchestration/agent-installer.js +0 -101
  64. package/dist/infrastructure/orchestration/agents-config-seed.js +0 -68
  65. package/dist/infrastructure/orchestration/aider-adapter.js +0 -611
  66. package/dist/infrastructure/orchestration/cassette-recorder.js +0 -120
  67. package/dist/infrastructure/orchestration/claude-code-adapter.js +0 -592
  68. package/dist/infrastructure/orchestration/codex-adapter.js +0 -574
  69. package/dist/infrastructure/orchestration/conductor-adapter.js +0 -416
  70. package/dist/infrastructure/orchestration/context-handoff.js +0 -162
  71. package/dist/infrastructure/orchestration/control/codex-control-surface.js +0 -99
  72. package/dist/infrastructure/orchestration/control/control-surface.js +0 -15
  73. package/dist/infrastructure/orchestration/detect-ollama.js +0 -75
  74. package/dist/infrastructure/orchestration/failover-classifier.js +0 -151
  75. package/dist/infrastructure/orchestration/failover-config.js +0 -67
  76. package/dist/infrastructure/orchestration/failover-policy.js +0 -106
  77. package/dist/infrastructure/orchestration/gemini-adapter.js +0 -663
  78. package/dist/infrastructure/orchestration/generic-cli-adapter.js +0 -689
  79. package/dist/infrastructure/orchestration/graphify-context.js +0 -209
  80. package/dist/infrastructure/orchestration/memory-injector.js +0 -380
  81. package/dist/infrastructure/orchestration/mocks/mock-agent-repl.js +0 -388
  82. package/dist/infrastructure/orchestration/mocks/mock-codex-app-server.js +0 -73
  83. package/dist/infrastructure/orchestration/mocks/mock-synthesis.js +0 -83
  84. package/dist/infrastructure/orchestration/mocks/resolve-agent-spawn.js +0 -37
  85. package/dist/infrastructure/orchestration/opencode-adapter.js +0 -580
  86. package/dist/infrastructure/orchestration/progress-aggregator.js +0 -906
  87. package/dist/infrastructure/orchestration/readiness.js +0 -103
  88. package/dist/infrastructure/orchestration/session-manager.js +0 -1590
  89. package/dist/infrastructure/orchestration/session-persistence.js +0 -394
  90. package/dist/infrastructure/orchestration/thread-key-store.js +0 -127
  91. package/dist/infrastructure/orchestration/write-pass-store.js +0 -38
  92. package/dist/infrastructure/protocols/cloud-sync.js +0 -207
  93. package/dist/infrastructure/protocols/mcp-helpers.js +0 -25
  94. package/dist/infrastructure/protocols/mcp-server-impl.js +0 -3935
  95. package/dist/infrastructure/protocols/mcp-tools.js +0 -401
  96. package/dist/infrastructure/protocols/probe-port.js +0 -36
  97. package/dist/infrastructure/protocols/thread-phase.js +0 -105
  98. package/dist/infrastructure/protocols/ui/app-script-artifacts.js +0 -121
  99. package/dist/infrastructure/protocols/ui/app-script-audit-footer.js +0 -44
  100. package/dist/infrastructure/protocols/ui/app-script-audit-verify.js +0 -56
  101. package/dist/infrastructure/protocols/ui/app-script-composer-cost.js +0 -588
  102. package/dist/infrastructure/protocols/ui/app-script-context-sources.js +0 -168
  103. package/dist/infrastructure/protocols/ui/app-script-conversation.js +0 -67
  104. package/dist/infrastructure/protocols/ui/app-script-drawer.js +0 -115
  105. package/dist/infrastructure/protocols/ui/app-script-failover.js +0 -133
  106. package/dist/infrastructure/protocols/ui/app-script-github.js +0 -113
  107. package/dist/infrastructure/protocols/ui/app-script-observer.js +0 -104
  108. package/dist/infrastructure/protocols/ui/app-script-onboarding.js +0 -80
  109. package/dist/infrastructure/protocols/ui/app-script-overlay.js +0 -203
  110. package/dist/infrastructure/protocols/ui/app-script-recovery.js +0 -136
  111. package/dist/infrastructure/protocols/ui/app-script-render.js +0 -166
  112. package/dist/infrastructure/protocols/ui/app-script-share.js +0 -78
  113. package/dist/infrastructure/protocols/ui/app-script-sidebar.js +0 -194
  114. package/dist/infrastructure/protocols/ui/app-script-tour.js +0 -78
  115. package/dist/infrastructure/protocols/ui/app-script-wpass.js +0 -312
  116. package/dist/infrastructure/protocols/ui/app-script.js +0 -2998
  117. package/dist/infrastructure/protocols/ui/font-faces.js +0 -7
  118. package/dist/infrastructure/protocols/ui/styles.js +0 -2147
  119. package/dist/infrastructure/protocols/ui/tokens.js +0 -96
  120. package/dist/infrastructure/protocols/ui-page-v2.js +0 -320
  121. package/dist/infrastructure/protocols/verify-page.js +0 -1677
  122. package/dist/infrastructure/security/file-collection.js +0 -118
  123. package/dist/infrastructure/security/fix-code.js +0 -144
  124. package/dist/infrastructure/security/fix-secret.js +0 -89
  125. package/dist/infrastructure/security/permissions-config.js +0 -235
  126. package/dist/infrastructure/security/scan-types.js +0 -10
  127. package/dist/infrastructure/security/ship-scan.js +0 -195
  128. package/dist/infrastructure/security/trust-scorer.js +0 -724
  129. package/dist/infrastructure/security/vibe-checks.js +0 -99
  130. package/dist/infrastructure/storage/atomic-write.js +0 -86
  131. package/dist/infrastructure/storage/cross-tool-agents.js +0 -268
  132. package/dist/infrastructure/storage/project-thread-migration.js +0 -237
  133. package/dist/infrastructure/storage/project-thread-mirror.js +0 -671
  134. package/dist/infrastructure/storage/project-thread-reader.js +0 -409
  135. package/dist/infrastructure/storage/project-thread-title-backfill.js +0 -214
  136. package/dist/monitoring.js +0 -212
  137. package/dist/presentation/cli/commands/audit-command.js +0 -201
  138. package/dist/presentation/cli/commands/budget-command.js +0 -79
  139. package/dist/presentation/cli/commands/config-command.js +0 -125
  140. package/dist/presentation/cli/commands/context-source-command.js +0 -217
  141. package/dist/presentation/cli/commands/hook-command.js +0 -265
  142. package/dist/presentation/cli/commands/init-command.js +0 -590
  143. package/dist/presentation/cli/commands/memory-command.js +0 -1031
  144. package/dist/presentation/cli/commands/narrator-command.js +0 -101
  145. package/dist/presentation/cli/commands/permission-command.js +0 -105
  146. package/dist/presentation/cli/commands/protocols-builder.js +0 -254
  147. package/dist/presentation/cli/commands/protocols-command.js +0 -84
  148. package/dist/presentation/cli/commands/repo-map-builder.js +0 -247
  149. package/dist/presentation/cli/commands/report-command.js +0 -403
  150. package/dist/presentation/cli/commands/scan-command.js +0 -52
  151. package/dist/presentation/cli/commands/scan-tool-command.js +0 -110
  152. package/dist/presentation/cli/commands/search-command.js +0 -51
  153. package/dist/presentation/cli/commands/setup-command.js +0 -330
  154. package/dist/presentation/cli/commands/status-command.js +0 -614
  155. package/dist/presentation/cli/commands/team-command.js +0 -256
  156. package/dist/presentation/cli/commands/thread-command.js +0 -370
  157. package/dist/presentation/cli/commands/trust-command.js +0 -328
  158. package/dist/presentation/cli/commands/verify-command.js +0 -298
  159. package/dist/presentation/cli/error-display.js +0 -328
  160. package/dist/presentation/cli/repl.js +0 -805
  161. package/dist/presentation/cli/task-deliverable.js +0 -153
  162. package/dist/testing/cassette.js +0 -125
  163. package/dist/testing/replay-adapter.js +0 -147
@@ -1,212 +0,0 @@
1
- /**
2
- * Enterprise Monitoring & Health Check System
3
- * Ensures 24/7 operation visibility
4
- */
5
- import { existsSync, mkdirSync } from 'fs';
6
- import { join, dirname } from 'path';
7
- import { fileURLToPath } from 'url';
8
- import { cohereCircuitBreaker } from './error-handler.js';
9
- class MetricsCollector {
10
- operations = {
11
- total: 0,
12
- successful: 0,
13
- failed: 0,
14
- retries: 0,
15
- };
16
- performance = {
17
- responseTimes: [],
18
- retryTimes: [],
19
- apiCalls: 0,
20
- cacheHits: 0,
21
- };
22
- errors = {
23
- byType: {},
24
- recent: [],
25
- };
26
- recordOperation(success, responseTime, retries) {
27
- this.operations.total++;
28
- if (success) {
29
- this.operations.successful++;
30
- }
31
- else {
32
- this.operations.failed++;
33
- }
34
- if (retries) {
35
- this.operations.retries += retries;
36
- }
37
- if (responseTime) {
38
- this.performance.responseTimes.push(responseTime);
39
- // Keep only last 1000 measurements
40
- if (this.performance.responseTimes.length > 1000) {
41
- this.performance.responseTimes.shift();
42
- }
43
- }
44
- }
45
- recordApiCall() {
46
- this.performance.apiCalls++;
47
- }
48
- recordCacheHit() {
49
- this.performance.cacheHits++;
50
- }
51
- recordError(type, message) {
52
- this.errors.byType[type] = (this.errors.byType[type] || 0) + 1;
53
- this.errors.recent.push({
54
- timestamp: new Date().toISOString(),
55
- type,
56
- message,
57
- });
58
- // Keep only last 100 errors
59
- if (this.errors.recent.length > 100) {
60
- this.errors.recent.shift();
61
- }
62
- }
63
- getMetrics() {
64
- const avgResponseTime = this.performance.responseTimes.length > 0
65
- ? this.performance.responseTimes.reduce((a, b) => a + b, 0) / this.performance.responseTimes.length
66
- : 0;
67
- const avgRetryTime = this.performance.retryTimes.length > 0
68
- ? this.performance.retryTimes.reduce((a, b) => a + b, 0) / this.performance.retryTimes.length
69
- : 0;
70
- return {
71
- operations: { ...this.operations },
72
- performance: {
73
- avgResponseTime,
74
- avgRetryTime,
75
- apiCalls: this.performance.apiCalls,
76
- cacheHits: this.performance.cacheHits,
77
- },
78
- errors: {
79
- byType: { ...this.errors.byType },
80
- recent: [...this.errors.recent],
81
- },
82
- };
83
- }
84
- reset() {
85
- this.operations = { total: 0, successful: 0, failed: 0, retries: 0 };
86
- this.performance = { responseTimes: [], retryTimes: [], apiCalls: 0, cacheHits: 0 };
87
- this.errors = { byType: {}, recent: [] };
88
- }
89
- }
90
- export const metricsCollector = new MetricsCollector();
91
- /**
92
- * Check API health
93
- */
94
- function checkApi() {
95
- const circuitState = cohereCircuitBreaker.getState();
96
- if (circuitState === 'OPEN') {
97
- return { status: 'circuit_open', message: 'API circuit breaker is OPEN - too many failures' };
98
- }
99
- if (circuitState === 'HALF_OPEN') {
100
- return { status: 'error', message: 'API circuit breaker is HALF_OPEN - recovering' };
101
- }
102
- // Check if any API key is configured
103
- const hasKey = !!(process.env.ANTHROPIC_API_KEY ||
104
- process.env.OPENAI_API_KEY ||
105
- process.env.COHERE_API_KEY ||
106
- process.env.OPENROUTER_API_KEY);
107
- if (!hasKey) {
108
- return { status: 'error', message: 'No API key configured' };
109
- }
110
- return { status: 'ok', message: 'API accessible' };
111
- }
112
- /**
113
- * Check filesystem health
114
- */
115
- function checkFilesystem() {
116
- try {
117
- const __filename = fileURLToPath(import.meta.url);
118
- const __dirname = dirname(__filename);
119
- const agentDir = join(__dirname, '..');
120
- const dataDir = join(agentDir, 'data');
121
- // Check if data directory exists or can be created
122
- if (!existsSync(dataDir)) {
123
- // Try to create it
124
- try {
125
- mkdirSync(dataDir, { recursive: true });
126
- }
127
- catch {
128
- return { status: 'error', message: 'Cannot create data directory' };
129
- }
130
- }
131
- return { status: 'ok', message: 'Filesystem accessible' };
132
- }
133
- catch (error) {
134
- return {
135
- status: 'error',
136
- message: `Filesystem check failed: ${error instanceof Error ? error.message : String(error)}`,
137
- };
138
- }
139
- }
140
- /**
141
- * Check memory usage
142
- */
143
- function checkMemory() {
144
- try {
145
- const usage = process.memoryUsage();
146
- const heapUsedMB = usage.heapUsed / 1024 / 1024;
147
- const heapTotalMB = usage.heapTotal / 1024 / 1024;
148
- const usagePercent = (heapUsedMB / heapTotalMB) * 100;
149
- if (usagePercent > 90) {
150
- return {
151
- status: 'warning',
152
- message: `High memory usage: ${usagePercent.toFixed(1)}%`,
153
- usage: usagePercent,
154
- };
155
- }
156
- return {
157
- status: 'ok',
158
- message: `Memory usage: ${usagePercent.toFixed(1)}%`,
159
- usage: usagePercent,
160
- };
161
- }
162
- catch {
163
- return {
164
- status: 'ok',
165
- message: 'Memory check unavailable',
166
- };
167
- }
168
- }
169
- /**
170
- * Perform health check
171
- */
172
- export function performHealthCheck() {
173
- const apiCheck = checkApi();
174
- const fsCheck = checkFilesystem();
175
- const memCheck = checkMemory();
176
- const checks = {
177
- api: apiCheck,
178
- filesystem: fsCheck,
179
- memory: memCheck,
180
- };
181
- let status = 'healthy';
182
- if (apiCheck.status === 'circuit_open' || fsCheck.status === 'error') {
183
- status = 'unhealthy';
184
- }
185
- else if (apiCheck.status === 'error' || memCheck.status === 'warning') {
186
- status = 'degraded';
187
- }
188
- return {
189
- status,
190
- timestamp: new Date().toISOString(),
191
- checks,
192
- };
193
- }
194
- /**
195
- * Get current metrics
196
- */
197
- export function getMetrics() {
198
- return metricsCollector.getMetrics();
199
- }
200
- /**
201
- * Format health status for display
202
- */
203
- export function formatHealthStatus(health) {
204
- const statusIcon = health.status === 'healthy' ? '✓' : health.status === 'degraded' ? '!' : '✕';
205
- let output = ` ${statusIcon} ${health.status.toUpperCase()}\n\n`;
206
- for (const [component, check] of Object.entries(health.checks)) {
207
- const icon = check.status === 'ok' ? '✓' : check.status === 'warning' ? '!' : '✕';
208
- output += ` ${icon} ${component.padEnd(12)} ${check.message}\n`;
209
- }
210
- return output;
211
- }
212
- //# sourceMappingURL=monitoring.js.map
@@ -1,201 +0,0 @@
1
- /**
2
- * CLI: `codehere audit`
3
- *
4
- * F-05 of the demo-v12 backlog · expose the hash-chained audit log verifier
5
- * + a "show" subcommand for forensic inspection. The chain is the source of
6
- * truth, NOT codehere itself · this command lets reviewers and CI verify it
7
- * without trusting our daemon.
8
- *
9
- * Subcommands:
10
- * codehere audit verify [--json] Walk the chain · report intact/tampered
11
- * + entry counts + every break point.
12
- * Exit 0 = valid, 1 = invalid.
13
- * codehere audit show <seq> [--json]
14
- * Print one entry by sequence number.
15
- *
16
- * Default audit file: ~/.codehere/audit/hook-events.jsonl
17
- * Override via CODEHERE_AUDIT_FILE env var (mirrors the hook's own resolution).
18
- */
19
- import { existsSync, readFileSync } from 'fs';
20
- import { colors, symbols } from '../../../ui.js';
21
- import { AUDIT_FILE, verifyAuditChain } from '../../../infrastructure/hooks/claude-sdk-hook.js';
22
- import { verifyAuditTip, tipBlocksVerification } from '../../../infrastructure/hooks/audit-tip-signature.js';
23
- import { exportAat, aatToJsonl } from '../../../application/use-cases/export-aat.js';
24
- import { writeFileSync as writeFileSyncFs } from 'fs';
25
- import { trustedKeySet } from '../../../infrastructure/orchestration/thread-key-store.js';
26
- export function executeAuditCommand(sub, arg, options = {}) {
27
- if (!sub || sub === 'verify')
28
- return verify(options.json ?? false);
29
- if (sub === 'show')
30
- return show(arg, options.json ?? false);
31
- if (sub === 'export')
32
- return exportAatCmd(arg);
33
- process.stderr.write(colors.error(`${symbols.error} Unknown audit subcommand: ${sub}\n`) +
34
- colors.dim('Try: codehere audit verify | codehere audit show <seq> | codehere audit export [out.jsonl]\n'));
35
- return 2;
36
- }
37
- /* ──────────────────────────────────────────────────────────────────────── */
38
- /* verify · the F-05 headline */
39
- /* ──────────────────────────────────────────────────────────────────────── */
40
- function verify(json) {
41
- const result = verifyAuditChain(AUDIT_FILE);
42
- // R2 · the tip signature catches a re-walked forgery the hash chain alone
43
- // can't (a determined edit + recomputed hashes verifies green, but the signed
44
- // entry's hash changes). ANCESTOR check: honest appends since signing are
45
- // expected and pass; an edit at/below the signed seq, truncation, an untrusted
46
- // re-sign, or a deleted .tipsig on a previously-signed chain all fail.
47
- const tip = verifyAuditTip(AUDIT_FILE, trustedKeySet());
48
- const tipTampered = tipBlocksVerification(tip);
49
- // An empty or missing log has nothing to verify, and a chain walk over zero entries
50
- // trivially succeeds. Reporting that as valid:true is the failure this product exists to
51
- // catch: deleting the audit log is exactly the attack the hash chain is meant to detect,
52
- // and the machine interface was answering "intact" to a machine that asked. The human
53
- // path already says "No audit entries yet" and claims nothing, so only --json was lying.
54
- // "Is my chain intact?" over no chain is not answered by yes.
55
- const verifiable = result.totalEntries > 0;
56
- const ok = verifiable && result.valid && !tipTampered;
57
- if (json) {
58
- process.stdout.write(JSON.stringify({
59
- path: AUDIT_FILE,
60
- valid: ok,
61
- verifiable,
62
- ...(verifiable ? {} : { reason: 'no audit entries — nothing to verify (is the hook installed?)' }),
63
- chainHashesValid: result.valid,
64
- writerMix: result.writerMix,
65
- tipSignature: {
66
- present: tip.present,
67
- expectedButMissing: tip.expectedButMissing,
68
- signatureValid: tip.signatureValid,
69
- ancestorIntact: tip.ancestorIntact,
70
- matchesTip: tip.matchesTip,
71
- trusted: tip.trusted,
72
- signer: tip.signerKeyB64,
73
- reason: tip.reason,
74
- },
75
- totalEntries: result.totalEntries,
76
- chainedEntries: result.chainedEntries,
77
- legacyEntries: result.legacyEntries,
78
- errors: result.errors,
79
- }, null, 2) + '\n');
80
- return ok ? 0 : 1;
81
- }
82
- // Human output · header, verdict line, counts, then errors if any.
83
- process.stdout.write('\n' + colors.dim('audit log: ') + colors.gray(AUDIT_FILE) + '\n\n');
84
- if (result.totalEntries === 0) {
85
- process.stdout.write(colors.gray(`${symbols.dot} No audit entries yet.`) +
86
- colors.dim(' Install the hook first: ') +
87
- colors.bold('codehere hook install') +
88
- '\n\n');
89
- return 0;
90
- }
91
- if (result.valid) {
92
- process.stdout.write(colors.green(`${symbols.success} Chain intact`) +
93
- colors.dim(' every entry verified against its predecessor hash.') +
94
- '\n\n');
95
- }
96
- else {
97
- process.stdout.write(colors.error(`${symbols.error} Chain BROKEN`) +
98
- colors.dim(` ${result.errors.length} break point${result.errors.length === 1 ? '' : 's'} detected.`) +
99
- '\n\n');
100
- }
101
- // R1.5 · writer-provenance mix — honest about WHO wrote the entries. The
102
- // verify surface must never imply everything went through the daemon when
103
- // some entries are the hook's direct fallback or predate provenance.
104
- const wm = result.writerMix;
105
- if (result.chainedEntries > 0) {
106
- process.stdout.write(colors.dim(` written by: ${wm.daemon} daemon \u00B7 ${wm.hookDirect} hook-direct (no daemon reachable) \u00B7 ${wm.unattributed} unattributed (no writer field)\n\n`));
107
- }
108
- // R2 · tip-signature line — catches a re-walked forgery the hash chain can't.
109
- if (tip.present && tip.signatureValid && tip.ancestorIntact && tip.trusted) {
110
- process.stdout.write(colors.green(`${symbols.success} Chain signed`) +
111
- colors.dim(tip.matchesTip
112
- ? " by a trusted key · no edits by anyone without this machine's key."
113
- : ' by a trusted key · the signed prefix is intact (the chain has grown since).') +
114
- '\n\n');
115
- }
116
- else if (tipTampered) {
117
- process.stdout.write(colors.error(`${symbols.error} Tip signature FAILED`) + colors.dim(` ${tip.reason}.`) + '\n\n');
118
- }
119
- process.stdout.write(colors.bold('Counts:\n'));
120
- process.stdout.write(` ${result.totalEntries.toString().padStart(6)} total entries\n`);
121
- process.stdout.write(` ${result.chainedEntries.toString().padStart(6)} hash-chained (verifiable)\n`);
122
- process.stdout.write(` ${result.legacyEntries.toString().padStart(6)} legacy pre-chain (un-verifiable)\n\n`);
123
- if (result.errors.length > 0) {
124
- process.stdout.write(colors.bold('Break points:\n'));
125
- for (const err of result.errors) {
126
- process.stdout.write(' ' +
127
- colors.error(`line ${err.lineNumber}`) +
128
- colors.dim(' ') +
129
- colors.gray(err.reason) +
130
- colors.dim(' ') +
131
- err.detail +
132
- '\n');
133
- }
134
- process.stdout.write('\n');
135
- }
136
- return ok ? 0 : 1;
137
- }
138
- function show(seqStr, json) {
139
- if (!seqStr || !/^\d+$/.test(seqStr)) {
140
- process.stderr.write(colors.error(`${symbols.error} Need a numeric sequence: codehere audit show <seq>\n`));
141
- return 2;
142
- }
143
- const target = parseInt(seqStr, 10);
144
- if (!existsSync(AUDIT_FILE)) {
145
- process.stderr.write(colors.gray(`${symbols.dot} No audit log yet.\n`));
146
- return 2;
147
- }
148
- const lines = readFileSync(AUDIT_FILE, 'utf-8').split('\n').filter(Boolean);
149
- for (const line of lines) {
150
- let entry;
151
- try {
152
- entry = JSON.parse(line);
153
- }
154
- catch {
155
- continue;
156
- }
157
- if (entry.seq !== target)
158
- continue;
159
- if (json) {
160
- process.stdout.write(JSON.stringify(entry, null, 2) + '\n');
161
- }
162
- else {
163
- process.stdout.write('\n' +
164
- colors.bold(`Entry #${target}`) +
165
- (entry.ts ? colors.dim(' ' + new Date(entry.ts).toISOString()) : '') +
166
- '\n\n');
167
- for (const [k, v] of Object.entries(entry)) {
168
- const val = typeof v === 'string' && v.length > 120 ? v.slice(0, 117) + '...' : JSON.stringify(v);
169
- process.stdout.write(` ${colors.dim(k.padEnd(12))} ${val}\n`);
170
- }
171
- process.stdout.write('\n');
172
- }
173
- return 0;
174
- }
175
- process.stderr.write(colors.error(`${symbols.error} No entry with seq=${target}.\n`) +
176
- colors.dim(' Tip: run `codehere audit verify` to see the chained-entry count.\n'));
177
- return 2;
178
- }
179
- /* ──────────────────────────────────────────────────────────────────────── */
180
- /** R-AAT · export the chain as IETF draft-sharif-agent-audit-trail-00 JSONL.
181
- * The header line carries the honest scope notes (L0 trust level, codehere
182
- * canonicalization, hashed inputs) so the FILE can't claim more than it is. */
183
- function exportAatCmd(outPath) {
184
- const exp = exportAat(AUDIT_FILE);
185
- const target = outPath && outPath.trim() ? outPath.trim() : 'codehere-audit-aat.jsonl';
186
- try {
187
- writeFileSyncFs(target, aatToJsonl(exp), 'utf-8');
188
- }
189
- catch (e) {
190
- process.stderr.write(colors.error(`${symbols.error} Could not write ${target}: ${e instanceof Error ? e.message : String(e)}\n`));
191
- return 2;
192
- }
193
- process.stdout.write(colors.green(`${symbols.success} Exported ${exp.header.record_count} records`) +
194
- colors.dim(` › ${target} (AAT draft-00 JSONL)\n`) +
195
- (exp.skippedLegacy > 0
196
- ? colors.dim(` ${exp.skippedLegacy} legacy pre-chain entries skipped (no hash-chained position to export)\n`)
197
- : '') +
198
- colors.dim(' trust_level=L0 throughout · agents carry no cryptographic identity; the daemon signs the chain tip (recorder identity). Details in the header line.\n'));
199
- return 0;
200
- }
201
- //# sourceMappingURL=audit-command.js.map
@@ -1,79 +0,0 @@
1
- /**
2
- * `codehere budget` — read or set the daily-spend budget.
3
- *
4
- * Subcommands:
5
- * show — print current ceiling, today's spend, % used
6
- * set <usd> — set daily ceiling in USD (e.g. `codehere budget set 5`)
7
- * off — disable the budget (omits daily_usd from yaml)
8
- *
9
- * Reads + writes ~/.codehere/budget.yaml via budget-config.ts. Per
10
- * claim_user_persona HIGH the YAML is hand-editable; the CLI is the
11
- * fast path for users who want one number, one command.
12
- */
13
- import { loadBudget, saveBudget, budgetUsedPct, isOverBudget } from '../../../infrastructure/cost/budget-config.js';
14
- import { computeSpendToday } from '../../../infrastructure/cost/spend-aggregator.js';
15
- import { success, error, info, newline } from '../../../ui.js';
16
- export async function executeBudgetCommand(subcommand, value) {
17
- const sub = subcommand ?? 'show';
18
- switch (sub) {
19
- case 'show':
20
- return showBudget();
21
- case 'set':
22
- if (!value) {
23
- console.error(error('Usage:'), 'codehere budget set <amount-in-usd> e.g. codehere budget set 5');
24
- process.exit(1);
25
- }
26
- return setBudget(value);
27
- case 'off':
28
- return disableBudget();
29
- default:
30
- console.error(error('Unknown subcommand:'), sub);
31
- console.error(info('Try:'), 'codehere budget [show | set <usd> | off]');
32
- process.exit(1);
33
- }
34
- }
35
- function fmtUsd(n) {
36
- return n >= 0.01 ? `$${n.toFixed(2)}` : `$${n.toFixed(3)}`;
37
- }
38
- function showBudget() {
39
- const cfg = loadBudget();
40
- const spend = computeSpendToday();
41
- newline();
42
- console.log(info("Today's estimated spend:"), fmtUsd(spend.totalUsd), `(${spend.sessionCount} session${spend.sessionCount === 1 ? '' : 's'})`);
43
- if (cfg.dailyUsd === null) {
44
- console.log(info('Daily budget:'), 'none · no enforcement');
45
- console.log(info('Set one with:'), 'codehere budget set 5');
46
- }
47
- else {
48
- const pct = budgetUsedPct(spend.totalUsd, cfg) ?? 0;
49
- const over = isOverBudget(spend.totalUsd, cfg);
50
- console.log(info('Daily budget:'), fmtUsd(cfg.dailyUsd), `(${pct}% used)`);
51
- if (over) {
52
- console.log(error('Over budget.'), 'New spawns are blocked until midnight or the budget is raised.');
53
- }
54
- else if (pct >= cfg.warnAtPct) {
55
- console.log(info('Approaching limit.'), `Warn threshold is ${cfg.warnAtPct}%.`);
56
- }
57
- }
58
- newline();
59
- }
60
- function setBudget(value) {
61
- const n = Number(value.replace(/[$,]/g, ''));
62
- if (!Number.isFinite(n) || n <= 0) {
63
- console.error(error('Invalid amount:'), value, '· expected a positive USD number.');
64
- process.exit(1);
65
- }
66
- const cfg = loadBudget();
67
- cfg.dailyUsd = n;
68
- saveBudget(cfg);
69
- console.log(success('Daily budget set to'), fmtUsd(n));
70
- console.log(info("Spawns will be blocked once today's estimated spend reaches this amount."));
71
- console.log(info('Disable with:'), 'codehere budget off');
72
- }
73
- function disableBudget() {
74
- const cfg = loadBudget();
75
- cfg.dailyUsd = null;
76
- saveBudget(cfg);
77
- console.log(success('Daily budget disabled.'), 'No enforcement on spawns.');
78
- }
79
- //# sourceMappingURL=budget-command.js.map
@@ -1,125 +0,0 @@
1
- /**
2
- * Config Command
3
- * Manage Codehere configuration and preferences
4
- */
5
- import { colors, separator, newline, sectionHeader, success, error, createTable, isMinimalStyle } from '../../../ui.js';
6
- import { getConfigManager } from '../../../infrastructure/config/config-manager.js';
7
- import { executionTracer } from '../../../infrastructure/observability/execution-tracer.js';
8
- import { findCodebaseRoot } from '../../../domain/services/codebase-detector.js';
9
- /**
10
- * Display current configuration
11
- */
12
- function displayConfig(config) {
13
- sectionHeader('Current Configuration');
14
- const configRows = [
15
- ['Preference', 'Value'],
16
- ['Auto Commit', config.preferences.autoCommit ? 'Yes' : 'No'],
17
- ['Ask Before Destructive', config.preferences.askBeforeDestructive ? 'Yes' : 'No'],
18
- ['Cross-Team Learning', config.preferences.enableCrossTeamLearning ? 'Enabled' : 'Disabled'],
19
- ['Default Model', config.preferences.defaultModel || 'auto (detects from API key)'],
20
- ['Max Tokens', String(config.preferences.maxTokens || 4096)],
21
- ['Temperature', String(config.preferences.temperature || 0.3)],
22
- ['Streaming', config.preferences.enableStreaming ? 'Enabled' : 'Disabled'],
23
- ['Output Format', config.ui.outputFormat || 'full'],
24
- ['Show Progress', config.ui.showProgress ? 'Yes' : 'No'],
25
- ['Show Summary', config.ui.showSummary ? 'Yes' : 'No'],
26
- ];
27
- if (config.codebase.root) {
28
- configRows.push(['Codebase Root', config.codebase.root]);
29
- if (config.codebase.lastIndexed) {
30
- const date = new Date(config.codebase.lastIndexed);
31
- configRows.push(['Last Indexed', date.toLocaleString()]);
32
- }
33
- }
34
- const table = createTable(['Preference', 'Value'], configRows.slice(1));
35
- console.log(table.toString());
36
- newline();
37
- console.log(colors.dim(`Config file: ${getConfigManager().getConfigPath()}`));
38
- newline();
39
- }
40
- /**
41
- * Execute config command
42
- */
43
- export async function executeConfigCommand(action, key, value) {
44
- // Start execution tracing
45
- const codebaseInfo = findCodebaseRoot(process.cwd());
46
- executionTracer.startRun('config', {
47
- codebaseId: codebaseInfo?.rootPath || process.cwd(),
48
- });
49
- try {
50
- if (!isMinimalStyle()) {
51
- newline();
52
- console.log(separator('═', 80));
53
- console.log(colors.bold('Codehere - Configuration Manager'));
54
- console.log(separator('═', 80));
55
- newline();
56
- }
57
- const configManager = getConfigManager();
58
- const config = configManager.getAll();
59
- // No action - show current config
60
- if (!action || action === 'show' || action === 'list') {
61
- displayConfig(config);
62
- return;
63
- }
64
- // Get value
65
- if (action === 'get' && key) {
66
- const preference = configManager.getPreference(key);
67
- if (preference !== undefined) {
68
- console.log(preference);
69
- }
70
- else {
71
- console.error(error(`Preference '${key}' not found.`));
72
- process.exit(1);
73
- }
74
- return;
75
- }
76
- // Set value
77
- if (action === 'set' && key && value !== undefined) {
78
- try {
79
- // Parse value (boolean, number, or string)
80
- let parsedValue = value;
81
- if (value.toLowerCase() === 'true')
82
- parsedValue = true;
83
- else if (value.toLowerCase() === 'false')
84
- parsedValue = false;
85
- else if (!isNaN(Number(value)))
86
- parsedValue = Number(value);
87
- configManager.setPreference(key, parsedValue);
88
- configManager.saveConfig();
89
- console.log(success(`Set ${key} = ${parsedValue}`));
90
- }
91
- catch (err) {
92
- console.error(error(`Failed to set preference: ${err instanceof Error ? err.message : String(err)}`));
93
- process.exit(1);
94
- }
95
- return;
96
- }
97
- // Reset to defaults
98
- if (action === 'reset') {
99
- configManager.reset();
100
- console.log(success('Configuration reset to defaults'));
101
- newline();
102
- displayConfig(configManager.getAll());
103
- return;
104
- }
105
- // Invalid action
106
- console.error(error(`Unknown action: ${action}`));
107
- newline();
108
- console.log(colors.bold('Usage:'));
109
- console.log(colors.cyan(' codehere config Show current configuration'));
110
- console.log(colors.cyan(' codehere config get <key> Get a preference value'));
111
- console.log(colors.cyan(' codehere config set <key> <value> Set a preference value'));
112
- console.log(colors.cyan(' codehere config reset Reset to defaults'));
113
- newline();
114
- console.log(colors.bold('Examples:'));
115
- console.log(colors.dim(' codehere config set autoCommit true'));
116
- console.log(colors.dim(' codehere config set temperature 0.5'));
117
- console.log(colors.dim(' codehere config get defaultModel'));
118
- newline();
119
- process.exit(1);
120
- }
121
- finally {
122
- executionTracer.endRun();
123
- }
124
- }
125
- //# sourceMappingURL=config-command.js.map