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,196 @@
1
+ "use strict";
2
+
3
+ // ── Readiness Evidence Closure ────────────────────────────────────────────────
4
+ // Contract: avorelo.readinessEvidenceClosure.v1
5
+ // Attempts safe, local, non-destructive actions to collect missing evidence.
6
+ // Does NOT apply hooks, modify MCP config, run destructive commands, or fake data.
7
+
8
+ const fs = require("fs");
9
+ const path = require("path");
10
+ const { nowIso } = require("./fsx");
11
+ const { appendProductLearningEvent } = require("./product-learning-events");
12
+
13
+ const CONTRACT = "avorelo.readinessEvidenceClosure.v1";
14
+ const SCHEMA_VERSION = 1;
15
+ const CLOSURE_DIR_REL = ".claude/cco/orchestration/full-readiness";
16
+ const ARTIFACT_REL = CLOSURE_DIR_REL + "/latest-evidence-closure.json";
17
+
18
+ function safeReadJson(absPath) {
19
+ try {
20
+ if (!fs.existsSync(absPath)) return null;
21
+ return JSON.parse(fs.readFileSync(absPath, "utf8").replace(/^/, ""));
22
+ } catch { return null; }
23
+ }
24
+
25
+ var EVIDENCE_CHECKS = [
26
+ { id: "install_ai_receipt", description: "AI install prompt receipt", artifactPath: ".claude/cco/orchestration/ai-install/latest-prompt.json", recoverCommand: "node bin/avorelo install-ai --json", safeToAutoRun: false, required: true },
27
+ { id: "prelaunch_readiness_receipt", description: "Prelaunch activation readiness receipt", artifactPath: ".claude/cco/orchestration/prelaunch-readiness/latest-activation-readiness.json", recoverCommand: "node bin/avorelo prelaunch-readiness --json", safeToAutoRun: false, required: true },
28
+ { id: "launch_hardening_receipt", description: "Launch hardening gate receipt", artifactPath: ".claude/cco/orchestration/launch-hardening/latest-gate.json", recoverCommand: "node bin/avorelo launch-hardening --json", safeToAutoRun: false, required: true },
29
+ { id: "token_efficiency_receipt", description: "Token efficiency evidence receipt", artifactPath: ".claude/cco/orchestration/token-efficiency/latest-evidence.json", recoverCommand: "node bin/avorelo token-efficiency --json", safeToAutoRun: false, required: false },
30
+ { id: "mcp_doctor_receipt", description: "MCP governance receipt", artifactPath: ".claude/cco/orchestration/mcp-tool-governance/latest-policy.json", recoverCommand: "node bin/avorelo mcp doctor --json", safeToAutoRun: false, required: true },
31
+ { id: "support_bundle_receipt", description: "Support bundle (redacted)", artifactPath: ".claude/cco/support/latest-support-bundle.json", recoverCommand: "node bin/avorelo support-bundle --json", safeToAutoRun: false, required: true },
32
+ { id: "proof_outcome_receipt", description: "Proof / value summary readiness evidence", artifactPath: ".claude/cco/orchestration/seamless-outcome/latest-proof-outcome-evidence.json", recoverCommand: "node bin/avorelo proof (after completing a real task)", safeToAutoRun: false, required: true },
33
+ { id: "prelaunch_intelligence_receipt", description: "Prelaunch intelligence", artifactPath: ".claude/cco/orchestration/prelaunch-intelligence/latest-intelligence.json", recoverCommand: "node bin/avorelo prelaunch-intelligence --json", safeToAutoRun: false, required: true },
34
+ { id: "feedback_intelligence_receipt", description: "Feedback intelligence", artifactPath: ".claude/cco/orchestration/prelaunch-intelligence/latest-feedback-intelligence.json", recoverCommand: "node bin/avorelo feedback intake-pack --json", safeToAutoRun: false, required: true },
35
+ { id: "design_partner_feedback_receipt", description: "Design partner feedback summary", artifactPath: ".claude/cco/feedback/design-partner/latest-summary.json", recoverCommand: "node bin/avorelo feedback summary --json", safeToAutoRun: false, required: false },
36
+ { id: "readiness_delta_receipt", description: "Readiness delta (score movement)", artifactPath: ".claude/cco/orchestration/readiness-delta/latest-readiness-delta.json", recoverCommand: "node bin/avorelo readiness-delta --json", safeToAutoRun: false, required: false },
37
+ { id: "token_cost_intelligence_receipt", description: "Token/cost intelligence", artifactPath: ".claude/cco/orchestration/prelaunch-intelligence/latest-token-cost-intelligence.json", recoverCommand: "node bin/avorelo token-cost --json", safeToAutoRun: false, required: true },
38
+ { id: "token_cost_capture_receipt", description: "Real usage token/cost capture", artifactPath: ".claude/cco/evidence/token-cost/latest-capture.json", recoverCommand: "node bin/avorelo token-cost capture --json", safeToAutoRun: false, required: false },
39
+ { id: "token_cost_summary_receipt", description: "Token/cost evidence summary", artifactPath: ".claude/cco/evidence/token-cost/summary.json", recoverCommand: "node bin/avorelo token-cost summary --json", safeToAutoRun: false, required: true },
40
+ { id: "company_loop_receipt", description: "Company loop recommendation", artifactPath: ".claude/cco/orchestration/company-loop/latest-report.json", recoverCommand: "node bin/avorelo company-loop --json", safeToAutoRun: false, required: false },
41
+ ];
42
+
43
+ var SAFETY_BOUNDARIES = ["hooks apply --yes", "mcp config patch", "deploy", "publish", "prod", "rm -rf", "destructive", "fake feedback", "fake token cost", "exact savings without source"];
44
+
45
+ function buildEvidenceClosurePlan(cwd, options) {
46
+ options = options || {};
47
+ return EVIDENCE_CHECKS.map(function(check) {
48
+ var exists = fs.existsSync(path.join(cwd, check.artifactPath));
49
+ var artifact = exists ? safeReadJson(path.join(cwd, check.artifactPath)) : null;
50
+ var sufficient = exists;
51
+ if (check.id === "feedback_intelligence_receipt") {
52
+ sufficient = exists && artifact && artifact.qualifiedFeedbackItemsCount > 0;
53
+ } else if (check.id === "token_cost_intelligence_receipt") {
54
+ sufficient = exists && artifact && artifact.realUsageSamplesCount > 0;
55
+ } else if (check.id === "token_cost_capture_receipt") {
56
+ sufficient = exists && artifact && artifact.realUsageSamplesCount > 0;
57
+ } else if (check.id === "token_cost_summary_receipt") {
58
+ sufficient = exists && artifact && artifact.realUsageSamplesCount > 0;
59
+ } else if (check.id === "prelaunch_intelligence_receipt") {
60
+ sufficient = exists && artifact && artifact.status !== "insufficient_data" && (artifact.missingEvidence || []).length === 0;
61
+ } else if (check.id === "proof_outcome_receipt") {
62
+ sufficient = exists && artifact && artifact.latestProofAvailable === true && artifact.realTaskProofCount > 0;
63
+ } else if (check.id === "launch_hardening_receipt") {
64
+ sufficient = exists && artifact && artifact.status !== "fail";
65
+ }
66
+ return Object.assign({}, check, {
67
+ evidencePresent: exists,
68
+ sufficient: sufficient,
69
+ artifactStatus: artifact && artifact.status || (exists ? "present" : "missing"),
70
+ action: exists ? "read" : "missing",
71
+ artifact: artifact,
72
+ });
73
+ });
74
+ }
75
+
76
+ function executeSafeEvidenceClosure(cwd, plan, options) {
77
+ options = options || {};
78
+ var actionsAttempted = [], evidenceGenerated = [], evidenceStillMissing = [], skippedActions = [], gaps = [];
79
+ plan.forEach(function(item) {
80
+ if (item.evidencePresent) {
81
+ actionsAttempted.push({ id: item.id, action: "read", result: "present" });
82
+ evidenceGenerated.push({
83
+ id: item.id,
84
+ description: item.description,
85
+ artifactPath: item.artifactPath,
86
+ status: item.artifactStatus,
87
+ sufficient: item.sufficient,
88
+ required: item.required,
89
+ });
90
+ if (!item.sufficient) {
91
+ var recoverCommand = (item.artifact && item.artifact.safeNextActions && item.artifact.safeNextActions[0]) || item.recoverCommand;
92
+ gaps.push({
93
+ id: item.id,
94
+ description: item.description,
95
+ recoverCommand: recoverCommand,
96
+ required: item.required,
97
+ reason: "artifact_present_but_insufficient",
98
+ canAutoRun: false,
99
+ });
100
+ }
101
+ } else {
102
+ skippedActions.push({ id: item.id, reason: "requires_user_run", recoverCommand: item.recoverCommand });
103
+ evidenceStillMissing.push({ id: item.id, description: item.description, recoverCommand: item.recoverCommand, required: item.required, canAutoRun: false });
104
+ gaps.push({
105
+ id: item.id,
106
+ description: item.description,
107
+ recoverCommand: item.recoverCommand,
108
+ required: item.required,
109
+ reason: "artifact_missing",
110
+ canAutoRun: false,
111
+ });
112
+ }
113
+ });
114
+ return { actionsAttempted: actionsAttempted, evidenceGenerated: evidenceGenerated, evidenceStillMissing: evidenceStillMissing, skippedActions: skippedActions, safetyBoundaries: SAFETY_BOUNDARIES, gaps: gaps };
115
+ }
116
+
117
+ function runReadinessEvidenceClosure(cwd, options) {
118
+ options = options || {};
119
+ var plan = buildEvidenceClosurePlan(cwd, options);
120
+ var result = executeSafeEvidenceClosure(cwd, plan, options);
121
+ var totalItems = plan.length;
122
+ var presentCount = result.evidenceGenerated.filter(function(item) { return item.sufficient; }).length;
123
+ var missingCount = result.gaps.length;
124
+ var requiredEvidence = plan.filter(function(item) { return item.required; }).map(function(item) { return item.id; });
125
+ var optionalEvidence = plan.filter(function(item) { return !item.required; }).map(function(item) { return item.id; });
126
+ var status = missingCount === 0 ? "completed" : presentCount > 0 ? "partial" : "blocked";
127
+ var safeNextActions = [];
128
+ result.gaps.forEach(function(gap) {
129
+ if (gap.recoverCommand && safeNextActions.indexOf(gap.recoverCommand) === -1) safeNextActions.push(gap.recoverCommand);
130
+ });
131
+ var nextAction = safeNextActions[0] || "All evidence collected. Run: node bin/avorelo full-readiness --json";
132
+ var closure = {
133
+ contract: CONTRACT,
134
+ schemaVersion: SCHEMA_VERSION,
135
+ createdAt: nowIso(),
136
+ status: status,
137
+ totalChecked: totalItems,
138
+ evidencePresentCount: presentCount,
139
+ evidenceMissingCount: missingCount,
140
+ actionsAttempted: result.actionsAttempted,
141
+ evidenceGenerated: result.evidenceGenerated,
142
+ evidenceStillMissing: result.evidenceStillMissing,
143
+ skippedActions: result.skippedActions,
144
+ gaps: result.gaps,
145
+ requiredEvidence: requiredEvidence,
146
+ optionalEvidence: optionalEvidence,
147
+ evidenceItems: plan.map(function(item) {
148
+ return {
149
+ id: item.id,
150
+ description: item.description,
151
+ artifactPath: item.artifactPath,
152
+ evidencePresent: item.evidencePresent,
153
+ sufficient: item.sufficient,
154
+ required: item.required,
155
+ status: item.artifactStatus,
156
+ canAutoRun: false,
157
+ };
158
+ }),
159
+ safeNextActions: safeNextActions,
160
+ safetyBoundaries: result.safetyBoundaries,
161
+ nextAction: nextAction,
162
+ canAutoRun: false,
163
+ redacted: true,
164
+ };
165
+ try { appendProductLearningEvent(cwd, { eventName: "readiness_evidence_closure_run", category: "full_readiness", status: status, evidencePresentCount: presentCount, evidenceMissingCount: missingCount }); } catch (e) {}
166
+ return closure;
167
+ }
168
+
169
+ function writeEvidenceClosure(cwd, closure) {
170
+ var dir = path.join(cwd, CLOSURE_DIR_REL);
171
+ if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
172
+ fs.writeFileSync(path.join(cwd, ARTIFACT_REL), JSON.stringify(closure, null, 2));
173
+ return closure;
174
+ }
175
+
176
+ function buildEvidenceClosureSurface(cwd, options) {
177
+ options = options || {};
178
+ var closure = safeReadJson(path.join(cwd, ARTIFACT_REL));
179
+ if (!closure) return { status: "not_available", evidencePresentCount: 0, evidenceMissingCount: 0 };
180
+ return { status: closure.status, evidencePresentCount: closure.evidencePresentCount, evidenceMissingCount: closure.evidenceMissingCount, nextAction: closure.nextAction, gaps: closure.gaps || [] };
181
+ }
182
+
183
+ function formatEvidenceClosureText(closure, options) {
184
+ options = options || {};
185
+ var lines = [];
186
+ lines.push("Evidence closure: " + closure.status);
187
+ lines.push("Evidence: " + closure.evidencePresentCount + "/" + closure.totalChecked + " present");
188
+ if ((closure.gaps || []).length > 0) {
189
+ lines.push(""); lines.push("Missing evidence:");
190
+ closure.gaps.forEach(function(m) { lines.push(" - " + m.description); lines.push(" Run: " + m.recoverCommand); });
191
+ }
192
+ lines.push(""); lines.push("Next: " + closure.nextAction);
193
+ return lines.join("\n");
194
+ }
195
+
196
+ module.exports = { CONTRACT, SCHEMA_VERSION, ARTIFACT_REL, runReadinessEvidenceClosure, buildEvidenceClosurePlan, executeSafeEvidenceClosure, writeEvidenceClosure, buildEvidenceClosureSurface, formatEvidenceClosureText };
@@ -0,0 +1,241 @@
1
+ "use strict";
2
+
3
+ const { ReentryMemoryStore } = require("./reentry-memory-store");
4
+
5
+ // Patterns for sensitive content detection
6
+ const SENSITIVE_PATTERNS = [
7
+ /sk-[a-zA-Z0-9._\-]{10,}/, // Anthropic/OpenAI API keys
8
+ /Bearer\s+[a-zA-Z0-9._\-]{20,}/i, // Bearer tokens
9
+ /AKIA[A-Z0-9]{16}/, // AWS access keys
10
+ /private[_\s]?key/i, // Private key references
11
+ /-----BEGIN [A-Z ]+KEY-----/, // PEM keys
12
+ /password\s*=\s*\S+/i, // password= assignments
13
+ /secret\s*=\s*\S+/i, // secret= assignments
14
+ /token\s*=\s*['"][a-zA-Z0-9._\-]{20,}['"]/i, // token= with value
15
+ /Authorization:\s*[^\n]{20,}/i, // Auth headers
16
+ /\.env\s+\S+\s*=\s*\S{10,}/, // .env style assignments
17
+ /GITHUB_TOKEN[^a-zA-Z0-9]/, // GitHub tokens
18
+ /ghp_[a-zA-Z0-9]{36,}/, // GitHub PATs
19
+ /ghs_[a-zA-Z0-9]{36,}/, // GitHub secrets
20
+ /sk_live_[a-zA-Z0-9]{20,}/, // Stripe live keys
21
+ /sk_test_[a-zA-Z0-9]{20,}/, // Stripe test keys
22
+ /eyJ[a-zA-Z0-9_\-]{8,}\.eyJ[a-zA-Z0-9_\-]{8,}\.[a-zA-Z0-9_\-]{8,}/, // JWTs
23
+ ];
24
+
25
+ const REDACTION_PLACEHOLDER = "[REDACTED]";
26
+ const MAX_RAW_OUTPUT_BYTES = 4 * 1024; // 4KB max for raw output in evidence
27
+
28
+ function detectSensitive(text) {
29
+ if (!text || typeof text !== "string") return false;
30
+ return SENSITIVE_PATTERNS.some((re) => re.test(text));
31
+ }
32
+
33
+ function redactSensitive(text) {
34
+ if (!text || typeof text !== "string") return text;
35
+ let result = text;
36
+ for (const re of SENSITIVE_PATTERNS) {
37
+ result = result.replace(new RegExp(re.source, re.flags + (re.flags.includes("g") ? "" : "g")), REDACTION_PLACEHOLDER);
38
+ }
39
+ return result;
40
+ }
41
+
42
+ function truncateLargeOutput(text, maxBytes = MAX_RAW_OUTPUT_BYTES) {
43
+ if (!text) return "";
44
+ const bytes = Buffer.byteLength(String(text), "utf8");
45
+ if (bytes <= maxBytes) return text;
46
+ const truncated = String(text).slice(0, maxBytes);
47
+ return truncated + `\n...(truncated, original ${bytes} bytes)`;
48
+ }
49
+
50
+ function isInternalProtocolPayload(text) {
51
+ if (!text || typeof text !== "string") return false;
52
+ // Skip task-notification-like system payloads
53
+ const lower = text.toLowerCase();
54
+ return (
55
+ lower.includes("<task-notification>") ||
56
+ lower.includes("<system-reminder>") ||
57
+ lower.includes("<local-command-caveat>") ||
58
+ lower.includes("<<autonomous-loop")
59
+ );
60
+ }
61
+
62
+ function captureMemoryItem(store, partial, opts = {}) {
63
+ const { captureSensitive = false } = opts;
64
+
65
+ // Skip internal protocol payloads
66
+ const combined = [partial.title, partial.summary, partial.evidence].join(" ");
67
+ if (isInternalProtocolPayload(combined)) return null;
68
+
69
+ // Sensitive detection
70
+ const isSensitive = detectSensitive(combined);
71
+ if (isSensitive && !captureSensitive) {
72
+ // Store a redacted version, flagged as sensitive and not auto-injectable
73
+ partial = {
74
+ ...partial,
75
+ summary: redactSensitive(partial.summary || ""),
76
+ evidence: redactSensitive(partial.evidence || ""),
77
+ sensitive: true,
78
+ safeForAutoInject: false,
79
+ };
80
+ } else if (isSensitive && captureSensitive) {
81
+ partial = {
82
+ ...partial,
83
+ sensitive: true,
84
+ safeForAutoInject: false,
85
+ };
86
+ }
87
+
88
+ // Deduplication: skip if same session already has this title+type
89
+ if (partial.sessionId && store.hasDuplicate(partial.sessionId, partial.title, partial.type)) {
90
+ return null;
91
+ }
92
+
93
+ // Truncate large evidence
94
+ if (partial.evidence) {
95
+ partial = { ...partial, evidence: truncateLargeOutput(partial.evidence) };
96
+ }
97
+
98
+ return store.append(partial);
99
+ }
100
+
101
+ function captureFromFailure(store, params, opts = {}) {
102
+ const {
103
+ sessionId,
104
+ toolName,
105
+ errorText,
106
+ relatedFiles = [],
107
+ relatedCommands = [],
108
+ repoRoot,
109
+ } = params;
110
+
111
+ if (!errorText || !errorText.trim()) return null;
112
+
113
+ const truncated = truncateLargeOutput(errorText, 800);
114
+ const title = `Tool failure: ${toolName || "unknown"} — ${truncated.slice(0, 80).replace(/\n/g, " ")}`;
115
+
116
+ return captureMemoryItem(store, {
117
+ sessionId,
118
+ type: "failure",
119
+ title,
120
+ summary: `${toolName || "unknown"} failed during session.`,
121
+ evidence: truncated,
122
+ relatedFiles,
123
+ relatedCommands: relatedCommands.length ? relatedCommands : (toolName ? [toolName] : []),
124
+ confidence: "medium",
125
+ riskLevel: "medium",
126
+ staleStatus: "fresh",
127
+ safeForAutoInject: false,
128
+ tags: ["tool-failure", toolName].filter(Boolean),
129
+ repoRoot,
130
+ }, opts);
131
+ }
132
+
133
+ function captureFromFileChange(store, params, opts = {}) {
134
+ const {
135
+ sessionId,
136
+ filePath,
137
+ toolName,
138
+ summary,
139
+ repoRoot,
140
+ } = params;
141
+
142
+ if (!filePath) return null;
143
+
144
+ const title = `File updated: ${filePath}`;
145
+
146
+ return captureMemoryItem(store, {
147
+ sessionId,
148
+ type: "file_change",
149
+ title,
150
+ summary: summary || `${toolName || "Write"} updated ${filePath}.`,
151
+ evidence: `file=${filePath} tool=${toolName || "Write"}`,
152
+ relatedFiles: [filePath],
153
+ relatedCommands: toolName ? [toolName] : [],
154
+ confidence: "high",
155
+ riskLevel: "low",
156
+ staleStatus: "fresh",
157
+ safeForAutoInject: true,
158
+ tags: ["file-change"],
159
+ repoRoot,
160
+ }, opts);
161
+ }
162
+
163
+ function captureFromValidation(store, params, opts = {}) {
164
+ const {
165
+ sessionId,
166
+ title,
167
+ summary,
168
+ evidence,
169
+ passed,
170
+ relatedFiles = [],
171
+ relatedCommands = [],
172
+ repoRoot,
173
+ } = params;
174
+
175
+ return captureMemoryItem(store, {
176
+ sessionId,
177
+ type: "validation",
178
+ title: title || (passed ? "Validation passed" : "Validation failed"),
179
+ summary: summary || (passed ? "Validation succeeded." : "Validation failed."),
180
+ evidence: evidence || "",
181
+ relatedFiles,
182
+ relatedCommands,
183
+ confidence: passed ? "high" : "medium",
184
+ riskLevel: passed ? "low" : "medium",
185
+ staleStatus: "fresh",
186
+ safeForAutoInject: passed,
187
+ tags: [passed ? "validation-pass" : "validation-fail"],
188
+ repoRoot,
189
+ }, opts);
190
+ }
191
+
192
+ function captureFromSessionEnd(store, params, opts = {}) {
193
+ const {
194
+ sessionId,
195
+ nextAction,
196
+ whereAmINow,
197
+ whatHappened,
198
+ relatedFiles = [],
199
+ repoRoot,
200
+ } = params;
201
+
202
+ if (!nextAction && !whereAmINow) return null;
203
+
204
+ const title = nextAction
205
+ ? `Next action: ${String(nextAction).slice(0, 120)}`
206
+ : `Session ended: ${String(whereAmINow || "unknown state").slice(0, 100)}`;
207
+
208
+ const summary = [
209
+ whereAmINow ? `State: ${whereAmINow}` : null,
210
+ whatHappened ? `What happened: ${whatHappened}` : null,
211
+ nextAction ? `Next: ${nextAction}` : null,
212
+ ].filter(Boolean).join(". ");
213
+
214
+ return captureMemoryItem(store, {
215
+ sessionId,
216
+ type: "next_action",
217
+ title,
218
+ summary,
219
+ evidence: `session=${sessionId}`,
220
+ relatedFiles,
221
+ relatedCommands: [],
222
+ confidence: "medium",
223
+ riskLevel: "low",
224
+ staleStatus: "fresh",
225
+ safeForAutoInject: false,
226
+ tags: ["session-end", "reentry"],
227
+ repoRoot,
228
+ }, opts);
229
+ }
230
+
231
+ module.exports = {
232
+ detectSensitive,
233
+ redactSensitive,
234
+ truncateLargeOutput,
235
+ isInternalProtocolPayload,
236
+ captureMemoryItem,
237
+ captureFromFailure,
238
+ captureFromFileChange,
239
+ captureFromValidation,
240
+ captureFromSessionEnd,
241
+ };