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,577 @@
1
+ "use strict";
2
+
3
+ const crypto = require("crypto");
4
+ const { ensureCcoDirs, nowIso, safeReadJson, safeWriteJson } = require("./fsx");
5
+ const { appendProductLearningEvent } = require("./product-learning-events");
6
+
7
+ const WORK_CONTROL_CONTRACT = "avorelo.workControlReceipt.v1";
8
+ const WORK_CONTROL_SCHEMA_VERSION = 1;
9
+ const LATEST_WC_RECEIPT_REL_PATH = ".claude/cco/orchestration/work-control/latest-receipt.json";
10
+ const WC_HISTORY_DIR_REL_PATH = ".claude/cco/orchestration/work-control/history";
11
+ const WC_EVENT_LOG_REL_PATH = ".claude/cco/events/work-control.jsonl";
12
+
13
+ const SECRET_PATTERN = /(?:sk-[A-Za-z0-9_-]{16,}|ghp_[A-Za-z0-9]{20,}|AKIA[0-9A-Z]{16}|(?:api[_ -]?key|token|password|secret|authorization)\s*[:=]\s*\S+)/i;
14
+
15
+ function unique(values) {
16
+ return [...new Set((values || []).filter(Boolean))];
17
+ }
18
+
19
+ function redactIfSecret(text) {
20
+ if (!text) return text;
21
+ const s = String(text);
22
+ return SECRET_PATTERN.test(s) ? "[REDACTED]" : s;
23
+ }
24
+
25
+ function createReceiptId() {
26
+ return `wc-${Date.now()}-${crypto.randomBytes(4).toString("hex")}`;
27
+ }
28
+
29
+ function readLatestWorkControlReceipt(cwd) {
30
+ return safeReadJson(cwd, LATEST_WC_RECEIPT_REL_PATH, null);
31
+ }
32
+
33
+ function computeFinalState(controls) {
34
+ const { guard, governance, safePath, installIntake } = controls;
35
+
36
+ const isBlocked =
37
+ guard?.decision === "block"
38
+ || governance?.decision === "block"
39
+ || safePath?.lastDecision === "block";
40
+
41
+ if (isBlocked) return "blocked";
42
+
43
+ const requiresApproval =
44
+ guard?.decision === "approval_required"
45
+ || governance?.decision === "approval_required"
46
+ || governance?.approvalBoundary === true
47
+ || safePath?.lastDecision === "approval_required"
48
+ || safePath?.approvalBoundary === true;
49
+
50
+ if (requiresApproval) return "approval_required";
51
+
52
+ const hasAttention =
53
+ (installIntake?.highRiskItems > 0)
54
+ || (installIntake?.unknownItems > 0)
55
+ || (governance?.subjectTrustStatus === "unknown")
56
+ || (guard?.riskLevel === "high" || guard?.riskLevel === "critical");
57
+
58
+ if (hasAttention) return "attention";
59
+
60
+ const hasEvidence =
61
+ guard?.evidencePath
62
+ || governance?.latestReceiptPath
63
+ || safePath?.latestReceiptPath
64
+ || installIntake?.latestReceiptPath;
65
+
66
+ return hasEvidence ? "ok" : "missing";
67
+ }
68
+
69
+ function computeNextSafestAction(controls, finalState) {
70
+ const { guard, governance, safePath, installIntake } = controls;
71
+
72
+ if (finalState === "blocked") {
73
+ return "Preserve the block — do not execute the destructive or blocked action.";
74
+ }
75
+ if (governance?.subjectTrustStatus === "unknown" || installIntake?.unknownItems > 0) {
76
+ return "Review unknown intake source or subject before proceeding.";
77
+ }
78
+ if (finalState === "approval_required") {
79
+ return safePath?.nextAction
80
+ || governance?.nextAction
81
+ || "Approve only the reduced scope before proceeding.";
82
+ }
83
+ if (finalState === "attention") {
84
+ return installIntake?.nextAction
85
+ || guard?.nextAction
86
+ || "Review high-risk intake items and confirm reduced scope.";
87
+ }
88
+ if (!guard?.evidencePath && !governance?.latestReceiptPath) {
89
+ return "Run `avorelo guard` on a risky action to generate the first control receipt.";
90
+ }
91
+ return "Continue with the smallest local scope. Re-run proof before next session.";
92
+ }
93
+
94
+ function buildDoNotRepeat(controls, proof) {
95
+ const items = [
96
+ "Do not rerun from scratch — use current proof/work-control receipt.",
97
+ "Do not trust unknown MCP server or package without running intake review first.",
98
+ "Do not paste huge status JSON into context — use `avorelo work-control --json` instead.",
99
+ ];
100
+ if (proof?.route?.selectedRoute?.includes("broad") || proof?.route?.safetyNotes?.some((n) => /broad/i.test(n))) {
101
+ items.push("Do not perform broad repo scan — route already recorded the relevant context.");
102
+ }
103
+ if (controls.installIntake?.unknownItems > 0) {
104
+ items.push("Do not execute tool or MCP call for unknown/unreviewed source.");
105
+ }
106
+ if (controls.safePath?.lastDecision === "recommend_reduced_scope") {
107
+ items.push("Do not use broad scope — safe path already recommended a reduced alternative.");
108
+ }
109
+ return unique(items);
110
+ }
111
+
112
+ function buildCarryForward(cwd, controls, proof, finalState, nextSafestAction) {
113
+ const items = {};
114
+
115
+ if (proof?.route?.selectedRoute) {
116
+ items.lastRoute = proof.route.selectedRoute;
117
+ }
118
+ if (proof?.task) {
119
+ items.lastTaskSummary = String(proof.task).slice(0, 200);
120
+ }
121
+ if (proof?.runId) {
122
+ items.lastRunId = proof.runId;
123
+ }
124
+ items.finalState = finalState;
125
+ items.nextSafestAction = nextSafestAction;
126
+
127
+ items.receiptPaths = [
128
+ controls.guard?.evidencePath ? `guard: ${controls.guard.evidencePath}` : null,
129
+ controls.governance?.latestReceiptPath ? `governance: ${controls.governance.latestReceiptPath}` : null,
130
+ controls.safePath?.latestReceiptPath ? `safe-path: ${controls.safePath.latestReceiptPath}` : null,
131
+ controls.installIntake?.latestReceiptPath ? `intake: ${controls.installIntake.latestReceiptPath}` : null,
132
+ controls.skills?.latestRouteReceiptPath ? `skills: ${controls.skills.latestRouteReceiptPath}` : null,
133
+ ].filter(Boolean);
134
+
135
+ const unchecked = [];
136
+ if (!controls.governance?.latestReceiptPath) unchecked.push("governance receipt missing");
137
+ if (!controls.safePath?.latestReceiptPath) unchecked.push("safe-path receipt missing");
138
+ if (!controls.skills?.latestRouteReceiptPath) unchecked.push("skills route receipt missing");
139
+ if (unchecked.length) items.uncheckedItems = unchecked;
140
+
141
+ items.restoreCommands = [
142
+ "node bin/avorelo work-control --json",
143
+ "node bin/avorelo proof",
144
+ ];
145
+
146
+ return items;
147
+ }
148
+
149
+ function buildWorkControlSummary(controls, finalState, nextSafestAction, doNotRepeat, carryForward) {
150
+ const { guard, governance, safePath, installIntake, skills } = controls;
151
+
152
+ const allowedCount = guard?.decision === "allow" ? 1 : 0;
153
+ const warnedCount = guard?.decision === "warn" ? 1 : 0;
154
+ const approvalRequiredCount = (guard?.decision === "approval_required" || finalState === "approval_required") ? 1 : 0;
155
+ const blockedCount = guard?.decision === "block" ? 1 : 0;
156
+ const reductionsRecommendedCount = safePath?.reductionsRecommended || 0;
157
+ const reviewedSourcesCount = skills?.reviewedSources || 0;
158
+ const unknownSourcesCount = skills?.deferredSources || 0;
159
+ const highRiskIntakeCount = installIntake?.highRiskItems || 0;
160
+
161
+ return {
162
+ allowedCount,
163
+ warnedCount,
164
+ approvalRequiredCount,
165
+ blockedCount,
166
+ reductionsRecommendedCount,
167
+ reviewedSourcesCount,
168
+ unknownSourcesCount,
169
+ highRiskIntakeCount,
170
+ finalState,
171
+ nextSafestAction,
172
+ doNotRepeat,
173
+ carryForward,
174
+ };
175
+ }
176
+
177
+ function buildWorkControlReceipt(cwd, options = {}) {
178
+ const { buildAgentAccessGovernanceSurface } = require("./agent-access-governance");
179
+ const { buildSafePathSurface } = require("./safe-path-engine");
180
+ const { buildInstallIntakeRiskSurface } = require("./install-intake-risk");
181
+ const { buildSkillsOperatingLayerSurface } = require("./skills-operating-layer");
182
+
183
+ let proof = null;
184
+ try {
185
+ const { readCurrentProof } = require("./orchestration");
186
+ proof = readCurrentProof(cwd);
187
+ } catch {}
188
+
189
+ const governanceSurface = buildAgentAccessGovernanceSurface(cwd);
190
+ const safePathSurface = buildSafePathSurface(cwd);
191
+ const intakeSurface = buildInstallIntakeRiskSurface(cwd);
192
+ const skillsSurface = buildSkillsOperatingLayerSurface(cwd);
193
+
194
+ const rawTask = (options.task || proof?.task || "");
195
+ const taskText = redactIfSecret(rawTask) || "";
196
+
197
+ const taskSection = {
198
+ text: taskText.slice(0, 400),
199
+ type: proof?.route?.task?.taskType || options.taskType || "unknown",
200
+ risk: proof?.route?.task?.risk || options.taskRisk || "unknown",
201
+ sensitivity: proof?.route?.task?.sensitivity || options.taskSensitivity || "unknown",
202
+ surface: proof?.surface || options.surface || "avorelo_cli",
203
+ };
204
+
205
+ const routeSection = proof?.route
206
+ ? {
207
+ selectedRoute: proof.route.selectedRoute || null,
208
+ chosenTool: proof.route.chosenTool || null,
209
+ selectedModel: proof.route.selectedModel || null,
210
+ chosenModelProfile: proof.route.chosenModelProfile || null,
211
+ fallbackTool: proof.route.fallbackTool || null,
212
+ safetyNotes: (proof.route.safetyNotes || []).slice(0, 5),
213
+ whyChosen: (proof.route.whyChosen || []).slice(0, 3),
214
+ whyNotChosen: (proof.route.whyNotChosen || []).slice(0, 3),
215
+ }
216
+ : {
217
+ selectedRoute: null,
218
+ chosenTool: null,
219
+ selectedModel: null,
220
+ chosenModelProfile: null,
221
+ fallbackTool: null,
222
+ safetyNotes: [],
223
+ whyChosen: [],
224
+ whyNotChosen: [],
225
+ };
226
+
227
+ const latestGovernanceReceipt = governanceSurface.latestReceipt;
228
+ const latestSafePathReceipt = safePathSurface.latestReceipt;
229
+
230
+ const guardSection = latestGovernanceReceipt
231
+ ? {
232
+ decision: latestGovernanceReceipt.decision || "unknown",
233
+ riskLevel: latestGovernanceReceipt.severity || "unknown",
234
+ reasonCodes: (latestGovernanceReceipt.reasonCodes || []).slice(0, 5),
235
+ matchedRules: [],
236
+ evidencePath: governanceSurface.latestReceiptPath || null,
237
+ nextAction: null,
238
+ }
239
+ : {
240
+ decision: "missing",
241
+ riskLevel: "unknown",
242
+ reasonCodes: [],
243
+ matchedRules: [],
244
+ evidencePath: null,
245
+ nextAction: "Run `avorelo guard` to generate the first governance receipt.",
246
+ };
247
+
248
+ const governanceSection = {
249
+ status: governanceSurface.status,
250
+ latestReceiptPath: governanceSurface.latestReceiptPath,
251
+ decision: latestGovernanceReceipt?.decision || "missing",
252
+ subjectType: latestGovernanceReceipt?.subjectSummary?.type || null,
253
+ subjectTrustStatus: latestGovernanceReceipt?.subjectSummary?.trustStatus || null,
254
+ requestedActionType: latestGovernanceReceipt?.requestedActionSummary?.type || null,
255
+ scopeSummary: latestGovernanceReceipt?.scopeSummary || null,
256
+ approvalBoundary: latestGovernanceReceipt?.approvalBoundary?.required === true,
257
+ nextAction: governanceSurface.nextAction,
258
+ };
259
+
260
+ const safePathSection = {
261
+ status: safePathSurface.status,
262
+ latestReceiptPath: safePathSurface.latestReceiptPath,
263
+ lastDecision: safePathSurface.lastDecision,
264
+ recommendedBoundary: latestSafePathReceipt?.recommendedBoundary || null,
265
+ reductionSummary: latestSafePathReceipt?.reductionSummary || null,
266
+ approvalBoundary: latestSafePathReceipt?.approvalBoundary?.required === true,
267
+ nextAction: safePathSurface.nextAction,
268
+ reductionsRecommended: safePathSurface.reductionsRecommended,
269
+ };
270
+
271
+ const intakeSection = {
272
+ status: intakeSurface.status,
273
+ latestReceiptPath: intakeSurface.latestReceiptPath,
274
+ totalItems: intakeSurface.totalItems,
275
+ unknownItems: intakeSurface.unknownItems,
276
+ highRiskItems: intakeSurface.highRiskItems,
277
+ topReasonCodes: (intakeSurface.topReasonCodes || []).slice(0, 5),
278
+ nextAction: intakeSurface.nextAction,
279
+ };
280
+
281
+ const skillsSection = {
282
+ status: skillsSurface.status,
283
+ primarySkill: null,
284
+ reviewedSources: skillsSurface.reviewedSources,
285
+ deferredSources: skillsSurface.deferredSources,
286
+ latestRouteReceiptPath: skillsSurface.latestSkillRouteReceiptPath || null,
287
+ evidenceRequirements: [],
288
+ };
289
+
290
+ const controls = {
291
+ guard: guardSection,
292
+ governance: governanceSection,
293
+ safePath: safePathSection,
294
+ installIntake: intakeSection,
295
+ skills: skillsSection,
296
+ };
297
+
298
+ const verification = {
299
+ status: proof?.verification?.status || "missing",
300
+ commandsRun: [],
301
+ passed: [],
302
+ failed: [],
303
+ notChecked: [
304
+ !governanceSurface.latestReceiptPath && "governance receipt",
305
+ !safePathSurface.latestReceiptPath && "safe-path receipt",
306
+ !skillsSurface.latestSkillRouteReceiptPath && "skills route receipt",
307
+ ].filter(Boolean),
308
+ proofPath: proof ? ".claude/cco/orchestration/current-proof.json" : null,
309
+ };
310
+
311
+ const finalState = computeFinalState(controls);
312
+ const nextSafestAction = computeNextSafestAction(controls, finalState);
313
+ const doNotRepeat = buildDoNotRepeat(controls, proof);
314
+ const carryForward = buildCarryForward(cwd, controls, proof, finalState, nextSafestAction);
315
+ const workControl = buildWorkControlSummary(controls, finalState, nextSafestAction, doNotRepeat, carryForward);
316
+
317
+ const allReceiptPaths = [
318
+ governanceSurface.latestReceiptPath,
319
+ safePathSurface.latestReceiptPath,
320
+ intakeSurface.latestReceiptPath,
321
+ skillsSurface.latestSkillRouteReceiptPath,
322
+ ].filter(Boolean);
323
+
324
+ const receipt = {
325
+ schemaVersion: WORK_CONTROL_SCHEMA_VERSION,
326
+ contract: WORK_CONTROL_CONTRACT,
327
+ receiptType: "work_control",
328
+ receiptId: createReceiptId(),
329
+ createdAt: nowIso(),
330
+ cwd,
331
+ task: taskSection,
332
+ route: routeSection,
333
+ controls,
334
+ verification,
335
+ workControl,
336
+ evidencePaths: allReceiptPaths,
337
+ productLearning: {
338
+ eventsWritten: 0,
339
+ suggestedEvents: ["work_control_receipt_written"],
340
+ },
341
+ redacted: true,
342
+ };
343
+
344
+ return receipt;
345
+ }
346
+
347
+ function writeWorkControlReceipt(cwd, receipt, options = {}) {
348
+ ensureCcoDirs(cwd);
349
+
350
+ const relPath = LATEST_WC_RECEIPT_REL_PATH;
351
+ safeWriteJson(cwd, relPath, receipt);
352
+
353
+ const fs = require("fs");
354
+ const path = require("path");
355
+ const historyDir = path.join(cwd, WC_HISTORY_DIR_REL_PATH);
356
+ fs.mkdirSync(historyDir, { recursive: true });
357
+
358
+ const canExport = options.plan && options.plan !== "free";
359
+ if (canExport) {
360
+ safeWriteJson(cwd, `${WC_HISTORY_DIR_REL_PATH}/${receipt.receiptId}.json`, receipt);
361
+ }
362
+
363
+ const eventLine = {
364
+ receiptId: receipt.receiptId,
365
+ finalState: receipt.workControl.finalState,
366
+ blockedCount: receipt.workControl.blockedCount,
367
+ approvalRequiredCount: receipt.workControl.approvalRequiredCount,
368
+ highRiskIntakeCount: receipt.workControl.highRiskIntakeCount,
369
+ receiptPath: relPath,
370
+ createdAt: receipt.createdAt,
371
+ };
372
+
373
+ try {
374
+ const abs = require("path").join(cwd, WC_EVENT_LOG_REL_PATH);
375
+ fs.mkdirSync(require("path").dirname(abs), { recursive: true });
376
+ fs.appendFileSync(abs, `${JSON.stringify(eventLine)}\n`, "utf8");
377
+ } catch {}
378
+
379
+ let eventsWritten = 0;
380
+
381
+ const productEvents = [];
382
+ productEvents.push({
383
+ eventName: "work_control_receipt_written",
384
+ category: "work_control",
385
+ status: "completed",
386
+ payload: {
387
+ finalState: receipt.workControl.finalState,
388
+ blockedCount: receipt.workControl.blockedCount,
389
+ approvalRequiredCount: receipt.workControl.approvalRequiredCount,
390
+ highRiskIntakeCount: receipt.workControl.highRiskIntakeCount,
391
+ evidencePathsCount: receipt.evidencePaths.length,
392
+ },
393
+ });
394
+
395
+ if (receipt.workControl.finalState === "blocked") {
396
+ productEvents.push({
397
+ eventName: "work_control_block_preserved",
398
+ category: "work_control",
399
+ status: "completed",
400
+ payload: {
401
+ receiptId: receipt.receiptId,
402
+ blockedCount: receipt.workControl.blockedCount,
403
+ },
404
+ });
405
+ }
406
+
407
+ if (receipt.workControl.finalState === "approval_required") {
408
+ productEvents.push({
409
+ eventName: "work_control_approval_required",
410
+ category: "work_control",
411
+ status: "recommended",
412
+ payload: {
413
+ approvalRequiredCount: receipt.workControl.approvalRequiredCount,
414
+ },
415
+ });
416
+ }
417
+
418
+ if (receipt.workControl.nextSafestAction) {
419
+ productEvents.push({
420
+ eventName: "work_control_next_action_recommended",
421
+ category: "work_control",
422
+ status: "recommended",
423
+ payload: {
424
+ finalState: receipt.workControl.finalState,
425
+ },
426
+ });
427
+ }
428
+
429
+ if (receipt.workControl.doNotRepeat?.length) {
430
+ productEvents.push({
431
+ eventName: "work_control_do_not_repeat_generated",
432
+ category: "work_control",
433
+ status: "completed",
434
+ payload: {
435
+ count: receipt.workControl.doNotRepeat.length,
436
+ },
437
+ });
438
+ }
439
+
440
+ productEvents.forEach((event) => {
441
+ try {
442
+ appendProductLearningEvent(cwd, event);
443
+ eventsWritten += 1;
444
+ } catch {}
445
+ });
446
+
447
+ receipt.productLearning.eventsWritten = eventsWritten;
448
+
449
+ return relPath;
450
+ }
451
+
452
+ function buildWorkControlSurface(cwd) {
453
+ const latestReceipt = readLatestWorkControlReceipt(cwd);
454
+ if (!latestReceipt) {
455
+ return {
456
+ status: "missing",
457
+ latestReceiptPath: null,
458
+ finalState: "missing",
459
+ nextSafestAction: "Run `avorelo work-control` to generate the first receipt.",
460
+ blockedCount: 0,
461
+ approvalRequiredCount: 0,
462
+ highRiskIntakeCount: 0,
463
+ unknownSourcesCount: 0,
464
+ proofAvailable: false,
465
+ carryForwardAvailable: false,
466
+ showInStatus: true,
467
+ showInDashboard: true,
468
+ statusLine: "Work Control: MISSING · no receipt yet",
469
+ };
470
+ }
471
+
472
+ const wc = latestReceipt.workControl || {};
473
+ const finalState = wc.finalState || "missing";
474
+ const stateLabel = finalState.toUpperCase().replace(/_/g, " ");
475
+
476
+ return {
477
+ status: "foundation",
478
+ latestReceiptPath: LATEST_WC_RECEIPT_REL_PATH,
479
+ finalState,
480
+ nextSafestAction: wc.nextSafestAction || null,
481
+ blockedCount: wc.blockedCount || 0,
482
+ approvalRequiredCount: wc.approvalRequiredCount || 0,
483
+ highRiskIntakeCount: wc.highRiskIntakeCount || 0,
484
+ unknownSourcesCount: wc.unknownSourcesCount || 0,
485
+ proofAvailable: Boolean(latestReceipt.verification?.proofPath),
486
+ carryForwardAvailable: Boolean(wc.carryForward?.receiptPaths?.length),
487
+ showInStatus: true,
488
+ showInDashboard: true,
489
+ statusLine: `Work Control: ${stateLabel} · blocked=${wc.blockedCount || 0} · approval=${wc.approvalRequiredCount || 0} · high-risk-intake=${wc.highRiskIntakeCount || 0} · latest receipt ${LATEST_WC_RECEIPT_REL_PATH}`,
490
+ };
491
+ }
492
+
493
+ function formatWorkControlText(surfaceOrReceipt, options = {}) {
494
+ const isHandoff = options.handoff === true;
495
+
496
+ if (!surfaceOrReceipt) {
497
+ return "Work Control: MISSING · no receipt yet\nNext: Run `avorelo work-control` to generate the first receipt.\n";
498
+ }
499
+
500
+ if (surfaceOrReceipt.contract === WORK_CONTROL_CONTRACT) {
501
+ const receipt = surfaceOrReceipt;
502
+ const wc = receipt.workControl || {};
503
+ const stateLabel = (wc.finalState || "missing").toUpperCase().replace(/_/g, " ");
504
+ const taskText = receipt.task?.text ? String(receipt.task.text).slice(0, 120) : "unknown";
505
+
506
+ const lines = [
507
+ `Work Control: ${stateLabel}`,
508
+ `Task: ${taskText}`,
509
+ `State: ${wc.finalState || "missing"}`,
510
+ ];
511
+
512
+ if (receipt.controls?.guard?.decision && receipt.controls.guard.decision !== "missing") {
513
+ lines.push(`Guard: ${receipt.controls.guard.decision} · ${(receipt.controls.guard.reasonCodes || []).join(", ") || "no codes"}`);
514
+ }
515
+ if (receipt.controls?.installIntake?.totalItems) {
516
+ lines.push(`Install Intake: ${receipt.controls.installIntake.totalItems} items · ${receipt.controls.installIntake.unknownItems} unknown · ${receipt.controls.installIntake.highRiskItems} high`);
517
+ }
518
+ if (receipt.controls?.safePath?.lastDecision) {
519
+ lines.push(`Safe Path: ${receipt.controls.safePath.lastDecision}`);
520
+ }
521
+ if (wc.nextSafestAction) {
522
+ lines.push(`Next: ${wc.nextSafestAction}`);
523
+ }
524
+ if (receipt.evidencePaths?.length) {
525
+ lines.push(`Evidence paths: ${receipt.evidencePaths.join(", ")}`);
526
+ }
527
+ lines.push(`Receipt: ${LATEST_WC_RECEIPT_REL_PATH}`);
528
+
529
+ if (isHandoff) {
530
+ lines.push("");
531
+ lines.push("## Handoff");
532
+ lines.push(`State: ${wc.finalState || "missing"}`);
533
+ lines.push("");
534
+ lines.push("### What was checked");
535
+ (receipt.evidencePaths || []).forEach((p) => lines.push(`- ${p}`));
536
+ if (!receipt.evidencePaths?.length) lines.push("- No evidence paths recorded");
537
+ lines.push("");
538
+ lines.push("### What was not checked");
539
+ (receipt.verification?.notChecked || []).forEach((item) => lines.push(`- ${item}`));
540
+ if (!receipt.verification?.notChecked?.length) lines.push("- Nothing explicitly unchecked");
541
+ lines.push("");
542
+ lines.push("### What to do next");
543
+ lines.push(wc.nextSafestAction || "Continue with smallest local scope.");
544
+ lines.push("");
545
+ lines.push("### Do not repeat");
546
+ (wc.doNotRepeat || []).forEach((item) => lines.push(`- ${item}`));
547
+ lines.push("");
548
+ lines.push("### Receipt paths");
549
+ (wc.carryForward?.receiptPaths || []).forEach((p) => lines.push(`- ${p}`));
550
+ lines.push(`- work-control: ${LATEST_WC_RECEIPT_REL_PATH}`);
551
+ }
552
+
553
+ return lines.join("\n") + "\n";
554
+ }
555
+
556
+ const surface = surfaceOrReceipt;
557
+ const stateLabel = (surface.finalState || "missing").toUpperCase().replace(/_/g, " ");
558
+ const lines = [
559
+ `Work Control: ${stateLabel}`,
560
+ `Final state: ${surface.finalState || "missing"}`,
561
+ ];
562
+ if (surface.nextSafestAction) lines.push(`Next: ${surface.nextSafestAction}`);
563
+ if (surface.latestReceiptPath) lines.push(`Receipt: ${surface.latestReceiptPath}`);
564
+ return lines.join("\n") + "\n";
565
+ }
566
+
567
+ module.exports = {
568
+ WORK_CONTROL_CONTRACT,
569
+ WORK_CONTROL_SCHEMA_VERSION,
570
+ LATEST_WC_RECEIPT_REL_PATH,
571
+ WC_EVENT_LOG_REL_PATH,
572
+ readLatestWorkControlReceipt,
573
+ buildWorkControlReceipt,
574
+ writeWorkControlReceipt,
575
+ buildWorkControlSurface,
576
+ formatWorkControlText,
577
+ };