avorelo 0.3.8 → 0.4.0-rc.2

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 (394) hide show
  1. package/LICENSE +16 -23
  2. package/README.md +62 -72
  3. package/bin/avorelo +9 -0
  4. package/package.json +147 -139
  5. package/scripts/README.md +40 -0
  6. package/scripts/avorelo-session-collision-guard.js +540 -0
  7. package/scripts/avorelo-workstream-preflight.js +918 -0
  8. package/scripts/cco-dashboard.js +346 -0
  9. package/scripts/cco-posttooluse.js +504 -0
  10. package/scripts/cco-pretooluse.js +381 -0
  11. package/scripts/cco-status.js +540 -0
  12. package/scripts/cco-stop.js +77 -0
  13. package/scripts/cco-userprompt-submit.js +83 -0
  14. package/scripts/lib/activation/account-state.js +37 -0
  15. package/scripts/lib/activation/activate-command.js +114 -0
  16. package/scripts/lib/activation/activation-runner.js +607 -0
  17. package/scripts/lib/activation/activation-self-healing.js +481 -0
  18. package/scripts/lib/activation/activation-state.js +96 -0
  19. package/scripts/lib/activation/activation-summary.js +241 -0
  20. package/scripts/lib/activation/adapters/claude-code.js +77 -0
  21. package/scripts/lib/activation/adapters/codex-cli.js +52 -0
  22. package/scripts/lib/activation/adapters/cursor.js +37 -0
  23. package/scripts/lib/activation/adapters/github-agent.js +39 -0
  24. package/scripts/lib/activation/adapters/terminal.js +42 -0
  25. package/scripts/lib/activation/adapters/vscode.js +39 -0
  26. package/scripts/lib/activation/adapters/windsurf.js +37 -0
  27. package/scripts/lib/activation/ai-surface-detector.js +151 -0
  28. package/scripts/lib/activation/connect-account.js +145 -0
  29. package/scripts/lib/activation/detect-environment.js +75 -0
  30. package/scripts/lib/activation/detect-hosts.js +62 -0
  31. package/scripts/lib/activation/format-activation-output.js +109 -0
  32. package/scripts/lib/activation/next-action.js +43 -0
  33. package/scripts/lib/activation/repair-engine.js +219 -0
  34. package/scripts/lib/activation/run-entry.js +346 -0
  35. package/scripts/lib/activation-distribution-readiness.js +507 -0
  36. package/scripts/lib/adapter-conformance.js +176 -0
  37. package/scripts/lib/adapter-readiness.js +428 -0
  38. package/scripts/lib/adapter-safety-boundaries.js +335 -0
  39. package/scripts/lib/adapter-technical-readiness-gate.js +205 -0
  40. package/scripts/lib/agent-access-governance.js +455 -0
  41. package/scripts/lib/agent-activation-readiness.js +878 -0
  42. package/scripts/lib/agent-enforcement.js +765 -0
  43. package/scripts/lib/agent-evolution-loop.js +479 -0
  44. package/scripts/lib/agent-policy-profile.js +210 -0
  45. package/scripts/lib/agent-security/action-evaluator.js +507 -0
  46. package/scripts/lib/agent-security/adapter-registry.js +98 -0
  47. package/scripts/lib/agent-security/auto-policy.js +139 -0
  48. package/scripts/lib/agent-security/bounded-scan.js +93 -0
  49. package/scripts/lib/agent-security/enforcement-adapter.js +174 -0
  50. package/scripts/lib/agent-security/enforcement-engine.js +1129 -0
  51. package/scripts/lib/agent-security/file-write-adapter.js +183 -0
  52. package/scripts/lib/agent-security/file-write-rules.js +178 -0
  53. package/scripts/lib/agent-security/index.js +3342 -0
  54. package/scripts/lib/agent-security/instruction-risk.js +181 -0
  55. package/scripts/lib/agent-security/mcp-action-adapter.js +185 -0
  56. package/scripts/lib/agent-security/mcp-action-rules.js +184 -0
  57. package/scripts/lib/agent-security/package-action-adapter.js +175 -0
  58. package/scripts/lib/agent-security/package-action-rules.js +233 -0
  59. package/scripts/lib/agent-security/performance.js +148 -0
  60. package/scripts/lib/agent-security/permission-minimizer.js +403 -0
  61. package/scripts/lib/agent-security/scan-cache.js +74 -0
  62. package/scripts/lib/agent-security/source-trust.js +146 -0
  63. package/scripts/lib/ai-efficiency-dogfood-pack.js +437 -0
  64. package/scripts/lib/ai-efficiency-eval.js +207 -0
  65. package/scripts/lib/ai-efficiency-guard-contract.js +209 -0
  66. package/scripts/lib/ai-efficiency-measured-value.js +106 -0
  67. package/scripts/lib/ai-install-prompt.js +293 -0
  68. package/scripts/lib/ai-task-inference.js +155 -0
  69. package/scripts/lib/ai-value-ledger.js +121 -0
  70. package/scripts/lib/ai-value-proof-table.js +151 -0
  71. package/scripts/lib/ai-work-efficiency-routing.js +623 -0
  72. package/scripts/lib/ai-workspace-hygiene.js +1499 -0
  73. package/scripts/lib/alpha-activation.js +520 -0
  74. package/scripts/lib/alpha-feedback.js +263 -0
  75. package/scripts/lib/alpha-readiness-gate.js +332 -0
  76. package/scripts/lib/anti-gaming.js +169 -0
  77. package/scripts/lib/artifact-health.js +431 -0
  78. package/scripts/lib/artifact-receipt-hygiene.js +619 -0
  79. package/scripts/lib/attribution.js +180 -0
  80. package/scripts/lib/audit.js +289 -0
  81. package/scripts/lib/avorelo-skill-registry.js +810 -0
  82. package/scripts/lib/batch-jobs.js +71 -0
  83. package/scripts/lib/brain-pack.js +578 -0
  84. package/scripts/lib/brand-boundary.js +424 -0
  85. package/scripts/lib/brand.js +74 -0
  86. package/scripts/lib/browser-capability.js +1048 -0
  87. package/scripts/lib/browser-proof-governed-workflow.js +1020 -0
  88. package/scripts/lib/browser-proof-preflight.js +321 -0
  89. package/scripts/lib/cache-readiness.js +296 -0
  90. package/scripts/lib/canonical-reentry.js +162 -0
  91. package/scripts/lib/capability-contract-validator.js +177 -0
  92. package/scripts/lib/capability-hygiene.js +504 -0
  93. package/scripts/lib/capability-intake-quarantine.js +789 -0
  94. package/scripts/lib/capability-kernel-registry.js +566 -0
  95. package/scripts/lib/capability-kernel.js +202 -0
  96. package/scripts/lib/capability-manifest.js +255 -0
  97. package/scripts/lib/capability-outcome-normalizer.js +104 -0
  98. package/scripts/lib/capability-packs.js +314 -0
  99. package/scripts/lib/capability-recommender.js +513 -0
  100. package/scripts/lib/capability-registry.js +1062 -0
  101. package/scripts/lib/carry-forward-surfacing.js +194 -0
  102. package/scripts/lib/ccusage-adapter.js +188 -0
  103. package/scripts/lib/claude-session-evidence/index.js +1027 -0
  104. package/scripts/lib/cli-output-sanitizer.js +118 -0
  105. package/scripts/lib/company-loop.js +1149 -0
  106. package/scripts/lib/config.js +641 -0
  107. package/scripts/lib/context-acquisition-plan.js +359 -0
  108. package/scripts/lib/context-authority-rules.js +138 -0
  109. package/scripts/lib/context-budget-guard.js +170 -0
  110. package/scripts/lib/context-budget-scanner.js +257 -0
  111. package/scripts/lib/context-budget.js +167 -0
  112. package/scripts/lib/context-claim-safety.js +116 -0
  113. package/scripts/lib/context-compiler.js +236 -0
  114. package/scripts/lib/context-optimizer.js +715 -0
  115. package/scripts/lib/context-packet.js +121 -0
  116. package/scripts/lib/context-receipt.js +57 -0
  117. package/scripts/lib/context-reduction-plan.js +179 -0
  118. package/scripts/lib/context-safety.js +88 -0
  119. package/scripts/lib/context-savings-engine.js +158 -0
  120. package/scripts/lib/context-source-registry.js +393 -0
  121. package/scripts/lib/context-task-profiles.js +147 -0
  122. package/scripts/lib/cost-abuse-guard.js +975 -0
  123. package/scripts/lib/cost-evidence.js +287 -0
  124. package/scripts/lib/cost-to-outcome-signals.js +639 -0
  125. package/scripts/lib/cross-host-install-plan.js +308 -0
  126. package/scripts/lib/cross-host-install-readiness.js +242 -0
  127. package/scripts/lib/cross-host-value-flow.js +268 -0
  128. package/scripts/lib/dashboard.js +1056 -0
  129. package/scripts/lib/data-permissions-guard.js +1187 -0
  130. package/scripts/lib/deployment-environment-guard.js +1236 -0
  131. package/scripts/lib/design-partner-feedback.js +346 -0
  132. package/scripts/lib/dogfood-evidence-freshness.js +567 -0
  133. package/scripts/lib/efficiency-receipt.js +354 -0
  134. package/scripts/lib/entitlements.js +100 -0
  135. package/scripts/lib/execution-packet.js +559 -0
  136. package/scripts/lib/execution-route-governor.js +179 -0
  137. package/scripts/lib/experimentation-events.js +547 -0
  138. package/scripts/lib/external-capability-compliance.js +107 -0
  139. package/scripts/lib/external-readiness/ai-visibility/ai-visibility-runner.js +322 -0
  140. package/scripts/lib/external-readiness/calibration/benchmark-site-catalog.js +121 -0
  141. package/scripts/lib/external-readiness/calibration/completion-gate.js +112 -0
  142. package/scripts/lib/external-readiness/calibration/real-site-benchmark-runner.js +284 -0
  143. package/scripts/lib/external-readiness/drift-detector.js +100 -0
  144. package/scripts/lib/external-readiness/endpoint-prober.js +332 -0
  145. package/scripts/lib/external-readiness/external-readiness-runner.js +112 -0
  146. package/scripts/lib/external-readiness/full-agent-readiness-scorer.js +220 -0
  147. package/scripts/lib/external-readiness/golden-path-runner.js +333 -0
  148. package/scripts/lib/external-readiness/inside-out-runner.js +118 -0
  149. package/scripts/lib/external-readiness/proof-receipt-writer.js +112 -0
  150. package/scripts/lib/external-readiness/safe-fix-executor.js +117 -0
  151. package/scripts/lib/external-readiness/skills/category-boundary-guard.js +30 -0
  152. package/scripts/lib/external-readiness/skills/pmm-positioning-guard.js +69 -0
  153. package/scripts/lib/external-readiness/skills/safe-fix-policy.js +35 -0
  154. package/scripts/lib/external-user-simulation.js +166 -0
  155. package/scripts/lib/failure-recovery-readiness.js +81 -0
  156. package/scripts/lib/failure-recovery.js +419 -0
  157. package/scripts/lib/feedback-intelligence.js +537 -0
  158. package/scripts/lib/feedback-signals.js +205 -0
  159. package/scripts/lib/file-integrity.js +68 -0
  160. package/scripts/lib/fsx.js +129 -0
  161. package/scripts/lib/full-readiness-gate.js +451 -0
  162. package/scripts/lib/governed-action-exposure-primitives.js +1514 -0
  163. package/scripts/lib/governed-exposure-planner.js +186 -0
  164. package/scripts/lib/governed-workspace-hygiene.js +946 -0
  165. package/scripts/lib/guard-suite-common.js +412 -0
  166. package/scripts/lib/guidance-builder.js +174 -0
  167. package/scripts/lib/hook-apply.js +1075 -0
  168. package/scripts/lib/hook-baseline.js +310 -0
  169. package/scripts/lib/hook-config-preview.js +275 -0
  170. package/scripts/lib/hook-contracts.js +290 -0
  171. package/scripts/lib/hook-safety-boundary-readiness.js +80 -0
  172. package/scripts/lib/host-capability-matrix.js +351 -0
  173. package/scripts/lib/host-support-context.js +254 -0
  174. package/scripts/lib/http-hook-action.js +538 -0
  175. package/scripts/lib/install-ai-readiness.js +84 -0
  176. package/scripts/lib/install-intake-risk.js +1051 -0
  177. package/scripts/lib/install-journey-intelligence.js +329 -0
  178. package/scripts/lib/intervention-guidance.js +57 -0
  179. package/scripts/lib/known-limitations.js +115 -0
  180. package/scripts/lib/l8-path-truth.js +146 -0
  181. package/scripts/lib/launch-hardening-gate.js +436 -0
  182. package/scripts/lib/launch-readiness.js +635 -0
  183. package/scripts/lib/learning-experimentation-foundation.js +1484 -0
  184. package/scripts/lib/learning-memory.js +686 -0
  185. package/scripts/lib/lifecycle-hooks.js +982 -0
  186. package/scripts/lib/local-package-smoke.js +436 -0
  187. package/scripts/lib/local-pricing.js +299 -0
  188. package/scripts/lib/mcp-enforcement.js +311 -0
  189. package/scripts/lib/mcp-least-privilege-policy.js +303 -0
  190. package/scripts/lib/mcp-tool-inventory.js +388 -0
  191. package/scripts/lib/mcp-tool-risk.js +0 -0
  192. package/scripts/lib/memory.js +335 -0
  193. package/scripts/lib/metrics.js +699 -0
  194. package/scripts/lib/micro-proof.js +133 -0
  195. package/scripts/lib/model-work-class-routing.js +79 -0
  196. package/scripts/lib/next-run-context.js +436 -0
  197. package/scripts/lib/next-run-continuity.js +1207 -0
  198. package/scripts/lib/observability-recovery-guard.js +1030 -0
  199. package/scripts/lib/operating-value.js +1662 -0
  200. package/scripts/lib/optimization-v3.js +122 -0
  201. package/scripts/lib/orchestration/adapters/_shared.js +49 -0
  202. package/scripts/lib/orchestration/adapters/aider.js +18 -0
  203. package/scripts/lib/orchestration/adapters/claude-code.js +35 -0
  204. package/scripts/lib/orchestration/adapters/codex.js +35 -0
  205. package/scripts/lib/orchestration/adapters/gemini-cli.js +18 -0
  206. package/scripts/lib/orchestration/adapters/git.js +25 -0
  207. package/scripts/lib/orchestration/adapters/index.js +31 -0
  208. package/scripts/lib/orchestration/adapters/lm-studio.js +18 -0
  209. package/scripts/lib/orchestration/adapters/ollama.js +18 -0
  210. package/scripts/lib/orchestration/adapters/opencode.js +18 -0
  211. package/scripts/lib/orchestration/adapters/openrouter.js +18 -0
  212. package/scripts/lib/orchestration/adapters/test-runner.js +25 -0
  213. package/scripts/lib/orchestration/cli.js +438 -0
  214. package/scripts/lib/orchestration/execution-manager.js +279 -0
  215. package/scripts/lib/orchestration/handoff.js +314 -0
  216. package/scripts/lib/orchestration/index.js +456 -0
  217. package/scripts/lib/orchestration/inventory.js +47 -0
  218. package/scripts/lib/orchestration/model-discovery.js +498 -0
  219. package/scripts/lib/orchestration/model-profiler.js +170 -0
  220. package/scripts/lib/orchestration/model-profiles.js +252 -0
  221. package/scripts/lib/orchestration/model-refresh-policy.js +72 -0
  222. package/scripts/lib/orchestration/proof-writer.js +349 -0
  223. package/scripts/lib/orchestration/provider-discovery/aider.js +49 -0
  224. package/scripts/lib/orchestration/provider-discovery/claude-code.js +56 -0
  225. package/scripts/lib/orchestration/provider-discovery/codex.js +49 -0
  226. package/scripts/lib/orchestration/provider-discovery/common.js +186 -0
  227. package/scripts/lib/orchestration/provider-discovery/gemini.js +106 -0
  228. package/scripts/lib/orchestration/provider-discovery/lm-studio.js +118 -0
  229. package/scripts/lib/orchestration/provider-discovery/models-dev.js +12 -0
  230. package/scripts/lib/orchestration/provider-discovery/ollama.js +100 -0
  231. package/scripts/lib/orchestration/provider-discovery/opencode.js +47 -0
  232. package/scripts/lib/orchestration/provider-discovery/openrouter.js +44 -0
  233. package/scripts/lib/orchestration/risk-classifier.js +130 -0
  234. package/scripts/lib/orchestration/routing-policy.js +486 -0
  235. package/scripts/lib/orchestration/settings.js +95 -0
  236. package/scripts/lib/orchestration/state.js +165 -0
  237. package/scripts/lib/orchestration/verification-manager.js +138 -0
  238. package/scripts/lib/outcome-evidence-stack.js +1083 -0
  239. package/scripts/lib/output-profiles.js +146 -0
  240. package/scripts/lib/package-content-audit.js +368 -0
  241. package/scripts/lib/package-runtime.js +278 -0
  242. package/scripts/lib/plan-surface.js +53 -0
  243. package/scripts/lib/plans.js +2327 -0
  244. package/scripts/lib/policy-provider.js +27 -0
  245. package/scripts/lib/prelaunch-activation-readiness.js +409 -0
  246. package/scripts/lib/prelaunch-evidence-store.js +816 -0
  247. package/scripts/lib/prelaunch-intelligence.js +869 -0
  248. package/scripts/lib/pricing-experiment.js +118 -0
  249. package/scripts/lib/pro-moment-events.js +77 -0
  250. package/scripts/lib/pro-moment-state.js +227 -0
  251. package/scripts/lib/pro-moments.js +1216 -0
  252. package/scripts/lib/product-home-receipt.js +1790 -0
  253. package/scripts/lib/product-learning-events.js +696 -0
  254. package/scripts/lib/production-confidence-control-tower.js +1209 -0
  255. package/scripts/lib/production-confidence.js +1858 -0
  256. package/scripts/lib/project-profile.js +555 -0
  257. package/scripts/lib/prompt-compiler-plan.js +94 -0
  258. package/scripts/lib/prompt-compiler.js +280 -0
  259. package/scripts/lib/prompt-lint.js +32 -0
  260. package/scripts/lib/prompt-suggestions.js +52 -0
  261. package/scripts/lib/proof-canonical.js +398 -0
  262. package/scripts/lib/proof-drilldown.js +383 -0
  263. package/scripts/lib/proof-e2e/promise-completion.js +141 -0
  264. package/scripts/lib/proof-e2e/promise-dashboard-claims.js +135 -0
  265. package/scripts/lib/proof-e2e/promise-local-proof.js +156 -0
  266. package/scripts/lib/proof-e2e/promise-provider-neutral.js +136 -0
  267. package/scripts/lib/proof-e2e/promise-registry.js +219 -0
  268. package/scripts/lib/proof-e2e/promise-security-trust.js +141 -0
  269. package/scripts/lib/proof-e2e/promise-skills-risk.js +163 -0
  270. package/scripts/lib/proof-e2e/promise-token-savings.js +112 -0
  271. package/scripts/lib/proof-e2e/promise-work-management.js +126 -0
  272. package/scripts/lib/proof-events.js +342 -0
  273. package/scripts/lib/proof-history.js +243 -0
  274. package/scripts/lib/proof-metrics.js +296 -0
  275. package/scripts/lib/proof-outcome-evidence.js +134 -0
  276. package/scripts/lib/proof-receipt.js +335 -0
  277. package/scripts/lib/proof-record.js +461 -0
  278. package/scripts/lib/proof-savings-report.js +1549 -0
  279. package/scripts/lib/public-activation-distribution-gate.js +266 -0
  280. package/scripts/lib/public-cli.js +5631 -0
  281. package/scripts/lib/public-distribution-truth.js +211 -0
  282. package/scripts/lib/public-distribution.js +73 -0
  283. package/scripts/lib/public-install-claim-checker.js +300 -0
  284. package/scripts/lib/publish-provenance-readiness.js +287 -0
  285. package/scripts/lib/readiness-delta.js +218 -0
  286. package/scripts/lib/readiness-evidence-closure.js +196 -0
  287. package/scripts/lib/reentry-memory-capture.js +241 -0
  288. package/scripts/lib/reentry-memory-retrieval.js +302 -0
  289. package/scripts/lib/reentry-memory-status.js +147 -0
  290. package/scripts/lib/reentry-memory-store.js +183 -0
  291. package/scripts/lib/reentry-state.js +66 -0
  292. package/scripts/lib/release-candidate-bundle.js +166 -0
  293. package/scripts/lib/remediation.js +81 -0
  294. package/scripts/lib/repo-map.js +391 -0
  295. package/scripts/lib/run-action-policy.js +104 -0
  296. package/scripts/lib/run-contract-receipt.js +48 -0
  297. package/scripts/lib/run-contract.js +288 -0
  298. package/scripts/lib/run-cost-to-verified-outcome.js +87 -0
  299. package/scripts/lib/run-improvements-lifecycle.js +330 -0
  300. package/scripts/lib/run-improvements.js +789 -0
  301. package/scripts/lib/run-proof-contract.js +116 -0
  302. package/scripts/lib/run-risk-classifier.js +131 -0
  303. package/scripts/lib/run-task-classifier.js +216 -0
  304. package/scripts/lib/runtime-decision-policy.js +387 -0
  305. package/scripts/lib/safe-path-engine.js +705 -0
  306. package/scripts/lib/safe-repair.js +877 -0
  307. package/scripts/lib/safe-run-controller.js +887 -0
  308. package/scripts/lib/scope-repair-before-approval.js +865 -0
  309. package/scripts/lib/score.js +262 -0
  310. package/scripts/lib/seamless-enforcement.js +329 -0
  311. package/scripts/lib/seamless-outcome.js +689 -0
  312. package/scripts/lib/seamless-reality-gate.js +5053 -0
  313. package/scripts/lib/security-confidence/activation-safety.js +78 -0
  314. package/scripts/lib/security-confidence/adapters/adapter-contract.js +125 -0
  315. package/scripts/lib/security-confidence/adapters/mock-claude-bughunter-adapter.js +36 -0
  316. package/scripts/lib/security-confidence/adapters/mock-decepticon-adapter.js +34 -0
  317. package/scripts/lib/security-confidence/adapters/mock-mcp-scan-adapter.js +35 -0
  318. package/scripts/lib/security-confidence/adapters/mock-snyk-agent-scan-adapter.js +35 -0
  319. package/scripts/lib/security-confidence/adapters/mock-tank-adapter.js +34 -0
  320. package/scripts/lib/security-confidence/adapters/reference-registry.js +63 -0
  321. package/scripts/lib/security-confidence/auth-rbac-plan.js +39 -0
  322. package/scripts/lib/security-confidence/component-inventory.js +151 -0
  323. package/scripts/lib/security-confidence/constants.js +191 -0
  324. package/scripts/lib/security-confidence/dependency-script-risk.js +95 -0
  325. package/scripts/lib/security-confidence/evidence-hygiene.js +127 -0
  326. package/scripts/lib/security-confidence/feature-impact-classifier.js +80 -0
  327. package/scripts/lib/security-confidence/file-utils.js +161 -0
  328. package/scripts/lib/security-confidence/finding-triage.js +90 -0
  329. package/scripts/lib/security-confidence/findings.js +115 -0
  330. package/scripts/lib/security-confidence/index.js +29 -0
  331. package/scripts/lib/security-confidence/permission-budget.js +93 -0
  332. package/scripts/lib/security-confidence/redaction.js +82 -0
  333. package/scripts/lib/security-confidence/redteam-fixtures.js +53 -0
  334. package/scripts/lib/security-confidence/reference-adoption.js +229 -0
  335. package/scripts/lib/security-confidence/reference-taxonomy.js +155 -0
  336. package/scripts/lib/security-confidence/report-quality.js +99 -0
  337. package/scripts/lib/security-confidence/report-writer.js +79 -0
  338. package/scripts/lib/security-confidence/risk-classifier.js +187 -0
  339. package/scripts/lib/security-confidence/runner.js +179 -0
  340. package/scripts/lib/security-confidence/schema.js +188 -0
  341. package/scripts/lib/security-confidence/secret-safety.js +74 -0
  342. package/scripts/lib/security-confidence/security-capability-router.js +98 -0
  343. package/scripts/lib/security-confidence/web-security-smoke-plan.js +46 -0
  344. package/scripts/lib/security-risk-classifier.js +511 -0
  345. package/scripts/lib/security-scan.js +396 -0
  346. package/scripts/lib/session-context-optimizer.js +1211 -0
  347. package/scripts/lib/session-timing.js +322 -0
  348. package/scripts/lib/skill-hygiene.js +805 -0
  349. package/scripts/lib/skill-packs.js +161 -0
  350. package/scripts/lib/skills-operating-layer-v1.js +1023 -0
  351. package/scripts/lib/skills-operating-layer.js +629 -0
  352. package/scripts/lib/smallest-safe-plan.js +214 -0
  353. package/scripts/lib/smart-routing-plan.js +115 -0
  354. package/scripts/lib/smart-work-routing.js +768 -0
  355. package/scripts/lib/source-catalog.js +1022 -0
  356. package/scripts/lib/status-value-summary.js +32 -0
  357. package/scripts/lib/supply-chain-dependency-guard.js +1333 -0
  358. package/scripts/lib/supply-chain-guard.js +219 -0
  359. package/scripts/lib/support-bundle.js +561 -0
  360. package/scripts/lib/support-redaction.js +66 -0
  361. package/scripts/lib/task-continuation.js +440 -0
  362. package/scripts/lib/test-helpers.js +15 -0
  363. package/scripts/lib/tier.js +38 -0
  364. package/scripts/lib/token-context-quality-gate.js +370 -0
  365. package/scripts/lib/token-cost-capture.js +187 -0
  366. package/scripts/lib/token-cost-evidence.js +862 -0
  367. package/scripts/lib/token-cost-intelligence.js +358 -0
  368. package/scripts/lib/token-efficiency-evidence.js +213 -0
  369. package/scripts/lib/token-efficiency-map.js +110 -0
  370. package/scripts/lib/token-evidence.js +703 -0
  371. package/scripts/lib/tokenish.js +17 -0
  372. package/scripts/lib/tool-output-sandbox.js +559 -0
  373. package/scripts/lib/trust-audit.js +136 -0
  374. package/scripts/lib/unified-events.js +396 -0
  375. package/scripts/lib/upgrade-interruption-recovery.js +407 -0
  376. package/scripts/lib/usage-ledger.js +201 -0
  377. package/scripts/lib/value-ledger.js +130 -0
  378. package/scripts/lib/value-proof-calibration.js +531 -0
  379. package/scripts/lib/visual-qa.js +231 -0
  380. package/scripts/lib/voice-alpha.js +29 -0
  381. package/scripts/lib/webhook-idempotency-guard.js +990 -0
  382. package/scripts/lib/work-aware-orchestration.js +976 -0
  383. package/scripts/lib/work-control-receipts.js +577 -0
  384. package/scripts/lib/work-ledger.js +1123 -0
  385. package/scripts/lib/work-panel-preview.js +352 -0
  386. package/scripts/lib/workflow-discipline.js +280 -0
  387. package/scripts/lib/workflow-intelligence-radar.js +804 -0
  388. package/scripts/lib/workflow-signals.js +419 -0
  389. package/scripts/lib/workspace-map.js +281 -0
  390. package/scripts/lib/workspace-registry.js +1367 -0
  391. package/scripts/lib/workspace-resolver.js +542 -0
  392. package/scripts/wuz-doctor.js +315 -0
  393. package/bin/avorelo.mjs +0 -7
  394. package/dist/avorelo.mjs +0 -24678
