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,946 @@
1
+ "use strict";
2
+
3
+ const fs = require("fs");
4
+ const path = require("path");
5
+ const crypto = require("crypto");
6
+
7
+ const { ensureCcoDirs, nowIso, safeReadJson, safeWriteJson } = require("./fsx");
8
+ const { listCapabilities } = require("./capability-registry");
9
+ const { buildSkillRegistry, GENERATED_SKILL_REGISTRY_REL_PATH } = require("./avorelo-skill-registry");
10
+ const { buildSkillHygiene } = require("./skill-hygiene");
11
+ const { buildMcpToolInventory, INVENTORY_REL } = require("./mcp-tool-inventory");
12
+ const { buildMcpToolRiskReport, RISK_REL } = require("./mcp-tool-risk");
13
+ const { getSource } = require("./source-catalog");
14
+ const { LATEST_RECEIPT_REL_PATH: GOVERNANCE_RECEIPT_REL_PATH } = require("./agent-access-governance");
15
+ const { LATEST_INSTALL_INTAKE_RECEIPT_REL_PATH } = require("./install-intake-risk");
16
+ const { LATEST_REPORT_REL: LEGACY_AI_WORKSPACE_HYGIENE_REL } = require("./ai-workspace-hygiene");
17
+
18
+ const CONTRACT = "avorelo.governedWorkspaceHygiene.v1";
19
+ const SCHEMA_VERSION = 1;
20
+ const REPORT_DIR_REL = ".claude/cco/orchestration/governed-workspace-hygiene";
21
+ const LATEST_REPORT_REL = `${REPORT_DIR_REL}/latest-report.json`;
22
+
23
+ const RELEVANT_FAMILIES = new Set([
24
+ "ai_workspace_hygiene",
25
+ "agent_access_governance",
26
+ "install_intake_risk",
27
+ "safe_path_engine",
28
+ "skills_skill_packs",
29
+ "source_intake",
30
+ "mcp_tool_governance",
31
+ "proof_evidence",
32
+ ]);
33
+
34
+ const FIRST_PARTY_MODULES = Object.freeze([
35
+ "scripts/lib/agent-access-governance.js",
36
+ "scripts/lib/ai-workspace-hygiene.js",
37
+ "scripts/lib/governed-workspace-hygiene.js",
38
+ "scripts/lib/install-intake-risk.js",
39
+ "scripts/lib/mcp-tool-inventory.js",
40
+ "scripts/lib/mcp-tool-risk.js",
41
+ "scripts/lib/outcome-evidence-stack.js",
42
+ "scripts/lib/source-catalog.js",
43
+ "scripts/lib/work-control-receipts.js",
44
+ ]);
45
+
46
+ const CONFIG_SOURCE_CANDIDATES = Object.freeze([
47
+ "AGENTS.md",
48
+ "CLAUDE.md",
49
+ "GEMINI.md",
50
+ ".claude/settings.json",
51
+ ".claude/settings.local.json",
52
+ ".codex/mcp.json",
53
+ ".cursor/mcp.json",
54
+ ".mcp.json",
55
+ "mcp.json",
56
+ ".openhands/config.json",
57
+ "package.json",
58
+ "config/http-hook-policy.json",
59
+ "config/intel-policy.json",
60
+ "config/intel-sources.json",
61
+ "config/pricing-experiment.json",
62
+ "config/security-intake-policy.json",
63
+ "config/tier-feature-map.json",
64
+ ]);
65
+
66
+ const DANGEROUS_REASON_CODES = new Set([
67
+ "BLOCKED_SOURCE",
68
+ "POLICY_BYPASS",
69
+ "UNSAFE_AUTO_EXECUTION",
70
+ "SECRET_ACCESS",
71
+ "SECRET_CAPABLE_MCP",
72
+ "DESTRUCTIVE_ACTION",
73
+ ]);
74
+
75
+ const DIMENSION_ORDER = Object.freeze({
76
+ read: 1,
77
+ path: 2,
78
+ write: 3,
79
+ execution: 3,
80
+ network: 3,
81
+ browser: 3,
82
+ production: 4,
83
+ secret: 5,
84
+ });
85
+
86
+ const RISK_MODEL = Object.freeze({
87
+ dimensions: [
88
+ "read",
89
+ "write",
90
+ "network",
91
+ "secret",
92
+ "path",
93
+ "execution",
94
+ "browser",
95
+ "production",
96
+ ],
97
+ levels: ["low", "medium", "high", "critical"],
98
+ });
99
+
100
+ const DOGFOOD_COMMANDS = Object.freeze([
101
+ "node bin/avorelo support --json",
102
+ "node bin/avorelo support --text",
103
+ "node bin/avorelo outcome-evidence --json",
104
+ "node bin/avorelo outcome-evidence --text",
105
+ "node bin/avorelo workspace-hygiene --json",
106
+ "node bin/avorelo workspace-hygiene --text",
107
+ "node bin/avorelo status --text",
108
+ "node bin/avorelo open --json",
109
+ "node bin/avorelo package-audit --json",
110
+ "node bin/avorelo package-smoke --json",
111
+ "node bin/avorelo install-claims --json",
112
+ "node bin/avorelo public-distribution --json",
113
+ "node bin/avorelo report --summary",
114
+ ]);
115
+
116
+ function sha256Short(value) {
117
+ return crypto.createHash("sha256").update(String(value || "")).digest("hex").slice(0, 12);
118
+ }
119
+
120
+ function unique(values) {
121
+ return [...new Set((values || []).filter(Boolean))];
122
+ }
123
+
124
+ function fileExists(absPath) {
125
+ try {
126
+ return fs.existsSync(absPath);
127
+ } catch {
128
+ return false;
129
+ }
130
+ }
131
+
132
+ function listDirectories(absPath) {
133
+ try {
134
+ return fs.readdirSync(absPath, { withFileTypes: true }).filter((entry) => entry.isDirectory());
135
+ } catch {
136
+ return [];
137
+ }
138
+ }
139
+
140
+ function readJsonFile(absPath) {
141
+ try {
142
+ return JSON.parse(fs.readFileSync(absPath, "utf8").replace(/^\uFEFF/, ""));
143
+ } catch {
144
+ return null;
145
+ }
146
+ }
147
+
148
+ function sanitizeText(value, max = 160) {
149
+ if (value === null || value === undefined) return null;
150
+ const trimmed = String(value).replace(/[\x00-\x08\x0b\x0c\x0e-\x1f]/g, "").trim();
151
+ if (!trimmed) return null;
152
+ return trimmed
153
+ .replace(/\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b/ig, "<redacted-email>")
154
+ .replace(/\b[A-Za-z]:\\[^\s"']+/g, "<redacted-path>")
155
+ .replace(/(?:^|[\s(])\/(?:Users|home|root|tmp|var|etc|opt|usr)\/[^\s"')]+/g, " <redacted-path>")
156
+ .replace(/sk-[A-Za-z0-9]{16,}/g, "[redacted-token]")
157
+ .replace(/gh[ps]_[A-Za-z0-9]{10,}/g, "[redacted-token]")
158
+ .replace(/AKIA[0-9A-Z]{16}/g, "[redacted-token]")
159
+ .replace(/((?:api[_ -]?key|token|password|secret|authorization)\s*[:=]\s*)([^\s'"]+)/ig, "$1[redacted]")
160
+ .slice(0, max);
161
+ }
162
+
163
+ function sanitizeRelPath(value) {
164
+ const text = sanitizeText(value, 200);
165
+ if (!text) return null;
166
+ return text.replace(/\\/g, "/");
167
+ }
168
+
169
+ function ownerSponsor(owner, sponsor) {
170
+ const normalizedOwner = sanitizeText(owner, 80) || "unknown";
171
+ const normalizedSponsor = sanitizeText(sponsor, 80) || "unknown";
172
+ return {
173
+ status: normalizedOwner === "unknown" || normalizedSponsor === "unknown" ? "unknown" : "known",
174
+ owner: normalizedOwner,
175
+ sponsor: normalizedSponsor,
176
+ };
177
+ }
178
+
179
+ function createInventoryItem(input) {
180
+ return {
181
+ id: input.id || `gwh-${input.type || "item"}-${sha256Short([input.type, input.name, input.source].join("|"))}`,
182
+ type: input.type,
183
+ name: sanitizeText(input.name, 120) || input.type,
184
+ source: sanitizeRelPath(input.source) || "local",
185
+ provenance: sanitizeText(input.provenance, 160) || "local_workspace",
186
+ trustLevel: input.trustLevel,
187
+ ownerSponsor: input.ownerSponsor,
188
+ riskDimensions: unique(input.riskDimensions || ["read"]),
189
+ riskLevel: input.riskLevel,
190
+ recommendedDecision: input.recommendedDecision,
191
+ reasonCodes: unique(input.reasonCodes || []),
192
+ proofRef: sanitizeRelPath(input.proofRef) || null,
193
+ safeNextAction: sanitizeText(input.safeNextAction, 220) || defaultSafeNextAction(input.recommendedDecision, input.name),
194
+ redacted: true,
195
+ };
196
+ }
197
+
198
+ function hasHighImpactDimensions(dimensions) {
199
+ const set = new Set(dimensions || []);
200
+ return ["write", "network", "secret", "path", "execution", "browser", "production"].some((dimension) => set.has(dimension));
201
+ }
202
+
203
+ function highestRiskDimension(dimensions) {
204
+ return unique(dimensions || ["read"])
205
+ .slice()
206
+ .sort((left, right) => (DIMENSION_ORDER[right] || 0) - (DIMENSION_ORDER[left] || 0))[0] || "read";
207
+ }
208
+
209
+ function riskLevelFromDimensions(dimensions) {
210
+ const topDimension = highestRiskDimension(dimensions);
211
+ if (topDimension === "secret") return "critical";
212
+ if (["production", "write", "execution", "browser", "network"].includes(topDimension)) return "high";
213
+ if (topDimension === "path") return "medium";
214
+ return "low";
215
+ }
216
+
217
+ function detectRiskDimensionsFromText(text) {
218
+ const value = String(text || "");
219
+ const dimensions = [];
220
+ if (/\b(write|patch|delete|remove|edit|create|mutate)\b/i.test(value)) dimensions.push("write");
221
+ if (/\b(exec|execute|shell|powershell|cmd|spawn|subprocess|command)\b/i.test(value)) dimensions.push("execution");
222
+ if (/\b(fetch|network|http|https|remote|url|webhook)\b/i.test(value)) dimensions.push("network");
223
+ if (/\b(secret|token|credential|authorization|password|env)\b/i.test(value)) dimensions.push("secret");
224
+ if (/\b(browser|playwright|chrome|selenium|devtools)\b/i.test(value)) dimensions.push("browser");
225
+ if (/\b(deploy|publish|release|production|prod)\b/i.test(value)) dimensions.push("production");
226
+ if (/\b(path|file|folder|directory|repo|filesystem)\b/i.test(value)) dimensions.push("path");
227
+ if (dimensions.length === 0) dimensions.push("read");
228
+ return unique(dimensions);
229
+ }
230
+
231
+ function mapSkillTrustLevel(skill) {
232
+ if (skill.packId === "avorelo") return "trusted";
233
+ if (skill.sourceReviewStatus === "trusted" || skill.sourceReviewStatus === "reviewed") return "trusted";
234
+ if (skill.sourceReviewStatus === "blocked") return "untrusted";
235
+ if (skill.sourceReviewStatus === "known") return "known";
236
+ return "unknown";
237
+ }
238
+
239
+ function defaultSafeNextAction(decision, name) {
240
+ const target = sanitizeText(name, 80) || "this item";
241
+ if (decision === "block") return `Keep ${target} blocked by default until its source and scope are reviewed.`;
242
+ if (decision === "approval_required") return `Review ${target} before granting broader local workspace access.`;
243
+ if (decision === "auto_limit") return `Keep ${target} limited to redacted local metadata only.`;
244
+ if (decision === "warn") return `Review ${target} metadata before treating it as fully trusted.`;
245
+ return `Keep ${target} local-first and redacted.`;
246
+ }
247
+
248
+ function reasonCodesFromWarningCodes(warnings) {
249
+ const codes = new Set();
250
+ for (const warning of warnings || []) {
251
+ const code = String(warning?.code || "").toLowerCase();
252
+ if (!code) continue;
253
+ if (code.includes("policy_bypass")) codes.add("POLICY_BYPASS");
254
+ if (code.includes("auto_execution")) codes.add("UNSAFE_AUTO_EXECUTION");
255
+ if (code.includes("hidden_unicode")) codes.add("HIDDEN_UNICODE");
256
+ if (code.includes("external_script")) codes.add("EXTERNAL_SCRIPT_METADATA_ONLY");
257
+ if (code.includes("secret")) codes.add("SECRET_ACCESS");
258
+ if (code.includes("browser")) codes.add("BROWSER_REFERENCE");
259
+ if (code.includes("mcp")) codes.add("MCP_REFERENCE");
260
+ if (code.includes("network")) codes.add("NETWORK_REFERENCE");
261
+ }
262
+ return Array.from(codes);
263
+ }
264
+
265
+ function decideGovernance(input) {
266
+ const reasonCodes = new Set(input.reasonCodes || []);
267
+ const ownerUnknown = input.ownerSponsor?.status === "unknown";
268
+ const highImpact = hasHighImpactDimensions(input.riskDimensions);
269
+ const externalCapability = reasonCodes.has("EXTERNAL_CAPABILITY");
270
+ const dangerous = Array.from(reasonCodes).some((code) => DANGEROUS_REASON_CODES.has(code));
271
+
272
+ let recommendedDecision = "allow";
273
+
274
+ if (input.type === "capability" && input.trustLevel === "trusted") {
275
+ recommendedDecision = (input.provenance || "").includes("metadata_only") ? "auto_limit" : "allow";
276
+ } else if (input.type === "skill" && input.trustLevel === "trusted" && !dangerous) {
277
+ recommendedDecision = reasonCodes.has("HIGH_CONTEXT_WEIGHT") ? "warn" : "allow";
278
+ } else if (input.trustLevel === "untrusted" && (highImpact || dangerous || input.riskLevel === "critical")) {
279
+ recommendedDecision = "block";
280
+ } else if (dangerous || (new Set(input.riskDimensions || []).has("secret"))) {
281
+ recommendedDecision = "block";
282
+ } else if (highImpact || ownerUnknown || externalCapability) {
283
+ recommendedDecision = "approval_required";
284
+ } else if (input.trustLevel === "unknown" || input.riskLevel === "medium" || reasonCodes.has("MISSING_PROVENANCE") || reasonCodes.has("INCOMPLETE_METADATA")) {
285
+ recommendedDecision = "warn";
286
+ }
287
+
288
+ if (ownerUnknown) reasonCodes.add("OWNER_SPONSOR_UNKNOWN");
289
+ if (input.trustLevel === "unknown") reasonCodes.add("UNKNOWN_PROVENANCE");
290
+ if (input.trustLevel === "untrusted") reasonCodes.add("UNTRUSTED_SOURCE");
291
+
292
+ return {
293
+ ...input,
294
+ recommendedDecision,
295
+ reasonCodes: Array.from(reasonCodes),
296
+ safeNextAction: input.safeNextAction || defaultSafeNextAction(recommendedDecision, input.name),
297
+ };
298
+ }
299
+
300
+ function capabilityDimensions(entry) {
301
+ const familyMap = {
302
+ ai_workspace_hygiene: ["read"],
303
+ agent_access_governance: ["read"],
304
+ install_intake_risk: ["read"],
305
+ safe_path_engine: ["read"],
306
+ skills_skill_packs: ["read"],
307
+ source_intake: ["read"],
308
+ mcp_tool_governance: ["read"],
309
+ proof_evidence: ["read"],
310
+ };
311
+ return familyMap[entry.familyId] || detectRiskDimensionsFromText([entry.shortDescription, entry.familyName, entry.name].join(" "));
312
+ }
313
+
314
+ function buildCapabilityInventory() {
315
+ return listCapabilities()
316
+ .filter((entry) => RELEVANT_FAMILIES.has(entry.familyId))
317
+ .map((entry) => {
318
+ const dimensions = capabilityDimensions(entry);
319
+ const decided = decideGovernance({
320
+ type: "capability",
321
+ name: entry.name,
322
+ source: entry.sourceOfTruth,
323
+ provenance: entry.familyId === "mcp_tool_governance" || entry.familyId === "install_intake_risk"
324
+ ? "first_party_capability_metadata_only"
325
+ : "first_party_capability_registry",
326
+ trustLevel: "trusted",
327
+ ownerSponsor: ownerSponsor("Avorelo", "Avorelo local policy"),
328
+ riskDimensions: dimensions,
329
+ riskLevel: riskLevelFromDimensions(dimensions),
330
+ reasonCodes: [entry.familyId.toUpperCase(), "FIRST_PARTY_LOCAL_POLICY"],
331
+ proofRef: entry.sourceOfTruth,
332
+ safeNextAction: entry.familyId === "mcp_tool_governance" || entry.familyId === "install_intake_risk"
333
+ ? `Use ${entry.name} in metadata-only mode until a reviewed local target requires more scope.`
334
+ : `Keep ${entry.name} limited to reviewed local workspace context.`,
335
+ });
336
+ return createInventoryItem({
337
+ id: `capability-${entry.id}`,
338
+ ...decided,
339
+ });
340
+ });
341
+ }
342
+
343
+ function buildSkillInventory(cwd) {
344
+ const registry = buildSkillRegistry(cwd);
345
+ const hygiene = buildSkillHygiene(registry);
346
+ const items = registry.skills.map((skill) => {
347
+ const source = getSource(skill.sourceId || skill.packId);
348
+ const warningCodes = reasonCodesFromWarningCodes(skill.warnings || []);
349
+ const provenance = skill.packId === "avorelo"
350
+ ? "first_party_skill_registry"
351
+ : source
352
+ ? "vendor_skillpack_with_reviewed_metadata"
353
+ : "vendor_skillpack_unknown_provenance";
354
+ const riskDimensions = unique([
355
+ "read",
356
+ warningCodes.includes("NETWORK_REFERENCE") ? "network" : null,
357
+ warningCodes.includes("BROWSER_REFERENCE") ? "browser" : null,
358
+ warningCodes.includes("SECRET_ACCESS") ? "secret" : null,
359
+ warningCodes.includes("MCP_REFERENCE") || warningCodes.includes("EXTERNAL_SCRIPT_METADATA_ONLY") ? "execution" : null,
360
+ ]);
361
+ const reasonCodes = unique([
362
+ ...warningCodes,
363
+ skill.routeEligible ? "ROUTE_ELIGIBLE" : "ROUTE_DEFERRED",
364
+ !source && skill.packId !== "avorelo" ? "MISSING_PROVENANCE" : null,
365
+ skill.sourceReviewStatus === "blocked" ? "BLOCKED_SOURCE" : null,
366
+ skill.sourceReviewStatus === "deferred" ? "DEFERRED_SOURCE" : null,
367
+ skill.contextWeight?.label === "high" ? "HIGH_CONTEXT_WEIGHT" : null,
368
+ ]);
369
+
370
+ const decided = decideGovernance({
371
+ type: "skill",
372
+ name: skill.name,
373
+ source: skill.path || GENERATED_SKILL_REGISTRY_REL_PATH,
374
+ provenance,
375
+ trustLevel: mapSkillTrustLevel(skill),
376
+ ownerSponsor: ownerSponsor(
377
+ source?.owner || (skill.packId === "avorelo" ? "Avorelo" : "unknown"),
378
+ skill.packId === "avorelo" ? "Avorelo local policy" : source?.name || "unknown"
379
+ ),
380
+ riskDimensions,
381
+ riskLevel: riskLevelFromDimensions(riskDimensions),
382
+ reasonCodes,
383
+ proofRef: GENERATED_SKILL_REGISTRY_REL_PATH,
384
+ safeNextAction: skill.routeEligible
385
+ ? `Keep ${skill.name} scoped to reviewed local tasks and redacted outputs.`
386
+ : `Review ${skill.name} source metadata before routing work through it.`,
387
+ });
388
+
389
+ return createInventoryItem({
390
+ id: `skill-${skill.id}`,
391
+ ...decided,
392
+ });
393
+ });
394
+
395
+ return {
396
+ registry,
397
+ hygiene,
398
+ items,
399
+ };
400
+ }
401
+
402
+ function buildMcpInventories(cwd) {
403
+ const inventory = buildMcpToolInventory(cwd);
404
+ const risk = buildMcpToolRiskReport(cwd, inventory);
405
+ const serverRiskById = new Map((risk.servers || []).map((entry) => [entry.serverId, entry]));
406
+
407
+ const mcpServers = (inventory.servers || []).map((server) => {
408
+ const serverRisk = serverRiskById.get(server.serverId) || {};
409
+ const trustLevel = server.trustedSource === "trusted" ? "trusted" : server.trustedSource === "known" ? "known" : "unknown";
410
+ const reasonCodes = unique([
411
+ ...(serverRisk.reasonCodes || []),
412
+ !server.owner || server.owner === "unknown" ? "MISSING_PROVENANCE" : null,
413
+ server.transport === "http" || server.transport === "sse" ? "EXTERNAL_CAPABILITY" : null,
414
+ ]);
415
+ const riskDimensions = unique([
416
+ "read",
417
+ ...detectRiskDimensionsFromText([
418
+ server.transport,
419
+ server.argsSummary,
420
+ server.envRefSummary,
421
+ server.urlRef,
422
+ ].join(" ")),
423
+ ]);
424
+
425
+ const decided = decideGovernance({
426
+ type: "mcp_server",
427
+ name: server.name,
428
+ source: server.sourceConfigRef || INVENTORY_REL,
429
+ provenance: "local_mcp_config_reference_only",
430
+ trustLevel,
431
+ ownerSponsor: ownerSponsor(server.owner, "workspace operator"),
432
+ riskDimensions,
433
+ riskLevel: serverRisk.riskLevel || riskLevelFromDimensions(riskDimensions),
434
+ reasonCodes,
435
+ proofRef: INVENTORY_REL,
436
+ });
437
+
438
+ return createInventoryItem({
439
+ id: `mcp-server-${server.serverId}`,
440
+ ...decided,
441
+ });
442
+ });
443
+
444
+ const tools = (risk.tools || []).map((tool) => {
445
+ const toolText = [tool.name, (tool.reasonCodes || []).join(" ")].join(" ");
446
+ const riskDimensions = unique([
447
+ ...detectRiskDimensionsFromText(toolText),
448
+ tool.reasonCodes?.includes("BROAD_FILESYSTEM_ACCESS") ? "path" : null,
449
+ tool.reasonCodes?.includes("NETWORK_ACCESS") ? "network" : null,
450
+ tool.reasonCodes?.includes("AUTH_REQUIRED") || tool.reasonCodes?.includes("TOKEN_OR_ENV_REFERENCE_PRESENT") ? "secret" : null,
451
+ tool.reasonCodes?.includes("SHELL_COMMAND_CAPABILITY") ? "execution" : null,
452
+ tool.reasonCodes?.includes("DEPLOY_OR_PROD_ACTION") ? "production" : null,
453
+ ]);
454
+ const reasonCodes = unique([
455
+ ...(tool.reasonCodes || []),
456
+ tool.riskLevel === "critical" || tool.riskLevel === "high" ? "EXTERNAL_CAPABILITY" : null,
457
+ ]);
458
+
459
+ const decided = decideGovernance({
460
+ type: "tool",
461
+ name: tool.name,
462
+ source: tool.serverId || RISK_REL,
463
+ provenance: "mcp_tool_metadata_only",
464
+ trustLevel: "unknown",
465
+ ownerSponsor: ownerSponsor("unknown", "workspace operator"),
466
+ riskDimensions,
467
+ riskLevel: tool.riskLevel || riskLevelFromDimensions(riskDimensions),
468
+ reasonCodes,
469
+ proofRef: RISK_REL,
470
+ });
471
+
472
+ return createInventoryItem({
473
+ id: `tool-${tool.toolId}`,
474
+ ...decided,
475
+ });
476
+ });
477
+
478
+ return { inventory, risk, mcpServers, tools };
479
+ }
480
+
481
+ function buildFirstPartySourceItems() {
482
+ return FIRST_PARTY_MODULES.map((relPath) => createInventoryItem({
483
+ id: `source-first-party-${sha256Short(relPath)}`,
484
+ ...decideGovernance({
485
+ type: "source",
486
+ name: path.basename(relPath),
487
+ source: relPath,
488
+ provenance: "first_party_module",
489
+ trustLevel: "trusted",
490
+ ownerSponsor: ownerSponsor("Avorelo", "Avorelo local policy"),
491
+ riskDimensions: ["read"],
492
+ riskLevel: "low",
493
+ reasonCodes: ["FIRST_PARTY_LOCAL_POLICY"],
494
+ proofRef: relPath,
495
+ safeNextAction: `Keep ${path.basename(relPath)} local and reviewed inside the repo.`,
496
+ }),
497
+ }));
498
+ }
499
+
500
+ function sourceMetadataStatus(sourceJson) {
501
+ if (!sourceJson) return "unknown";
502
+ if (sourceJson.id && sourceJson.name && sourceJson.license && sourceJson.upstreamCommit) return "known";
503
+ return "unknown";
504
+ }
505
+
506
+ function buildVendorSourceItems(cwd, skillRegistry) {
507
+ const root = path.join(cwd, "vendor", "skillpacks");
508
+ const locallyReferenced = new Set(
509
+ (skillRegistry.skills || [])
510
+ .map((skill) => skill.packId)
511
+ .filter((packId) => packId && packId !== "avorelo")
512
+ );
513
+ return listDirectories(root)
514
+ .filter((entry) => locallyReferenced.size === 0 || locallyReferenced.has(entry.name))
515
+ .map((entry) => {
516
+ const relRoot = sanitizeRelPath(path.join("vendor", "skillpacks", entry.name));
517
+ const sourceJsonPath = path.join(root, entry.name, "SOURCE.json");
518
+ const sourceJson = readJsonFile(sourceJsonPath);
519
+ const sourceCatalogEntry = getSource(entry.name);
520
+ const hasLicense = fileExists(path.join(root, entry.name, "LICENSE")) || fileExists(path.join(root, entry.name, "LICENSE.md"));
521
+ const hasScriptsDir = fileExists(path.join(root, entry.name, "scripts"));
522
+ const trustLevel = sourceCatalogEntry && sourceCatalogEntry.sourceReviewStatus === "reviewed"
523
+ ? "trusted"
524
+ : sourceMetadataStatus(sourceJson) === "known" && hasLicense
525
+ ? "known"
526
+ : hasScriptsDir && !sourceJson
527
+ ? "untrusted"
528
+ : "unknown";
529
+ const riskDimensions = unique([
530
+ "read",
531
+ hasScriptsDir ? "execution" : null,
532
+ ]);
533
+ const reasonCodes = unique([
534
+ sourceCatalogEntry ? "SOURCE_CATALOG_MATCH" : null,
535
+ sourceJson ? "SOURCE_METADATA_PRESENT" : "MISSING_PROVENANCE",
536
+ hasLicense ? "LICENSE_PRESENT" : "LICENSE_MISSING",
537
+ hasScriptsDir ? "EXTERNAL_CAPABILITY" : null,
538
+ hasScriptsDir && !(sourceJson && /data_only|no_auto_execution/i.test(String(sourceJson.runtimePolicy || sourceJson.notes || "")))
539
+ ? "UNSAFE_AUTO_EXECUTION"
540
+ : null,
541
+ ]);
542
+
543
+ const decided = decideGovernance({
544
+ type: "source",
545
+ name: sourceCatalogEntry?.name || sourceJson?.name || entry.name,
546
+ source: relRoot,
547
+ provenance: sourceCatalogEntry
548
+ ? "vendor_skillpack_with_catalog_metadata"
549
+ : sourceJson
550
+ ? "vendor_skillpack_with_local_metadata"
551
+ : "vendor_skillpack_unknown_provenance",
552
+ trustLevel,
553
+ ownerSponsor: ownerSponsor(sourceCatalogEntry?.owner || sourceJson?.owner, sourceCatalogEntry?.name || sourceJson?.name),
554
+ riskDimensions,
555
+ riskLevel: riskLevelFromDimensions(riskDimensions),
556
+ reasonCodes,
557
+ proofRef: sanitizeRelPath(path.join(relRoot, "SOURCE.json")) || relRoot,
558
+ safeNextAction: trustLevel === "trusted"
559
+ ? `Keep ${entry.name} data-only and reviewed before deeper adaptation.`
560
+ : `Add or review SOURCE.json and license metadata for ${entry.name} before trusting it.`,
561
+ });
562
+
563
+ return createInventoryItem({
564
+ id: `source-vendor-${entry.name}`,
565
+ ...decided,
566
+ });
567
+ });
568
+ }
569
+
570
+ function buildConfigSourceItems(cwd, mcpInventories) {
571
+ const riskyConfigs = new Set((mcpInventories.mcpServers || []).map((item) => item.source));
572
+ return CONFIG_SOURCE_CANDIDATES
573
+ .filter((relPath) => fileExists(path.join(cwd, relPath)))
574
+ .map((relPath) => {
575
+ const normalizedPath = sanitizeRelPath(relPath);
576
+ const isMcpConfig = /\.mcp\.json$|mcp\.json$|\.codex\/mcp\.json$|\.cursor\/mcp\.json$/i.test(normalizedPath);
577
+ const riskDimensions = isMcpConfig ? ["read", "path"] : ["read"];
578
+ const reasonCodes = unique([
579
+ "LOCAL_CONFIG_SOURCE",
580
+ isMcpConfig ? "EXTERNAL_CAPABILITY" : null,
581
+ riskyConfigs.has(normalizedPath) ? "MISSING_PROVENANCE" : null,
582
+ ]);
583
+ const trustLevel = isMcpConfig ? "unknown" : "known";
584
+
585
+ const decided = decideGovernance({
586
+ type: "source",
587
+ name: path.basename(normalizedPath),
588
+ source: normalizedPath,
589
+ provenance: isMcpConfig ? "local_mcp_config_reference_only" : "local_repo_config",
590
+ trustLevel,
591
+ ownerSponsor: ownerSponsor(isMcpConfig ? "unknown" : "Avorelo", isMcpConfig ? "workspace operator" : "Avorelo local policy"),
592
+ riskDimensions,
593
+ riskLevel: riskLevelFromDimensions(riskDimensions),
594
+ reasonCodes,
595
+ proofRef: normalizedPath,
596
+ safeNextAction: isMcpConfig
597
+ ? `Review ${normalizedPath} before trusting any MCP server it references.`
598
+ : `Keep ${normalizedPath} local and redacted.`,
599
+ });
600
+
601
+ return createInventoryItem({
602
+ id: `source-config-${sha256Short(normalizedPath)}`,
603
+ ...decided,
604
+ });
605
+ });
606
+ }
607
+
608
+ function buildSourceInventory(cwd, skillRegistry, mcpInventories) {
609
+ return [
610
+ ...buildFirstPartySourceItems(),
611
+ ...buildVendorSourceItems(cwd, skillRegistry),
612
+ ...buildConfigSourceItems(cwd, mcpInventories),
613
+ ];
614
+ }
615
+
616
+ function createReceipt(item) {
617
+ return {
618
+ receiptId: `gwh-receipt-${sha256Short([item.id, item.recommendedDecision, item.source].join("|"))}`,
619
+ createdAt: nowIso(),
620
+ decision: item.recommendedDecision,
621
+ reasonCodes: item.reasonCodes.slice(0, 8),
622
+ itemId: item.id,
623
+ itemType: item.type,
624
+ source: item.source,
625
+ safeNextAction: item.safeNextAction,
626
+ redacted: true,
627
+ };
628
+ }
629
+
630
+ function summarizeDecision(item) {
631
+ return {
632
+ itemId: item.id,
633
+ itemType: item.type,
634
+ name: item.name,
635
+ trustLevel: item.trustLevel,
636
+ ownerSponsor: item.ownerSponsor,
637
+ riskDimensions: item.riskDimensions,
638
+ decision: item.recommendedDecision,
639
+ reasonCodes: item.reasonCodes.slice(0, 8),
640
+ safeNextAction: item.safeNextAction,
641
+ redacted: true,
642
+ };
643
+ }
644
+
645
+ function buildGovernanceSection(allItems, receiptRefs) {
646
+ const decisions = allItems.map(summarizeDecision);
647
+ const exposureReductions = allItems
648
+ .filter((item) => item.recommendedDecision === "auto_limit" || item.recommendedDecision === "warn")
649
+ .slice(0, 12)
650
+ .map((item) => ({
651
+ itemId: item.id,
652
+ reduction: item.recommendedDecision === "auto_limit"
653
+ ? "metadata_only"
654
+ : "review_before_auto_use",
655
+ summary: item.recommendedDecision === "auto_limit"
656
+ ? `Keep ${item.name} limited to redacted local metadata.`
657
+ : `Keep ${item.name} visible but not silently trusted.`,
658
+ redacted: true,
659
+ }));
660
+ const approvalBoundaries = allItems
661
+ .filter((item) => item.recommendedDecision === "approval_required" || item.recommendedDecision === "block")
662
+ .map((item) => ({
663
+ itemId: item.id,
664
+ decision: item.recommendedDecision,
665
+ summary: item.recommendedDecision === "block"
666
+ ? `Blocked by default: ${item.name}.`
667
+ : `Approval required before ${item.name} can expand beyond local redacted review.`,
668
+ reasonCodes: item.reasonCodes.slice(0, 8),
669
+ redacted: true,
670
+ }));
671
+ const receipts = allItems
672
+ .filter((item) => item.recommendedDecision !== "allow")
673
+ .map(createReceipt);
674
+
675
+ receiptRefs
676
+ .filter(Boolean)
677
+ .forEach((ref) => {
678
+ receipts.push({
679
+ receiptId: `gwh-existing-${sha256Short(ref)}`,
680
+ createdAt: nowIso(),
681
+ decision: "observed",
682
+ reasonCodes: ["EXISTING_SAFE_LOCAL_RECEIPT"],
683
+ itemId: `receipt-${sha256Short(ref)}`,
684
+ itemType: "source",
685
+ source: sanitizeRelPath(ref),
686
+ safeNextAction: "Keep existing local receipts redacted and local-first.",
687
+ redacted: true,
688
+ });
689
+ });
690
+
691
+ return {
692
+ decisions,
693
+ exposureReductions,
694
+ approvalBoundaries,
695
+ receipts,
696
+ };
697
+ }
698
+
699
+ function safeNextActionFromSummary(status, summary) {
700
+ if (status === "fail") {
701
+ return "Review blocked local sources first and keep workspace exposure reduced to reviewed metadata only.";
702
+ }
703
+ if (summary.approvalRequired > 0) {
704
+ return "Review approval-required capabilities before expanding local workspace access.";
705
+ }
706
+ if (summary.unknownSources > 0) {
707
+ return "Add provenance and owner metadata for unknown local sources before trusting them.";
708
+ }
709
+ return "Keep workspace exposure limited to reviewed low-risk local sources and metadata-only scans.";
710
+ }
711
+
712
+ function collectReceiptRefs(cwd) {
713
+ const refs = [
714
+ GOVERNANCE_RECEIPT_REL_PATH,
715
+ LATEST_INSTALL_INTAKE_RECEIPT_REL_PATH,
716
+ LEGACY_AI_WORKSPACE_HYGIENE_REL,
717
+ INVENTORY_REL,
718
+ RISK_REL,
719
+ LATEST_REPORT_REL,
720
+ GENERATED_SKILL_REGISTRY_REL_PATH,
721
+ ];
722
+ return refs.filter((relPath) => fileExists(path.join(cwd, relPath)));
723
+ }
724
+
725
+ function readPackageJson(cwd) {
726
+ return safeReadJson(cwd, "package.json", {}) || {};
727
+ }
728
+
729
+ function buildOutcomeReadiness(summary, governance) {
730
+ const found = [];
731
+ const needsAttention = [];
732
+ const savedOrProved = [];
733
+
734
+ if (summary.unknownSources > 0) found.push(`${summary.unknownSources} unknown local source(s) need provenance review.`);
735
+ if (summary.blockedSources > 0) found.push(`${summary.blockedSources} source(s) stay blocked by default.`);
736
+ if (summary.approvalRequired > 0) found.push(`${summary.approvalRequired} approval boundary suggestion(s) were generated.`);
737
+
738
+ if (governance.receipts.length > 0) {
739
+ savedOrProved.push(`${governance.receipts.length} safe local receipt(s) were prepared.`);
740
+ }
741
+ if (summary.approvalRequired > 0) {
742
+ needsAttention.push(`Review ${summary.approvalRequired} approval-required item(s) before broader tool or source access.`);
743
+ }
744
+ if (summary.blockedSources > 0) {
745
+ needsAttention.push(`Keep ${summary.blockedSources} blocked source(s) out of the active AI workspace until provenance is resolved.`);
746
+ }
747
+
748
+ return {
749
+ found,
750
+ fixed: [],
751
+ savedOrProved,
752
+ needsAttention,
753
+ };
754
+ }
755
+
756
+ function buildDogfoodSection(cwd) {
757
+ const pkg = readPackageJson(cwd);
758
+ const ranOnAvorelo = pkg.name === "avorelo";
759
+ return {
760
+ ranOnAvorelo,
761
+ commands: ranOnAvorelo ? DOGFOOD_COMMANDS.slice() : [],
762
+ summary: ranOnAvorelo
763
+ ? "Avorelo can inventory and govern its own local AI workspace without uploading data or executing discovered tools."
764
+ : "Workspace hygiene stays local-first and redacted.",
765
+ };
766
+ }
767
+
768
+ function writeGovernedWorkspaceHygieneReport(cwd, report) {
769
+ ensureCcoDirs(cwd);
770
+ safeWriteJson(cwd, LATEST_REPORT_REL, report);
771
+ return LATEST_REPORT_REL;
772
+ }
773
+
774
+ function buildGovernedWorkspaceHygieneReport(cwd, options = {}) {
775
+ const capabilityItems = buildCapabilityInventory();
776
+ const skillInventory = buildSkillInventory(cwd);
777
+ const mcpInventories = buildMcpInventories(cwd);
778
+ const sourceItems = buildSourceInventory(cwd, skillInventory.registry, mcpInventories);
779
+ const allItems = [
780
+ ...capabilityItems,
781
+ ...skillInventory.items,
782
+ ...mcpInventories.tools,
783
+ ...mcpInventories.mcpServers,
784
+ ...sourceItems,
785
+ ];
786
+ const receiptRefs = collectReceiptRefs(cwd);
787
+ const governance = buildGovernanceSection(allItems, receiptRefs);
788
+ const unknownSources = sourceItems.filter((item) => item.trustLevel === "unknown").length;
789
+ const trustedSources = sourceItems.filter((item) => item.trustLevel === "trusted").length;
790
+ const deferredSources = sourceItems.filter((item) => item.trustLevel === "unknown" && item.recommendedDecision !== "block").length;
791
+ const blockedSources = sourceItems.filter((item) => item.recommendedDecision === "block").length;
792
+ const approvalRequired = governance.decisions.filter((item) => item.decision === "approval_required").length;
793
+ const blockedCount = governance.decisions.filter((item) => item.decision === "block").length;
794
+ const status = blockedCount > 0 ? "fail" : (approvalRequired > 0 || unknownSources > 0 ? "warn" : "pass");
795
+
796
+ const report = {
797
+ contract: CONTRACT,
798
+ schemaVersion: SCHEMA_VERSION,
799
+ generatedAt: nowIso(),
800
+ status,
801
+ redacted: true,
802
+ summary: {
803
+ capabilitiesReviewed: capabilityItems.length,
804
+ toolsReviewed: mcpInventories.tools.length,
805
+ skillsReviewed: skillInventory.items.length,
806
+ mcpServersReviewed: mcpInventories.mcpServers.length,
807
+ unknownSources,
808
+ trustedSources,
809
+ deferredSources,
810
+ blockedSources,
811
+ approvalRequired,
812
+ blockedCount,
813
+ receiptCount: governance.receipts.length,
814
+ safeNextAction: safeNextActionFromSummary(status, {
815
+ unknownSources,
816
+ approvalRequired,
817
+ blockedSources,
818
+ }),
819
+ },
820
+ inventory: {
821
+ capabilities: capabilityItems,
822
+ skills: skillInventory.items,
823
+ tools: mcpInventories.tools,
824
+ mcpServers: mcpInventories.mcpServers,
825
+ sources: sourceItems,
826
+ },
827
+ governance,
828
+ riskModel: RISK_MODEL,
829
+ outcomeReadiness: buildOutcomeReadiness({
830
+ unknownSources,
831
+ blockedSources,
832
+ approvalRequired,
833
+ }, governance),
834
+ dogfood: buildDogfoodSection(cwd),
835
+ };
836
+
837
+ if (options.writeReport !== false) {
838
+ writeGovernedWorkspaceHygieneReport(cwd, report);
839
+ }
840
+
841
+ return {
842
+ report,
843
+ detail: {
844
+ skillRegistry: skillInventory.registry,
845
+ skillHygiene: skillInventory.hygiene,
846
+ mcpInventory: mcpInventories.inventory,
847
+ mcpRisk: mcpInventories.risk,
848
+ receiptRefs,
849
+ },
850
+ };
851
+ }
852
+
853
+ function readLatestGovernedWorkspaceHygieneReport(cwd) {
854
+ return safeReadJson(cwd, LATEST_REPORT_REL, null);
855
+ }
856
+
857
+ function buildGovernedWorkspaceHygieneSurface(cwd, options = {}) {
858
+ const report = readLatestGovernedWorkspaceHygieneReport(cwd)
859
+ || (options.buildIfMissing ? buildGovernedWorkspaceHygieneReport(cwd, { writeReport: false }).report : null);
860
+ if (!report) {
861
+ return {
862
+ status: "not_run",
863
+ showInStatus: true,
864
+ showInDashboard: true,
865
+ reviewedCount: 0,
866
+ unknownSources: 0,
867
+ approvalRequired: 0,
868
+ blockedSources: 0,
869
+ receiptCount: 0,
870
+ nextAction: "Run `avorelo workspace-hygiene --json` to build the first governed workspace report.",
871
+ latestReportPath: null,
872
+ statusLine: "Workspace hygiene: NOT RUN · run `avorelo workspace-hygiene --json`",
873
+ };
874
+ }
875
+
876
+ const statusLine = report.status === "pass"
877
+ ? `Workspace hygiene: PASS · reviewed local capabilities low-risk · receipts=${report.summary.receiptCount || 0}`
878
+ : report.status === "fail"
879
+ ? `Workspace hygiene: FAIL · ${report.summary.blockedSources || 0} blocked source(s) · ${report.summary.approvalRequired || 0} approval boundary suggested`
880
+ : `Workspace hygiene: WARN · ${report.summary.unknownSources || 0} unknown source(s) · ${report.summary.approvalRequired || 0} approval boundary suggested`;
881
+
882
+ return {
883
+ status: report.status,
884
+ showInStatus: true,
885
+ showInDashboard: true,
886
+ reviewedCount: (report.summary.capabilitiesReviewed || 0) + (report.summary.skillsReviewed || 0) + (report.summary.toolsReviewed || 0),
887
+ unknownSources: report.summary.unknownSources || 0,
888
+ approvalRequired: report.summary.approvalRequired || 0,
889
+ blockedSources: report.summary.blockedSources || 0,
890
+ receiptCount: report.summary.receiptCount || 0,
891
+ nextAction: report.summary.safeNextAction,
892
+ latestReportPath: LATEST_REPORT_REL,
893
+ statusLine,
894
+ };
895
+ }
896
+
897
+ function formatGovernedWorkspaceHygieneText(report, options = {}) {
898
+ const lines = [
899
+ "Avorelo Workspace Hygiene",
900
+ `Status: ${String(report.status || "warn").toUpperCase()}`,
901
+ `Reviewed: ${report.summary.capabilitiesReviewed} capabilities, ${report.summary.toolsReviewed} tools, ${report.summary.skillsReviewed} skills, ${report.summary.mcpServersReviewed} MCP servers`,
902
+ `Found: ${report.summary.unknownSources} unknown sources, ${report.summary.approvalRequired} approval boundary suggestions, ${report.summary.blockedSources} blocked sources`,
903
+ `Needs attention: ${(report.outcomeReadiness.needsAttention || [report.summary.safeNextAction]).slice(0, 2).join(" ") || "None."}`,
904
+ `Safe next action: ${report.summary.safeNextAction}`,
905
+ ];
906
+
907
+ if (options.debug) {
908
+ lines.push("");
909
+ lines.push("Inventory detail:");
910
+ lines.push(`- Capabilities: ${report.inventory.capabilities.length}`);
911
+ lines.push(`- Skills: ${report.inventory.skills.length}`);
912
+ lines.push(`- Tools: ${report.inventory.tools.length}`);
913
+ lines.push(`- MCP servers: ${report.inventory.mcpServers.length}`);
914
+ lines.push(`- Sources: ${report.inventory.sources.length}`);
915
+ }
916
+
917
+ lines.push("");
918
+ return lines.join("\n");
919
+ }
920
+
921
+ function buildOutcomeEvidenceWorkspaceSignal(cwd) {
922
+ const report = readLatestGovernedWorkspaceHygieneReport(cwd);
923
+ if (!report) return null;
924
+ return {
925
+ status: report.status,
926
+ unknownSources: report.summary.unknownSources || 0,
927
+ blockedSources: report.summary.blockedSources || 0,
928
+ approvalRequired: report.summary.approvalRequired || 0,
929
+ receiptCount: report.summary.receiptCount || 0,
930
+ safeNextAction: report.summary.safeNextAction || null,
931
+ };
932
+ }
933
+
934
+ module.exports = {
935
+ CONTRACT,
936
+ SCHEMA_VERSION,
937
+ LATEST_REPORT_REL,
938
+ RISK_MODEL,
939
+ DOGFOOD_COMMANDS,
940
+ buildGovernedWorkspaceHygieneReport,
941
+ buildGovernedWorkspaceHygieneSurface,
942
+ readLatestGovernedWorkspaceHygieneReport,
943
+ writeGovernedWorkspaceHygieneReport,
944
+ formatGovernedWorkspaceHygieneText,
945
+ buildOutcomeEvidenceWorkspaceSignal,
946
+ };