avorelo 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (258) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +56 -0
  3. package/bin/avorelo +9 -0
  4. package/package.json +135 -0
  5. package/scripts/README.md +40 -0
  6. package/scripts/cco-dashboard.js +252 -0
  7. package/scripts/cco-status.js +430 -0
  8. package/scripts/lib/activation/account-state.js +37 -0
  9. package/scripts/lib/activation/activation-runner.js +546 -0
  10. package/scripts/lib/activation/activation-self-healing.js +480 -0
  11. package/scripts/lib/activation/activation-state.js +83 -0
  12. package/scripts/lib/activation/activation-summary.js +191 -0
  13. package/scripts/lib/activation/adapters/claude-code.js +77 -0
  14. package/scripts/lib/activation/adapters/codex-cli.js +52 -0
  15. package/scripts/lib/activation/adapters/cursor.js +37 -0
  16. package/scripts/lib/activation/adapters/github-agent.js +39 -0
  17. package/scripts/lib/activation/adapters/terminal.js +42 -0
  18. package/scripts/lib/activation/adapters/vscode.js +39 -0
  19. package/scripts/lib/activation/adapters/windsurf.js +37 -0
  20. package/scripts/lib/activation/ai-surface-detector.js +151 -0
  21. package/scripts/lib/activation/connect-account.js +145 -0
  22. package/scripts/lib/activation/detect-environment.js +75 -0
  23. package/scripts/lib/activation/detect-hosts.js +62 -0
  24. package/scripts/lib/activation/format-activation-output.js +109 -0
  25. package/scripts/lib/activation/next-action.js +43 -0
  26. package/scripts/lib/activation/repair-engine.js +219 -0
  27. package/scripts/lib/activation-distribution-readiness.js +507 -0
  28. package/scripts/lib/adapter-conformance.js +176 -0
  29. package/scripts/lib/adapter-readiness.js +417 -0
  30. package/scripts/lib/adapter-safety-boundaries.js +335 -0
  31. package/scripts/lib/adapter-technical-readiness-gate.js +205 -0
  32. package/scripts/lib/agent-access-governance.js +455 -0
  33. package/scripts/lib/agent-enforcement.js +765 -0
  34. package/scripts/lib/agent-policy-profile.js +210 -0
  35. package/scripts/lib/agent-security/action-evaluator.js +507 -0
  36. package/scripts/lib/agent-security/adapter-registry.js +98 -0
  37. package/scripts/lib/agent-security/auto-policy.js +139 -0
  38. package/scripts/lib/agent-security/bounded-scan.js +93 -0
  39. package/scripts/lib/agent-security/enforcement-adapter.js +174 -0
  40. package/scripts/lib/agent-security/enforcement-engine.js +1129 -0
  41. package/scripts/lib/agent-security/file-write-adapter.js +183 -0
  42. package/scripts/lib/agent-security/file-write-rules.js +178 -0
  43. package/scripts/lib/agent-security/index.js +3342 -0
  44. package/scripts/lib/agent-security/instruction-risk.js +181 -0
  45. package/scripts/lib/agent-security/mcp-action-adapter.js +185 -0
  46. package/scripts/lib/agent-security/mcp-action-rules.js +184 -0
  47. package/scripts/lib/agent-security/package-action-adapter.js +175 -0
  48. package/scripts/lib/agent-security/package-action-rules.js +233 -0
  49. package/scripts/lib/agent-security/performance.js +148 -0
  50. package/scripts/lib/agent-security/permission-minimizer.js +403 -0
  51. package/scripts/lib/agent-security/scan-cache.js +74 -0
  52. package/scripts/lib/agent-security/source-trust.js +146 -0
  53. package/scripts/lib/ai-install-prompt.js +288 -0
  54. package/scripts/lib/ai-workspace-hygiene.js +1499 -0
  55. package/scripts/lib/alpha-activation.js +520 -0
  56. package/scripts/lib/alpha-feedback.js +263 -0
  57. package/scripts/lib/alpha-readiness-gate.js +332 -0
  58. package/scripts/lib/anti-gaming.js +169 -0
  59. package/scripts/lib/artifact-health.js +431 -0
  60. package/scripts/lib/attribution.js +180 -0
  61. package/scripts/lib/audit.js +289 -0
  62. package/scripts/lib/avorelo-skill-registry.js +810 -0
  63. package/scripts/lib/batch-jobs.js +71 -0
  64. package/scripts/lib/brain-pack.js +578 -0
  65. package/scripts/lib/brand-boundary.js +424 -0
  66. package/scripts/lib/brand.js +74 -0
  67. package/scripts/lib/browser-capability.js +1048 -0
  68. package/scripts/lib/browser-proof-preflight.js +321 -0
  69. package/scripts/lib/cache-readiness.js +187 -0
  70. package/scripts/lib/canonical-reentry.js +162 -0
  71. package/scripts/lib/capability-packs.js +314 -0
  72. package/scripts/lib/capability-recommender.js +512 -0
  73. package/scripts/lib/capability-registry.js +1059 -0
  74. package/scripts/lib/carry-forward-surfacing.js +194 -0
  75. package/scripts/lib/ccusage-adapter.js +188 -0
  76. package/scripts/lib/company-loop.js +1149 -0
  77. package/scripts/lib/config.js +637 -0
  78. package/scripts/lib/context-acquisition-plan.js +287 -0
  79. package/scripts/lib/context-budget-guard.js +170 -0
  80. package/scripts/lib/context-budget-scanner.js +257 -0
  81. package/scripts/lib/context-optimizer.js +715 -0
  82. package/scripts/lib/context-reduction-plan.js +178 -0
  83. package/scripts/lib/context-safety.js +88 -0
  84. package/scripts/lib/context-savings-engine.js +158 -0
  85. package/scripts/lib/cost-evidence.js +254 -0
  86. package/scripts/lib/cross-host-install-plan.js +308 -0
  87. package/scripts/lib/cross-host-install-readiness.js +237 -0
  88. package/scripts/lib/cross-host-value-flow.js +268 -0
  89. package/scripts/lib/dashboard.js +900 -0
  90. package/scripts/lib/design-partner-feedback.js +346 -0
  91. package/scripts/lib/entitlements.js +100 -0
  92. package/scripts/lib/execution-packet.js +559 -0
  93. package/scripts/lib/experimentation-events.js +547 -0
  94. package/scripts/lib/external-capability-compliance.js +107 -0
  95. package/scripts/lib/external-user-simulation.js +166 -0
  96. package/scripts/lib/failure-recovery-readiness.js +81 -0
  97. package/scripts/lib/failure-recovery.js +419 -0
  98. package/scripts/lib/feedback-intelligence.js +537 -0
  99. package/scripts/lib/feedback-signals.js +205 -0
  100. package/scripts/lib/file-integrity.js +68 -0
  101. package/scripts/lib/fsx.js +127 -0
  102. package/scripts/lib/full-readiness-gate.js +451 -0
  103. package/scripts/lib/guidance-builder.js +174 -0
  104. package/scripts/lib/hook-apply.js +1019 -0
  105. package/scripts/lib/hook-baseline.js +310 -0
  106. package/scripts/lib/hook-config-preview.js +275 -0
  107. package/scripts/lib/hook-contracts.js +290 -0
  108. package/scripts/lib/hook-safety-boundary-readiness.js +80 -0
  109. package/scripts/lib/host-capability-matrix.js +351 -0
  110. package/scripts/lib/host-support-context.js +254 -0
  111. package/scripts/lib/http-hook-action.js +538 -0
  112. package/scripts/lib/install-ai-readiness.js +84 -0
  113. package/scripts/lib/install-intake-risk.js +1037 -0
  114. package/scripts/lib/install-journey-intelligence.js +329 -0
  115. package/scripts/lib/intervention-guidance.js +57 -0
  116. package/scripts/lib/known-limitations.js +115 -0
  117. package/scripts/lib/l8-path-truth.js +146 -0
  118. package/scripts/lib/launch-hardening-gate.js +436 -0
  119. package/scripts/lib/launch-readiness.js +628 -0
  120. package/scripts/lib/learning-memory.js +686 -0
  121. package/scripts/lib/lifecycle-hooks.js +802 -0
  122. package/scripts/lib/local-package-smoke.js +423 -0
  123. package/scripts/lib/local-pricing.js +299 -0
  124. package/scripts/lib/mcp-enforcement.js +311 -0
  125. package/scripts/lib/mcp-least-privilege-policy.js +303 -0
  126. package/scripts/lib/mcp-tool-inventory.js +388 -0
  127. package/scripts/lib/mcp-tool-risk.js +0 -0
  128. package/scripts/lib/memory.js +335 -0
  129. package/scripts/lib/metrics.js +699 -0
  130. package/scripts/lib/micro-proof.js +133 -0
  131. package/scripts/lib/next-run-context.js +436 -0
  132. package/scripts/lib/operating-value.js +1648 -0
  133. package/scripts/lib/optimization-v3.js +122 -0
  134. package/scripts/lib/orchestration/adapters/_shared.js +49 -0
  135. package/scripts/lib/orchestration/adapters/aider.js +18 -0
  136. package/scripts/lib/orchestration/adapters/claude-code.js +35 -0
  137. package/scripts/lib/orchestration/adapters/codex.js +35 -0
  138. package/scripts/lib/orchestration/adapters/gemini-cli.js +18 -0
  139. package/scripts/lib/orchestration/adapters/git.js +25 -0
  140. package/scripts/lib/orchestration/adapters/index.js +31 -0
  141. package/scripts/lib/orchestration/adapters/lm-studio.js +18 -0
  142. package/scripts/lib/orchestration/adapters/ollama.js +18 -0
  143. package/scripts/lib/orchestration/adapters/opencode.js +18 -0
  144. package/scripts/lib/orchestration/adapters/openrouter.js +18 -0
  145. package/scripts/lib/orchestration/adapters/test-runner.js +25 -0
  146. package/scripts/lib/orchestration/cli.js +438 -0
  147. package/scripts/lib/orchestration/execution-manager.js +279 -0
  148. package/scripts/lib/orchestration/handoff.js +314 -0
  149. package/scripts/lib/orchestration/index.js +456 -0
  150. package/scripts/lib/orchestration/inventory.js +47 -0
  151. package/scripts/lib/orchestration/model-discovery.js +498 -0
  152. package/scripts/lib/orchestration/model-profiler.js +170 -0
  153. package/scripts/lib/orchestration/model-profiles.js +252 -0
  154. package/scripts/lib/orchestration/model-refresh-policy.js +72 -0
  155. package/scripts/lib/orchestration/proof-writer.js +349 -0
  156. package/scripts/lib/orchestration/provider-discovery/aider.js +49 -0
  157. package/scripts/lib/orchestration/provider-discovery/claude-code.js +56 -0
  158. package/scripts/lib/orchestration/provider-discovery/codex.js +49 -0
  159. package/scripts/lib/orchestration/provider-discovery/common.js +186 -0
  160. package/scripts/lib/orchestration/provider-discovery/gemini.js +106 -0
  161. package/scripts/lib/orchestration/provider-discovery/lm-studio.js +118 -0
  162. package/scripts/lib/orchestration/provider-discovery/models-dev.js +12 -0
  163. package/scripts/lib/orchestration/provider-discovery/ollama.js +100 -0
  164. package/scripts/lib/orchestration/provider-discovery/opencode.js +47 -0
  165. package/scripts/lib/orchestration/provider-discovery/openrouter.js +44 -0
  166. package/scripts/lib/orchestration/risk-classifier.js +130 -0
  167. package/scripts/lib/orchestration/routing-policy.js +486 -0
  168. package/scripts/lib/orchestration/settings.js +112 -0
  169. package/scripts/lib/orchestration/state.js +165 -0
  170. package/scripts/lib/orchestration/verification-manager.js +138 -0
  171. package/scripts/lib/output-profiles.js +146 -0
  172. package/scripts/lib/package-content-audit.js +368 -0
  173. package/scripts/lib/package-runtime.js +278 -0
  174. package/scripts/lib/plan-surface.js +53 -0
  175. package/scripts/lib/plans.js +2318 -0
  176. package/scripts/lib/policy-provider.js +27 -0
  177. package/scripts/lib/prelaunch-activation-readiness.js +409 -0
  178. package/scripts/lib/prelaunch-evidence-store.js +816 -0
  179. package/scripts/lib/prelaunch-intelligence.js +869 -0
  180. package/scripts/lib/pricing-experiment.js +118 -0
  181. package/scripts/lib/pro-moment-events.js +77 -0
  182. package/scripts/lib/pro-moment-state.js +227 -0
  183. package/scripts/lib/pro-moments.js +1216 -0
  184. package/scripts/lib/product-learning-events.js +629 -0
  185. package/scripts/lib/project-profile.js +555 -0
  186. package/scripts/lib/prompt-compiler.js +280 -0
  187. package/scripts/lib/prompt-lint.js +32 -0
  188. package/scripts/lib/prompt-suggestions.js +52 -0
  189. package/scripts/lib/proof-canonical.js +398 -0
  190. package/scripts/lib/proof-drilldown.js +383 -0
  191. package/scripts/lib/proof-events.js +342 -0
  192. package/scripts/lib/proof-history.js +243 -0
  193. package/scripts/lib/proof-metrics.js +296 -0
  194. package/scripts/lib/proof-outcome-evidence.js +134 -0
  195. package/scripts/lib/proof-receipt.js +335 -0
  196. package/scripts/lib/proof-record.js +461 -0
  197. package/scripts/lib/public-activation-distribution-gate.js +258 -0
  198. package/scripts/lib/public-cli.js +3891 -0
  199. package/scripts/lib/public-distribution-truth.js +211 -0
  200. package/scripts/lib/public-install-claim-checker.js +294 -0
  201. package/scripts/lib/publish-provenance-readiness.js +283 -0
  202. package/scripts/lib/readiness-delta.js +218 -0
  203. package/scripts/lib/readiness-evidence-closure.js +196 -0
  204. package/scripts/lib/reentry-memory-capture.js +241 -0
  205. package/scripts/lib/reentry-memory-retrieval.js +302 -0
  206. package/scripts/lib/reentry-memory-status.js +146 -0
  207. package/scripts/lib/reentry-memory-store.js +178 -0
  208. package/scripts/lib/reentry-state.js +66 -0
  209. package/scripts/lib/release-candidate-bundle.js +166 -0
  210. package/scripts/lib/remediation.js +81 -0
  211. package/scripts/lib/repo-map.js +391 -0
  212. package/scripts/lib/run-improvements-lifecycle.js +330 -0
  213. package/scripts/lib/run-improvements.js +789 -0
  214. package/scripts/lib/runtime-decision-policy.js +387 -0
  215. package/scripts/lib/safe-path-engine.js +705 -0
  216. package/scripts/lib/safe-run-controller.js +887 -0
  217. package/scripts/lib/score.js +262 -0
  218. package/scripts/lib/seamless-enforcement.js +329 -0
  219. package/scripts/lib/seamless-outcome.js +689 -0
  220. package/scripts/lib/seamless-reality-gate.js +5043 -0
  221. package/scripts/lib/security-risk-classifier.js +511 -0
  222. package/scripts/lib/security-scan.js +384 -0
  223. package/scripts/lib/session-context-optimizer.js +1211 -0
  224. package/scripts/lib/session-timing.js +315 -0
  225. package/scripts/lib/skill-hygiene.js +805 -0
  226. package/scripts/lib/skill-packs.js +161 -0
  227. package/scripts/lib/skills-operating-layer.js +580 -0
  228. package/scripts/lib/smart-work-routing.js +768 -0
  229. package/scripts/lib/source-catalog.js +700 -0
  230. package/scripts/lib/status-value-summary.js +32 -0
  231. package/scripts/lib/support-bundle.js +578 -0
  232. package/scripts/lib/task-continuation.js +440 -0
  233. package/scripts/lib/test-helpers.js +15 -0
  234. package/scripts/lib/tier.js +38 -0
  235. package/scripts/lib/token-context-quality-gate.js +370 -0
  236. package/scripts/lib/token-cost-capture.js +187 -0
  237. package/scripts/lib/token-cost-intelligence.js +358 -0
  238. package/scripts/lib/token-efficiency-evidence.js +213 -0
  239. package/scripts/lib/token-evidence.js +699 -0
  240. package/scripts/lib/tokenish.js +17 -0
  241. package/scripts/lib/tool-output-sandbox.js +304 -0
  242. package/scripts/lib/trust-audit.js +136 -0
  243. package/scripts/lib/unified-events.js +396 -0
  244. package/scripts/lib/upgrade-interruption-recovery.js +407 -0
  245. package/scripts/lib/usage-ledger.js +201 -0
  246. package/scripts/lib/value-ledger.js +130 -0
  247. package/scripts/lib/value-proof-calibration.js +531 -0
  248. package/scripts/lib/visual-qa.js +231 -0
  249. package/scripts/lib/voice-alpha.js +29 -0
  250. package/scripts/lib/work-aware-orchestration.js +976 -0
  251. package/scripts/lib/work-control-receipts.js +577 -0
  252. package/scripts/lib/work-ledger.js +1123 -0
  253. package/scripts/lib/work-panel-preview.js +352 -0
  254. package/scripts/lib/workflow-discipline.js +280 -0
  255. package/scripts/lib/workflow-signals.js +419 -0
  256. package/scripts/lib/workspace-map.js +281 -0
  257. package/scripts/lib/workspace-registry.js +1367 -0
  258. package/scripts/lib/workspace-resolver.js +480 -0