@@ -0,0 +1,619 @@
1
+ "use strict";
2
+
3
+ const fs = require("fs");
4
+ const path = require("path");
5
+
6
+ const { nowIso, safeReadJson, safeWriteJson } = require("./fsx");
7
+
8
+ const CONTRACT = "avorelo.artifactReceiptHygiene.v1";
9
+ const REPORT_DIR_REL = ".claude/cco/reports/artifact-receipt-hygiene";
10
+ const REPORT_JSON_REL = `${REPORT_DIR_REL}/latest-report.json`;
11
+
12
+ const MAX_FILES = 1500;
13
+ const MAX_FINDINGS = 25;
14
+ const MAX_EVIDENCE_REFS_PER_FINDING = 3;
15
+ const MAX_ARTIFACT_SIZE = 256 * 1024; // 256KB
16
+ const OVERSIZED_THRESHOLD = 128 * 1024; // 128KB considered oversized for a single artifact
17
+ const STALE_DAYS = 90;
18
+
19
+ const SKIP_DIRS = new Set([
20
+ ".git", "node_modules", "dist", "build", "coverage", ".next", ".nuxt", ".turbo", ".wasp", "temp",
21
+ ]);
22
+
23
+ // Matches a Windows drive path (C:\ or C:/dir) but NOT a URL scheme like
24
+ // http://, https://, postgresql://, wuz:// — a URL has `://` (two slashes after
25
+ // the colon) and is never an absolute LOCAL path. Excluding it removes a
26
+ // false-positive class without weakening local-path detection.
27
+ const ABSOLUTE_WINDOWS_PATH_RE = /[A-Za-z]:(?:\\|\/(?!\/))/;
28
+ const ABSOLUTE_UNIX_PATH_RE = /(?:^|\s|")\/(?:Users|home|tmp|var|etc)\//;
29
+ // `sk-` requires a leading non-alphanumeric boundary so it matches real API
30
+ // keys (e.g. "sk-ant-...") but NOT the "sk-" buried inside ordinary words like
31
+ // "ri[sk-]governance" or "ta[sk-]specific". Without the boundary, hyphenated
32
+ // English phrases were flagged as secrets — a false-positive class.
33
+ const SECRET_PATTERN_RE = /(?:(?<![A-Za-z0-9])sk-[A-Za-z0-9_-]{16,}|gh[ps]_[A-Za-z0-9]{12,}|npm_[A-Za-z0-9]{12,}|AKIA[0-9A-Z]{16})/;
34
+ const SECRET_ASSIGNMENT_RE = /(?:api[_ -]?key|token|password|secret|authorization|credentials?)\s*[:=]\s*["']?[^\s'"]{8,}/i;
35
+ const RAW_LOG_RE = /(?:\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}:\d{2}[.\d]*Z?\s+(?:ERROR|WARN|INFO|DEBUG|TRACE)\b|\[(?:error|warn|info|debug)\])/i;
36
+ const RAW_PROMPT_RE = /(?:system\s*:\s*(?:you are|as an|act as)|<system>|<human>|<assistant>|Human:|Assistant:|<<SYS>>)/i;
37
+ const RAW_TRANSCRIPT_RE = /(?:^\s*(?:Human|Assistant|User|System)\s*:\s*.{20,}$)/m;
38
+ const RAW_CODE_DUMP_RE = /(?:"(?:sourceCode|rawCode|codeContent|fullSource)"\s*:\s*"[\s\S]{500,}")/;
39
+ const PUBLIC_CLAIM_RE = /(?:"publicClaimAllowed"\s*:\s*true)/;
40
+ const VALUE_FIELDS = ["measured", "estimated", "heuristic", "unavailable"];
41
+ const UNSAFE_PUBLIC_CLAIM_RE = /(?:guaranteed|production.ready|guaranteed.secure|guaranteed.savings|launch.ready|published.verified|certified|marketplace|auto.install)/i;
42
+
43
+ // A claim term is only an UNSUPPORTED public claim when it is asserted as TRUE.
44
+ // The same vocabulary appears constantly in HONEST evidence that DISCLAIMS the
45
+ // claim ("No guaranteed savings claimed", "Does not claim production certified",
46
+ // "Not a marketplace", "Do NOT claim published_verified"), in detection-term
47
+ // lists, and as snake_case enum/identifier values (e.g. `published_verified`,
48
+ // `noGuaranteedRecallClaim`). Flagging those is a false positive — and rewording
49
+ // honest disclaimers to dodge the regex would REDUCE honesty. This context check
50
+ // preserves the original intent (catch positive overclaims) while skipping
51
+ // negated / disclaimed / technical-identifier usages.
52
+ // Disclaimer / detection / exclusion / technical-identifier cues. When any of
53
+ // these share the claim term's line (or nearby context), the term is being
54
+ // disclaimed, screened, deferred, or used as an enum — not asserted.
55
+ const CLAIM_DISCLAIMER_RE = /(?:\bno\b|\bnot\b|\bnon\b|\bnever\b|\bwithout\b|\bcannot\b|can't|won't|don't|doesn't|do not|does not|\bavoid(?:ed|s)?\b|deferred|\bdefer\b|\bfalse\b|premature|absent|\bnone\b|forbidden|disallow|blocked|terms ?checked|unsafeterms|screened|blocked copy|\bexamples?\b|not claim|cannot claim|requires?|ready_to_publish|not_available|not included|out of scope|excluded|non-goals?|separate track|no local|do not say|never say|→ ?never|❌)/i;
56
+
57
+ function hasUnsupportedPublicClaim(text) {
58
+ if (!text) return false;
59
+ const re = new RegExp(UNSAFE_PUBLIC_CLAIM_RE.source, "gi");
60
+ let m;
61
+ while ((m = re.exec(text)) !== null) {
62
+ const tok = m[0];
63
+ const start = m.index;
64
+ const end = start + tok.length;
65
+ if (tok.includes("_")) continue; // snake_case enum/identifier
66
+ if (/[A-Za-z0-9_]/.test(text[start - 1] || "")) continue; // embedded in a larger word/identifier
67
+ if (/[A-Za-z0-9_]/.test(text[end] || "")) continue; // embedded in a larger word/identifier
68
+ // Context = a bounded window before the match (catches a preceding section
69
+ // header such as "does not add:" / "What is not included") PLUS the rest of
70
+ // the current line (catches a same-line trailing qualifier such as
71
+ // "(no local evidence)" or "| No network |"). Markdown bullets/tables and
72
+ // exclusion lists carry the disclaimer in one of these two places.
73
+ let lineEnd = text.indexOf("\n", end);
74
+ if (lineEnd === -1) lineEnd = text.length;
75
+ const before = text.slice(Math.max(0, start - 160), start);
76
+ const restOfLine = text.slice(end, Math.min(lineEnd, end + 120));
77
+ if (CLAIM_DISCLAIMER_RE.test(before + " " + restOfLine)) continue; // disclaimed / screened / deferred / technical
78
+ return true; // a positive, asserted public claim
79
+ }
80
+ return false;
81
+ }
82
+
83
+ function toPosix(value) {
84
+ return String(value || "").replace(/\\/g, "/");
85
+ }
86
+
87
+ function sanitizeText(value, max = 220) {
88
+ const text = String(value || "")
89
+ .replace(/\s+/g, " ")
90
+ .replace(/(?:(?<![A-Za-z0-9])sk-[A-Za-z0-9_-]{16,}|gh[ps]_[A-Za-z0-9]{12,}|npm_[A-Za-z0-9]{12,}|AKIA[0-9A-Z]{16})/g, "[redacted-token]")
91
+ .replace(/(bearer\s+)[A-Za-z0-9._-]{8,}/ig, "$1[redacted]")
92
+ .replace(/((?:api[_ -]?key|token|password|secret|authorization)\s*[:=]\s*)([^\s'"]+)/ig, "$1[redacted]")
93
+ .trim();
94
+ if (!text) return null;
95
+ return text.length > max ? `${text.slice(0, max - 3).trimEnd()}...` : text;
96
+ }
97
+
98
+ function sanitizeRef(ref) {
99
+ const text = toPosix(String(ref || "").trim());
100
+ if (!text || text.startsWith("..")) return null;
101
+ return text;
102
+ }
103
+
104
+ function makeEvidenceRef(relPath, label) {
105
+ const base = sanitizeRef(relPath);
106
+ if (!base) return null;
107
+ const note = label ? ` (${sanitizeText(label, 80)})` : "";
108
+ return `${base}${note}`;
109
+ }
110
+
111
+ function severityRank(severity) {
112
+ if (severity === "block") return 3;
113
+ if (severity === "warn") return 2;
114
+ if (severity === "info") return 1;
115
+ return 0;
116
+ }
117
+
118
+ function isStaleDate(isoString) {
119
+ if (!isoString) return false;
120
+ try {
121
+ const d = new Date(isoString);
122
+ if (isNaN(d.getTime())) return false;
123
+ return (Date.now() - d.getTime()) > (STALE_DAYS * 24 * 60 * 60 * 1000);
124
+ } catch {
125
+ return false;
126
+ }
127
+ }
128
+
129
+ // ── Walk artifact directories ───────────────────────────────────────────────
130
+
131
+ function walkArtifactDirs(cwd) {
132
+ const roots = [
133
+ "artifacts",
134
+ ".claude/cco/reports",
135
+ ".claude/cco/state",
136
+ "docs/dogfood",
137
+ "docs/releases",
138
+ ];
139
+
140
+ const files = [];
141
+ for (const root of roots) {
142
+ const absRoot = path.join(cwd, root);
143
+ if (!fs.existsSync(absRoot)) continue;
144
+ walkDir(absRoot, cwd, files, 5);
145
+ }
146
+ return files;
147
+ }
148
+
149
+ function walkDir(dirPath, cwd, files, maxDepth) {
150
+ if (maxDepth <= 0 || files.length >= MAX_FILES) return;
151
+ try {
152
+ for (const entry of fs.readdirSync(dirPath, { withFileTypes: true })) {
153
+ if (files.length >= MAX_FILES) return;
154
+ const absPath = path.join(dirPath, entry.name);
155
+ if (entry.isDirectory()) {
156
+ if (SKIP_DIRS.has(entry.name)) continue;
157
+ walkDir(absPath, cwd, files, maxDepth - 1);
158
+ continue;
159
+ }
160
+ if (!entry.isFile()) continue;
161
+ if (!entry.name.endsWith(".json") && !entry.name.endsWith(".md")) continue;
162
+ const relPath = toPosix(path.relative(cwd, absPath));
163
+ try {
164
+ const stat = fs.statSync(absPath);
165
+ files.push({ absPath, relPath, size: stat.size });
166
+ } catch {
167
+ files.push({ absPath, relPath, size: 0 });
168
+ }
169
+ }
170
+ } catch {}
171
+ }
172
+
173
+ // ── Core analysis ───────────────────────────────────────────────────────────
174
+
175
+ function buildArtifactReceiptHygieneReport(cwd = process.cwd(), options = {}) {
176
+ const limitsApplied = [];
177
+ const findings = [];
178
+ const seenCodes = new Map();
179
+
180
+ function addFinding(severity, reasonCode, title, safeNextAction, evidenceRefs) {
181
+ if (findings.length >= MAX_FINDINGS) {
182
+ if (!limitsApplied.includes("MAX_FINDINGS_REACHED")) limitsApplied.push("MAX_FINDINGS_REACHED");
183
+ return;
184
+ }
185
+ const key = `${reasonCode}:${(evidenceRefs || [])[0] || ""}`;
186
+ if (seenCodes.has(key)) return;
187
+ seenCodes.set(key, true);
188
+ findings.push({
189
+ severity,
190
+ reasonCode,
191
+ title: sanitizeText(title, 220),
192
+ safeNextAction: sanitizeText(safeNextAction, 220),
193
+ evidenceRefs: (evidenceRefs || []).slice(0, MAX_EVIDENCE_REFS_PER_FINDING).filter(Boolean),
194
+ });
195
+ }
196
+
197
+ const files = walkArtifactDirs(cwd);
198
+
199
+ if (files.length === 0) {
200
+ const emptyReport = buildEmptyReport(limitsApplied);
201
+ if (options.write !== false) {
202
+ safeWriteJson(cwd, REPORT_JSON_REL, emptyReport);
203
+ }
204
+ return emptyReport;
205
+ }
206
+
207
+ if (files.length >= MAX_FILES) {
208
+ limitsApplied.push("SCAN_LIMIT_APPLIED");
209
+ addFinding("warn", "ARTIFACT_HYGIENE_REVIEW_REQUIRED", `Artifact file count reached scan limit (${MAX_FILES})`, "Review artifact directories manually — some files were not inspected.", []);
210
+ }
211
+
212
+ let staleCount = 0;
213
+ let missingSchemaCount = 0;
214
+ let unsafeCount = 0;
215
+ let oversizedCount = 0;
216
+ let brokenRefCount = 0;
217
+ let artifactsInspected = 0;
218
+
219
+ for (const file of files) {
220
+ // Skip very large files
221
+ if (file.size > MAX_ARTIFACT_SIZE) {
222
+ addFinding("warn", "ARTIFACT_OVERSIZED", `Artifact ${file.relPath} is ${Math.round(file.size / 1024)}KB — exceeds inspection limit`, "Consider splitting or compacting this artifact.", [makeEvidenceRef(file.relPath, "oversized")]);
223
+ oversizedCount++;
224
+ continue;
225
+ }
226
+
227
+ // Skip non-JSON for structured checks (md files get text checks only)
228
+ if (file.relPath.endsWith(".md")) {
229
+ artifactsInspected++;
230
+ try {
231
+ const content = fs.readFileSync(file.absPath, "utf8");
232
+
233
+ // Check for absolute paths
234
+ if (ABSOLUTE_WINDOWS_PATH_RE.test(content) || ABSOLUTE_UNIX_PATH_RE.test(content)) {
235
+ addFinding("block", "ARTIFACT_ABSOLUTE_PATH_FOUND", `Absolute local path found in ${file.relPath}`, "Replace with repo-relative paths.", [makeEvidenceRef(file.relPath, "absolute path")]);
236
+ unsafeCount++;
237
+ }
238
+
239
+ // Check for secret patterns
240
+ if (SECRET_PATTERN_RE.test(content) || SECRET_ASSIGNMENT_RE.test(content)) {
241
+ addFinding("block", "ARTIFACT_SECRET_PATTERN_FOUND", `Secret-like pattern found in ${file.relPath}`, "Remove or redact secret values.", [makeEvidenceRef(file.relPath, "secret")]);
242
+ unsafeCount++;
243
+ }
244
+
245
+ // Check for unsafe public claims (asserted, not disclaimed)
246
+ if (hasUnsupportedPublicClaim(content)) {
247
+ addFinding("block", "ARTIFACT_PUBLIC_CLAIM_UNSUPPORTED", `Unsupported public claim found in ${file.relPath}`, "Remove or qualify the claim with evidence and caveats.", [makeEvidenceRef(file.relPath, "unsupported claim")]);
248
+ unsafeCount++;
249
+ }
250
+
251
+ // Check for raw prompts
252
+ if (RAW_PROMPT_RE.test(content)) {
253
+ addFinding("block", "ARTIFACT_RAW_PROMPT_FOUND", `Raw prompt/system message found in ${file.relPath}`, "Remove raw prompts from artifacts.", [makeEvidenceRef(file.relPath, "raw prompt")]);
254
+ unsafeCount++;
255
+ }
256
+
257
+ // Check for oversized threshold
258
+ if (file.size > OVERSIZED_THRESHOLD) {
259
+ addFinding("warn", "ARTIFACT_OVERSIZED", `Artifact ${file.relPath} is ${Math.round(file.size / 1024)}KB`, "Consider compacting this artifact.", [makeEvidenceRef(file.relPath, "large")]);
260
+ oversizedCount++;
261
+ }
262
+ } catch {}
263
+ continue;
264
+ }
265
+
266
+ // JSON artifact checks
267
+ if (!file.relPath.endsWith(".json")) continue;
268
+
269
+ let data;
270
+ try {
271
+ const raw = fs.readFileSync(file.absPath, "utf8").replace(/^/, "");
272
+ data = JSON.parse(raw);
273
+ artifactsInspected++;
274
+ } catch {
275
+ continue;
276
+ }
277
+
278
+ // Check schemaVersion
279
+ if (!data.schemaVersion) {
280
+ addFinding("warn", "ARTIFACT_SCHEMA_MISSING", `Artifact ${file.relPath} has no schemaVersion`, "Add schemaVersion to the artifact.", [makeEvidenceRef(file.relPath, "missing schema")]);
281
+ missingSchemaCount++;
282
+ } else {
283
+ addFinding("info", "ARTIFACT_SCHEMA_FOUND", `Schema '${data.schemaVersion}' found in ${file.relPath}`, "No action needed.", [makeEvidenceRef(file.relPath, data.schemaVersion)]);
284
+ }
285
+
286
+ // Check generatedAt
287
+ if (data.generatedAt) {
288
+ addFinding("info", "ARTIFACT_GENERATED_AT_FOUND", `generatedAt present in ${file.relPath}`, "No action needed.", [makeEvidenceRef(file.relPath, "timestamp")]);
289
+ if (isStaleDate(data.generatedAt)) {
290
+ addFinding("warn", "ARTIFACT_STALE", `Artifact ${file.relPath} generatedAt is older than ${STALE_DAYS} days`, "Re-generate the artifact.", [makeEvidenceRef(file.relPath, "stale")]);
291
+ staleCount++;
292
+ }
293
+ } else if (data.schemaVersion) {
294
+ // Only warn about missing generatedAt on schema-versioned artifacts
295
+ addFinding("warn", "ARTIFACT_GENERATED_AT_MISSING", `Schema-versioned artifact ${file.relPath} has no generatedAt`, "Add generatedAt timestamp.", [makeEvidenceRef(file.relPath, "no timestamp")]);
296
+ }
297
+
298
+ // Stringify and check content
299
+ const rawContent = JSON.stringify(data);
300
+
301
+ // Absolute paths
302
+ if (ABSOLUTE_WINDOWS_PATH_RE.test(rawContent) || ABSOLUTE_UNIX_PATH_RE.test(rawContent)) {
303
+ addFinding("block", "ARTIFACT_ABSOLUTE_PATH_FOUND", `Absolute local path found in ${file.relPath}`, "Replace with repo-relative paths.", [makeEvidenceRef(file.relPath, "absolute path")]);
304
+ unsafeCount++;
305
+ }
306
+
307
+ // Secret patterns
308
+ if (SECRET_PATTERN_RE.test(rawContent)) {
309
+ addFinding("block", "ARTIFACT_SECRET_PATTERN_FOUND", `Secret-like token found in ${file.relPath}`, "Remove or redact secret values.", [makeEvidenceRef(file.relPath, "secret")]);
310
+ unsafeCount++;
311
+ }
312
+
313
+ // Raw logs
314
+ if (RAW_LOG_RE.test(rawContent)) {
315
+ addFinding("block", "ARTIFACT_RAW_LOG_FOUND", `Raw log entries found in ${file.relPath}`, "Remove raw logs from artifacts.", [makeEvidenceRef(file.relPath, "raw log")]);
316
+ unsafeCount++;
317
+ }
318
+
319
+ // Raw prompts
320
+ if (RAW_PROMPT_RE.test(rawContent)) {
321
+ addFinding("block", "ARTIFACT_RAW_PROMPT_FOUND", `Raw prompt/system message found in ${file.relPath}`, "Remove raw prompts from artifacts.", [makeEvidenceRef(file.relPath, "raw prompt")]);
322
+ unsafeCount++;
323
+ }
324
+
325
+ // Raw transcript
326
+ if (RAW_TRANSCRIPT_RE.test(rawContent)) {
327
+ addFinding("block", "ARTIFACT_RAW_TRANSCRIPT_FOUND", `Raw transcript found in ${file.relPath}`, "Remove raw transcripts from artifacts.", [makeEvidenceRef(file.relPath, "raw transcript")]);
328
+ unsafeCount++;
329
+ }
330
+
331
+ // Raw code dump
332
+ if (RAW_CODE_DUMP_RE.test(rawContent)) {
333
+ addFinding("block", "ARTIFACT_RAW_CODE_FOUND", `Raw source code dump found in ${file.relPath}`, "Remove raw code from artifacts.", [makeEvidenceRef(file.relPath, "raw code")]);
334
+ unsafeCount++;
335
+ }
336
+
337
+ // Unsupported public claim
338
+ if (PUBLIC_CLAIM_RE.test(rawContent)) {
339
+ // Check if there's evidence backing it
340
+ const hasProof = data.valueProof && (data.valueProof.measured === true || data.valueProof.dogfooded === true);
341
+ if (!hasProof) {
342
+ addFinding("block", "ARTIFACT_PUBLIC_CLAIM_UNSUPPORTED", `publicClaimAllowed=true without proof support in ${file.relPath}`, "Set publicClaimAllowed to false or add proof evidence.", [makeEvidenceRef(file.relPath, "unsupported claim")]);
343
+ unsafeCount++;
344
+ }
345
+ }
346
+
347
+ // Value label check
348
+ if (data.valueProof && typeof data.valueProof === "object") {
349
+ const mt = data.valueProof.measurementType;
350
+ if (!mt || !VALUE_FIELDS.includes(mt)) {
351
+ addFinding("warn", "ARTIFACT_VALUE_LABEL_MISSING", `Missing or unknown measurementType in ${file.relPath}`, "Add measurementType: measured|estimated|heuristic|unavailable.", [makeEvidenceRef(file.relPath, "value label")]);
352
+ }
353
+ }
354
+
355
+ // Broken evidence refs
356
+ if (Array.isArray(data.valueProof?.evidenceRefs)) {
357
+ for (const ref of data.valueProof.evidenceRefs.slice(0, 5)) {
358
+ const refPath = String(ref || "").split(" (")[0].split(":")[0];
359
+ if (refPath && !refPath.startsWith("[") && !fs.existsSync(path.join(cwd, refPath))) {
360
+ addFinding("warn", "ARTIFACT_BROKEN_EVIDENCE_REF", `Broken evidence ref '${sanitizeText(refPath, 80)}' in ${file.relPath}`, "Update or remove the broken reference.", [makeEvidenceRef(file.relPath, `broken: ${refPath}`)]);
361
+ brokenRefCount++;
362
+ }
363
+ }
364
+ }
365
+
366
+ // Redaction check
367
+ if (data.redacted === false || (data.privacy && data.privacy.redacted === false)) {
368
+ addFinding("warn", "ARTIFACT_REDACTION_MISSING", `Artifact ${file.relPath} is not marked as redacted`, "Set redacted: true or ensure content is redacted.", [makeEvidenceRef(file.relPath, "not redacted")]);
369
+ }
370
+
371
+ // Oversized
372
+ if (file.size > OVERSIZED_THRESHOLD) {
373
+ addFinding("warn", "ARTIFACT_OVERSIZED", `Artifact ${file.relPath} is ${Math.round(file.size / 1024)}KB`, "Consider compacting this artifact.", [makeEvidenceRef(file.relPath, "large")]);
374
+ oversizedCount++;
375
+ }
376
+
377
+ // Unsafe public text claim (asserted, not disclaimed)
378
+ if (hasUnsupportedPublicClaim(rawContent)) {
379
+ addFinding("block", "ARTIFACT_PUBLIC_CLAIM_UNSUPPORTED", `Unsupported public claim text found in ${file.relPath}`, "Remove or qualify the claim.", [makeEvidenceRef(file.relPath, "unsupported claim text")]);
380
+ unsafeCount++;
381
+ }
382
+ }
383
+
384
+ // ── Determine overall status ──
385
+ const hasBlock = findings.some(f => f.severity === "block");
386
+ const hasWarn = findings.some(f => f.severity === "warn");
387
+ const status = hasBlock ? "blocked" : hasWarn ? "warn" : "pass";
388
+
389
+ const warnCount = findings.filter(f => f.severity === "warn").length;
390
+ const blockCount = findings.filter(f => f.severity === "block").length;
391
+ const infoCount = findings.filter(f => f.severity === "info").length;
392
+
393
+ const safeNextAction = hasBlock
394
+ ? "Remove raw secrets, prompts, logs, code dumps, or unsupported claims from artifacts before sharing."
395
+ : hasWarn
396
+ ? "Review stale, oversized, or schema-missing artifacts and update accordingly."
397
+ : "Artifacts and receipts are clean. Safe to proceed.";
398
+
399
+ const report = {
400
+ schemaVersion: CONTRACT,
401
+ generatedAt: nowIso(),
402
+ status,
403
+ redacted: true,
404
+ summary: {
405
+ title: "Local Artifact & Receipt Hygiene Guard",
406
+ text: `${artifactsInspected} artifacts inspected. ${staleCount} stale, ${missingSchemaCount} missing schema, ${unsafeCount} unsafe, ${oversizedCount} oversized.`,
407
+ findingCounts: { info: infoCount, warn: warnCount, block: blockCount },
408
+ safeNextAction,
409
+ },
410
+ surfaceEvidence: {
411
+ filesInspected: files.length,
412
+ artifactsInspected,
413
+ capabilitiesInspected: 0,
414
+ limitsApplied,
415
+ },
416
+ hygieneCounts: {
417
+ artifactsInspected,
418
+ staleCount,
419
+ missingSchemaCount,
420
+ unsafeCount,
421
+ oversizedCount,
422
+ brokenRefCount,
423
+ },
424
+ findings: findings.sort((a, b) => severityRank(b.severity) - severityRank(a.severity)),
425
+ productHome: {
426
+ cardSource: "artifact-receipt-hygiene",
427
+ status,
428
+ found: findings.filter(f => f.severity === "warn" || f.severity === "block").map(f => sanitizeText(f.title, 120)).slice(0, 5),
429
+ fixedOrPrepared: [],
430
+ savedOrProved: unsafeCount === 0 && staleCount === 0 ? ["Artifacts and receipts are clean and redacted"] : [],
431
+ forReview: findings.filter(f => f.severity === "block").map(f => sanitizeText(f.title, 120)).slice(0, 3),
432
+ safeNextAction,
433
+ },
434
+ valueProof: {
435
+ implemented: true,
436
+ dogfooded: false,
437
+ measured: false,
438
+ measurementType: "heuristic",
439
+ publicClaimAllowed: false,
440
+ evidenceRefs: [makeEvidenceRef(REPORT_JSON_REL, "artifact hygiene report")].filter(Boolean),
441
+ caveat: "Hygiene checks are pattern-based. No exhaustive secret scanning or content validation performed.",
442
+ },
443
+ limits: {
444
+ localFirst: true,
445
+ deterministicFirst: true,
446
+ modelCalls: false,
447
+ networkCalls: false,
448
+ providerCalls: false,
449
+ registryCalls: false,
450
+ rawDump: false,
451
+ autoFix: false,
452
+ },
453
+ };
454
+
455
+ if (options.write !== false) {
456
+ safeWriteJson(cwd, REPORT_JSON_REL, report);
457
+ }
458
+
459
+ return report;
460
+ }
461
+
462
+ function buildEmptyReport(limitsApplied = []) {
463
+ return {
464
+ schemaVersion: CONTRACT,
465
+ generatedAt: nowIso(),
466
+ status: "no_data",
467
+ redacted: true,
468
+ summary: {
469
+ title: "Local Artifact & Receipt Hygiene Guard",
470
+ text: "No artifacts or receipts found.",
471
+ findingCounts: { info: 0, warn: 0, block: 0 },
472
+ safeNextAction: "No artifacts available. Run commands that generate artifacts first.",
473
+ },
474
+ surfaceEvidence: {
475
+ filesInspected: 0,
476
+ artifactsInspected: 0,
477
+ capabilitiesInspected: 0,
478
+ limitsApplied,
479
+ },
480
+ hygieneCounts: {
481
+ artifactsInspected: 0,
482
+ staleCount: 0,
483
+ missingSchemaCount: 0,
484
+ unsafeCount: 0,
485
+ oversizedCount: 0,
486
+ brokenRefCount: 0,
487
+ },
488
+ findings: [],
489
+ productHome: {
490
+ cardSource: "artifact-receipt-hygiene",
491
+ status: "no_data",
492
+ found: [],
493
+ fixedOrPrepared: [],
494
+ savedOrProved: [],
495
+ forReview: [],
496
+ safeNextAction: "No artifacts available.",
497
+ },
498
+ valueProof: {
499
+ implemented: true,
500
+ dogfooded: false,
501
+ measured: false,
502
+ measurementType: "unavailable",
503
+ publicClaimAllowed: false,
504
+ evidenceRefs: [],
505
+ caveat: "No data to measure against.",
506
+ },
507
+ limits: {
508
+ localFirst: true,
509
+ deterministicFirst: true,
510
+ modelCalls: false,
511
+ networkCalls: false,
512
+ providerCalls: false,
513
+ registryCalls: false,
514
+ rawDump: false,
515
+ autoFix: false,
516
+ },
517
+ };
518
+ }
519
+
520
+ // ── Generate / Load / Format / Surface ──────────────────────────────────────
521
+
522
+ function generateArtifactReceiptHygiene(cwd = process.cwd(), options = {}) {
523
+ const report = buildArtifactReceiptHygieneReport(cwd, options);
524
+ return { report, reportPath: path.join(cwd, REPORT_JSON_REL) };
525
+ }
526
+
527
+ function loadArtifactReceiptHygiene(cwd = process.cwd()) {
528
+ return safeReadJson(cwd, REPORT_JSON_REL, null);
529
+ }
530
+
531
+ function formatArtifactReceiptHygieneText(report) {
532
+ if (!report || report.schemaVersion !== CONTRACT) {
533
+ return [
534
+ "Avorelo Local Artifact & Receipt Hygiene Guard",
535
+ "Status: NO DATA",
536
+ "No artifacts or receipts found yet.",
537
+ "Safe next action: Run commands that generate artifacts first.",
538
+ ].join("\n");
539
+ }
540
+
541
+ const hc = report.hygieneCounts || {};
542
+ const lines = [
543
+ "Avorelo Local Artifact & Receipt Hygiene Guard",
544
+ `Status: ${String(report.status || "no_data").toUpperCase()} · redacted=${report.redacted === true ? "yes" : "no"}`,
545
+ `Artifacts: ${hc.artifactsInspected || 0} · stale=${hc.staleCount || 0} · missing-schema=${hc.missingSchemaCount || 0} · unsafe=${hc.unsafeCount || 0} · oversized=${hc.oversizedCount || 0}`,
546
+ "Notes: local static scan only · no auto-fix · no raw dump",
547
+ ];
548
+
549
+ if (Array.isArray(report.findings) && report.findings.length > 0) {
550
+ lines.push("");
551
+ lines.push("Findings:");
552
+ for (const finding of report.findings.slice(0, 5)) {
553
+ lines.push(`- [${finding.severity}] ${finding.title}${finding.evidenceRefs?.length ? ` · ${finding.evidenceRefs[0]}` : ""}`);
554
+ }
555
+ if (report.findings.length > 5) {
556
+ lines.push(` ... and ${report.findings.length - 5} more`);
557
+ }
558
+ }
559
+
560
+ lines.push("");
561
+ lines.push(`Safe next action: ${report.summary?.safeNextAction || "Review artifact hygiene."}`);
562
+ return lines.join("\n");
563
+ }
564
+
565
+ function formatArtifactReceiptHygieneStatusLine(report) {
566
+ if (!report || report.schemaVersion !== CONTRACT) {
567
+ return "Artifact hygiene: NOT RUN · run `avorelo artifact-hygiene --text`";
568
+ }
569
+ const hc = report.hygieneCounts || {};
570
+ return `Artifact hygiene: ${String(report.status || "no_data").toUpperCase()}`
571
+ + ` · artifacts=${hc.artifactsInspected || 0}`
572
+ + ` · unsafe=${hc.unsafeCount || 0}`
573
+ + ` · stale=${hc.staleCount || 0}`
574
+ + ` · next: ${sanitizeText(report.summary?.safeNextAction, 140) || "Review artifact hygiene."}`;
575
+ }
576
+
577
+ function buildArtifactReceiptHygieneSurface(cwd = process.cwd(), options = {}) {
578
+ const report = loadArtifactReceiptHygiene(cwd) || (options.buildIfMissing ? buildArtifactReceiptHygieneReport(cwd, { write: false }) : null);
579
+ if (!report) {
580
+ return {
581
+ status: "not_run",
582
+ artifactsInspected: 0,
583
+ unsafeCount: 0,
584
+ staleCount: 0,
585
+ nextBestAction: "Run `avorelo artifact-hygiene --text` to check artifact hygiene.",
586
+ statusLine: "Artifact hygiene: NOT RUN · run `avorelo artifact-hygiene --text`",
587
+ showInStatus: true,
588
+ showInDashboard: true,
589
+ evidenceRef: null,
590
+ limitations: ["Local pattern-based scan only. No exhaustive secret scanning."],
591
+ };
592
+ }
593
+
594
+ const hc = report.hygieneCounts || {};
595
+ return {
596
+ status: report.status,
597
+ artifactsInspected: hc.artifactsInspected || 0,
598
+ unsafeCount: hc.unsafeCount || 0,
599
+ staleCount: hc.staleCount || 0,
600
+ oversizedCount: hc.oversizedCount || 0,
601
+ nextBestAction: report.summary?.safeNextAction,
602
+ statusLine: formatArtifactReceiptHygieneStatusLine(report),
603
+ showInStatus: true,
604
+ showInDashboard: true,
605
+ evidenceRef: REPORT_JSON_REL,
606
+ limitations: ["Local pattern-based scan only. No exhaustive secret scanning."],
607
+ };
608
+ }
609
+
610
+ module.exports = {
611
+ CONTRACT,
612
+ REPORT_JSON_REL,
613
+ buildArtifactReceiptHygieneReport,
614
+ generateArtifactReceiptHygiene,
615
+ loadArtifactReceiptHygiene,
616
+ formatArtifactReceiptHygieneText,
617
+ formatArtifactReceiptHygieneStatusLine,
618
+ buildArtifactReceiptHygieneSurface,
619
+ };