avorelo 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +23 -16
- package/README.md +91 -51
- package/bin/avorelo.mjs +7 -0
- package/dist/avorelo.mjs +14337 -0
- package/package.json +106 -120
- package/bin/avorelo +0 -9
- package/scripts/README.md +0 -40
- package/scripts/cco-dashboard.js +0 -252
- package/scripts/cco-status.js +0 -430
- package/scripts/lib/activation/account-state.js +0 -37
- package/scripts/lib/activation/activation-runner.js +0 -546
- package/scripts/lib/activation/activation-self-healing.js +0 -480
- package/scripts/lib/activation/activation-state.js +0 -83
- package/scripts/lib/activation/activation-summary.js +0 -191
- package/scripts/lib/activation/adapters/claude-code.js +0 -77
- package/scripts/lib/activation/adapters/codex-cli.js +0 -52
- package/scripts/lib/activation/adapters/cursor.js +0 -37
- package/scripts/lib/activation/adapters/github-agent.js +0 -39
- package/scripts/lib/activation/adapters/terminal.js +0 -42
- package/scripts/lib/activation/adapters/vscode.js +0 -39
- package/scripts/lib/activation/adapters/windsurf.js +0 -37
- package/scripts/lib/activation/ai-surface-detector.js +0 -151
- package/scripts/lib/activation/connect-account.js +0 -145
- package/scripts/lib/activation/detect-environment.js +0 -75
- package/scripts/lib/activation/detect-hosts.js +0 -62
- package/scripts/lib/activation/format-activation-output.js +0 -109
- package/scripts/lib/activation/next-action.js +0 -43
- package/scripts/lib/activation/repair-engine.js +0 -219
- package/scripts/lib/activation-distribution-readiness.js +0 -507
- package/scripts/lib/adapter-conformance.js +0 -176
- package/scripts/lib/adapter-readiness.js +0 -417
- package/scripts/lib/adapter-safety-boundaries.js +0 -335
- package/scripts/lib/adapter-technical-readiness-gate.js +0 -205
- package/scripts/lib/agent-access-governance.js +0 -455
- package/scripts/lib/agent-enforcement.js +0 -765
- package/scripts/lib/agent-policy-profile.js +0 -210
- package/scripts/lib/agent-security/action-evaluator.js +0 -507
- package/scripts/lib/agent-security/adapter-registry.js +0 -98
- package/scripts/lib/agent-security/auto-policy.js +0 -139
- package/scripts/lib/agent-security/bounded-scan.js +0 -93
- package/scripts/lib/agent-security/enforcement-adapter.js +0 -174
- package/scripts/lib/agent-security/enforcement-engine.js +0 -1129
- package/scripts/lib/agent-security/file-write-adapter.js +0 -183
- package/scripts/lib/agent-security/file-write-rules.js +0 -178
- package/scripts/lib/agent-security/index.js +0 -3342
- package/scripts/lib/agent-security/instruction-risk.js +0 -181
- package/scripts/lib/agent-security/mcp-action-adapter.js +0 -185
- package/scripts/lib/agent-security/mcp-action-rules.js +0 -184
- package/scripts/lib/agent-security/package-action-adapter.js +0 -175
- package/scripts/lib/agent-security/package-action-rules.js +0 -233
- package/scripts/lib/agent-security/performance.js +0 -148
- package/scripts/lib/agent-security/permission-minimizer.js +0 -403
- package/scripts/lib/agent-security/scan-cache.js +0 -74
- package/scripts/lib/agent-security/source-trust.js +0 -146
- package/scripts/lib/ai-install-prompt.js +0 -288
- package/scripts/lib/ai-workspace-hygiene.js +0 -1499
- package/scripts/lib/alpha-activation.js +0 -520
- package/scripts/lib/alpha-feedback.js +0 -263
- package/scripts/lib/alpha-readiness-gate.js +0 -332
- package/scripts/lib/anti-gaming.js +0 -169
- package/scripts/lib/artifact-health.js +0 -431
- package/scripts/lib/attribution.js +0 -180
- package/scripts/lib/audit.js +0 -289
- package/scripts/lib/avorelo-skill-registry.js +0 -810
- package/scripts/lib/batch-jobs.js +0 -71
- package/scripts/lib/brain-pack.js +0 -578
- package/scripts/lib/brand-boundary.js +0 -424
- package/scripts/lib/brand.js +0 -74
- package/scripts/lib/browser-capability.js +0 -1048
- package/scripts/lib/browser-proof-preflight.js +0 -321
- package/scripts/lib/cache-readiness.js +0 -187
- package/scripts/lib/canonical-reentry.js +0 -162
- package/scripts/lib/capability-packs.js +0 -314
- package/scripts/lib/capability-recommender.js +0 -512
- package/scripts/lib/capability-registry.js +0 -1059
- package/scripts/lib/carry-forward-surfacing.js +0 -194
- package/scripts/lib/ccusage-adapter.js +0 -188
- package/scripts/lib/company-loop.js +0 -1149
- package/scripts/lib/config.js +0 -637
- package/scripts/lib/context-acquisition-plan.js +0 -287
- package/scripts/lib/context-budget-guard.js +0 -170
- package/scripts/lib/context-budget-scanner.js +0 -257
- package/scripts/lib/context-optimizer.js +0 -715
- package/scripts/lib/context-reduction-plan.js +0 -178
- package/scripts/lib/context-safety.js +0 -88
- package/scripts/lib/context-savings-engine.js +0 -158
- package/scripts/lib/cost-evidence.js +0 -254
- package/scripts/lib/cross-host-install-plan.js +0 -308
- package/scripts/lib/cross-host-install-readiness.js +0 -237
- package/scripts/lib/cross-host-value-flow.js +0 -268
- package/scripts/lib/dashboard.js +0 -900
- package/scripts/lib/design-partner-feedback.js +0 -346
- package/scripts/lib/entitlements.js +0 -100
- package/scripts/lib/execution-packet.js +0 -559
- package/scripts/lib/experimentation-events.js +0 -547
- package/scripts/lib/external-capability-compliance.js +0 -107
- package/scripts/lib/external-user-simulation.js +0 -166
- package/scripts/lib/failure-recovery-readiness.js +0 -81
- package/scripts/lib/failure-recovery.js +0 -419
- package/scripts/lib/feedback-intelligence.js +0 -537
- package/scripts/lib/feedback-signals.js +0 -205
- package/scripts/lib/file-integrity.js +0 -68
- package/scripts/lib/fsx.js +0 -127
- package/scripts/lib/full-readiness-gate.js +0 -451
- package/scripts/lib/guidance-builder.js +0 -174
- package/scripts/lib/hook-apply.js +0 -1019
- package/scripts/lib/hook-baseline.js +0 -310
- package/scripts/lib/hook-config-preview.js +0 -275
- package/scripts/lib/hook-contracts.js +0 -290
- package/scripts/lib/hook-safety-boundary-readiness.js +0 -80
- package/scripts/lib/host-capability-matrix.js +0 -351
- package/scripts/lib/host-support-context.js +0 -254
- package/scripts/lib/http-hook-action.js +0 -538
- package/scripts/lib/install-ai-readiness.js +0 -84
- package/scripts/lib/install-intake-risk.js +0 -1037
- package/scripts/lib/install-journey-intelligence.js +0 -329
- package/scripts/lib/intervention-guidance.js +0 -57
- package/scripts/lib/known-limitations.js +0 -115
- package/scripts/lib/l8-path-truth.js +0 -146
- package/scripts/lib/launch-hardening-gate.js +0 -436
- package/scripts/lib/launch-readiness.js +0 -628
- package/scripts/lib/learning-memory.js +0 -686
- package/scripts/lib/lifecycle-hooks.js +0 -802
- package/scripts/lib/local-package-smoke.js +0 -423
- package/scripts/lib/local-pricing.js +0 -299
- package/scripts/lib/mcp-enforcement.js +0 -311
- package/scripts/lib/mcp-least-privilege-policy.js +0 -303
- package/scripts/lib/mcp-tool-inventory.js +0 -388
- package/scripts/lib/mcp-tool-risk.js +0 -0
- package/scripts/lib/memory.js +0 -335
- package/scripts/lib/metrics.js +0 -699
- package/scripts/lib/micro-proof.js +0 -133
- package/scripts/lib/next-run-context.js +0 -436
- package/scripts/lib/operating-value.js +0 -1648
- package/scripts/lib/optimization-v3.js +0 -122
- package/scripts/lib/orchestration/adapters/_shared.js +0 -49
- package/scripts/lib/orchestration/adapters/aider.js +0 -18
- package/scripts/lib/orchestration/adapters/claude-code.js +0 -35
- package/scripts/lib/orchestration/adapters/codex.js +0 -35
- package/scripts/lib/orchestration/adapters/gemini-cli.js +0 -18
- package/scripts/lib/orchestration/adapters/git.js +0 -25
- package/scripts/lib/orchestration/adapters/index.js +0 -31
- package/scripts/lib/orchestration/adapters/lm-studio.js +0 -18
- package/scripts/lib/orchestration/adapters/ollama.js +0 -18
- package/scripts/lib/orchestration/adapters/opencode.js +0 -18
- package/scripts/lib/orchestration/adapters/openrouter.js +0 -18
- package/scripts/lib/orchestration/adapters/test-runner.js +0 -25
- package/scripts/lib/orchestration/cli.js +0 -438
- package/scripts/lib/orchestration/execution-manager.js +0 -279
- package/scripts/lib/orchestration/handoff.js +0 -314
- package/scripts/lib/orchestration/index.js +0 -456
- package/scripts/lib/orchestration/inventory.js +0 -47
- package/scripts/lib/orchestration/model-discovery.js +0 -498
- package/scripts/lib/orchestration/model-profiler.js +0 -170
- package/scripts/lib/orchestration/model-profiles.js +0 -252
- package/scripts/lib/orchestration/model-refresh-policy.js +0 -72
- package/scripts/lib/orchestration/proof-writer.js +0 -349
- package/scripts/lib/orchestration/provider-discovery/aider.js +0 -49
- package/scripts/lib/orchestration/provider-discovery/claude-code.js +0 -56
- package/scripts/lib/orchestration/provider-discovery/codex.js +0 -49
- package/scripts/lib/orchestration/provider-discovery/common.js +0 -186
- package/scripts/lib/orchestration/provider-discovery/gemini.js +0 -106
- package/scripts/lib/orchestration/provider-discovery/lm-studio.js +0 -118
- package/scripts/lib/orchestration/provider-discovery/models-dev.js +0 -12
- package/scripts/lib/orchestration/provider-discovery/ollama.js +0 -100
- package/scripts/lib/orchestration/provider-discovery/opencode.js +0 -47
- package/scripts/lib/orchestration/provider-discovery/openrouter.js +0 -44
- package/scripts/lib/orchestration/risk-classifier.js +0 -130
- package/scripts/lib/orchestration/routing-policy.js +0 -486
- package/scripts/lib/orchestration/settings.js +0 -112
- package/scripts/lib/orchestration/state.js +0 -165
- package/scripts/lib/orchestration/verification-manager.js +0 -138
- package/scripts/lib/output-profiles.js +0 -146
- package/scripts/lib/package-content-audit.js +0 -368
- package/scripts/lib/package-runtime.js +0 -278
- package/scripts/lib/plan-surface.js +0 -53
- package/scripts/lib/plans.js +0 -2318
- package/scripts/lib/policy-provider.js +0 -27
- package/scripts/lib/prelaunch-activation-readiness.js +0 -409
- package/scripts/lib/prelaunch-evidence-store.js +0 -816
- package/scripts/lib/prelaunch-intelligence.js +0 -869
- package/scripts/lib/pricing-experiment.js +0 -118
- package/scripts/lib/pro-moment-events.js +0 -77
- package/scripts/lib/pro-moment-state.js +0 -227
- package/scripts/lib/pro-moments.js +0 -1216
- package/scripts/lib/product-learning-events.js +0 -629
- package/scripts/lib/project-profile.js +0 -555
- package/scripts/lib/prompt-compiler.js +0 -280
- package/scripts/lib/prompt-lint.js +0 -32
- package/scripts/lib/prompt-suggestions.js +0 -52
- package/scripts/lib/proof-canonical.js +0 -398
- package/scripts/lib/proof-drilldown.js +0 -383
- package/scripts/lib/proof-events.js +0 -342
- package/scripts/lib/proof-history.js +0 -243
- package/scripts/lib/proof-metrics.js +0 -296
- package/scripts/lib/proof-outcome-evidence.js +0 -134
- package/scripts/lib/proof-receipt.js +0 -335
- package/scripts/lib/proof-record.js +0 -461
- package/scripts/lib/public-activation-distribution-gate.js +0 -258
- package/scripts/lib/public-cli.js +0 -3891
- package/scripts/lib/public-distribution-truth.js +0 -211
- package/scripts/lib/public-install-claim-checker.js +0 -294
- package/scripts/lib/publish-provenance-readiness.js +0 -283
- package/scripts/lib/readiness-delta.js +0 -218
- package/scripts/lib/readiness-evidence-closure.js +0 -196
- package/scripts/lib/reentry-memory-capture.js +0 -241
- package/scripts/lib/reentry-memory-retrieval.js +0 -302
- package/scripts/lib/reentry-memory-status.js +0 -146
- package/scripts/lib/reentry-memory-store.js +0 -178
- package/scripts/lib/reentry-state.js +0 -66
- package/scripts/lib/release-candidate-bundle.js +0 -166
- package/scripts/lib/remediation.js +0 -81
- package/scripts/lib/repo-map.js +0 -391
- package/scripts/lib/run-improvements-lifecycle.js +0 -330
- package/scripts/lib/run-improvements.js +0 -789
- package/scripts/lib/runtime-decision-policy.js +0 -387
- package/scripts/lib/safe-path-engine.js +0 -705
- package/scripts/lib/safe-run-controller.js +0 -887
- package/scripts/lib/score.js +0 -262
- package/scripts/lib/seamless-enforcement.js +0 -329
- package/scripts/lib/seamless-outcome.js +0 -689
- package/scripts/lib/seamless-reality-gate.js +0 -5043
- package/scripts/lib/security-risk-classifier.js +0 -511
- package/scripts/lib/security-scan.js +0 -384
- package/scripts/lib/session-context-optimizer.js +0 -1211
- package/scripts/lib/session-timing.js +0 -315
- package/scripts/lib/skill-hygiene.js +0 -805
- package/scripts/lib/skill-packs.js +0 -161
- package/scripts/lib/skills-operating-layer.js +0 -580
- package/scripts/lib/smart-work-routing.js +0 -768
- package/scripts/lib/source-catalog.js +0 -700
- package/scripts/lib/status-value-summary.js +0 -32
- package/scripts/lib/support-bundle.js +0 -578
- package/scripts/lib/task-continuation.js +0 -440
- package/scripts/lib/test-helpers.js +0 -15
- package/scripts/lib/tier.js +0 -38
- package/scripts/lib/token-context-quality-gate.js +0 -370
- package/scripts/lib/token-cost-capture.js +0 -187
- package/scripts/lib/token-cost-intelligence.js +0 -358
- package/scripts/lib/token-efficiency-evidence.js +0 -213
- package/scripts/lib/token-evidence.js +0 -699
- package/scripts/lib/tokenish.js +0 -17
- package/scripts/lib/tool-output-sandbox.js +0 -304
- package/scripts/lib/trust-audit.js +0 -136
- package/scripts/lib/unified-events.js +0 -396
- package/scripts/lib/upgrade-interruption-recovery.js +0 -407
- package/scripts/lib/usage-ledger.js +0 -201
- package/scripts/lib/value-ledger.js +0 -130
- package/scripts/lib/value-proof-calibration.js +0 -531
- package/scripts/lib/visual-qa.js +0 -231
- package/scripts/lib/voice-alpha.js +0 -29
- package/scripts/lib/work-aware-orchestration.js +0 -976
- package/scripts/lib/work-control-receipts.js +0 -577
- package/scripts/lib/work-ledger.js +0 -1123
- package/scripts/lib/work-panel-preview.js +0 -352
- package/scripts/lib/workflow-discipline.js +0 -280
- package/scripts/lib/workflow-signals.js +0 -419
- package/scripts/lib/workspace-map.js +0 -281
- package/scripts/lib/workspace-registry.js +0 -1367
- package/scripts/lib/workspace-resolver.js +0 -480
|
@@ -1,512 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Avorelo Capability Recommender
|
|
5
|
-
*
|
|
6
|
-
* Deterministic, local-first recommendation logic.
|
|
7
|
-
* Takes workflow signals (from workflow-signals.js) and local file probes,
|
|
8
|
-
* returns the recommended capability pack and next action.
|
|
9
|
-
*
|
|
10
|
-
* No AI/LLM calls. No external requests. All logic is deterministic and testable.
|
|
11
|
-
*
|
|
12
|
-
* Output:
|
|
13
|
-
* { recommendedPack, reason, status, entitlement, riskLevel, nextAction,
|
|
14
|
-
* evidencePath, additionalPacks }
|
|
15
|
-
*/
|
|
16
|
-
|
|
17
|
-
const fs = require("fs");
|
|
18
|
-
const path = require("path");
|
|
19
|
-
const { CAPABILITY_PACKS, getPack } = require("./capability-packs");
|
|
20
|
-
|
|
21
|
-
// ─── Local file probes ────────────────────────────────────────────────────────
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Probe local files to detect frontend project signals.
|
|
25
|
-
* Returns { isFrontend, hasPlaywright, hasReact, hasVue, hasNext }
|
|
26
|
-
*/
|
|
27
|
-
function probeFrontendSignals(cwd) {
|
|
28
|
-
const base = cwd || process.cwd();
|
|
29
|
-
let isFrontend = false;
|
|
30
|
-
let hasPlaywright = false;
|
|
31
|
-
let hasReact = false;
|
|
32
|
-
let hasVue = false;
|
|
33
|
-
let hasNext = false;
|
|
34
|
-
|
|
35
|
-
// Check playwright config files
|
|
36
|
-
const playwrightFiles = [
|
|
37
|
-
"playwright.config.ts",
|
|
38
|
-
"playwright.config.js",
|
|
39
|
-
"e2e-tests/playwright.config.ts",
|
|
40
|
-
"e2e-tests/playwright.landing-qa.config.ts",
|
|
41
|
-
];
|
|
42
|
-
for (const rel of playwrightFiles) {
|
|
43
|
-
if (fs.existsSync(path.join(base, rel))) {
|
|
44
|
-
hasPlaywright = true;
|
|
45
|
-
isFrontend = true;
|
|
46
|
-
break;
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
// Check package.json for frontend frameworks
|
|
51
|
-
try {
|
|
52
|
-
const pkg = JSON.parse(fs.readFileSync(path.join(base, "package.json"), "utf8"));
|
|
53
|
-
const allDeps = {
|
|
54
|
-
...(pkg.dependencies || {}),
|
|
55
|
-
...(pkg.devDependencies || {}),
|
|
56
|
-
};
|
|
57
|
-
if (allDeps["react"] || allDeps["react-dom"]) { hasReact = true; isFrontend = true; }
|
|
58
|
-
if (allDeps["vue"]) { hasVue = true; isFrontend = true; }
|
|
59
|
-
if (allDeps["next"]) { hasNext = true; isFrontend = true; }
|
|
60
|
-
if (allDeps["vite"] || allDeps["@vitejs/plugin-react"]) { isFrontend = true; }
|
|
61
|
-
if (allDeps["svelte"] || allDeps["@sveltejs/kit"]) { isFrontend = true; }
|
|
62
|
-
} catch {
|
|
63
|
-
// No package.json or parse error — not a frontend signal
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
// Check apps/public-web (Avorelo's own pattern)
|
|
67
|
-
if (fs.existsSync(path.join(base, "apps/public-web"))) {
|
|
68
|
-
isFrontend = true;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
return { isFrontend, hasPlaywright, hasReact, hasVue, hasNext };
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* Probe activation state — is Avorelo activated in this repo?
|
|
76
|
-
*/
|
|
77
|
-
function probeActivationState(cwd) {
|
|
78
|
-
const base = cwd || process.cwd();
|
|
79
|
-
const activationPaths = [
|
|
80
|
-
".claude/cco/state/activation.json",
|
|
81
|
-
".claude/cco/config.json",
|
|
82
|
-
".claude/cco/state",
|
|
83
|
-
];
|
|
84
|
-
for (const rel of activationPaths) {
|
|
85
|
-
if (fs.existsSync(path.join(base, rel))) {
|
|
86
|
-
return { activated: true };
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
return { activated: false };
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
* Probe for reentry memory / carry-forward state.
|
|
94
|
-
*/
|
|
95
|
-
function probeReentryState(cwd) {
|
|
96
|
-
const base = cwd || process.cwd();
|
|
97
|
-
const reentryPaths = [
|
|
98
|
-
".claude/cco/state/reentry-memory.jsonl",
|
|
99
|
-
".claude/cco/state/reentry-carry-forward.json",
|
|
100
|
-
".claude/cco/state/reentry-state.json",
|
|
101
|
-
];
|
|
102
|
-
for (const rel of reentryPaths) {
|
|
103
|
-
try {
|
|
104
|
-
const stat = fs.statSync(path.join(base, rel));
|
|
105
|
-
if (stat.size > 0) return { hasReentry: true, path: rel };
|
|
106
|
-
} catch {
|
|
107
|
-
// file missing
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
return { hasReentry: false, path: null };
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
function probeWorkspaceSignals(cwd) {
|
|
114
|
-
const base = cwd || process.cwd();
|
|
115
|
-
let docsCount = 0;
|
|
116
|
-
let testsCount = 0;
|
|
117
|
-
let hasSourceCatalog = false;
|
|
118
|
-
let hasLocalSkills = false;
|
|
119
|
-
let hasPackageManifest = false;
|
|
120
|
-
try {
|
|
121
|
-
docsCount = fs.existsSync(path.join(base, "docs")) ? fs.readdirSync(path.join(base, "docs")).length : 0;
|
|
122
|
-
testsCount = fs.existsSync(path.join(base, "tests")) ? fs.readdirSync(path.join(base, "tests")).length : 0;
|
|
123
|
-
hasSourceCatalog = fs.existsSync(path.join(base, "scripts", "lib", "source-catalog.js"));
|
|
124
|
-
hasLocalSkills =
|
|
125
|
-
fs.existsSync(path.join(base, "skills", "avorelo")) ||
|
|
126
|
-
fs.existsSync(path.join(base, "vendor", "skillpacks"));
|
|
127
|
-
hasPackageManifest = fs.existsSync(path.join(base, "package.json"));
|
|
128
|
-
} catch {}
|
|
129
|
-
return {
|
|
130
|
-
largeRepo: docsCount + testsCount >= 20,
|
|
131
|
-
hasSourceCatalog,
|
|
132
|
-
hasLocalSkills,
|
|
133
|
-
hasPackageManifest,
|
|
134
|
-
};
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
function probeSafePathState(cwd) {
|
|
138
|
-
const base = cwd || process.cwd();
|
|
139
|
-
const relPath = ".claude/cco/security/safe-path/latest-receipt.json";
|
|
140
|
-
const absPath = path.join(base, relPath);
|
|
141
|
-
if (!fs.existsSync(absPath)) {
|
|
142
|
-
return { hasSafePath: false, latestReceiptPath: null };
|
|
143
|
-
}
|
|
144
|
-
return { hasSafePath: true, latestReceiptPath: relPath };
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
function probeInstallIntakeState(cwd) {
|
|
148
|
-
const base = cwd || process.cwd();
|
|
149
|
-
const relPath = ".claude/cco/security/install-intake/latest-receipt.json";
|
|
150
|
-
const absPath = path.join(base, relPath);
|
|
151
|
-
if (!fs.existsSync(absPath)) {
|
|
152
|
-
return { hasInstallIntake: false, latestReceiptPath: null };
|
|
153
|
-
}
|
|
154
|
-
return { hasInstallIntake: true, latestReceiptPath: relPath };
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
/**
|
|
158
|
-
* Probe for latest evidence / proof receipts.
|
|
159
|
-
*/
|
|
160
|
-
function probeEvidencePath(cwd) {
|
|
161
|
-
const base = cwd || process.cwd();
|
|
162
|
-
const receiptsDir = path.join(base, ".claude/cco/receipts");
|
|
163
|
-
try {
|
|
164
|
-
const files = fs.readdirSync(receiptsDir).filter((f) => f.endsWith(".json"));
|
|
165
|
-
if (files.length > 0) {
|
|
166
|
-
const sorted = files
|
|
167
|
-
.map((f) => ({ f, mtime: fs.statSync(path.join(receiptsDir, f)).mtimeMs }))
|
|
168
|
-
.sort((a, b) => b.mtime - a.mtime);
|
|
169
|
-
return path.posix.join(".claude/cco/receipts", sorted[0].f);
|
|
170
|
-
}
|
|
171
|
-
} catch {
|
|
172
|
-
// no receipts dir
|
|
173
|
-
}
|
|
174
|
-
return null;
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
// ─── Signal → Pack mapping ─────────────────────────────────────────────────────
|
|
178
|
-
|
|
179
|
-
/**
|
|
180
|
-
* Priority-ordered recommendation rules.
|
|
181
|
-
* Each rule is { test(signals, probes) → boolean, packId, reason, nextAction }.
|
|
182
|
-
* First matching rule wins for recommendedPack.
|
|
183
|
-
* All matching rules contribute to additionalPacks.
|
|
184
|
-
*/
|
|
185
|
-
const RECOMMENDATION_RULES = [
|
|
186
|
-
{
|
|
187
|
-
packId: "install_intake_risk",
|
|
188
|
-
reason: "Local intake visibility is relevant because this workspace has package, source, or skill surfaces that should be reviewed before runtime trust.",
|
|
189
|
-
nextAction: "Run `avorelo intake --json` to scan local intake items, review unknown or deferred sources, and capture a compact intake receipt.",
|
|
190
|
-
test: (_signals, probes) =>
|
|
191
|
-
probes.installIntake?.hasInstallIntake === true ||
|
|
192
|
-
probes.workspace?.hasPackageManifest === true,
|
|
193
|
-
},
|
|
194
|
-
{
|
|
195
|
-
packId: "safe_path_engine",
|
|
196
|
-
reason: "Guard and governance signals suggest reduced-scope Safe Path recommendations are relevant here.",
|
|
197
|
-
nextAction: "Run `avorelo guard --action <type> --target <target> --json` to see a bounded Safe Path with approval boundaries and safer alternatives.",
|
|
198
|
-
test: (signals, probes) =>
|
|
199
|
-
probes.safePath.hasSafePath === true ||
|
|
200
|
-
signals.agentSecurityState === "approve" ||
|
|
201
|
-
signals.agentSecurityState === "enforce" ||
|
|
202
|
-
Number(signals.riskyIntercepts || 0) > 0,
|
|
203
|
-
},
|
|
204
|
-
{
|
|
205
|
-
packId: "agent_security",
|
|
206
|
-
reason: "High-risk signals or risky agent intercepts detected in this repo.",
|
|
207
|
-
nextAction: "Run `avorelo status` to review security findings, then run `avorelo audit` to resolve the top active finding.",
|
|
208
|
-
test: (signals) =>
|
|
209
|
-
signals.riskLevel === "high" ||
|
|
210
|
-
Number(signals.riskyIntercepts || 0) > 0 ||
|
|
211
|
-
Number(signals.trustAlerts || 0) > 0 ||
|
|
212
|
-
signals.agentSecurityState === "enforce" ||
|
|
213
|
-
signals.agentSecurityState === "approve",
|
|
214
|
-
},
|
|
215
|
-
{
|
|
216
|
-
packId: "release_readiness",
|
|
217
|
-
reason: "Staged changes and validation evidence suggest release readiness is relevant.",
|
|
218
|
-
nextAction: "Run `avorelo status` to review proof summary, then address remaining gaps before shipping.",
|
|
219
|
-
test: (signals) =>
|
|
220
|
-
signals.hasStagedChanges === true &&
|
|
221
|
-
(signals.validationState === "passed" || signals.validationState === "partial"),
|
|
222
|
-
},
|
|
223
|
-
{
|
|
224
|
-
packId: "source_backed_skills",
|
|
225
|
-
reason: "Reviewed skill sources and deterministic skill routing are available in this workspace.",
|
|
226
|
-
nextAction: "Run `avorelo skills route --task \"<task>\"` to select a reviewed skill path before broad work.",
|
|
227
|
-
test: (_signals, probes) =>
|
|
228
|
-
probes.workspace.hasSourceCatalog === true && probes.workspace.hasLocalSkills === true,
|
|
229
|
-
},
|
|
230
|
-
{
|
|
231
|
-
packId: "workspace_navigation",
|
|
232
|
-
reason: "Repo navigation and context reduction look relevant for this workspace.",
|
|
233
|
-
nextAction: "Run `avorelo workspace-map --json` to generate compact navigation context before broad scans.",
|
|
234
|
-
test: (signals, probes) =>
|
|
235
|
-
signals.contextPressure === "warn" ||
|
|
236
|
-
signals.contextPressure === "critical" ||
|
|
237
|
-
probes.reentry.hasReentry === true ||
|
|
238
|
-
probes.workspace.largeRepo === true,
|
|
239
|
-
},
|
|
240
|
-
{
|
|
241
|
-
packId: "workflow_efficiency",
|
|
242
|
-
reason: "Context pressure or reentry state signals that workflow efficiency is relevant.",
|
|
243
|
-
nextAction: "Run `avorelo status` to see context budget, carry-forward state, and next actions.",
|
|
244
|
-
test: (signals, probes) =>
|
|
245
|
-
signals.contextPressure === "critical" ||
|
|
246
|
-
signals.contextPressure === "warn" ||
|
|
247
|
-
probes.reentry.hasReentry === true ||
|
|
248
|
-
signals.reentryState === "available",
|
|
249
|
-
},
|
|
250
|
-
{
|
|
251
|
-
packId: "frontend_readiness",
|
|
252
|
-
reason: "Frontend project detected — Visual QA and browser readiness checks are available.",
|
|
253
|
-
nextAction: "Run `avorelo visual-qa --dry-run` to check Visual QA availability, or `avorelo capabilities --pack frontend_readiness` for details.",
|
|
254
|
-
test: (_signals, probes) =>
|
|
255
|
-
probes.frontend.isFrontend === true,
|
|
256
|
-
},
|
|
257
|
-
{
|
|
258
|
-
packId: "agent_readiness",
|
|
259
|
-
reason: "No activation state found — start with Agent Readiness to get set up safely.",
|
|
260
|
-
nextAction: "Run `avorelo activate` to set up Avorelo in this repo, then `avorelo doctor` to check readiness.",
|
|
261
|
-
test: (_signals, probes) =>
|
|
262
|
-
probes.activation.activated === false,
|
|
263
|
-
},
|
|
264
|
-
];
|
|
265
|
-
|
|
266
|
-
/** Fallback when no rule matches */
|
|
267
|
-
const FALLBACK = {
|
|
268
|
-
packId: "agent_readiness",
|
|
269
|
-
reason: "No specific signals detected — Agent Readiness is the recommended starting point.",
|
|
270
|
-
nextAction: "Run `avorelo status` to see current state, or `avorelo doctor` to check setup.",
|
|
271
|
-
};
|
|
272
|
-
|
|
273
|
-
// ─── Main recommender ──────────────────────────────────────────────────────────
|
|
274
|
-
|
|
275
|
-
/**
|
|
276
|
-
* Recommend capability packs based on deterministic signals.
|
|
277
|
-
*
|
|
278
|
-
* @param {object} options
|
|
279
|
-
* @param {string} options.cwd - working directory
|
|
280
|
-
* @param {object} options.signals - pre-built workflow signals (from workflow-signals.js)
|
|
281
|
-
* @param {object} options.probes - pre-built local probes (optional, for testing)
|
|
282
|
-
* @param {string} options.plan - 'free' | 'pro'
|
|
283
|
-
* @returns {object} recommendation
|
|
284
|
-
*/
|
|
285
|
-
function recommendCapabilities(options = {}) {
|
|
286
|
-
const cwd = options.cwd || process.cwd();
|
|
287
|
-
const signals = options.signals || {};
|
|
288
|
-
const plan = String(options.plan || "free").toLowerCase();
|
|
289
|
-
|
|
290
|
-
// Build or use probes
|
|
291
|
-
const probes = options.probes || {
|
|
292
|
-
frontend: probeFrontendSignals(cwd),
|
|
293
|
-
activation: probeActivationState(cwd),
|
|
294
|
-
reentry: probeReentryState(cwd),
|
|
295
|
-
workspace: probeWorkspaceSignals(cwd),
|
|
296
|
-
safePath: probeSafePathState(cwd),
|
|
297
|
-
installIntake: probeInstallIntakeState(cwd),
|
|
298
|
-
};
|
|
299
|
-
|
|
300
|
-
// Evaluate all rules — first match = recommended, all matches = additional
|
|
301
|
-
let recommendedRule = null;
|
|
302
|
-
const additionalPackIds = [];
|
|
303
|
-
|
|
304
|
-
for (const rule of RECOMMENDATION_RULES) {
|
|
305
|
-
let matched = false;
|
|
306
|
-
try {
|
|
307
|
-
matched = rule.test(signals, probes);
|
|
308
|
-
} catch {
|
|
309
|
-
matched = false;
|
|
310
|
-
}
|
|
311
|
-
if (matched) {
|
|
312
|
-
if (!recommendedRule) {
|
|
313
|
-
recommendedRule = rule;
|
|
314
|
-
} else if (rule.packId !== recommendedRule.packId) {
|
|
315
|
-
additionalPackIds.push(rule.packId);
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
// Use fallback if nothing matched
|
|
321
|
-
const winner = recommendedRule || FALLBACK;
|
|
322
|
-
const recommendedPack = getPack(winner.packId);
|
|
323
|
-
|
|
324
|
-
const additionalPacks = [...new Set(additionalPackIds)]
|
|
325
|
-
.filter((id) => id !== winner.packId)
|
|
326
|
-
.map((id) => getPack(id))
|
|
327
|
-
.filter(Boolean)
|
|
328
|
-
.slice(0, 3);
|
|
329
|
-
|
|
330
|
-
// Determine entitlement
|
|
331
|
-
const packEntitlement = recommendedPack?.defaultEntitlement || "free";
|
|
332
|
-
const isGated = packEntitlement === "pro" && plan === "free";
|
|
333
|
-
|
|
334
|
-
// Determine status
|
|
335
|
-
let status = "available";
|
|
336
|
-
if (isGated) status = "gated";
|
|
337
|
-
else if (!probes.activation.activated && winner.packId !== "agent_readiness") status = "suggested";
|
|
338
|
-
|
|
339
|
-
// Evidence path
|
|
340
|
-
const evidencePath = probeEvidencePath(cwd);
|
|
341
|
-
|
|
342
|
-
return {
|
|
343
|
-
recommendedPack: recommendedPack
|
|
344
|
-
? {
|
|
345
|
-
id: recommendedPack.id,
|
|
346
|
-
name: recommendedPack.name,
|
|
347
|
-
description: recommendedPack.description,
|
|
348
|
-
userFacingCopy: recommendedPack.userFacingCopy,
|
|
349
|
-
statusCopy: recommendedPack.statusCopy,
|
|
350
|
-
dashboardCopy: recommendedPack.dashboardCopy,
|
|
351
|
-
}
|
|
352
|
-
: null,
|
|
353
|
-
reason: winner.reason,
|
|
354
|
-
status,
|
|
355
|
-
entitlement: packEntitlement,
|
|
356
|
-
riskLevel: signals.riskLevel || "low",
|
|
357
|
-
nextAction: winner.nextAction,
|
|
358
|
-
evidencePath,
|
|
359
|
-
additionalPacks: additionalPacks.map((p) => ({
|
|
360
|
-
id: p.id,
|
|
361
|
-
name: p.name,
|
|
362
|
-
userFacingCopy: p.userFacingCopy,
|
|
363
|
-
})),
|
|
364
|
-
signals: {
|
|
365
|
-
riskLevel: signals.riskLevel || "low",
|
|
366
|
-
contextPressure: signals.contextPressure || "unknown",
|
|
367
|
-
reentryState: signals.reentryState || (probes.reentry.hasReentry ? "available" : "missing"),
|
|
368
|
-
hasStagedChanges: signals.hasStagedChanges || false,
|
|
369
|
-
validationState: signals.validationState || "missing",
|
|
370
|
-
frontendDetected: probes.frontend.isFrontend || false,
|
|
371
|
-
activated: probes.activation.activated,
|
|
372
|
-
largeRepo: probes.workspace.largeRepo || false,
|
|
373
|
-
},
|
|
374
|
-
};
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
/**
|
|
378
|
-
* Build a compact capability layer surface for dashboard/status.
|
|
379
|
-
* Safe to call from dashboard.js — fails open with null on any error.
|
|
380
|
-
*/
|
|
381
|
-
function buildCapabilityLayerSurface(cwd, config, prebuiltSignals) {
|
|
382
|
-
try {
|
|
383
|
-
const plan = config?.tier || "free";
|
|
384
|
-
let signals = prebuiltSignals || {};
|
|
385
|
-
const probes = {
|
|
386
|
-
frontend: probeFrontendSignals(cwd),
|
|
387
|
-
activation: probeActivationState(cwd),
|
|
388
|
-
reentry: probeReentryState(cwd),
|
|
389
|
-
workspace: probeWorkspaceSignals(cwd),
|
|
390
|
-
safePath: probeSafePathState(cwd),
|
|
391
|
-
installIntake: probeInstallIntakeState(cwd),
|
|
392
|
-
};
|
|
393
|
-
|
|
394
|
-
// If no pre-built signals, try to collect them
|
|
395
|
-
if (!prebuiltSignals) {
|
|
396
|
-
try {
|
|
397
|
-
const { collectWorkflowSignals } = require("./workflow-signals");
|
|
398
|
-
signals = collectWorkflowSignals({ cwd });
|
|
399
|
-
} catch {
|
|
400
|
-
signals = {};
|
|
401
|
-
}
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
// Merge in agent security surface data if available
|
|
405
|
-
try {
|
|
406
|
-
const { buildAgentSecuritySurface } = require("./agent-security");
|
|
407
|
-
const secSurface = buildAgentSecuritySurface(cwd, config);
|
|
408
|
-
if (secSurface) {
|
|
409
|
-
signals = {
|
|
410
|
-
...signals,
|
|
411
|
-
riskyIntercepts: Number(secSurface.summary?.highRisk || 0) + Number(secSurface.summary?.mediumRisk || 0),
|
|
412
|
-
trustAlerts: Number(secSurface.summary?.unknownRisk || 0),
|
|
413
|
-
agentSecurityState: secSurface.mode || signals.agentSecurityState,
|
|
414
|
-
};
|
|
415
|
-
}
|
|
416
|
-
} catch {
|
|
417
|
-
// agent security surface unavailable — continue
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
const recommendation = recommendCapabilities({ cwd, signals, probes, plan });
|
|
421
|
-
|
|
422
|
-
// Determine active packs (packs with evidence of activity)
|
|
423
|
-
const activePacks = [];
|
|
424
|
-
if (signals.agentSecurityState && signals.agentSecurityState !== "off") {
|
|
425
|
-
activePacks.push({ id: "agent_security", name: "Agent Security" });
|
|
426
|
-
}
|
|
427
|
-
if (probes.safePath.hasSafePath || signals.agentSecurityState === "approve" || signals.agentSecurityState === "enforce") {
|
|
428
|
-
activePacks.push({ id: "safe_path_engine", name: "Safe Path Engine" });
|
|
429
|
-
}
|
|
430
|
-
if (probes.installIntake?.hasInstallIntake || probes.workspace?.hasPackageManifest) {
|
|
431
|
-
activePacks.push({ id: "install_intake_risk", name: "Install / Intake Risk" });
|
|
432
|
-
}
|
|
433
|
-
if (signals.contextPressure !== "unknown" && signals.contextPressure !== undefined) {
|
|
434
|
-
activePacks.push({ id: "workflow_efficiency", name: "Workflow Efficiency" });
|
|
435
|
-
}
|
|
436
|
-
if (recommendation.additionalPacks.some((pack) => pack.id === "workspace_navigation") || recommendation.recommendedPack?.id === "workspace_navigation") {
|
|
437
|
-
activePacks.push({ id: "workspace_navigation", name: "Workspace Navigation" });
|
|
438
|
-
}
|
|
439
|
-
if (probes.workspace.hasSourceCatalog && probes.workspace.hasLocalSkills) {
|
|
440
|
-
activePacks.push({ id: "source_backed_skills", name: "Source-Backed Skills" });
|
|
441
|
-
}
|
|
442
|
-
if (recommendation.signals.activated) {
|
|
443
|
-
activePacks.push({ id: "agent_readiness", name: "Agent Readiness" });
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
return {
|
|
447
|
-
capabilityLayerVersion: 1,
|
|
448
|
-
recommendedPack: recommendation.recommendedPack,
|
|
449
|
-
reason: recommendation.reason,
|
|
450
|
-
status: recommendation.status,
|
|
451
|
-
entitlement: recommendation.entitlement,
|
|
452
|
-
riskLevel: recommendation.riskLevel,
|
|
453
|
-
nextAction: recommendation.nextAction,
|
|
454
|
-
evidencePath: recommendation.evidencePath,
|
|
455
|
-
additionalPacks: recommendation.additionalPacks,
|
|
456
|
-
activePacks: activePacks.slice(0, 5),
|
|
457
|
-
trustRiskState: {
|
|
458
|
-
riskLevel: recommendation.riskLevel,
|
|
459
|
-
agentSecurityState: signals.agentSecurityState || "off",
|
|
460
|
-
},
|
|
461
|
-
entitlementSummary: {
|
|
462
|
-
plan,
|
|
463
|
-
note: plan === "free"
|
|
464
|
-
? "Free plan includes basic capability packs. Upgrade to Pro for deeper checks and richer evidence."
|
|
465
|
-
: "Pro plan includes all capability packs with deeper checks and richer evidence.",
|
|
466
|
-
},
|
|
467
|
-
};
|
|
468
|
-
} catch {
|
|
469
|
-
return null;
|
|
470
|
-
}
|
|
471
|
-
}
|
|
472
|
-
|
|
473
|
-
/**
|
|
474
|
-
* Format a compact capability summary for CLI status output.
|
|
475
|
-
* Returns a string, or empty string on error.
|
|
476
|
-
*/
|
|
477
|
-
function formatCapabilitySummary(capabilityLayer) {
|
|
478
|
-
if (!capabilityLayer) return "";
|
|
479
|
-
try {
|
|
480
|
-
const lines = ["── Capability Layer ──────────────────────────────────"];
|
|
481
|
-
if (capabilityLayer.recommendedPack) {
|
|
482
|
-
lines.push(` Recommended: ${capabilityLayer.recommendedPack.name} (${capabilityLayer.entitlement})`);
|
|
483
|
-
lines.push(` Why: ${capabilityLayer.reason}`);
|
|
484
|
-
}
|
|
485
|
-
if (capabilityLayer.activePacks && capabilityLayer.activePacks.length > 0) {
|
|
486
|
-
lines.push(` Active packs: ${capabilityLayer.activePacks.map((p) => p.name).join(", ")}`);
|
|
487
|
-
}
|
|
488
|
-
if (capabilityLayer.nextAction) {
|
|
489
|
-
lines.push(` Next: ${capabilityLayer.nextAction}`);
|
|
490
|
-
}
|
|
491
|
-
if (capabilityLayer.evidencePath) {
|
|
492
|
-
lines.push(` Evidence: ${capabilityLayer.evidencePath}`);
|
|
493
|
-
}
|
|
494
|
-
lines.push("");
|
|
495
|
-
return lines.join("\n");
|
|
496
|
-
} catch {
|
|
497
|
-
return "";
|
|
498
|
-
}
|
|
499
|
-
}
|
|
500
|
-
|
|
501
|
-
module.exports = {
|
|
502
|
-
recommendCapabilities,
|
|
503
|
-
buildCapabilityLayerSurface,
|
|
504
|
-
formatCapabilitySummary,
|
|
505
|
-
probeFrontendSignals,
|
|
506
|
-
probeActivationState,
|
|
507
|
-
probeReentryState,
|
|
508
|
-
probeWorkspaceSignals,
|
|
509
|
-
probeSafePathState,
|
|
510
|
-
probeInstallIntakeState,
|
|
511
|
-
probeEvidencePath,
|
|
512
|
-
};
|