avorelo 0.1.0 → 0.2.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 (260) hide show
  1. package/LICENSE +23 -16
  2. package/README.md +91 -51
  3. package/bin/avorelo.mjs +7 -0
  4. package/dist/avorelo.mjs +14337 -0
  5. package/package.json +106 -120
  6. package/bin/avorelo +0 -9
  7. package/scripts/README.md +0 -40
  8. package/scripts/cco-dashboard.js +0 -252
  9. package/scripts/cco-status.js +0 -430
  10. package/scripts/lib/activation/account-state.js +0 -37
  11. package/scripts/lib/activation/activation-runner.js +0 -546
  12. package/scripts/lib/activation/activation-self-healing.js +0 -480
  13. package/scripts/lib/activation/activation-state.js +0 -83
  14. package/scripts/lib/activation/activation-summary.js +0 -191
  15. package/scripts/lib/activation/adapters/claude-code.js +0 -77
  16. package/scripts/lib/activation/adapters/codex-cli.js +0 -52
  17. package/scripts/lib/activation/adapters/cursor.js +0 -37
  18. package/scripts/lib/activation/adapters/github-agent.js +0 -39
  19. package/scripts/lib/activation/adapters/terminal.js +0 -42
  20. package/scripts/lib/activation/adapters/vscode.js +0 -39
  21. package/scripts/lib/activation/adapters/windsurf.js +0 -37
  22. package/scripts/lib/activation/ai-surface-detector.js +0 -151
  23. package/scripts/lib/activation/connect-account.js +0 -145
  24. package/scripts/lib/activation/detect-environment.js +0 -75
  25. package/scripts/lib/activation/detect-hosts.js +0 -62
  26. package/scripts/lib/activation/format-activation-output.js +0 -109
  27. package/scripts/lib/activation/next-action.js +0 -43
  28. package/scripts/lib/activation/repair-engine.js +0 -219
  29. package/scripts/lib/activation-distribution-readiness.js +0 -507
  30. package/scripts/lib/adapter-conformance.js +0 -176
  31. package/scripts/lib/adapter-readiness.js +0 -417
  32. package/scripts/lib/adapter-safety-boundaries.js +0 -335
  33. package/scripts/lib/adapter-technical-readiness-gate.js +0 -205
  34. package/scripts/lib/agent-access-governance.js +0 -455
  35. package/scripts/lib/agent-enforcement.js +0 -765
  36. package/scripts/lib/agent-policy-profile.js +0 -210
  37. package/scripts/lib/agent-security/action-evaluator.js +0 -507
  38. package/scripts/lib/agent-security/adapter-registry.js +0 -98
  39. package/scripts/lib/agent-security/auto-policy.js +0 -139
  40. package/scripts/lib/agent-security/bounded-scan.js +0 -93
  41. package/scripts/lib/agent-security/enforcement-adapter.js +0 -174
  42. package/scripts/lib/agent-security/enforcement-engine.js +0 -1129
  43. package/scripts/lib/agent-security/file-write-adapter.js +0 -183
  44. package/scripts/lib/agent-security/file-write-rules.js +0 -178
  45. package/scripts/lib/agent-security/index.js +0 -3342
  46. package/scripts/lib/agent-security/instruction-risk.js +0 -181
  47. package/scripts/lib/agent-security/mcp-action-adapter.js +0 -185
  48. package/scripts/lib/agent-security/mcp-action-rules.js +0 -184
  49. package/scripts/lib/agent-security/package-action-adapter.js +0 -175
  50. package/scripts/lib/agent-security/package-action-rules.js +0 -233
  51. package/scripts/lib/agent-security/performance.js +0 -148
  52. package/scripts/lib/agent-security/permission-minimizer.js +0 -403
  53. package/scripts/lib/agent-security/scan-cache.js +0 -74
  54. package/scripts/lib/agent-security/source-trust.js +0 -146
  55. package/scripts/lib/ai-install-prompt.js +0 -288
  56. package/scripts/lib/ai-workspace-hygiene.js +0 -1499
  57. package/scripts/lib/alpha-activation.js +0 -520
  58. package/scripts/lib/alpha-feedback.js +0 -263
  59. package/scripts/lib/alpha-readiness-gate.js +0 -332
  60. package/scripts/lib/anti-gaming.js +0 -169
  61. package/scripts/lib/artifact-health.js +0 -431
  62. package/scripts/lib/attribution.js +0 -180
  63. package/scripts/lib/audit.js +0 -289
  64. package/scripts/lib/avorelo-skill-registry.js +0 -810
  65. package/scripts/lib/batch-jobs.js +0 -71
  66. package/scripts/lib/brain-pack.js +0 -578
  67. package/scripts/lib/brand-boundary.js +0 -424
  68. package/scripts/lib/brand.js +0 -74
  69. package/scripts/lib/browser-capability.js +0 -1048
  70. package/scripts/lib/browser-proof-preflight.js +0 -321
  71. package/scripts/lib/cache-readiness.js +0 -187
  72. package/scripts/lib/canonical-reentry.js +0 -162
  73. package/scripts/lib/capability-packs.js +0 -314
  74. package/scripts/lib/capability-recommender.js +0 -512
  75. package/scripts/lib/capability-registry.js +0 -1059
  76. package/scripts/lib/carry-forward-surfacing.js +0 -194
  77. package/scripts/lib/ccusage-adapter.js +0 -188
  78. package/scripts/lib/company-loop.js +0 -1149
  79. package/scripts/lib/config.js +0 -637
  80. package/scripts/lib/context-acquisition-plan.js +0 -287
  81. package/scripts/lib/context-budget-guard.js +0 -170
  82. package/scripts/lib/context-budget-scanner.js +0 -257
  83. package/scripts/lib/context-optimizer.js +0 -715
  84. package/scripts/lib/context-reduction-plan.js +0 -178
  85. package/scripts/lib/context-safety.js +0 -88
  86. package/scripts/lib/context-savings-engine.js +0 -158
  87. package/scripts/lib/cost-evidence.js +0 -254
  88. package/scripts/lib/cross-host-install-plan.js +0 -308
  89. package/scripts/lib/cross-host-install-readiness.js +0 -237
  90. package/scripts/lib/cross-host-value-flow.js +0 -268
  91. package/scripts/lib/dashboard.js +0 -900
  92. package/scripts/lib/design-partner-feedback.js +0 -346
  93. package/scripts/lib/entitlements.js +0 -100
  94. package/scripts/lib/execution-packet.js +0 -559
  95. package/scripts/lib/experimentation-events.js +0 -547
  96. package/scripts/lib/external-capability-compliance.js +0 -107
  97. package/scripts/lib/external-user-simulation.js +0 -166
  98. package/scripts/lib/failure-recovery-readiness.js +0 -81
  99. package/scripts/lib/failure-recovery.js +0 -419
  100. package/scripts/lib/feedback-intelligence.js +0 -537
  101. package/scripts/lib/feedback-signals.js +0 -205
  102. package/scripts/lib/file-integrity.js +0 -68
  103. package/scripts/lib/fsx.js +0 -127
  104. package/scripts/lib/full-readiness-gate.js +0 -451
  105. package/scripts/lib/guidance-builder.js +0 -174
  106. package/scripts/lib/hook-apply.js +0 -1019
  107. package/scripts/lib/hook-baseline.js +0 -310
  108. package/scripts/lib/hook-config-preview.js +0 -275
  109. package/scripts/lib/hook-contracts.js +0 -290
  110. package/scripts/lib/hook-safety-boundary-readiness.js +0 -80
  111. package/scripts/lib/host-capability-matrix.js +0 -351
  112. package/scripts/lib/host-support-context.js +0 -254
  113. package/scripts/lib/http-hook-action.js +0 -538
  114. package/scripts/lib/install-ai-readiness.js +0 -84
  115. package/scripts/lib/install-intake-risk.js +0 -1037
  116. package/scripts/lib/install-journey-intelligence.js +0 -329
  117. package/scripts/lib/intervention-guidance.js +0 -57
  118. package/scripts/lib/known-limitations.js +0 -115
  119. package/scripts/lib/l8-path-truth.js +0 -146
  120. package/scripts/lib/launch-hardening-gate.js +0 -436
  121. package/scripts/lib/launch-readiness.js +0 -628
  122. package/scripts/lib/learning-memory.js +0 -686
  123. package/scripts/lib/lifecycle-hooks.js +0 -802
  124. package/scripts/lib/local-package-smoke.js +0 -423
  125. package/scripts/lib/local-pricing.js +0 -299
  126. package/scripts/lib/mcp-enforcement.js +0 -311
  127. package/scripts/lib/mcp-least-privilege-policy.js +0 -303
  128. package/scripts/lib/mcp-tool-inventory.js +0 -388
  129. package/scripts/lib/mcp-tool-risk.js +0 -0
  130. package/scripts/lib/memory.js +0 -335
  131. package/scripts/lib/metrics.js +0 -699
  132. package/scripts/lib/micro-proof.js +0 -133
  133. package/scripts/lib/next-run-context.js +0 -436
  134. package/scripts/lib/operating-value.js +0 -1648
  135. package/scripts/lib/optimization-v3.js +0 -122
  136. package/scripts/lib/orchestration/adapters/_shared.js +0 -49
  137. package/scripts/lib/orchestration/adapters/aider.js +0 -18
  138. package/scripts/lib/orchestration/adapters/claude-code.js +0 -35
  139. package/scripts/lib/orchestration/adapters/codex.js +0 -35
  140. package/scripts/lib/orchestration/adapters/gemini-cli.js +0 -18
  141. package/scripts/lib/orchestration/adapters/git.js +0 -25
  142. package/scripts/lib/orchestration/adapters/index.js +0 -31
  143. package/scripts/lib/orchestration/adapters/lm-studio.js +0 -18
  144. package/scripts/lib/orchestration/adapters/ollama.js +0 -18
  145. package/scripts/lib/orchestration/adapters/opencode.js +0 -18
  146. package/scripts/lib/orchestration/adapters/openrouter.js +0 -18
  147. package/scripts/lib/orchestration/adapters/test-runner.js +0 -25
  148. package/scripts/lib/orchestration/cli.js +0 -438
  149. package/scripts/lib/orchestration/execution-manager.js +0 -279
  150. package/scripts/lib/orchestration/handoff.js +0 -314
  151. package/scripts/lib/orchestration/index.js +0 -456
  152. package/scripts/lib/orchestration/inventory.js +0 -47
  153. package/scripts/lib/orchestration/model-discovery.js +0 -498
  154. package/scripts/lib/orchestration/model-profiler.js +0 -170
  155. package/scripts/lib/orchestration/model-profiles.js +0 -252
  156. package/scripts/lib/orchestration/model-refresh-policy.js +0 -72
  157. package/scripts/lib/orchestration/proof-writer.js +0 -349
  158. package/scripts/lib/orchestration/provider-discovery/aider.js +0 -49
  159. package/scripts/lib/orchestration/provider-discovery/claude-code.js +0 -56
  160. package/scripts/lib/orchestration/provider-discovery/codex.js +0 -49
  161. package/scripts/lib/orchestration/provider-discovery/common.js +0 -186
  162. package/scripts/lib/orchestration/provider-discovery/gemini.js +0 -106
  163. package/scripts/lib/orchestration/provider-discovery/lm-studio.js +0 -118
  164. package/scripts/lib/orchestration/provider-discovery/models-dev.js +0 -12
  165. package/scripts/lib/orchestration/provider-discovery/ollama.js +0 -100
  166. package/scripts/lib/orchestration/provider-discovery/opencode.js +0 -47
  167. package/scripts/lib/orchestration/provider-discovery/openrouter.js +0 -44
  168. package/scripts/lib/orchestration/risk-classifier.js +0 -130
  169. package/scripts/lib/orchestration/routing-policy.js +0 -486
  170. package/scripts/lib/orchestration/settings.js +0 -112
  171. package/scripts/lib/orchestration/state.js +0 -165
  172. package/scripts/lib/orchestration/verification-manager.js +0 -138
  173. package/scripts/lib/output-profiles.js +0 -146
  174. package/scripts/lib/package-content-audit.js +0 -368
  175. package/scripts/lib/package-runtime.js +0 -278
  176. package/scripts/lib/plan-surface.js +0 -53
  177. package/scripts/lib/plans.js +0 -2318
  178. package/scripts/lib/policy-provider.js +0 -27
  179. package/scripts/lib/prelaunch-activation-readiness.js +0 -409
  180. package/scripts/lib/prelaunch-evidence-store.js +0 -816
  181. package/scripts/lib/prelaunch-intelligence.js +0 -869
  182. package/scripts/lib/pricing-experiment.js +0 -118
  183. package/scripts/lib/pro-moment-events.js +0 -77
  184. package/scripts/lib/pro-moment-state.js +0 -227
  185. package/scripts/lib/pro-moments.js +0 -1216
  186. package/scripts/lib/product-learning-events.js +0 -629
  187. package/scripts/lib/project-profile.js +0 -555
  188. package/scripts/lib/prompt-compiler.js +0 -280
  189. package/scripts/lib/prompt-lint.js +0 -32
  190. package/scripts/lib/prompt-suggestions.js +0 -52
  191. package/scripts/lib/proof-canonical.js +0 -398
  192. package/scripts/lib/proof-drilldown.js +0 -383
  193. package/scripts/lib/proof-events.js +0 -342
  194. package/scripts/lib/proof-history.js +0 -243
  195. package/scripts/lib/proof-metrics.js +0 -296
  196. package/scripts/lib/proof-outcome-evidence.js +0 -134
  197. package/scripts/lib/proof-receipt.js +0 -335
  198. package/scripts/lib/proof-record.js +0 -461
  199. package/scripts/lib/public-activation-distribution-gate.js +0 -258
  200. package/scripts/lib/public-cli.js +0 -3891
  201. package/scripts/lib/public-distribution-truth.js +0 -211
  202. package/scripts/lib/public-install-claim-checker.js +0 -294
  203. package/scripts/lib/publish-provenance-readiness.js +0 -283
  204. package/scripts/lib/readiness-delta.js +0 -218
  205. package/scripts/lib/readiness-evidence-closure.js +0 -196
  206. package/scripts/lib/reentry-memory-capture.js +0 -241
  207. package/scripts/lib/reentry-memory-retrieval.js +0 -302
  208. package/scripts/lib/reentry-memory-status.js +0 -146
  209. package/scripts/lib/reentry-memory-store.js +0 -178
  210. package/scripts/lib/reentry-state.js +0 -66
  211. package/scripts/lib/release-candidate-bundle.js +0 -166
  212. package/scripts/lib/remediation.js +0 -81
  213. package/scripts/lib/repo-map.js +0 -391
  214. package/scripts/lib/run-improvements-lifecycle.js +0 -330
  215. package/scripts/lib/run-improvements.js +0 -789
  216. package/scripts/lib/runtime-decision-policy.js +0 -387
  217. package/scripts/lib/safe-path-engine.js +0 -705
  218. package/scripts/lib/safe-run-controller.js +0 -887
  219. package/scripts/lib/score.js +0 -262
  220. package/scripts/lib/seamless-enforcement.js +0 -329
  221. package/scripts/lib/seamless-outcome.js +0 -689
  222. package/scripts/lib/seamless-reality-gate.js +0 -5043
  223. package/scripts/lib/security-risk-classifier.js +0 -511
  224. package/scripts/lib/security-scan.js +0 -384
  225. package/scripts/lib/session-context-optimizer.js +0 -1211
  226. package/scripts/lib/session-timing.js +0 -315
  227. package/scripts/lib/skill-hygiene.js +0 -805
  228. package/scripts/lib/skill-packs.js +0 -161
  229. package/scripts/lib/skills-operating-layer.js +0 -580
  230. package/scripts/lib/smart-work-routing.js +0 -768
  231. package/scripts/lib/source-catalog.js +0 -700
  232. package/scripts/lib/status-value-summary.js +0 -32
  233. package/scripts/lib/support-bundle.js +0 -578
  234. package/scripts/lib/task-continuation.js +0 -440
  235. package/scripts/lib/test-helpers.js +0 -15
  236. package/scripts/lib/tier.js +0 -38
  237. package/scripts/lib/token-context-quality-gate.js +0 -370
  238. package/scripts/lib/token-cost-capture.js +0 -187
  239. package/scripts/lib/token-cost-intelligence.js +0 -358
  240. package/scripts/lib/token-efficiency-evidence.js +0 -213
  241. package/scripts/lib/token-evidence.js +0 -699
  242. package/scripts/lib/tokenish.js +0 -17
  243. package/scripts/lib/tool-output-sandbox.js +0 -304
  244. package/scripts/lib/trust-audit.js +0 -136
  245. package/scripts/lib/unified-events.js +0 -396
  246. package/scripts/lib/upgrade-interruption-recovery.js +0 -407
  247. package/scripts/lib/usage-ledger.js +0 -201
  248. package/scripts/lib/value-ledger.js +0 -130
  249. package/scripts/lib/value-proof-calibration.js +0 -531
  250. package/scripts/lib/visual-qa.js +0 -231
  251. package/scripts/lib/voice-alpha.js +0 -29
  252. package/scripts/lib/work-aware-orchestration.js +0 -976
  253. package/scripts/lib/work-control-receipts.js +0 -577
  254. package/scripts/lib/work-ledger.js +0 -1123
  255. package/scripts/lib/work-panel-preview.js +0 -352
  256. package/scripts/lib/workflow-discipline.js +0 -280
  257. package/scripts/lib/workflow-signals.js +0 -419
  258. package/scripts/lib/workspace-map.js +0 -281
  259. package/scripts/lib/workspace-registry.js +0 -1367
  260. package/scripts/lib/workspace-resolver.js +0 -480