@@ -0,0 +1,310 @@
1
+ "use strict";
2
+
3
+ const fs = require("node:fs");
4
+ const path = require("node:path");
5
+
6
+ const CONTRACT = "avorelo.hookBaseline.v1";
7
+ const SCHEMA_VERSION = 1;
8
+
9
+ const BASELINE_DIR_REL = ".claude/cco/orchestration/hook-baseline";
10
+ const LATEST_BASELINE_REL = `${BASELINE_DIR_REL}/latest-baseline.json`;
11
+
12
+ const LIFECYCLE_EVENTS = Object.freeze([
13
+ "SessionStart",
14
+ "UserPromptSubmit",
15
+ "PreToolUse",
16
+ "PostToolUse",
17
+ "Stop",
18
+ "SessionEnd",
19
+ ]);
20
+
21
+ // Blocking: PreToolUse (guard/packet enforcement), Stop (proof gate)
22
+ // UserPromptSubmit: blocking only when prohibited/destructive intent detected
23
+ // SessionStart, PostToolUse, SessionEnd: non-blocking
24
+ const BLOCKING_EVENTS = Object.freeze(["PreToolUse", "Stop"]);
25
+ const CONDITIONALLY_BLOCKING_EVENTS = Object.freeze(["UserPromptSubmit"]);
26
+ const NON_BLOCKING_EVENTS = Object.freeze(["SessionStart", "PostToolUse", "SessionEnd"]);
27
+
28
+ function ensureDir(dir) {
29
+ fs.mkdirSync(dir, { recursive: true });
30
+ }
31
+
32
+ function safeWriteJson(filePath, data) {
33
+ ensureDir(path.dirname(filePath));
34
+ fs.writeFileSync(filePath, `${JSON.stringify(data, null, 2)}\n`, "utf8");
35
+ }
36
+
37
+ function nowIso() {
38
+ return new Date().toISOString();
39
+ }
40
+
41
+ function getBaselineHookDefinitions() {
42
+ return [
43
+ {
44
+ hookId: "session-start",
45
+ event: "SessionStart",
46
+ blocking: false,
47
+ purpose: "Prepare project/workspace state for the session. Load project profile, run workspace hygiene summary, and prepare run/session state.",
48
+ defaultMode: "automatic",
49
+ capabilities: [
50
+ "ai_coding_readiness",
51
+ "ai_workspace_hygiene_basic",
52
+ "project_profile_basic",
53
+ ],
54
+ inputs: ["cwd", "session_context"],
55
+ outputs: ["session_state", "profile_summary", "workspace_status"],
56
+ command: "node bin/avorelo lifecycle-hook session-start --json",
57
+ writesLedger: true,
58
+ writesProof: false,
59
+ customerVisible: false,
60
+ debugVisible: true,
61
+ safeDefault: true,
62
+ reasonCodes: [
63
+ "NON_BLOCKING_PHASE",
64
+ "SESSION_STATE_PREPARATION",
65
+ "PROFILE_LOADED",
66
+ ],
67
+ redacted: true,
68
+ },
69
+ {
70
+ hookId: "user-prompt-submit",
71
+ event: "UserPromptSubmit",
72
+ blocking: false,
73
+ blockingCondition: "Blocking only when prompt explicitly asks for prohibited/destructive/secrets/deploy/prod action.",
74
+ purpose: "Classify the task, prepare/update execution packet, smart-route, and build a safe run plan. Non-blocking by default; blocking if the prompt is prohibited.",
75
+ defaultMode: "automatic",
76
+ capabilities: [
77
+ "smart_route_hook_binding_basic",
78
+ "execution_packet_hook_binding_basic",
79
+ "safe_run_hook_binding_basic",
80
+ "hook_baseline_registry_basic",
81
+ ],
82
+ inputs: ["prompt_text", "session_context", "cwd"],
83
+ outputs: ["execution_packet", "safe_run_plan", "route_decision", "blocking_decision"],
84
+ command: "node bin/avorelo lifecycle-hook user-prompt-submit --json",
85
+ writesLedger: true,
86
+ writesProof: false,
87
+ customerVisible: false,
88
+ debugVisible: true,
89
+ safeDefault: true,
90
+ reasonCodes: [
91
+ "TASK_CLASSIFICATION",
92
+ "EXECUTION_PACKET_PREPARED",
93
+ "SMART_ROUTE_DECIDED",
94
+ "SAFE_RUN_PLAN_BUILT",
95
+ "BLOCKING_ONLY_FOR_PROHIBITED_PROMPTS",
96
+ ],
97
+ redacted: true,
98
+ },
99
+ {
100
+ hookId: "pre-tool-use",
101
+ event: "PreToolUse",
102
+ blocking: true,
103
+ purpose: "Enforce packet boundaries, run guard/safe-path for tool/action/target. Block destructive/secrets/deploy/prod actions. Return structured decision: allow|warn|approval_required|block.",
104
+ defaultMode: "automatic",
105
+ capabilities: [
106
+ "pre_tool_use_guard_mapping_basic",
107
+ "execution_packet_hook_binding_basic",
108
+ "safe_run_hook_binding_basic",
109
+ ],
110
+ inputs: ["tool_name", "tool_input", "execution_packet", "cwd"],
111
+ outputs: ["decision", "safeNextAction", "reasonCodes", "ledger_receipt"],
112
+ command: "node bin/avorelo lifecycle-hook pre-tool-use --json",
113
+ writesLedger: true,
114
+ writesProof: false,
115
+ customerVisible: false,
116
+ debugVisible: true,
117
+ safeDefault: true,
118
+ reasonCodes: [
119
+ "BLOCKING_HOOK",
120
+ "PACKET_BOUNDARY_ENFORCED",
121
+ "GUARD_SAFE_PATH_APPLIED",
122
+ "DESTRUCTIVE_BLOCKED",
123
+ "SECRETS_BLOCKED",
124
+ "DEPLOY_PROD_BLOCKED",
125
+ ],
126
+ redacted: true,
127
+ },
128
+ {
129
+ hookId: "post-tool-use",
130
+ event: "PostToolUse",
131
+ blocking: false,
132
+ purpose: "Record tool/action result summary, write ledger entry and product-learning event. No raw output dump.",
133
+ defaultMode: "automatic",
134
+ capabilities: [
135
+ "post_tool_use_ledger_mapping_basic",
136
+ ],
137
+ inputs: ["tool_name", "tool_result_summary", "execution_packet", "cwd"],
138
+ outputs: ["ledger_entry", "product_learning_event"],
139
+ command: "node bin/avorelo lifecycle-hook post-tool-use --json",
140
+ writesLedger: true,
141
+ writesProof: false,
142
+ customerVisible: false,
143
+ debugVisible: true,
144
+ safeDefault: true,
145
+ reasonCodes: [
146
+ "NON_BLOCKING_PHASE",
147
+ "LEDGER_UPDATED",
148
+ "PRODUCT_LEARNING_RECORDED",
149
+ "NO_RAW_OUTPUT_DUMP",
150
+ ],
151
+ redacted: true,
152
+ },
153
+ {
154
+ hookId: "stop",
155
+ event: "Stop",
156
+ blocking: true,
157
+ purpose: "Check whether proof is required from execution packet/safe-run. If proof required and missing, block and require continuation. If proof exists or not required, allow.",
158
+ defaultMode: "automatic",
159
+ capabilities: [
160
+ "stop_proof_gate_mapping_basic",
161
+ ],
162
+ inputs: ["execution_packet", "safe_run_result", "cwd"],
163
+ outputs: ["proof_status", "blocking_decision", "safeNextAction"],
164
+ command: "node bin/avorelo lifecycle-hook stop --json",
165
+ writesLedger: true,
166
+ writesProof: true,
167
+ customerVisible: false,
168
+ debugVisible: true,
169
+ safeDefault: true,
170
+ reasonCodes: [
171
+ "BLOCKING_HOOK",
172
+ "PROOF_GATE_APPLIED",
173
+ "PROOF_REQUIRED_IF_CODE_CHANGE",
174
+ "SAFE_NEXT_ACTION_PROVIDED",
175
+ ],
176
+ redacted: true,
177
+ },
178
+ {
179
+ hookId: "session-end",
180
+ event: "SessionEnd",
181
+ blocking: false,
182
+ purpose: "Run outcome summary, update ledger, run company-loop, prepare handoff summary. Non-blocking. Compact output.",
183
+ defaultMode: "automatic",
184
+ capabilities: [
185
+ "session_end_summary_handoff_mapping_basic",
186
+ ],
187
+ inputs: ["session_context", "ledger_state", "cwd"],
188
+ outputs: ["outcome_summary", "ledger_update", "company_loop_update", "handoff_summary"],
189
+ command: "node bin/avorelo lifecycle-hook session-end --json",
190
+ writesLedger: true,
191
+ writesProof: false,
192
+ customerVisible: false,
193
+ debugVisible: true,
194
+ safeDefault: true,
195
+ reasonCodes: [
196
+ "NON_BLOCKING_PHASE",
197
+ "OUTCOME_WRITTEN",
198
+ "LEDGER_UPDATED",
199
+ "COMPANY_LOOP_UPDATED",
200
+ "HANDOFF_PREPARED",
201
+ ],
202
+ redacted: true,
203
+ },
204
+ ];
205
+ }
206
+
207
+ function buildHookBindingMap(cwd, options = {}) {
208
+ const defs = getBaselineHookDefinitions();
209
+ const map = {};
210
+ for (const def of defs) {
211
+ map[def.event] = {
212
+ hookId: def.hookId,
213
+ blocking: def.blocking,
214
+ blockingCondition: def.blockingCondition || null,
215
+ command: def.command,
216
+ capabilities: def.capabilities,
217
+ writesLedger: def.writesLedger,
218
+ writesProof: def.writesProof,
219
+ safeDefault: def.safeDefault,
220
+ reasonCodes: def.reasonCodes,
221
+ redacted: true,
222
+ };
223
+ }
224
+ return map;
225
+ }
226
+
227
+ function buildHookBaseline(cwd, options = {}) {
228
+ const defs = getBaselineHookDefinitions();
229
+ const bindingMap = buildHookBindingMap(cwd, options);
230
+
231
+ const blockingEvents = defs.filter((d) => d.blocking).map((d) => d.event);
232
+ const nonBlockingEvents = defs.filter((d) => !d.blocking).map((d) => d.event);
233
+
234
+ return {
235
+ contract: CONTRACT,
236
+ schemaVersion: SCHEMA_VERSION,
237
+ createdAt: nowIso(),
238
+ status: "ready",
239
+ hookCount: defs.length,
240
+ eventsRegistered: LIFECYCLE_EVENTS.slice(),
241
+ blockingEvents,
242
+ nonBlockingEvents,
243
+ conditionallyBlockingEvents: CONDITIONALLY_BLOCKING_EVENTS.slice(),
244
+ hooks: defs,
245
+ bindingMap,
246
+ installStatus: "preview_only",
247
+ installNote: "No user config has been modified. Hooks are preview/readiness only. Apply requires explicit user approval.",
248
+ approvalRequiredBeforeApply: true,
249
+ redacted: true,
250
+ };
251
+ }
252
+
253
+ function writeHookBaseline(cwd, baseline) {
254
+ const absPath = path.join(cwd, LATEST_BASELINE_REL);
255
+ ensureDir(path.dirname(absPath));
256
+ safeWriteJson(absPath, baseline);
257
+ return { path: LATEST_BASELINE_REL, written: true };
258
+ }
259
+
260
+ function buildHookBaselineSurface(cwd, options = {}) {
261
+ const baseline = buildHookBaseline(cwd, options);
262
+ const writeResult = writeHookBaseline(cwd, baseline);
263
+ return { baseline, writeResult };
264
+ }
265
+
266
+ function formatHookBaselineText(baseline, options = {}) {
267
+ const debug = options.debug || false;
268
+
269
+ const lines = [
270
+ "Avorelo hook baseline: ready.",
271
+ "",
272
+ `Events registered: ${baseline.eventsRegistered.join(", ")}`,
273
+ `Blocking: ${baseline.blockingEvents.join(", ")}`,
274
+ `Non-blocking: ${baseline.nonBlockingEvents.join(", ")}`,
275
+ `Conditionally blocking: ${baseline.conditionallyBlockingEvents.join(", ")} (prohibited/destructive prompts only)`,
276
+ "",
277
+ "Status: preview only. No user config has been modified.",
278
+ `Hooks: ${baseline.hookCount} defined. Apply requires explicit user approval.`,
279
+ ];
280
+
281
+ if (debug) {
282
+ lines.push("", "Hook commands:");
283
+ for (const hook of baseline.hooks) {
284
+ lines.push(` [${hook.event}] ${hook.blocking ? "blocking" : "non-blocking"} — ${hook.command}`);
285
+ lines.push(` Purpose: ${hook.purpose}`);
286
+ lines.push(` Capabilities: ${hook.capabilities.join(", ")}`);
287
+ if (hook.blockingCondition) {
288
+ lines.push(` Blocking condition: ${hook.blockingCondition}`);
289
+ }
290
+ }
291
+ }
292
+
293
+ return lines.join("\n");
294
+ }
295
+
296
+ module.exports = {
297
+ CONTRACT,
298
+ SCHEMA_VERSION,
299
+ LATEST_BASELINE_REL,
300
+ LIFECYCLE_EVENTS,
301
+ BLOCKING_EVENTS,
302
+ CONDITIONALLY_BLOCKING_EVENTS,
303
+ NON_BLOCKING_EVENTS,
304
+ getBaselineHookDefinitions,
305
+ buildHookBindingMap,
306
+ buildHookBaseline,
307
+ writeHookBaseline,
308
+ buildHookBaselineSurface,
309
+ formatHookBaselineText,
310
+ };
@@ -0,0 +1,275 @@
1
+ "use strict";
2
+
3
+ const fs = require("node:fs");
4
+ const path = require("node:path");
5
+
6
+ const CONTRACT = "avorelo.hookConfigPreview.v1";
7
+ const SCHEMA_VERSION = 1;
8
+
9
+ const PREVIEW_DIR_REL = ".claude/cco/orchestration/hook-baseline";
10
+ const LATEST_PREVIEW_JSON_REL = `${PREVIEW_DIR_REL}/latest-preview.json`;
11
+ const LATEST_PREVIEW_MD_REL = `${PREVIEW_DIR_REL}/latest-preview.md`;
12
+
13
+ // The lifecycle-hook commands that would be wired up
14
+ const LIFECYCLE_HOOK_COMMANDS = Object.freeze([
15
+ { event: "SessionStart", command: "node bin/avorelo lifecycle-hook session-start --json", blocking: false },
16
+ { event: "UserPromptSubmit", command: "node bin/avorelo lifecycle-hook user-prompt-submit --json", blocking: false },
17
+ { event: "PreToolUse", command: "node bin/avorelo lifecycle-hook pre-tool-use --json", blocking: true },
18
+ { event: "PostToolUse", command: "node bin/avorelo lifecycle-hook post-tool-use --json", blocking: false },
19
+ { event: "Stop", command: "node bin/avorelo lifecycle-hook stop --json", blocking: true },
20
+ { event: "SessionEnd", command: "node bin/avorelo lifecycle-hook session-end --json", blocking: false },
21
+ ]);
22
+
23
+ function ensureDir(dir) {
24
+ fs.mkdirSync(dir, { recursive: true });
25
+ }
26
+
27
+ function nowIso() {
28
+ return new Date().toISOString();
29
+ }
30
+
31
+ function safeWriteJson(filePath, data) {
32
+ ensureDir(path.dirname(filePath));
33
+ fs.writeFileSync(filePath, `${JSON.stringify(data, null, 2)}\n`, "utf8");
34
+ }
35
+
36
+ function safeWriteText(filePath, text) {
37
+ ensureDir(path.dirname(filePath));
38
+ fs.writeFileSync(filePath, text, "utf8");
39
+ }
40
+
41
+ function buildHostPreview(host) {
42
+ if (host === "claude_code") {
43
+ return {
44
+ host,
45
+ label: "Claude Code",
46
+ configPath: ".claude/settings.json",
47
+ wouldAddFormat: "hooks array in settings.json",
48
+ note: "Preview only. settings.json will NOT be modified without explicit user approval.",
49
+ exampleStructure: {
50
+ hooks: LIFECYCLE_HOOK_COMMANDS.map((lh) => ({
51
+ event: lh.event,
52
+ command: lh.command,
53
+ blocking: lh.blocking,
54
+ })),
55
+ },
56
+ };
57
+ }
58
+ if (host === "openhands") {
59
+ return {
60
+ host,
61
+ label: "OpenHands",
62
+ configPath: ".openhands/hooks.json",
63
+ wouldAddFormat: "hooks.json entries",
64
+ note: "Preview only. hooks.json will NOT be modified without explicit user approval.",
65
+ exampleStructure: {
66
+ hooks: LIFECYCLE_HOOK_COMMANDS.map((lh) => ({
67
+ event: lh.event,
68
+ command: lh.command,
69
+ blocking: lh.blocking,
70
+ })),
71
+ },
72
+ };
73
+ }
74
+ // generic_cli
75
+ return {
76
+ host: "generic_cli",
77
+ label: "Generic CLI",
78
+ configPath: null,
79
+ wouldAddFormat: "manual shell integration",
80
+ note: "Generic CLI mode. No config file to modify. Commands can be run manually.",
81
+ exampleStructure: {
82
+ commands: LIFECYCLE_HOOK_COMMANDS.map((lh) => ({
83
+ event: lh.event,
84
+ command: lh.command,
85
+ blocking: lh.blocking,
86
+ usage: `Run before/after ${lh.event}`,
87
+ })),
88
+ },
89
+ };
90
+ }
91
+
92
+ function buildHookConfigPreview(cwd, options = {}) {
93
+ const { buildAdapterReadiness } = require("./adapter-readiness");
94
+ const readiness = buildAdapterReadiness(cwd, options);
95
+
96
+ const detectedHosts = readiness.hosts.filter((h) => h.detected || h.fallback).map((h) => h.host);
97
+ const previewHosts = detectedHosts.length > 0 ? detectedHosts : ["generic_cli"];
98
+
99
+ const hosts = previewHosts.map(buildHostPreview);
100
+
101
+ const wouldAdd = {};
102
+ for (const lh of LIFECYCLE_HOOK_COMMANDS) {
103
+ wouldAdd[lh.event] = {
104
+ command: lh.command,
105
+ blocking: lh.blocking,
106
+ note: lh.blocking ? "Blocking hook — will pause execution until handler completes." : "Non-blocking hook.",
107
+ };
108
+ }
109
+
110
+ const configPaths = hosts.filter((h) => h.configPath).map((h) => h.configPath);
111
+
112
+ return {
113
+ contract: CONTRACT,
114
+ schemaVersion: SCHEMA_VERSION,
115
+ createdAt: nowIso(),
116
+ mode: "preview_only",
117
+ hosts,
118
+ wouldAdd,
119
+ wouldNotModify: configPaths,
120
+ approvalRequiredBeforeApply: true,
121
+ caveats: [
122
+ "This is a preview only. No user config has been modified.",
123
+ "Applying hooks requires explicit user approval in a future PR.",
124
+ "No global hook installation.",
125
+ "No full Claude plugin.",
126
+ "No full OpenHands adapter.",
127
+ ],
128
+ configPaths,
129
+ adapterReadinessStatus: readiness.status,
130
+ redacted: true,
131
+ };
132
+ }
133
+
134
+ function buildPreviewMarkdown(preview) {
135
+ const lines = [
136
+ "# Avorelo Hook Config Preview",
137
+ "",
138
+ "> **Preview only.** No user config has been modified. Applying hooks requires explicit user approval.",
139
+ "",
140
+ `Generated: ${preview.createdAt}`,
141
+ `Mode: ${preview.mode}`,
142
+ `Adapter readiness: ${preview.adapterReadinessStatus}`,
143
+ "",
144
+ "## What Would Be Added",
145
+ "",
146
+ "If hooks were applied, the following lifecycle commands would be registered:",
147
+ "",
148
+ "| Event | Command | Blocking |",
149
+ "|-------|---------|----------|",
150
+ ];
151
+
152
+ for (const [event, info] of Object.entries(preview.wouldAdd || {})) {
153
+ lines.push(`| ${event} | \`${info.command}\` | ${info.blocking ? "Yes" : "No"} |`);
154
+ }
155
+
156
+ lines.push(
157
+ "",
158
+ "## Would NOT Modify",
159
+ "",
160
+ "The following files would NOT be modified without explicit approval:",
161
+ "",
162
+ );
163
+ for (const p of preview.wouldNotModify || []) {
164
+ lines.push(`- \`${p}\``);
165
+ }
166
+
167
+ lines.push(
168
+ "",
169
+ "## Hosts",
170
+ "",
171
+ );
172
+ for (const host of preview.hosts || []) {
173
+ lines.push(`### ${host.label}`);
174
+ if (host.configPath) {
175
+ lines.push(`- Config path: \`${host.configPath}\``);
176
+ }
177
+ lines.push(`- Format: ${host.wouldAddFormat}`);
178
+ lines.push(`- ${host.note}`);
179
+ lines.push("");
180
+ }
181
+
182
+ lines.push(
183
+ "## Caveats",
184
+ "",
185
+ );
186
+ for (const caveat of preview.caveats || []) {
187
+ lines.push(`- ${caveat}`);
188
+ }
189
+
190
+ lines.push(
191
+ "",
192
+ "## Next Steps",
193
+ "",
194
+ "1. Review this preview.",
195
+ "2. If satisfied, request hook application in a future PR.",
196
+ "3. Hook application will require explicit approval and will be a separate, scoped change.",
197
+ );
198
+
199
+ return lines.join("\n");
200
+ }
201
+
202
+ function writeHookConfigPreview(cwd, preview) {
203
+ const jsonPath = path.join(cwd, LATEST_PREVIEW_JSON_REL);
204
+ const mdPath = path.join(cwd, LATEST_PREVIEW_MD_REL);
205
+
206
+ safeWriteJson(jsonPath, preview);
207
+ safeWriteText(mdPath, buildPreviewMarkdown(preview));
208
+
209
+ return {
210
+ jsonPath: LATEST_PREVIEW_JSON_REL,
211
+ mdPath: LATEST_PREVIEW_MD_REL,
212
+ written: true,
213
+ };
214
+ }
215
+
216
+ function buildHookConfigPreviewSurface(cwd, options = {}) {
217
+ const preview = buildHookConfigPreview(cwd, options);
218
+ const writeResult = writeHookConfigPreview(cwd, preview);
219
+ return { preview, writeResult };
220
+ }
221
+
222
+ function formatHookConfigPreviewText(preview, options = {}) {
223
+ const debug = options.debug || false;
224
+ const lines = [
225
+ "Avorelo hook config preview: ready.",
226
+ "",
227
+ "Mode: preview_only",
228
+ "No user config has been modified.",
229
+ `Adapter readiness: ${preview.adapterReadinessStatus}`,
230
+ "",
231
+ "What would be added (pending user approval):",
232
+ ];
233
+
234
+ for (const [event, info] of Object.entries(preview.wouldAdd || {})) {
235
+ lines.push(` ${event}: ${info.command}`);
236
+ }
237
+
238
+ lines.push(
239
+ "",
240
+ "Would NOT modify:",
241
+ );
242
+ for (const p of preview.wouldNotModify || []) {
243
+ lines.push(` - ${p}`);
244
+ }
245
+
246
+ lines.push(
247
+ "",
248
+ "Approval required before any config change: true",
249
+ );
250
+
251
+ if (debug) {
252
+ lines.push("", "Hosts:");
253
+ for (const h of preview.hosts || []) {
254
+ lines.push(` [${h.host}] config: ${h.configPath || "none"}`);
255
+ }
256
+ lines.push("", "Caveats:");
257
+ for (const c of preview.caveats || []) {
258
+ lines.push(` - ${c}`);
259
+ }
260
+ }
261
+
262
+ return lines.join("\n");
263
+ }
264
+
265
+ module.exports = {
266
+ CONTRACT,
267
+ SCHEMA_VERSION,
268
+ LATEST_PREVIEW_JSON_REL,
269
+ LATEST_PREVIEW_MD_REL,
270
+ LIFECYCLE_HOOK_COMMANDS,
271
+ buildHookConfigPreview,
272
+ writeHookConfigPreview,
273
+ buildHookConfigPreviewSurface,
274
+ formatHookConfigPreviewText,
275
+ };