@@ -1,1211 +0,0 @@
1
- "use strict";
2
-
3
- const fs = require("fs");
4
- const path = require("path");
5
- const crypto = require("crypto");
6
- const { ensureCcoDirs, nowIso, safeReadJson, safeWriteJson, safeWriteText } = require("./fsx");
7
- const { appendProductLearningEvent } = require("./product-learning-events");
8
-
9
- const SESSION_CONTEXT_CONTRACT = "avorelo.sessionContext.v1";
10
- const SESSION_CONTEXT_SCHEMA_VERSION = 1;
11
- const LATEST_CONTEXT_REL_PATH = ".claude/cco/orchestration/session-context/latest-context.json";
12
- const LATEST_CONTEXT_MD_REL_PATH = ".claude/cco/orchestration/session-context/latest-context.md";
13
- const CONTEXT_HISTORY_DIR_REL_PATH = ".claude/cco/orchestration/session-context/history";
14
- const CONTEXT_EVENT_LOG_REL_PATH = ".claude/cco/events/session-context.jsonl";
15
-
16
- const DEFAULT_MAX_CHARS = 6000;
17
- const HARD_MAX_CHARS = 12000;
18
-
19
- 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;
20
-
21
- function redactIfSecret(text) {
22
- if (!text) return text;
23
- const s = String(text);
24
- return SECRET_PATTERN.test(s) ? "[REDACTED]" : s;
25
- }
26
-
27
- function createContextId() {
28
- return `sc-${Date.now()}-${crypto.randomBytes(4).toString("hex")}`;
29
- }
30
-
31
- function estimateTokens(chars) {
32
- return Math.ceil(chars / 4);
33
- }
34
-
35
- // ── Source receipt readers ────────────────────────────────────────────────────
36
-
37
- function readWorkControlReceipt(cwd) {
38
- try {
39
- const { readLatestWorkControlReceipt } = require("./work-control-receipts");
40
- return readLatestWorkControlReceipt(cwd);
41
- } catch {
42
- return null;
43
- }
44
- }
45
-
46
- function readProof(cwd) {
47
- try {
48
- const { readCurrentProof } = require("./orchestration");
49
- return readCurrentProof(cwd);
50
- } catch {
51
- return null;
52
- }
53
- }
54
-
55
- function readOrBuildWorkspaceMap(cwd, options = {}) {
56
- try {
57
- const { readWorkspaceMap, writeWorkspaceMap } = require("./workspace-map");
58
- const existing = readWorkspaceMap(cwd);
59
- if (existing && !options.refreshWorkspaceMap) return existing;
60
- return writeWorkspaceMap(cwd, { task: options.task || "" });
61
- } catch {
62
- return null;
63
- }
64
- }
65
-
66
- function readWorkspaceRegistry(cwd) {
67
- try {
68
- const { readLatestRegistry } = require("./workspace-registry");
69
- return readLatestRegistry(cwd);
70
- } catch {
71
- return null;
72
- }
73
- }
74
-
75
- // ── Section builders ──────────────────────────────────────────────────────────
76
-
77
- function buildObjectiveSection(options, wcReceipt, proof) {
78
- const taskText = redactIfSecret(
79
- options.task
80
- || wcReceipt?.task?.text
81
- || proof?.task
82
- || "Session Context / Continuation Optimization Foundation v1"
83
- );
84
- return String(taskText).slice(0, 300);
85
- }
86
-
87
- function buildCurrentStateSection(wcReceipt) {
88
- if (!wcReceipt) {
89
- return {
90
- finalState: "missing",
91
- receiptPath: null,
92
- source: "no-work-control-receipt",
93
- };
94
- }
95
- const wc = wcReceipt.workControl || {};
96
- return {
97
- finalState: wc.finalState || "missing",
98
- receiptPath: ".claude/cco/orchestration/work-control/latest-receipt.json",
99
- blockedCount: wc.blockedCount || 0,
100
- approvalRequiredCount: wc.approvalRequiredCount || 0,
101
- highRiskIntakeCount: wc.highRiskIntakeCount || 0,
102
- unknownSourcesCount: wc.unknownSourcesCount || 0,
103
- source: "work-control-receipt",
104
- };
105
- }
106
-
107
- function buildNextSafestAction(wcReceipt) {
108
- if (!wcReceipt) {
109
- return "Run `node bin/avorelo work-control --json` to establish current state before proceeding.";
110
- }
111
- return wcReceipt.workControl?.nextSafestAction
112
- || "Continue with the smallest local scope. Re-run proof before next session.";
113
- }
114
-
115
- function buildAlreadyDone(wcReceipt, proof) {
116
- const items = [];
117
- if (wcReceipt?.workControl?.carryForward?.lastRoute) {
118
- items.push(`Last route: ${wcReceipt.workControl.carryForward.lastRoute}`);
119
- }
120
- if (wcReceipt?.workControl?.carryForward?.lastTaskSummary) {
121
- items.push(`Last task: ${String(wcReceipt.workControl.carryForward.lastTaskSummary).slice(0, 120)}`);
122
- }
123
- if (wcReceipt?.evidencePaths?.length) {
124
- items.push(`Evidence receipts recorded: ${wcReceipt.evidencePaths.length}`);
125
- }
126
- if (proof?.runId) {
127
- items.push(`Proof run: ${proof.runId}`);
128
- }
129
- if (proof?.route?.selectedRoute) {
130
- items.push(`Route proven: ${proof.route.selectedRoute}`);
131
- }
132
- return items.length ? items : ["No prior carry-forward found — start from current work-control receipt."];
133
- }
134
-
135
- function buildDoNotRepeat(wcReceipt) {
136
- const base = [
137
- "Do not broad-scan the repo — use workspace map and named files first.",
138
- "Do not paste huge JSON into context — use `avorelo work-control --json` for compact receipts.",
139
- "Do not start over — read latest-context.md or work-control receipt to continue.",
140
- ];
141
- const fromReceipt = wcReceipt?.workControl?.doNotRepeat || [];
142
- const combined = [...new Set([...base, ...fromReceipt])];
143
- return combined.slice(0, 8);
144
- }
145
-
146
- function buildActiveRisks(wcReceipt) {
147
- const risks = [];
148
- if (!wcReceipt) {
149
- risks.push("No work-control receipt — run `avorelo work-control` before proceeding.");
150
- return risks;
151
- }
152
- const intake = wcReceipt.controls?.installIntake;
153
- const governance = wcReceipt.controls?.governance;
154
- const safePath = wcReceipt.controls?.safePath;
155
-
156
- if (intake?.highRiskItems > 0) {
157
- risks.push(`Install intake: ${intake.highRiskItems} high-risk items — review before tool/MCP use.`);
158
- }
159
- if (intake?.unknownItems > 0) {
160
- risks.push(`Install intake: ${intake.unknownItems} unknown-source items — do not execute without review.`);
161
- }
162
- if (governance?.subjectTrustStatus === "unknown") {
163
- risks.push(`Governance: subject trust status is 'unknown' — requires review before proceeding.`);
164
- }
165
- if (governance?.decision === "block" || wcReceipt.workControl?.blockedCount > 0) {
166
- risks.push(`Governance: blocked action recorded — preserve block, do not bypass.`);
167
- }
168
- if (safePath?.lastDecision === "recommend_reduced_scope") {
169
- risks.push(`Safe Path: reduced scope recommended — use narrow local boundary only.`);
170
- }
171
- if (!governance?.latestReceiptPath) {
172
- risks.push("Governance receipt missing — run `avorelo guard` to establish governance baseline.");
173
- }
174
- if (!safePath?.latestReceiptPath) {
175
- risks.push("Safe Path receipt missing — run `avorelo guard` to establish safe-path baseline.");
176
- }
177
- return risks.length ? risks : ["No active risks detected — re-run `avorelo work-control` to refresh."];
178
- }
179
-
180
- function buildRelevantFiles(wcReceipt, workspaceMap, options = {}) {
181
- const task = String(options.task || wcReceipt?.task?.text || "").toLowerCase();
182
- const maxFiles = options.maxFiles || 20;
183
- const files = [];
184
-
185
- // Task-aware file selection from workspace map
186
- if (workspaceMap) {
187
- const taskKeywords = {
188
- "session": ["scripts/lib/session-context-optimizer.js", "tests/session-context-optimization.test.js"],
189
- "context": ["scripts/lib/session-context-optimizer.js", "scripts/lib/workspace-map.js"],
190
- "brain": ["scripts/lib/brain-pack.js", "tests/brain-pack.test.js"],
191
- "recipe": ["scripts/lib/brain-pack.js", "tests/brain-pack.test.js"],
192
- "work-control": ["scripts/lib/work-control-receipts.js", "tests/work-control-receipts.test.js"],
193
- "workspace": ["scripts/lib/workspace-map.js", "tests/workspace-map.test.js"],
194
- "registry": ["scripts/lib/workspace-registry.js", "tests/workspace-registry.test.js"],
195
- "capability": ["scripts/lib/plans.js", "scripts/lib/capability-registry.js", "scripts/lib/capability-packs.js"],
196
- "skill": ["scripts/lib/skills-operating-layer.js", "scripts/lib/avorelo-skill-registry.js"],
197
- "intake": ["scripts/lib/install-intake-risk.js", "tests/install-intake-risk.test.js"],
198
- "safe-path": ["scripts/lib/safe-path-engine.js"],
199
- "governance": ["scripts/lib/agent-access-governance.js", "scripts/lib/agent-enforcement.js"],
200
- "product-learning": ["scripts/lib/product-learning-events.js", "docs/Product-Learning-Telemetry.md"],
201
- "status": ["scripts/cco-status.js", "scripts/lib/dashboard.js"],
202
- "cli": ["scripts/lib/public-cli.js", "bin/avorelo"],
203
- };
204
-
205
- for (const [keyword, keyFiles] of Object.entries(taskKeywords)) {
206
- if (task.includes(keyword)) {
207
- files.push(...keyFiles);
208
- }
209
- }
210
- }
211
-
212
- // Optionally enrich from workspace registry (read latest, do not rebuild)
213
- if (options.useRegistry !== false) {
214
- const registry = readWorkspaceRegistry(options.cwd || process.cwd());
215
- if (registry && Array.isArray(registry.recommendations?.sessionContextRelevantFiles)) {
216
- const regFiles = registry.recommendations.sessionContextRelevantFiles.slice(0, 10);
217
- files.push(...regFiles);
218
- }
219
- }
220
-
221
- // Always include core files for this feature
222
- const coreFiles = [
223
- "scripts/lib/session-context-optimizer.js",
224
- "scripts/lib/brain-pack.js",
225
- "scripts/lib/work-control-receipts.js",
226
- "scripts/lib/workspace-map.js",
227
- "scripts/lib/public-cli.js",
228
- "scripts/lib/plans.js",
229
- "scripts/lib/product-learning-events.js",
230
- "tests/session-context-optimization.test.js",
231
- "docs/dogfood/session-context-optimization-dogfood.md",
232
- ];
233
-
234
- const combined = [...new Set([...files, ...coreFiles])].slice(0, maxFiles);
235
- return combined;
236
- }
237
-
238
- // ── Dynamic commands (task/target-aware) ──────────────────────────────────────
239
-
240
- const TASK_COMMAND_MAP = [
241
- {
242
- signals: ["intake", "mcp", "package", "install", "dependency", "risk"],
243
- commands: [
244
- "node bin/avorelo intake --json",
245
- "node bin/avorelo guard --action tool_call --target \"unknown-mcp-server\" --json",
246
- "node --test tests/install-intake-risk.test.js",
247
- ],
248
- },
249
- {
250
- signals: ["safe-path", "governance", "guard", "block", "agent"],
251
- commands: [
252
- "node bin/avorelo guard --action file_write --target \".env\" --json",
253
- "node --test tests/avorelo-agent-enforcement.test.js",
254
- ],
255
- },
256
- {
257
- signals: ["session", "context", "continuation", "handoff", "rediscovery"],
258
- commands: [
259
- "node bin/avorelo session-context --json",
260
- "node bin/avorelo session-context --handoff",
261
- "node --test tests/session-context-optimization.test.js",
262
- ],
263
- },
264
- {
265
- signals: ["brain", "brain-pack", "brain pack", "context intelligence"],
266
- commands: [
267
- "node bin/avorelo brain-pack --json",
268
- "node --test tests/brain-pack.test.js",
269
- ],
270
- },
271
- {
272
- signals: ["skill", "recipe", "workflow", "source-backed"],
273
- commands: [
274
- "node bin/avorelo skills route --task \"<task>\"",
275
- ],
276
- },
277
- {
278
- signals: ["frontend", "browser", "screenshot", "visual", "playwright"],
279
- commands: [
280
- "node bin/avorelo visual-qa --dry-run",
281
- ],
282
- },
283
- {
284
- signals: ["release", "merge", "ci", "build", "validate", "pr", "pull request"],
285
- commands: [
286
- "node scripts/validate-operating-layer.js",
287
- "cmd /c npm test",
288
- "node bin/avorelo proof",
289
- ],
290
- },
291
- ];
292
-
293
- const BASE_COMMANDS = [
294
- "node bin/avorelo work-control --json",
295
- "node bin/avorelo session-context --json",
296
- "node bin/avorelo session-context --handoff",
297
- "node bin/avorelo proof",
298
- ];
299
-
300
- function buildRelevantCommands(task, targetSurface, wcReceipt, options = {}) {
301
- const taskStr = String(task || wcReceipt?.task?.text || "").toLowerCase();
302
- const matched = [];
303
-
304
- for (const entry of TASK_COMMAND_MAP) {
305
- if (entry.signals.some((s) => taskStr.includes(s))) {
306
- matched.push(...entry.commands);
307
- }
308
- }
309
-
310
- // Substitute <task> placeholder
311
- const taskSlice = String(task || wcReceipt?.task?.text || "current task").slice(0, 60);
312
- const substituted = matched.map((c) => c.replace(/<task>/g, taskSlice));
313
-
314
- const combined = [...new Set([...BASE_COMMANDS, ...substituted])];
315
-
316
- // Target-specific filtering
317
- if (targetSurface === "local_model") {
318
- // Local model: minimal — only the most essential
319
- return combined.slice(0, 3);
320
- }
321
- if (targetSurface === "codex") {
322
- // Codex: command/test oriented — drop explanation-heavy ones
323
- return combined
324
- .filter((c) => c.includes("--test") || c.includes("npm test") || c.includes("validate-operating-layer") || c.includes("work-control") || c.includes("proof"))
325
- .slice(0, 6);
326
- }
327
-
328
- return combined.slice(0, 8);
329
- }
330
-
331
- // ── Skills route fallback ──────────────────────────────────────────────────────
332
-
333
- function buildSkillsRouteFallback(wcReceipt, task) {
334
- const skills = wcReceipt?.controls?.skills;
335
- const skillsReceiptMissing = !skills || skills.status === "missing" || !skills.latestRouteReceiptPath;
336
-
337
- if (!skillsReceiptMissing) return null;
338
-
339
- const taskStr = String(task || wcReceipt?.task?.text || "");
340
- if (!taskStr) return null;
341
-
342
- // Only recommend fallback for task types where skills route is useful
343
- const skillsSignals = ["skill", "recipe", "workflow", "reference", "source-backed", "build", "implement", "refactor"];
344
- const isRelevant = skillsSignals.some((s) => taskStr.toLowerCase().includes(s));
345
- if (!isRelevant) return null;
346
-
347
- return {
348
- fallbackCommand: `node bin/avorelo skills route --task "${taskStr.slice(0, 60)}"`,
349
- reason: "No skills route receipt found — run this command to get source-backed workflow guidance.",
350
- note: "This is a fallback only. Skills route is not run automatically.",
351
- };
352
- }
353
-
354
- function buildModelEffortRecommendation(wcReceipt, proof) {
355
- if (!proof?.route) {
356
- if (!wcReceipt) {
357
- return {
358
- source: "none",
359
- recommendation: "Run `avorelo route <task>` to get model/effort recommendation.",
360
- };
361
- }
362
- return {
363
- source: "work-control",
364
- recommendation: wcReceipt.workControl?.nextSafestAction
365
- ? "Use smallest safe local scope per work-control guidance."
366
- : "No route available — run `avorelo route <task>` for routing recommendation.",
367
- };
368
- }
369
- const route = proof.route;
370
- return {
371
- source: "proof-route",
372
- selectedRoute: route.selectedRoute || null,
373
- chosenTool: route.chosenTool || null,
374
- selectedModel: route.selectedModel || null,
375
- chosenModelProfile: route.chosenModelProfile || null,
376
- fallbackTool: route.fallbackTool || null,
377
- recommendation: [
378
- route.chosenTool ? `Use: ${route.chosenTool}` : null,
379
- route.selectedModel ? `Model: ${route.selectedModel}` : null,
380
- route.chosenModelProfile ? `Profile: ${route.chosenModelProfile}` : null,
381
- (route.safetyNotes || []).slice(0, 2).join("; ") || null,
382
- ].filter(Boolean).join(" · ") || "Use medium scope, local-first.",
383
- };
384
- }
385
-
386
- function buildSkillsHints(wcReceipt) {
387
- const skills = wcReceipt?.controls?.skills;
388
- if (!skills || skills.status === "missing") {
389
- return null;
390
- }
391
- return {
392
- status: skills.status,
393
- reviewedSources: skills.reviewedSources || 0,
394
- deferredSources: skills.deferredSources || 0,
395
- latestRouteReceiptPath: skills.latestRouteReceiptPath || null,
396
- hint: skills.deferredSources > 0
397
- ? `${skills.deferredSources} skill sources deferred — do not use without intake review.`
398
- : "Skill sources reviewed — use existing skill route receipt.",
399
- };
400
- }
401
-
402
- function buildReceiptPathSummary(wcReceipt) {
403
- const paths = [];
404
- paths.push("work-control: .claude/cco/orchestration/work-control/latest-receipt.json");
405
- const cf = wcReceipt?.workControl?.carryForward;
406
- if (cf?.receiptPaths?.length) {
407
- paths.push(...cf.receiptPaths.slice(0, 5));
408
- }
409
- const unchecked = cf?.uncheckedItems || [];
410
- return { checked: paths, unchecked };
411
- }
412
-
413
- // ── Compact prompt builder ────────────────────────────────────────────────────
414
-
415
- function buildCompactPrompt(sessionStart, targetSurface) {
416
- const toolName = targetSurface === "codex"
417
- ? "Codex"
418
- : targetSurface === "local_model"
419
- ? "your local model"
420
- : "Claude";
421
-
422
- const lines = [
423
- `# Start here — do not rediscover repo`,
424
- "",
425
- `**Task:** ${sessionStart.objective}`,
426
- "",
427
- `**Current state:** ${sessionStart.currentState.finalState?.toUpperCase() || "UNKNOWN"}`,
428
- `**Next safest action:** ${sessionStart.nextSafestAction}`,
429
- "",
430
- "## Do not repeat",
431
- ...(sessionStart.doNotRepeat || []).slice(0, 5).map((item) => `- ${item}`),
432
- "",
433
- "## Relevant files (start here)",
434
- ...(sessionStart.relevantFiles || []).slice(0, 12).map((f) => `- ${f}`),
435
- "",
436
- "## Commands to run first",
437
- ...(sessionStart.relevantCommands || []).slice(0, 5).map((c) => `- \`${c}\``),
438
- "",
439
- "## Active risks",
440
- ...(sessionStart.activeRisks || []).slice(0, 4).map((r) => `- ${r}`),
441
- ];
442
-
443
- if (sessionStart.recommendedModelOrWorker?.recommendation) {
444
- lines.push("", `**Model/effort:** ${sessionStart.recommendedModelOrWorker.recommendation}`);
445
- }
446
-
447
- if (sessionStart.skillsHints) {
448
- lines.push("", `**Skills:** ${sessionStart.skillsHints.hint}`);
449
- }
450
-
451
- if (sessionStart.skillsRouteFallback) {
452
- lines.push("", `**Skills fallback:** ${sessionStart.skillsRouteFallback.reason}`);
453
- lines.push(` Command: \`${sessionStart.skillsRouteFallback.fallbackCommand}\``);
454
- }
455
-
456
- if (sessionStart.capabilityRecommendation?.recommendedCapabilityPack) {
457
- lines.push("", `**Capability:** ${sessionStart.capabilityRecommendation.recommendedCapabilityPackName || sessionStart.capabilityRecommendation.recommendedCapabilityPack}`);
458
- lines.push(` Why: ${sessionStart.capabilityRecommendation.capabilityReason || ""}`);
459
- }
460
-
461
- if (sessionStart.nextRunContext?.compactText) {
462
- lines.push("", sessionStart.nextRunContext.compactText);
463
- }
464
-
465
- lines.push(
466
- "",
467
- `*Context generated by Avorelo session-context. Do not paste raw receipts — use \`avorelo work-control --json\` for live state.*`,
468
- );
469
-
470
- return lines.join("\n");
471
- }
472
-
473
- // ── Context budget guard ──────────────────────────────────────────────────────
474
-
475
- function applyContextBudget(context, maxChars) {
476
- const hard = Math.min(maxChars, HARD_MAX_CHARS);
477
- const sections = context.sessionStart;
478
- const prompt = buildCompactPrompt(sections, context.targetSurface || "generic");
479
-
480
- if (prompt.length <= hard) {
481
- return {
482
- compactPrompt: prompt,
483
- truncationApplied: false,
484
- includedSections: Object.keys(sections),
485
- excludedSections: [],
486
- estimatedTokens: estimateTokens(prompt.length),
487
- avoidedJsonDump: true,
488
- avoidedBroadRediscovery: true,
489
- };
490
- }
491
-
492
- // Drop lowest priority sections to fit budget
493
- const dropOrder = [
494
- "alreadyDone",
495
- "receiptPathSummary",
496
- "skillsHints",
497
- "recommendedModelOrWorker",
498
- "relevantFiles",
499
- "activeRisks",
500
- ];
501
-
502
- const reduced = { ...sections };
503
- const excluded = [];
504
-
505
- for (const key of dropOrder) {
506
- const test = buildCompactPrompt(reduced, context.targetSurface || "generic");
507
- if (test.length <= hard) break;
508
- if (key in reduced) {
509
- delete reduced[key];
510
- excluded.push(key);
511
- }
512
- }
513
-
514
- const finalPrompt = buildCompactPrompt(reduced, context.targetSurface || "generic");
515
- return {
516
- compactPrompt: finalPrompt,
517
- truncationApplied: excluded.length > 0,
518
- includedSections: Object.keys(reduced),
519
- excludedSections: excluded,
520
- estimatedTokens: estimateTokens(finalPrompt.length),
521
- avoidedJsonDump: true,
522
- avoidedBroadRediscovery: true,
523
- };
524
- }
525
-
526
- // ── Markdown handoff builder ──────────────────────────────────────────────────
527
-
528
- function buildMarkdownHandoff(context, budgetResult) {
529
- const targetLabel = {
530
- claude: "Claude Code",
531
- codex: "Codex",
532
- local_model: "Local Model",
533
- generic: "AI Assistant",
534
- }[context.targetSurface || "generic"] || "AI Assistant";
535
-
536
- const s = context.sessionStart;
537
- const lines = [
538
- `# Avorelo Session Context — ${targetLabel}`,
539
- `> **Start here — do not rediscover repo**`,
540
- `> Generated: ${context.createdAt}`,
541
- `> Context ID: ${context.contextId}`,
542
- "",
543
- `## Task`,
544
- s.objective,
545
- "",
546
- `## Current State`,
547
- `- **Status:** ${s.currentState?.finalState?.toUpperCase() || "UNKNOWN"}`,
548
- s.currentState?.blockedCount > 0 ? `- **Blocked actions:** ${s.currentState.blockedCount}` : null,
549
- s.currentState?.highRiskIntakeCount > 0 ? `- **High-risk intake items:** ${s.currentState.highRiskIntakeCount}` : null,
550
- `- **Receipt:** \`.claude/cco/orchestration/work-control/latest-receipt.json\``,
551
- "",
552
- `## Next Safest Action`,
553
- s.nextSafestAction,
554
- "",
555
- `## Do Not Repeat`,
556
- ...(s.doNotRepeat || []).map((item) => `- ${item}`),
557
- "",
558
- `## Relevant Files`,
559
- ...(s.relevantFiles || []).map((f) => `- \`${f}\``),
560
- "",
561
- `## Commands to Run First`,
562
- ...(s.relevantCommands || []).map((c) => `- \`${c}\``),
563
- "",
564
- `## Active Risks`,
565
- ...(s.activeRisks || []).map((r) => `- ${r}`),
566
- "",
567
- ].filter((line) => line !== null);
568
-
569
- if (s.alreadyDone?.length) {
570
- lines.push("## Already Done");
571
- s.alreadyDone.forEach((item) => lines.push(`- ${item}`));
572
- lines.push("");
573
- }
574
-
575
- if (s.recommendedModelOrWorker?.recommendation) {
576
- lines.push("## Model / Effort");
577
- lines.push(s.recommendedModelOrWorker.recommendation);
578
- lines.push("");
579
- }
580
-
581
- if (s.skillsHints) {
582
- lines.push("## Skills Continuation");
583
- lines.push(s.skillsHints.hint);
584
- lines.push("");
585
- }
586
-
587
- if (s.skillsRouteFallback) {
588
- lines.push("## Skills Route Fallback");
589
- lines.push(s.skillsRouteFallback.reason);
590
- lines.push(`\`${s.skillsRouteFallback.fallbackCommand}\``);
591
- lines.push("");
592
- }
593
-
594
- if (s.capabilityRecommendation?.recommendedCapabilityPack) {
595
- const cap = s.capabilityRecommendation;
596
- lines.push("## Recommended Capability");
597
- lines.push(`- Pack: **${cap.recommendedCapabilityPackName || cap.recommendedCapabilityPack}**`);
598
- lines.push(`- Why: ${cap.capabilityReason || ""}`);
599
- lines.push(`- Next: ${cap.capabilityNextAction || ""}`);
600
- if (cap.additionalCapabilityPacks?.length) {
601
- lines.push(`- Also relevant: ${cap.additionalCapabilityPacks.map((p) => p.name).join(", ")}`);
602
- }
603
- lines.push("");
604
- }
605
-
606
- if (s.brainPackSummary) {
607
- const bp = s.brainPackSummary;
608
- lines.push("## Brain Pack");
609
- lines.push(`- Project: ${bp.projectName || ""}`);
610
- lines.push(`- Stage: ${bp.currentRoadmapStage || ""}`);
611
- if (bp.detectedRecipe) lines.push(`- Recipe: ${bp.detectedRecipe}`);
612
- lines.push(`- Path: \`${bp.jsonPath}\``);
613
- lines.push("");
614
- }
615
-
616
- if (s.targetSpecific) {
617
- const ts = s.targetSpecific;
618
- lines.push(`## Target: ${ts.targetLabel}`);
619
- lines.push(ts.topNote);
620
- if (ts.architectureNote) lines.push(`> ${ts.architectureNote}`);
621
- if (ts.doNotStart?.length) {
622
- ts.doNotStart.forEach((d) => lines.push(`- ${d}`));
623
- }
624
- lines.push("");
625
- }
626
-
627
- if (s.nextRunContext?.compactText) {
628
- lines.push("## Run Improvements · Next-Run Context");
629
- lines.push(s.nextRunContext.compactText);
630
- lines.push(`- Status: ${s.nextRunContext.status} · ${s.nextRunContext.defaultsCount} default(s)`);
631
- lines.push(`- Artifact: \`${s.nextRunContext.artifactPath}\``);
632
- lines.push("");
633
- }
634
-
635
- lines.push("## Context Budget");
636
- lines.push(`- Estimated tokens: ${budgetResult.estimatedTokens}`);
637
- lines.push(`- Truncation applied: ${budgetResult.truncationApplied}`);
638
- if (budgetResult.excludedSections.length) {
639
- lines.push(`- Excluded sections: ${budgetResult.excludedSections.join(", ")}`);
640
- }
641
- lines.push("");
642
- lines.push("---");
643
- lines.push("*Generated by `avorelo session-context`. Do not paste raw receipts — use `avorelo work-control --json` for live state.*");
644
-
645
- return lines.join("\n");
646
- }
647
-
648
- // ── Main build function ───────────────────────────────────────────────────────
649
-
650
- // ── Capability recommender integration ────────────────────────────────────────
651
-
652
- function readCapabilityRecommendation(cwd) {
653
- try {
654
- const { recommendCapabilities } = require("./capability-recommender");
655
- const rec = recommendCapabilities({ cwd, signals: {}, plan: "free" });
656
- return {
657
- recommendedCapabilityPack: rec.recommendedPack?.id || null,
658
- recommendedCapabilityPackName: rec.recommendedPack?.name || null,
659
- capabilityReason: rec.reason || null,
660
- capabilityNextAction: rec.nextAction || null,
661
- capabilityFirstCommand: rec.nextAction
662
- ? rec.nextAction.replace(/^Run\s+/, "").replace(/\s+to\s.*$/, "").replace(/[`'"]/g, "").trim()
663
- : null,
664
- additionalCapabilityPacks: (rec.additionalPacks || []).map((p) => ({
665
- id: p.id,
666
- name: p.name,
667
- })),
668
- };
669
- } catch {
670
- return null;
671
- }
672
- }
673
-
674
- // ── Brain Pack reader (safe) ──────────────────────────────────────────────────
675
-
676
- function readBrainPackForContext(cwd) {
677
- try {
678
- const { readLatestBrainPack } = require("./brain-pack");
679
- const bp = readLatestBrainPack(cwd);
680
- if (!bp) return null;
681
- // Return a compact summary only — never the full brain pack
682
- return {
683
- brainPackId: bp.brainPackId,
684
- projectName: bp.project?.name || null,
685
- currentRoadmapStage: bp.project?.currentRoadmapStage || null,
686
- contextRules: bp.contextRules || null,
687
- lastWorkControlFinalState: bp.signals?.lastWorkControlFinalState || null,
688
- capabilityRecommended: bp.capabilityRecommendation?.recommendedPackId || null,
689
- recipesCount: (bp.recipes || []).length,
690
- detectedRecipe: (bp.recipes || [])[0]?.detectedRecipe || null,
691
- jsonPath: ".claude/cco/context/brain-pack/latest.json",
692
- };
693
- } catch {
694
- return null;
695
- }
696
- }
697
-
698
- // ── Target-specific context additions ────────────────────────────────────────
699
-
700
- function buildTargetSpecificGuidance(targetSurface, objective, capabilityRec) {
701
- switch (targetSurface) {
702
- case "claude":
703
- return {
704
- targetLabel: "Claude Code",
705
- emphasis: "full context, architecture awareness, named files, bounded implementation",
706
- topNote: "Do not rediscover repo. Read named files first. Inspect before coding. Keep scope bounded.",
707
- architectureNote: "Capability Recommender is the single router — no duplicate routing tables.",
708
- doNotStart: capabilityRec?.additionalCapabilityPacks?.map((p) => `Do not start ${p.name} work in this session`) || [],
709
- };
710
- case "codex":
711
- return {
712
- targetLabel: "Codex",
713
- emphasis: "command/test oriented, short scope, exact validation commands",
714
- topNote: "Use exact commands. Run tests to verify. Avoid broad explanation. Stay within bounded scope.",
715
- architectureNote: null,
716
- doNotStart: ["Do not do broad codebase explanation.", "Use exact test commands to verify changes."],
717
- };
718
- case "local_model":
719
- return {
720
- targetLabel: "Local Model",
721
- emphasis: "shortest context, fewer files, simple tasks only",
722
- topNote: "Minimal context. Simple bounded task only. Do not attempt architecture-heavy changes.",
723
- architectureNote: null,
724
- doNotStart: ["Do not attempt complex multi-file changes.", "Prefer single-file bounded edits."],
725
- };
726
- default:
727
- return {
728
- targetLabel: "AI Assistant",
729
- emphasis: "neutral compact handoff",
730
- topNote: "Start from current state. Do not rediscover repo. Use named files.",
731
- architectureNote: null,
732
- doNotStart: [],
733
- };
734
- }
735
- }
736
-
737
- function buildSessionContext(cwd, options = {}) {
738
- const maxChars = Math.min(
739
- options.maxChars || DEFAULT_MAX_CHARS,
740
- HARD_MAX_CHARS,
741
- );
742
- const targetSurface = options.targetSurface || "generic";
743
- const task = options.task;
744
-
745
- const wcReceipt = readWorkControlReceipt(cwd);
746
- const proof = readProof(cwd);
747
- const workspaceMap = readOrBuildWorkspaceMap(cwd, {
748
- refreshWorkspaceMap: options.refreshWorkspaceMap || false,
749
- task: task || wcReceipt?.task?.text || "",
750
- });
751
-
752
- const objective = buildObjectiveSection(options, wcReceipt, proof);
753
- const currentState = buildCurrentStateSection(wcReceipt);
754
- const nextSafestAction = buildNextSafestAction(wcReceipt);
755
- const alreadyDone = buildAlreadyDone(wcReceipt, proof);
756
- const doNotRepeat = buildDoNotRepeat(wcReceipt);
757
- const activeRisks = buildActiveRisks(wcReceipt);
758
- const relevantFiles = buildRelevantFiles(wcReceipt, workspaceMap, {
759
- task: task || wcReceipt?.task?.text || "",
760
- maxFiles: 20,
761
- cwd,
762
- });
763
- const relevantCommands = buildRelevantCommands(task, targetSurface, wcReceipt, {});
764
- const recommendedModelOrWorker = buildModelEffortRecommendation(wcReceipt, proof);
765
- const skillsHints = buildSkillsHints(wcReceipt);
766
- const skillsRouteFallback = buildSkillsRouteFallback(wcReceipt, task || wcReceipt?.task?.text);
767
- const receiptPathSummary = buildReceiptPathSummary(wcReceipt);
768
-
769
- // Next-run context (run improvements + learning) — compact injection only
770
- let nextRunContext = null;
771
- try {
772
- const { loadNextRunContext, buildCompactContextText } = require("./next-run-context");
773
- const nrc = loadNextRunContext(cwd);
774
- if (nrc && (nrc.status === "prepared" || nrc.status === "applied" || nrc.status === "injected") && (nrc.appliedDefaults || []).length > 0) {
775
- nextRunContext = {
776
- status: nrc.status,
777
- defaultsCount: (nrc.appliedDefaults || []).length,
778
- topDefault: (nrc.appliedDefaults || [])[0]?.text || null,
779
- compactText: buildCompactContextText(nrc),
780
- artifactPath: ".claude/cco/state/next-run-context.json",
781
- };
782
- }
783
- } catch {}
784
-
785
- // Capability recommender integration (reuse, do not duplicate)
786
- const capabilityRecommendation = readCapabilityRecommendation(cwd);
787
-
788
- // Brain pack compact inclusion
789
- const brainPackSummary = readBrainPackForContext(cwd);
790
-
791
- // Target-specific guidance
792
- const targetSpecific = buildTargetSpecificGuidance(targetSurface, objective, capabilityRecommendation);
793
-
794
- const sessionStart = {
795
- objective,
796
- currentState,
797
- nextSafestAction,
798
- alreadyDone,
799
- doNotRepeat,
800
- activeRisks,
801
- relevantFiles,
802
- relevantCommands,
803
- recommendedModelOrWorker,
804
- skillsHints,
805
- skillsRouteFallback,
806
- receiptPathSummary,
807
- contextBudget: { maxChars, hardMaxChars: HARD_MAX_CHARS },
808
- capabilityRecommendation,
809
- brainPackSummary,
810
- targetSpecific,
811
- nextRunContext,
812
- };
813
-
814
- const contextId = createContextId();
815
- const createdAt = nowIso();
816
-
817
- const baseContext = {
818
- schemaVersion: SESSION_CONTEXT_SCHEMA_VERSION,
819
- contract: SESSION_CONTEXT_CONTRACT,
820
- contextType: "session_start",
821
- contextId,
822
- createdAt,
823
- targetSurface,
824
- sourceReceipts: {
825
- workControl: wcReceipt ? ".claude/cco/orchestration/work-control/latest-receipt.json" : null,
826
- proof: proof ? ".claude/cco/orchestration/current-proof.json" : null,
827
- route: proof?.route ? "via-proof" : null,
828
- intake: wcReceipt?.controls?.installIntake?.latestReceiptPath || null,
829
- governance: wcReceipt?.controls?.governance?.latestReceiptPath || null,
830
- safePath: wcReceipt?.controls?.safePath?.latestReceiptPath || null,
831
- skills: wcReceipt?.controls?.skills?.latestRouteReceiptPath || null,
832
- workspaceMap: workspaceMap?.artifactPath || null,
833
- },
834
- sessionStart,
835
- };
836
-
837
- const budgetResult = applyContextBudget(baseContext, maxChars);
838
- const markdownHandoff = buildMarkdownHandoff(baseContext, budgetResult);
839
-
840
- baseContext.sessionStart.compactPrompt = budgetResult.compactPrompt;
841
- baseContext.sessionStart.markdownHandoff = markdownHandoff;
842
-
843
- baseContext.tokenDiscipline = {
844
- maxChars,
845
- estimatedTokens: budgetResult.estimatedTokens,
846
- avoidedJsonDump: budgetResult.avoidedJsonDump,
847
- avoidedBroadRediscovery: budgetResult.avoidedBroadRediscovery,
848
- includedSections: budgetResult.includedSections,
849
- excludedSections: budgetResult.excludedSections,
850
- truncationApplied: budgetResult.truncationApplied,
851
- };
852
-
853
- // Brain Pack is now real — scaffold is superseded
854
- baseContext.brainPackUsed = Boolean(brainPackSummary);
855
- baseContext.brainPackSummary = brainPackSummary;
856
- baseContext.targetSpecificOutput = targetSurface !== "generic";
857
- baseContext.dynamicCommands = true;
858
-
859
- baseContext.featureCoverageLedger = [
860
- { feature: "compact_session_start_context", status: "implemented_now" },
861
- { feature: "continuation_packet_from_work_control", status: "implemented_now" },
862
- { feature: "do_not_repeat_guidance", status: "implemented_now" },
863
- { feature: "branch_worktree_task_summary", status: "implemented_now" },
864
- { feature: "receipt_path_summary", status: "implemented_now" },
865
- { feature: "next_safest_action", status: "implemented_now" },
866
- { feature: "what_was_checked_not_checked", status: "implemented_now" },
867
- { feature: "relevant_files_from_workspace_map", status: "implemented_now" },
868
- { feature: "avoid_huge_json_dumps", status: "implemented_now" },
869
- { feature: "avoid_broad_repo_rediscovery", status: "implemented_now" },
870
- { feature: "context_budget_guard", status: "implemented_now" },
871
- { feature: "model_effort_recommendation_summary", status: "implemented_now" },
872
- { feature: "skills_aware_continuation_hints", status: "implemented_now" },
873
- { feature: "intake_governance_safe_path_risk_summary", status: "implemented_now" },
874
- { feature: "cli_command_session_context", status: "implemented_now" },
875
- { feature: "product_learning_events", status: "implemented_now" },
876
- { feature: "status_proof_dashboard_compact_surface", status: "implemented_now" },
877
- { feature: "dogfood_with_avorelo_on_this_pr", status: "implemented_now" },
878
- { feature: "brain_pack_basic", status: "implemented_now" },
879
- { feature: "recipe_detection_basic", status: "implemented_now" },
880
- { feature: "dynamic_relevant_commands", status: "implemented_now" },
881
- { feature: "target_specific_handoff", status: "implemented_now" },
882
- { feature: "skills_route_fallback", status: "implemented_now" },
883
- { feature: "capability_recommender_context_bridge", status: "implemented_now" },
884
- { feature: "dogfood_feedback_loop_structured", status: "implemented_now" },
885
- { feature: "task_context_pack_builder_shape", status: "scaffolded_now" },
886
- { feature: "post_run_proof_summary_hook", status: "scaffolded_now" },
887
- { feature: "tool_connector_gating_hook", status: "scaffolded_now" },
888
- { feature: "local_premium_routing_hints", status: "scaffolded_now" },
889
- { feature: "token_savings_estimate", status: "scaffolded_now" },
890
- { feature: "adapter_output_hook", status: "scaffolded_now" },
891
- { feature: "full_brain_pack_management", status: "documented_deferred" },
892
- { feature: "full_ai_workflow_discipline_system", status: "documented_deferred" },
893
- { feature: "workflow_intelligence_radar", status: "documented_deferred" },
894
- { feature: "ai_workspace_registry_asset_inventory", status: "documented_deferred" },
895
- { feature: "browser_proof_evidence", status: "documented_deferred" },
896
- { feature: "full_token_cost_analytics_dashboard", status: "documented_deferred" },
897
- { feature: "full_recipe_library", status: "documented_deferred" },
898
- { feature: "full_model_gateway_optillm", status: "documented_deferred" },
899
- { feature: "team_cloud_sync", status: "documented_deferred" },
900
- { feature: "pricing_website_plugin_launch", status: "documented_deferred" },
901
- ];
902
-
903
- baseContext.productLearning = {
904
- eventsWritten: 0,
905
- suggestedEvents: [
906
- "session_context_generated",
907
- "session_context_handoff_generated",
908
- "context_budget_applied",
909
- "broad_rediscovery_avoided",
910
- "huge_json_dump_avoided",
911
- "continuation_packet_used",
912
- "model_effort_recommendation_generated",
913
- "brain_pack_used_in_session_context",
914
- "dynamic_commands_generated",
915
- "target_specific_handoff_generated",
916
- "capability_recommendation_embedded",
917
- "skills_route_fallback_recommended",
918
- ],
919
- };
920
-
921
- baseContext.redacted = true;
922
- return baseContext;
923
- }
924
-
925
- function writeSessionContext(cwd, context, options = {}) {
926
- ensureCcoDirs(cwd);
927
-
928
- const fs2 = require("fs");
929
- const path2 = require("path");
930
-
931
- // Ensure session-context dir exists
932
- const scDir = path2.join(cwd, ".claude", "cco", "orchestration", "session-context");
933
- fs2.mkdirSync(scDir, { recursive: true });
934
-
935
- // Write latest JSON (without markdownHandoff to keep it compact)
936
- const jsonPayload = { ...context };
937
- const { markdownHandoff, compactPrompt, ...sessionStartWithoutBulky } = context.sessionStart;
938
- jsonPayload.sessionStart = {
939
- ...sessionStartWithoutBulky,
940
- compactPromptLength: compactPrompt?.length || 0,
941
- markdownHandoffLength: markdownHandoff?.length || 0,
942
- markdownHandoffPath: LATEST_CONTEXT_MD_REL_PATH,
943
- };
944
- safeWriteJson(cwd, LATEST_CONTEXT_REL_PATH, jsonPayload);
945
-
946
- // Write latest Markdown
947
- safeWriteText(cwd, LATEST_CONTEXT_MD_REL_PATH, markdownHandoff || "");
948
-
949
- // Write history (plan-gated)
950
- const canExport = options.plan && options.plan !== "free";
951
- if (canExport) {
952
- const historyDir = path2.join(cwd, CONTEXT_HISTORY_DIR_REL_PATH);
953
- fs2.mkdirSync(historyDir, { recursive: true });
954
- safeWriteJson(cwd, `${CONTEXT_HISTORY_DIR_REL_PATH}/${context.contextId}.json`, jsonPayload);
955
- }
956
-
957
- // Append to event log
958
- const eventLine = {
959
- contextId: context.contextId,
960
- finalState: context.sessionStart?.currentState?.finalState || "missing",
961
- estimatedTokens: context.tokenDiscipline?.estimatedTokens || 0,
962
- truncationApplied: context.tokenDiscipline?.truncationApplied || false,
963
- targetSurface: context.targetSurface || "generic",
964
- createdAt: context.createdAt,
965
- };
966
- try {
967
- const abs = path2.join(cwd, CONTEXT_EVENT_LOG_REL_PATH);
968
- fs2.mkdirSync(path2.dirname(abs), { recursive: true });
969
- fs2.appendFileSync(abs, `${JSON.stringify(eventLine)}\n`, "utf8");
970
- } catch {}
971
-
972
- // Write product learning events
973
- let eventsWritten = 0;
974
- const productEvents = [
975
- {
976
- eventName: "session_context_generated",
977
- category: "session_context",
978
- status: "completed",
979
- payload: {
980
- finalState: context.sessionStart?.currentState?.finalState || "missing",
981
- estimatedTokens: context.tokenDiscipline?.estimatedTokens || 0,
982
- truncationApplied: context.tokenDiscipline?.truncationApplied || false,
983
- targetSurface: context.targetSurface || "generic",
984
- avoidedJsonDump: context.tokenDiscipline?.avoidedJsonDump || false,
985
- avoidedBroadRediscovery: context.tokenDiscipline?.avoidedBroadRediscovery || false,
986
- },
987
- },
988
- {
989
- eventName: "context_budget_applied",
990
- category: "session_context",
991
- status: "completed",
992
- payload: {
993
- maxChars: context.tokenDiscipline?.maxChars || DEFAULT_MAX_CHARS,
994
- estimatedTokens: context.tokenDiscipline?.estimatedTokens || 0,
995
- truncationApplied: context.tokenDiscipline?.truncationApplied || false,
996
- excludedSectionsCount: (context.tokenDiscipline?.excludedSections || []).length,
997
- },
998
- },
999
- {
1000
- eventName: "broad_rediscovery_avoided",
1001
- category: "session_context",
1002
- status: "completed",
1003
- payload: {
1004
- relevantFilesCount: (context.sessionStart?.relevantFiles || []).length,
1005
- workspaceMapUsed: Boolean(context.sourceReceipts?.workspaceMap),
1006
- },
1007
- },
1008
- {
1009
- eventName: "huge_json_dump_avoided",
1010
- category: "session_context",
1011
- status: "completed",
1012
- payload: {
1013
- avoidedJsonDump: true,
1014
- estimatedTokens: context.tokenDiscipline?.estimatedTokens || 0,
1015
- },
1016
- },
1017
- {
1018
- eventName: "continuation_packet_used",
1019
- category: "session_context",
1020
- status: "completed",
1021
- payload: {
1022
- workControlReceiptAvailable: Boolean(context.sourceReceipts?.workControl),
1023
- carryForwardAvailable: Boolean(context.sessionStart?.alreadyDone?.length),
1024
- },
1025
- },
1026
- ];
1027
-
1028
- if (context.sessionStart?.recommendedModelOrWorker?.source !== "none") {
1029
- productEvents.push({
1030
- eventName: "model_effort_recommendation_generated",
1031
- category: "session_context",
1032
- status: "completed",
1033
- payload: {
1034
- source: context.sessionStart.recommendedModelOrWorker.source || "unknown",
1035
- hasChosenTool: Boolean(context.sessionStart.recommendedModelOrWorker.chosenTool),
1036
- },
1037
- });
1038
- }
1039
-
1040
- if (context.brainPackUsed) {
1041
- productEvents.push({
1042
- eventName: "brain_pack_used_in_session_context",
1043
- category: "brain_pack",
1044
- status: "completed",
1045
- payload: {
1046
- brainPackId: context.brainPackSummary?.brainPackId || null,
1047
- detectedRecipe: context.brainPackSummary?.detectedRecipe || null,
1048
- },
1049
- });
1050
- }
1051
-
1052
- if (context.dynamicCommands) {
1053
- productEvents.push({
1054
- eventName: "dynamic_commands_generated",
1055
- category: "session_context",
1056
- status: "completed",
1057
- payload: {
1058
- commandsCount: (context.sessionStart?.relevantCommands || []).length,
1059
- targetSurface: context.targetSurface || "generic",
1060
- },
1061
- });
1062
- }
1063
-
1064
- if (context.targetSpecificOutput) {
1065
- productEvents.push({
1066
- eventName: "target_specific_handoff_generated",
1067
- category: "session_context",
1068
- status: "completed",
1069
- payload: {
1070
- targetSurface: context.targetSurface || "generic",
1071
- targetLabel: context.sessionStart?.targetSpecific?.targetLabel || null,
1072
- },
1073
- });
1074
- }
1075
-
1076
- if (context.sessionStart?.capabilityRecommendation?.recommendedCapabilityPack) {
1077
- productEvents.push({
1078
- eventName: "capability_recommendation_embedded",
1079
- category: "session_context",
1080
- status: "completed",
1081
- payload: {
1082
- recommendedPackId: context.sessionStart.capabilityRecommendation.recommendedCapabilityPack,
1083
- additionalPacksCount: (context.sessionStart.capabilityRecommendation.additionalCapabilityPacks || []).length,
1084
- },
1085
- });
1086
- }
1087
-
1088
- if (context.sessionStart?.skillsRouteFallback) {
1089
- productEvents.push({
1090
- eventName: "skills_route_fallback_recommended",
1091
- category: "session_context",
1092
- status: "completed",
1093
- payload: {
1094
- reason: context.sessionStart.skillsRouteFallback.reason || null,
1095
- },
1096
- });
1097
- }
1098
-
1099
- productEvents.forEach((event) => {
1100
- try {
1101
- appendProductLearningEvent(cwd, event);
1102
- eventsWritten += 1;
1103
- } catch {}
1104
- });
1105
-
1106
- context.productLearning.eventsWritten = eventsWritten;
1107
- return LATEST_CONTEXT_REL_PATH;
1108
- }
1109
-
1110
- function readLatestSessionContext(cwd) {
1111
- return safeReadJson(cwd, LATEST_CONTEXT_REL_PATH, null);
1112
- }
1113
-
1114
- function buildSessionContextSurface(cwd) {
1115
- const latest = readLatestSessionContext(cwd);
1116
- if (!latest) {
1117
- return {
1118
- status: "missing",
1119
- latestContextPath: null,
1120
- latestMarkdownPath: null,
1121
- estimatedTokens: 0,
1122
- avoidedJsonDump: false,
1123
- avoidedBroadRediscovery: false,
1124
- contextBudgetStatus: "no-context-generated",
1125
- nextAction: "Run `avorelo session-context` to generate the first session context.",
1126
- showInStatus: true,
1127
- showInDashboard: true,
1128
- statusLine: "Session Context: MISSING · no context generated yet",
1129
- };
1130
- }
1131
-
1132
- const td = latest.tokenDiscipline || {};
1133
- const budgetStatus = td.truncationApplied ? "truncated" : "within-budget";
1134
-
1135
- return {
1136
- status: "active",
1137
- latestContextPath: LATEST_CONTEXT_REL_PATH,
1138
- latestMarkdownPath: LATEST_CONTEXT_MD_REL_PATH,
1139
- estimatedTokens: td.estimatedTokens || 0,
1140
- avoidedJsonDump: td.avoidedJsonDump || false,
1141
- avoidedBroadRediscovery: td.avoidedBroadRediscovery || false,
1142
- contextBudgetStatus: budgetStatus,
1143
- finalState: latest.sessionStart?.currentState?.finalState || "missing",
1144
- brainPackUsed: latest.brainPackUsed || false,
1145
- targetSpecificOutput: latest.targetSpecificOutput || false,
1146
- dynamicCommands: latest.dynamicCommands || false,
1147
- recommendedCapabilityPack: latest.sessionStart?.capabilityRecommendation?.recommendedCapabilityPack || null,
1148
- nextAction: latest.sessionStart?.nextSafestAction
1149
- || "Continue from session context — run `avorelo session-context --handoff`.",
1150
- showInStatus: true,
1151
- showInDashboard: true,
1152
- statusLine: `Session Context: ${budgetStatus.toUpperCase()} · ~${td.estimatedTokens || 0} tokens · latest ${LATEST_CONTEXT_REL_PATH}`,
1153
- };
1154
- }
1155
-
1156
- function formatSessionContextText(contextOrSurface, options = {}) {
1157
- const isHandoff = options.handoff === true;
1158
- const targetSurface = options.targetSurface || contextOrSurface?.targetSurface || "generic";
1159
-
1160
- if (!contextOrSurface) {
1161
- return "Session Context: MISSING · run `avorelo session-context` to generate.\n";
1162
- }
1163
-
1164
- if (contextOrSurface.contract === SESSION_CONTEXT_CONTRACT) {
1165
- const ctx = contextOrSurface;
1166
- const s = ctx.sessionStart || {};
1167
-
1168
- if (isHandoff) {
1169
- return (s.markdownHandoff || buildMarkdownHandoff(ctx, { estimatedTokens: 0, truncationApplied: false, excludedSections: [] })) + "\n";
1170
- }
1171
-
1172
- const lines = [
1173
- `Session Context: ${ctx.contextId}`,
1174
- `State: ${s.currentState?.finalState?.toUpperCase() || "UNKNOWN"}`,
1175
- `Target: ${ctx.targetSurface || "generic"}`,
1176
- `Next: ${s.nextSafestAction || "Continue from context."}`,
1177
- `Capability: ${s.capabilityRecommendation?.recommendedCapabilityPackName || "none"}`,
1178
- `BrainPack: ${ctx.brainPackUsed ? "used" : "missing"}`,
1179
- `Tokens: ~${ctx.tokenDiscipline?.estimatedTokens || 0}`,
1180
- `Budget: ${ctx.tokenDiscipline?.truncationApplied ? "truncated" : "within-budget"}`,
1181
- `Context: ${LATEST_CONTEXT_REL_PATH}`,
1182
- `Handoff: ${LATEST_CONTEXT_MD_REL_PATH}`,
1183
- ];
1184
-
1185
- return lines.join("\n") + "\n";
1186
- }
1187
-
1188
- // Surface object
1189
- const surface = contextOrSurface;
1190
- const lines = [
1191
- `Session Context: ${surface.contextBudgetStatus?.toUpperCase() || "MISSING"}`,
1192
- `Tokens: ~${surface.estimatedTokens || 0}`,
1193
- ];
1194
- if (surface.nextAction) lines.push(`Next: ${surface.nextAction}`);
1195
- if (surface.latestContextPath) lines.push(`Context: ${surface.latestContextPath}`);
1196
- return lines.join("\n") + "\n";
1197
- }
1198
-
1199
- module.exports = {
1200
- SESSION_CONTEXT_CONTRACT,
1201
- SESSION_CONTEXT_SCHEMA_VERSION,
1202
- LATEST_CONTEXT_REL_PATH,
1203
- LATEST_CONTEXT_MD_REL_PATH,
1204
- DEFAULT_MAX_CHARS,
1205
- HARD_MAX_CHARS,
1206
- buildSessionContext,
1207
- writeSessionContext,
1208
- readLatestSessionContext,
1209
- buildSessionContextSurface,
1210
- formatSessionContextText,
1211
- };