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,1149 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
const fs = require("node:fs");
|
|
4
|
-
const path = require("node:path");
|
|
5
|
-
|
|
6
|
-
const CONTRACT = "avorelo.companyLoop.v1";
|
|
7
|
-
const SCHEMA_VERSION = 1;
|
|
8
|
-
|
|
9
|
-
const LOOP_DIR_REL = ".claude/cco/orchestration/company-loop";
|
|
10
|
-
const LATEST_REPORT_REL = `${LOOP_DIR_REL}/latest-report.json`;
|
|
11
|
-
|
|
12
|
-
const PERSONAS = Object.freeze([
|
|
13
|
-
"product_manager",
|
|
14
|
-
"qa_verification",
|
|
15
|
-
"ux_design",
|
|
16
|
-
"security",
|
|
17
|
-
"devex",
|
|
18
|
-
"cost_cogs",
|
|
19
|
-
"support_cs",
|
|
20
|
-
"marketing_growth",
|
|
21
|
-
]);
|
|
22
|
-
|
|
23
|
-
const PERSONA_LABELS = Object.freeze({
|
|
24
|
-
product_manager: "Product Manager",
|
|
25
|
-
qa_verification: "QA / Verification",
|
|
26
|
-
ux_design: "UX / Design Reviewer",
|
|
27
|
-
security: "Security Reviewer",
|
|
28
|
-
devex: "DevEx",
|
|
29
|
-
cost_cogs: "Cost / COGS",
|
|
30
|
-
support_cs: "Support / Customer Success",
|
|
31
|
-
marketing_growth: "Marketing / Growth",
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
const FRICTION_CLUSTER_TYPES = Object.freeze([
|
|
35
|
-
"missing_evidence",
|
|
36
|
-
"noisy_output",
|
|
37
|
-
"manual_fallback_required",
|
|
38
|
-
"generic_next_action",
|
|
39
|
-
"verification_missing",
|
|
40
|
-
"proof_missing",
|
|
41
|
-
"unavailable_worker",
|
|
42
|
-
"context_too_large",
|
|
43
|
-
"unknown_asset_repeated",
|
|
44
|
-
"high_risk_blocked_without_continuation",
|
|
45
|
-
"value_claim_not_evidence_backed",
|
|
46
|
-
"activation_friction",
|
|
47
|
-
"support_explainability_gap",
|
|
48
|
-
]);
|
|
49
|
-
|
|
50
|
-
const ROADMAP_CANDIDATES = Object.freeze([
|
|
51
|
-
"hook_baseline_pack",
|
|
52
|
-
"mcp_least_privilege_cleanup",
|
|
53
|
-
"browser_proof_evidence",
|
|
54
|
-
"plugin_adapter_technical_readiness",
|
|
55
|
-
"activation_alpha_readiness",
|
|
56
|
-
"repair_work_orchestration_accuracy",
|
|
57
|
-
"repair_value_evidence_ledger",
|
|
58
|
-
"repair_ux_noise_compactness",
|
|
59
|
-
]);
|
|
60
|
-
|
|
61
|
-
function safeReadJson(filePath) {
|
|
62
|
-
try {
|
|
63
|
-
if (!fs.existsSync(filePath)) return null;
|
|
64
|
-
return JSON.parse(fs.readFileSync(filePath, "utf8"));
|
|
65
|
-
} catch {
|
|
66
|
-
return null;
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
function makePersonaFinding(persona, status, finding, options = {}) {
|
|
71
|
-
return {
|
|
72
|
-
persona,
|
|
73
|
-
status,
|
|
74
|
-
finding,
|
|
75
|
-
evidence: options.evidence || null,
|
|
76
|
-
recommendedFix: options.recommendedFix || null,
|
|
77
|
-
severity: options.severity || (status === "fail" ? "high" : status === "warn" ? "medium" : "low"),
|
|
78
|
-
reasonCodes: options.reasonCodes || [],
|
|
79
|
-
redacted: true,
|
|
80
|
-
};
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
// --- Product Manager ---
|
|
84
|
-
function reviewProductManager(ledger) {
|
|
85
|
-
const rollup = ledger.rollup || {};
|
|
86
|
-
const nextAction = rollup.nextAction;
|
|
87
|
-
const completedItems = (rollup.completed || []).filter((c) => c !== "not_available");
|
|
88
|
-
const orchEntry = (ledger.entries || []).find((e) => e.type === "orchestration");
|
|
89
|
-
|
|
90
|
-
if (completedItems.length === 0 && !orchEntry) {
|
|
91
|
-
return makePersonaFinding(
|
|
92
|
-
"product_manager",
|
|
93
|
-
"warn",
|
|
94
|
-
"No completed work or orchestration plan found. Ledger may be empty or first run.",
|
|
95
|
-
{
|
|
96
|
-
evidence: "ledger.rollup.completed = not_available",
|
|
97
|
-
recommendedFix: "Run a full Avorelo task to populate ledger entries.",
|
|
98
|
-
reasonCodes: ["NO_COMPLETED_WORK"],
|
|
99
|
-
}
|
|
100
|
-
);
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
if (!nextAction || nextAction.includes("Run node bin/avorelo outcome")) {
|
|
104
|
-
return makePersonaFinding(
|
|
105
|
-
"product_manager",
|
|
106
|
-
"warn",
|
|
107
|
-
"Next action is generic. Recommend a more specific next action from ledger evidence.",
|
|
108
|
-
{
|
|
109
|
-
evidence: nextAction,
|
|
110
|
-
recommendedFix: "Improve nextAction resolution from Reality Gate gaps or persona findings.",
|
|
111
|
-
reasonCodes: ["GENERIC_NEXT_ACTION"],
|
|
112
|
-
}
|
|
113
|
-
);
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
return makePersonaFinding(
|
|
117
|
-
"product_manager",
|
|
118
|
-
"pass",
|
|
119
|
-
`Next action clear. ${completedItems.length} completed item(s) in ledger.`,
|
|
120
|
-
{ evidence: nextAction }
|
|
121
|
-
);
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
// --- QA / Verification ---
|
|
125
|
-
function reviewQaVerification(ledger) {
|
|
126
|
-
const gateEntry = (ledger.entries || []).find((e) => e.type === "reality_gate");
|
|
127
|
-
const outcomeEntry = (ledger.entries || []).find((e) => e.type === "outcome");
|
|
128
|
-
const verified = ledger.rollup?.verified || [];
|
|
129
|
-
|
|
130
|
-
if (!gateEntry && !outcomeEntry) {
|
|
131
|
-
return makePersonaFinding(
|
|
132
|
-
"qa_verification",
|
|
133
|
-
"warn",
|
|
134
|
-
"No Reality Gate or outcome receipt found. Verification evidence missing.",
|
|
135
|
-
{
|
|
136
|
-
evidence: null,
|
|
137
|
-
recommendedFix: "Run node bin/avorelo outcome --gate to generate Reality Gate.",
|
|
138
|
-
reasonCodes: ["VERIFICATION_MISSING", "PROOF_MISSING"],
|
|
139
|
-
}
|
|
140
|
-
);
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
const gateStatus = gateEntry?.status;
|
|
144
|
-
if (gateStatus === "fail") {
|
|
145
|
-
return makePersonaFinding(
|
|
146
|
-
"qa_verification",
|
|
147
|
-
"fail",
|
|
148
|
-
`Reality Gate failed. ${gateEntry.summary}`,
|
|
149
|
-
{
|
|
150
|
-
evidence: gateEntry.evidencePath,
|
|
151
|
-
recommendedFix: "Fix Reality Gate failures before merging.",
|
|
152
|
-
severity: "high",
|
|
153
|
-
reasonCodes: gateEntry.reasonCodes || [],
|
|
154
|
-
}
|
|
155
|
-
);
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
if (gateStatus === "warn") {
|
|
159
|
-
return makePersonaFinding(
|
|
160
|
-
"qa_verification",
|
|
161
|
-
"warn",
|
|
162
|
-
`Reality Gate has warnings. ${gateEntry.summary}`,
|
|
163
|
-
{
|
|
164
|
-
evidence: gateEntry.evidencePath,
|
|
165
|
-
recommendedFix: "Review Reality Gate warnings and address where possible.",
|
|
166
|
-
reasonCodes: gateEntry.reasonCodes || [],
|
|
167
|
-
}
|
|
168
|
-
);
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
return makePersonaFinding(
|
|
172
|
-
"qa_verification",
|
|
173
|
-
"pass",
|
|
174
|
-
`Verification evidence present. ${verified.length > 0 ? verified.join(", ") : "Reality Gate available."}`,
|
|
175
|
-
{ evidence: gateEntry?.evidencePath || outcomeEntry?.evidencePath }
|
|
176
|
-
);
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
// --- UX / Design ---
|
|
180
|
-
function reviewUxDesign(ledger) {
|
|
181
|
-
const friction = ledger.rollup?.friction || [];
|
|
182
|
-
const noisyFriction = friction.filter(
|
|
183
|
-
(f) =>
|
|
184
|
-
f.includes("noisy") ||
|
|
185
|
-
f.includes("verbose") ||
|
|
186
|
-
f.includes("dump") ||
|
|
187
|
-
f.includes("scattered")
|
|
188
|
-
);
|
|
189
|
-
|
|
190
|
-
if (noisyFriction.length > 0) {
|
|
191
|
-
return makePersonaFinding(
|
|
192
|
-
"ux_design",
|
|
193
|
-
"warn",
|
|
194
|
-
`Noisy output signals detected: ${noisyFriction.join(", ")}.`,
|
|
195
|
-
{
|
|
196
|
-
evidence: noisyFriction.join(", "),
|
|
197
|
-
recommendedFix: "Audit default CLI output for verbosity and move details behind --debug.",
|
|
198
|
-
reasonCodes: ["NOISY_DEFAULT_OUTPUT"],
|
|
199
|
-
}
|
|
200
|
-
);
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
const orchEntry = (ledger.entries || []).find((e) => e.type === "orchestration");
|
|
204
|
-
if (orchEntry?.status === "pass") {
|
|
205
|
-
return makePersonaFinding(
|
|
206
|
-
"ux_design",
|
|
207
|
-
"pass",
|
|
208
|
-
"Ledger compact by default. Debug detail available via --debug flag.",
|
|
209
|
-
{ evidence: "ledger.formatWorkLedgerText" }
|
|
210
|
-
);
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
return makePersonaFinding(
|
|
214
|
-
"ux_design",
|
|
215
|
-
"skip",
|
|
216
|
-
"No specific UX signal in current ledger. Compact default assumed.",
|
|
217
|
-
{}
|
|
218
|
-
);
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
// --- Security ---
|
|
222
|
-
function reviewSecurity(ledger) {
|
|
223
|
-
const guardEntry = (ledger.entries || []).find((e) => e.type === "guard");
|
|
224
|
-
const hygieneEntry = (ledger.entries || []).find((e) => e.type === "workspace_hygiene");
|
|
225
|
-
|
|
226
|
-
const riskSignals = ledger.entries
|
|
227
|
-
? ledger.entries.flatMap((e) => e.riskSignals || [])
|
|
228
|
-
: [];
|
|
229
|
-
|
|
230
|
-
if (!guardEntry && !hygieneEntry) {
|
|
231
|
-
return makePersonaFinding(
|
|
232
|
-
"security",
|
|
233
|
-
"warn",
|
|
234
|
-
"No guard or workspace hygiene receipt found. Security posture unverified.",
|
|
235
|
-
{
|
|
236
|
-
recommendedFix: "Run node bin/avorelo workspace-hygiene and node bin/avorelo guard.",
|
|
237
|
-
reasonCodes: ["GUARD_RECEIPT_MISSING", "HYGIENE_RECEIPT_MISSING"],
|
|
238
|
-
}
|
|
239
|
-
);
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
const highRisk = riskSignals.filter(
|
|
243
|
-
(r) =>
|
|
244
|
-
r.includes("critical") ||
|
|
245
|
-
r.includes("unknown_subjects") ||
|
|
246
|
-
r.includes("high_risk")
|
|
247
|
-
);
|
|
248
|
-
|
|
249
|
-
if (highRisk.length > 0) {
|
|
250
|
-
return makePersonaFinding(
|
|
251
|
-
"security",
|
|
252
|
-
"warn",
|
|
253
|
-
`High-risk signals present: ${highRisk.join(", ")}.`,
|
|
254
|
-
{
|
|
255
|
-
evidence: riskSignals.join(", "),
|
|
256
|
-
recommendedFix: "Review high-risk assets and unknown subjects before proceeding.",
|
|
257
|
-
reasonCodes: highRisk,
|
|
258
|
-
}
|
|
259
|
-
);
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
return makePersonaFinding(
|
|
263
|
-
"security",
|
|
264
|
-
"pass",
|
|
265
|
-
`Guard and hygiene evidence present. Risk signals: ${riskSignals.join(", ") || "none"}.`,
|
|
266
|
-
{ evidence: guardEntry?.evidencePath || hygieneEntry?.evidencePath }
|
|
267
|
-
);
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
// --- DevEx ---
|
|
271
|
-
function reviewDevEx(ledger) {
|
|
272
|
-
const orchEntry = (ledger.entries || []).find((e) => e.type === "orchestration");
|
|
273
|
-
const friction = ledger.rollup?.friction || [];
|
|
274
|
-
const handoffFriction = friction.filter(
|
|
275
|
-
(f) => f.includes("handoff") || f.includes("continuation") || f.includes("manual_fallback")
|
|
276
|
-
);
|
|
277
|
-
|
|
278
|
-
if (handoffFriction.length > 0) {
|
|
279
|
-
return makePersonaFinding(
|
|
280
|
-
"devex",
|
|
281
|
-
"warn",
|
|
282
|
-
`Handoff/continuation friction: ${handoffFriction.join(", ")}.`,
|
|
283
|
-
{
|
|
284
|
-
evidence: handoffFriction.join(", "),
|
|
285
|
-
recommendedFix: "Improve stage handoff and continuation paths.",
|
|
286
|
-
reasonCodes: ["HANDOFF_FRICTION"],
|
|
287
|
-
}
|
|
288
|
-
);
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
if (orchEntry?.status === "pass") {
|
|
292
|
-
const orchData = orchEntry.summary;
|
|
293
|
-
return makePersonaFinding(
|
|
294
|
-
"devex",
|
|
295
|
-
"pass",
|
|
296
|
-
`Orchestration available and usable. ${orchData}`,
|
|
297
|
-
{ evidence: orchEntry.evidencePath }
|
|
298
|
-
);
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
return makePersonaFinding(
|
|
302
|
-
"devex",
|
|
303
|
-
"skip",
|
|
304
|
-
"DevEx signals not determinable from current ledger.",
|
|
305
|
-
{}
|
|
306
|
-
);
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
// --- Cost / COGS ---
|
|
310
|
-
function reviewCostCogs(ledger) {
|
|
311
|
-
const saved = ledger.rollup?.saved || [];
|
|
312
|
-
const orchEntry = (ledger.entries || []).find((e) => e.type === "orchestration");
|
|
313
|
-
const frictions = ledger.rollup?.friction || [];
|
|
314
|
-
const contextLarge = frictions.filter(
|
|
315
|
-
(f) => f.includes("context_too_large") || f.includes("broad_scan")
|
|
316
|
-
);
|
|
317
|
-
|
|
318
|
-
if (contextLarge.length > 0) {
|
|
319
|
-
return makePersonaFinding(
|
|
320
|
-
"cost_cogs",
|
|
321
|
-
"warn",
|
|
322
|
-
`Context/cost friction detected: ${contextLarge.join(", ")}.`,
|
|
323
|
-
{
|
|
324
|
-
evidence: contextLarge.join(", "),
|
|
325
|
-
recommendedFix: "Reduce context budget or improve hygiene-guided exclusions.",
|
|
326
|
-
reasonCodes: ["CONTEXT_TOO_LARGE"],
|
|
327
|
-
}
|
|
328
|
-
);
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
const localSignals = saved.filter((s) => s.includes("local") || s.includes("cheap"));
|
|
332
|
-
|
|
333
|
-
if (localSignals.length > 0) {
|
|
334
|
-
return makePersonaFinding(
|
|
335
|
-
"cost_cogs",
|
|
336
|
-
"pass",
|
|
337
|
-
`Local/cheap stages used: ${localSignals.join(", ")}.`,
|
|
338
|
-
{
|
|
339
|
-
evidence: localSignals.join(", "),
|
|
340
|
-
}
|
|
341
|
-
);
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
return makePersonaFinding(
|
|
345
|
-
"cost_cogs",
|
|
346
|
-
"skip",
|
|
347
|
-
"Cost/COGS signals not determinable. No local-stage evidence in ledger.",
|
|
348
|
-
{
|
|
349
|
-
recommendedFix: "Run orchestrate to generate stage worker evidence.",
|
|
350
|
-
}
|
|
351
|
-
);
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
// --- Support / CS ---
|
|
355
|
-
function reviewSupportCs(ledger) {
|
|
356
|
-
const outcomeEntry = (ledger.entries || []).find((e) => e.type === "outcome");
|
|
357
|
-
const rollup = ledger.rollup || {};
|
|
358
|
-
|
|
359
|
-
if (!outcomeEntry) {
|
|
360
|
-
return makePersonaFinding(
|
|
361
|
-
"support_cs",
|
|
362
|
-
"warn",
|
|
363
|
-
"No outcome receipt found. Customer-explainable summary unavailable.",
|
|
364
|
-
{
|
|
365
|
-
recommendedFix: "Run node bin/avorelo outcome to generate value summary.",
|
|
366
|
-
reasonCodes: ["SUPPORT_EXPLAINABILITY_GAP"],
|
|
367
|
-
}
|
|
368
|
-
);
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
const hasEvidence = ledger.evidence?.receiptPaths?.length > 0;
|
|
372
|
-
return makePersonaFinding(
|
|
373
|
-
"support_cs",
|
|
374
|
-
"pass",
|
|
375
|
-
`Outcome summary available. Evidence paths: ${hasEvidence ? ledger.evidence.receiptPaths.length : 0}.`,
|
|
376
|
-
{ evidence: outcomeEntry.evidencePath }
|
|
377
|
-
);
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
// --- Marketing / Growth ---
|
|
381
|
-
function reviewMarketingGrowth(ledger) {
|
|
382
|
-
const frictions = ledger.rollup?.friction || [];
|
|
383
|
-
const valueClaims = frictions.filter((f) => f.includes("not_evidence_backed"));
|
|
384
|
-
|
|
385
|
-
if (valueClaims.length > 0) {
|
|
386
|
-
return makePersonaFinding(
|
|
387
|
-
"marketing_growth",
|
|
388
|
-
"warn",
|
|
389
|
-
`Value claims not fully evidence-backed: ${valueClaims.join(", ")}.`,
|
|
390
|
-
{
|
|
391
|
-
evidence: valueClaims.join(", "),
|
|
392
|
-
recommendedFix: "Ensure all value signals reference receipt evidence paths.",
|
|
393
|
-
reasonCodes: ["VALUE_CLAIM_NOT_EVIDENCE_BACKED"],
|
|
394
|
-
}
|
|
395
|
-
);
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
return makePersonaFinding(
|
|
399
|
-
"marketing_growth",
|
|
400
|
-
"pass",
|
|
401
|
-
"No positioning drift detected. Value claims reference receipt evidence.",
|
|
402
|
-
{}
|
|
403
|
-
);
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
function runInternalPersonaReview(ledger) {
|
|
407
|
-
return [
|
|
408
|
-
reviewProductManager(ledger),
|
|
409
|
-
reviewQaVerification(ledger),
|
|
410
|
-
reviewUxDesign(ledger),
|
|
411
|
-
reviewSecurity(ledger),
|
|
412
|
-
reviewDevEx(ledger),
|
|
413
|
-
reviewCostCogs(ledger),
|
|
414
|
-
reviewSupportCs(ledger),
|
|
415
|
-
reviewMarketingGrowth(ledger),
|
|
416
|
-
];
|
|
417
|
-
}
|
|
418
|
-
|
|
419
|
-
function clusterFriction(ledger, personaFindings) {
|
|
420
|
-
const clusters = [];
|
|
421
|
-
|
|
422
|
-
function countFriction(signalMatches, clusterType, severity, examples, recommendedFix) {
|
|
423
|
-
if (signalMatches.length === 0) return;
|
|
424
|
-
clusters.push({
|
|
425
|
-
clusterId: `cluster-${clusterType.replace(/_/g, "-")}`,
|
|
426
|
-
type: clusterType,
|
|
427
|
-
severity,
|
|
428
|
-
count: signalMatches.length,
|
|
429
|
-
examples: signalMatches.slice(0, 3),
|
|
430
|
-
evidencePaths: ledger.evidence?.receiptPaths?.slice(0, 3) || [],
|
|
431
|
-
recommendedFix,
|
|
432
|
-
candidateRoadmapItem: mapFrictionToRoadmap(clusterType),
|
|
433
|
-
redacted: true,
|
|
434
|
-
});
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
const frictionSignals = [
|
|
438
|
-
...(ledger.rollup?.friction || []),
|
|
439
|
-
...personaFindings
|
|
440
|
-
.filter((pf) => pf.status === "warn" || pf.status === "fail")
|
|
441
|
-
.flatMap((pf) => pf.reasonCodes || []),
|
|
442
|
-
];
|
|
443
|
-
|
|
444
|
-
const allEntries = ledger.entries || [];
|
|
445
|
-
|
|
446
|
-
// Missing evidence
|
|
447
|
-
const missingEv = frictionSignals.filter(
|
|
448
|
-
(f) =>
|
|
449
|
-
f.includes("missing") ||
|
|
450
|
-
f.includes("not_available") ||
|
|
451
|
-
f.includes("MISSING") ||
|
|
452
|
-
f.includes("NO_")
|
|
453
|
-
);
|
|
454
|
-
countFriction(missingEv, "missing_evidence", "medium", missingEv,
|
|
455
|
-
"Generate missing receipts with full Avorelo run.");
|
|
456
|
-
|
|
457
|
-
// Noisy output
|
|
458
|
-
const noisy = frictionSignals.filter((f) => f.includes("noisy") || f.includes("verbose"));
|
|
459
|
-
countFriction(noisy, "noisy_output", "low", noisy,
|
|
460
|
-
"Move debug detail behind --debug flag.");
|
|
461
|
-
|
|
462
|
-
// Manual fallback
|
|
463
|
-
const manual = frictionSignals.filter(
|
|
464
|
-
(f) => f.includes("manual_fallback") || f.includes("INSPECT_MAP_FIRST")
|
|
465
|
-
);
|
|
466
|
-
countFriction(manual, "manual_fallback_required", "medium", manual,
|
|
467
|
-
"Run workspace-hygiene before orchestrate to enable automatic context selection.");
|
|
468
|
-
|
|
469
|
-
// Generic next action
|
|
470
|
-
const generic = personaFindings.filter(
|
|
471
|
-
(pf) => (pf.reasonCodes || []).includes("GENERIC_NEXT_ACTION")
|
|
472
|
-
);
|
|
473
|
-
if (generic.length > 0) {
|
|
474
|
-
countFriction(
|
|
475
|
-
generic.map((g) => g.persona),
|
|
476
|
-
"generic_next_action",
|
|
477
|
-
"medium",
|
|
478
|
-
generic.map((g) => g.finding),
|
|
479
|
-
"Resolve Reality Gate gaps to produce specific next action."
|
|
480
|
-
);
|
|
481
|
-
}
|
|
482
|
-
|
|
483
|
-
// Verification missing
|
|
484
|
-
const verMissing = frictionSignals.filter(
|
|
485
|
-
(f) => f.includes("VERIFICATION_MISSING") || f.includes("reality_gate_failures")
|
|
486
|
-
);
|
|
487
|
-
countFriction(verMissing, "verification_missing", "high", verMissing,
|
|
488
|
-
"Run node bin/avorelo outcome --gate to produce verification evidence.");
|
|
489
|
-
|
|
490
|
-
// Proof missing
|
|
491
|
-
const proofMissing = frictionSignals.filter((f) => f.includes("PROOF_MISSING"));
|
|
492
|
-
countFriction(proofMissing, "proof_missing", "medium", proofMissing,
|
|
493
|
-
"Run node bin/avorelo proof after task completion.");
|
|
494
|
-
|
|
495
|
-
// Unknown asset repeated
|
|
496
|
-
const unknownAsset = frictionSignals.filter(
|
|
497
|
-
(f) => f.includes("unknown_asset") || f.includes("UNKNOWN_ASSET")
|
|
498
|
-
);
|
|
499
|
-
countFriction(unknownAsset, "unknown_asset_repeated", "medium", unknownAsset,
|
|
500
|
-
"Review and classify unknown workspace assets.");
|
|
501
|
-
|
|
502
|
-
// Value not evidence-backed
|
|
503
|
-
const valueClaims = frictionSignals.filter(
|
|
504
|
-
(f) => f.includes("not_evidence_backed") || f.includes("VALUE_CLAIM")
|
|
505
|
-
);
|
|
506
|
-
countFriction(valueClaims, "value_claim_not_evidence_backed", "medium", valueClaims,
|
|
507
|
-
"Link value signals to receipt evidence paths.");
|
|
508
|
-
|
|
509
|
-
// Context too large
|
|
510
|
-
const contextLarge = frictionSignals.filter(
|
|
511
|
-
(f) => f.includes("context_too_large") || f.includes("CONTEXT_TOO_LARGE")
|
|
512
|
-
);
|
|
513
|
-
countFriction(contextLarge, "context_too_large", "medium", contextLarge,
|
|
514
|
-
"Reduce context budget or improve hygiene-guided exclusions.");
|
|
515
|
-
|
|
516
|
-
// Support explainability gap
|
|
517
|
-
const suppGap = frictionSignals.filter(
|
|
518
|
-
(f) => f.includes("SUPPORT_EXPLAINABILITY_GAP") || f.includes("explainability")
|
|
519
|
-
);
|
|
520
|
-
countFriction(suppGap, "support_explainability_gap", "low", suppGap,
|
|
521
|
-
"Generate outcome summary before completing task.");
|
|
522
|
-
|
|
523
|
-
return clusters;
|
|
524
|
-
}
|
|
525
|
-
|
|
526
|
-
function mapFrictionToRoadmap(clusterType) {
|
|
527
|
-
const map = {
|
|
528
|
-
missing_evidence: "repair_value_evidence_ledger",
|
|
529
|
-
noisy_output: "repair_ux_noise_compactness",
|
|
530
|
-
manual_fallback_required: "hook_baseline_pack",
|
|
531
|
-
generic_next_action: "repair_value_evidence_ledger",
|
|
532
|
-
verification_missing: "repair_work_orchestration_accuracy",
|
|
533
|
-
proof_missing: "browser_proof_evidence",
|
|
534
|
-
unknown_asset_repeated: "mcp_least_privilege_cleanup",
|
|
535
|
-
context_too_large: "repair_work_orchestration_accuracy",
|
|
536
|
-
value_claim_not_evidence_backed: "repair_value_evidence_ledger",
|
|
537
|
-
support_explainability_gap: "activation_alpha_readiness",
|
|
538
|
-
activation_friction: "activation_alpha_readiness",
|
|
539
|
-
high_risk_blocked_without_continuation: "repair_work_orchestration_accuracy",
|
|
540
|
-
};
|
|
541
|
-
return map[clusterType] || null;
|
|
542
|
-
}
|
|
543
|
-
|
|
544
|
-
function buildCostCogsQualityRollup(ledger, personaFindings) {
|
|
545
|
-
const saved = ledger.rollup?.saved || [];
|
|
546
|
-
const verified = ledger.rollup?.verified || [];
|
|
547
|
-
const friction = ledger.rollup?.friction || [];
|
|
548
|
-
|
|
549
|
-
const localStages = saved.filter((s) => s.includes("local")).length;
|
|
550
|
-
const tokenSavings = saved
|
|
551
|
-
.filter((s) => s.includes("token"))
|
|
552
|
-
.map((s) => {
|
|
553
|
-
const m = s.match(/(\d+)/);
|
|
554
|
-
return m ? parseInt(m[1], 10) : 0;
|
|
555
|
-
});
|
|
556
|
-
const totalTokenSavingsEstimate = tokenSavings.reduce((a, b) => a + b, 0);
|
|
557
|
-
|
|
558
|
-
const costPersona = personaFindings.find((p) => p.persona === "cost_cogs");
|
|
559
|
-
const qaPersona = personaFindings.find((p) => p.persona === "qa_verification");
|
|
560
|
-
|
|
561
|
-
return {
|
|
562
|
-
estimatedLocalStagesUsed: localStages,
|
|
563
|
-
estimatedContextTokensSaved: totalTokenSavingsEstimate,
|
|
564
|
-
estimateMethod: totalTokenSavingsEstimate > 0 ? "receipt_based_estimate" : "not_available",
|
|
565
|
-
qualityChecksVerified: verified.length,
|
|
566
|
-
frictionPointsDetected: friction.length,
|
|
567
|
-
costPersonaStatus: costPersona?.status || "skip",
|
|
568
|
-
qualityPersonaStatus: qaPersona?.status || "skip",
|
|
569
|
-
caveats: [
|
|
570
|
-
"Token savings are estimates from receipt data, not exact billing amounts.",
|
|
571
|
-
"No exact/guaranteed savings are claimed.",
|
|
572
|
-
],
|
|
573
|
-
redacted: true,
|
|
574
|
-
};
|
|
575
|
-
}
|
|
576
|
-
|
|
577
|
-
function recommendNextPr(ledger, personaFindings, frictionClusters) {
|
|
578
|
-
const friction = ledger.rollup?.friction || [];
|
|
579
|
-
const frictionTypes = frictionClusters.map((c) => c.type);
|
|
580
|
-
const realityGateEntry = (ledger.entries || []).find((e) => e.type === "reality_gate");
|
|
581
|
-
const gateStatus = realityGateEntry?.status;
|
|
582
|
-
const evidencePaths = ledger.evidence?.receiptPaths || [];
|
|
583
|
-
|
|
584
|
-
let recommended = null;
|
|
585
|
-
let whyNow = null;
|
|
586
|
-
let confidence = "low";
|
|
587
|
-
|
|
588
|
-
// Hook Apply — lifecycle hooks not yet applied (PR #141)
|
|
589
|
-
const hooksNotApplied = friction.some((f) => f === "hooks_not_yet_applied" || f === "hooks_not_yet_installed");
|
|
590
|
-
const hooksApplied = evidencePaths.some((p) => p.includes("hook-apply/latest-apply.json"));
|
|
591
|
-
if (hooksNotApplied && !hooksApplied) {
|
|
592
|
-
recommended = "Explicit Hook Apply + Lifecycle Live";
|
|
593
|
-
whyNow = "Lifecycle hooks are previewed but not yet applied. Apply to make Avorelo seamless.";
|
|
594
|
-
confidence = "high";
|
|
595
|
-
}
|
|
596
|
-
|
|
597
|
-
// Hook Baseline Pack — lifecycle/hook evidence missing or manual fallback
|
|
598
|
-
else if (
|
|
599
|
-
frictionTypes.includes("manual_fallback_required") ||
|
|
600
|
-
friction.some((f) => f.includes("INSPECT_MAP_FIRST") || f.includes("NO_HYGIENE_REPORT"))
|
|
601
|
-
) {
|
|
602
|
-
recommended = "Hook Baseline Pack + Claude/OpenHands-compatible adapters";
|
|
603
|
-
whyNow = "Manual fallback and missing lifecycle evidence are the top friction clusters.";
|
|
604
|
-
confidence = "medium";
|
|
605
|
-
}
|
|
606
|
-
|
|
607
|
-
// MCP Least-Privilege Cleanup
|
|
608
|
-
else if (frictionTypes.includes("unknown_asset_repeated")) {
|
|
609
|
-
recommended = "MCP Least-Privilege Cleanup";
|
|
610
|
-
whyNow = "Unknown/broad workspace assets repeatedly appear in hygiene and context receipts.";
|
|
611
|
-
confidence = "medium";
|
|
612
|
-
}
|
|
613
|
-
|
|
614
|
-
// Browser Proof / Evidence
|
|
615
|
-
else if (frictionTypes.includes("proof_missing")) {
|
|
616
|
-
recommended = "Browser Proof / Evidence";
|
|
617
|
-
whyNow = "Proof gaps detected across ledger entries.";
|
|
618
|
-
confidence = "low";
|
|
619
|
-
}
|
|
620
|
-
|
|
621
|
-
// Post-activation: if alpha activation is present and gate passes, recommend next layer
|
|
622
|
-
else if (
|
|
623
|
-
evidencePaths.some((p) => p.includes("alpha-readiness/latest-gate.json")) &&
|
|
624
|
-
evidencePaths.some((p) => p.includes("orchestration/activation/latest-activation.json"))
|
|
625
|
-
) {
|
|
626
|
-
recommended = "MCP Least-Privilege Cleanup or Launch Hardening";
|
|
627
|
-
whyNow = "Alpha activation and readiness gate are in place. Next: harden for launch or clean MCP surfaces.";
|
|
628
|
-
confidence = "medium";
|
|
629
|
-
}
|
|
630
|
-
|
|
631
|
-
// Activation / Alpha Readiness
|
|
632
|
-
else if (
|
|
633
|
-
frictionTypes.includes("activation_friction") ||
|
|
634
|
-
frictionTypes.includes("support_explainability_gap")
|
|
635
|
-
) {
|
|
636
|
-
recommended = "Activation / Alpha Readiness / Customer Feedback Loop";
|
|
637
|
-
whyNow = "Activation friction and support explainability gaps dominate.";
|
|
638
|
-
confidence = "medium";
|
|
639
|
-
}
|
|
640
|
-
|
|
641
|
-
// Repair: Value evidence / ledger accuracy
|
|
642
|
-
else if (
|
|
643
|
-
frictionTypes.includes("missing_evidence") ||
|
|
644
|
-
frictionTypes.includes("value_claim_not_evidence_backed")
|
|
645
|
-
) {
|
|
646
|
-
recommended = "Repair: Value evidence / ledger accuracy";
|
|
647
|
-
whyNow = "Missing or unevidenced value claims in ledger rollup.";
|
|
648
|
-
confidence = "medium";
|
|
649
|
-
}
|
|
650
|
-
|
|
651
|
-
// Repair: Work-Aware Orchestration accuracy
|
|
652
|
-
else if (
|
|
653
|
-
frictionTypes.includes("verification_missing") ||
|
|
654
|
-
frictionTypes.includes("context_too_large")
|
|
655
|
-
) {
|
|
656
|
-
recommended = "Repair: Work-Aware Orchestration accuracy";
|
|
657
|
-
whyNow = "Verification gaps or context overload in orchestration stage.";
|
|
658
|
-
confidence = "low";
|
|
659
|
-
}
|
|
660
|
-
|
|
661
|
-
// Default — Repair UX/noise/compactness
|
|
662
|
-
else if (frictionTypes.includes("noisy_output")) {
|
|
663
|
-
recommended = "Repair: UX/noise/compactness";
|
|
664
|
-
whyNow = "Noisy output friction detected in default surfaces.";
|
|
665
|
-
confidence = "low";
|
|
666
|
-
}
|
|
667
|
-
|
|
668
|
-
// Fallback
|
|
669
|
-
else {
|
|
670
|
-
recommended = "Repair: Value evidence / ledger accuracy";
|
|
671
|
-
whyNow = "No dominant friction cluster — ledger may need more receipt population.";
|
|
672
|
-
confidence = "low";
|
|
673
|
-
}
|
|
674
|
-
|
|
675
|
-
const notRecommendedYet = [
|
|
676
|
-
"Public positioning / pricing / website changes — deferred until Alpha Readiness passes.",
|
|
677
|
-
"Cloud telemetry / external analytics — intentionally deferred.",
|
|
678
|
-
"Browser Proof — deferred unless proof_missing is dominant cluster.",
|
|
679
|
-
"Full execution runtime — deferred.",
|
|
680
|
-
];
|
|
681
|
-
|
|
682
|
-
return {
|
|
683
|
-
recommendedNextPr: recommended,
|
|
684
|
-
whyNow,
|
|
685
|
-
evidencePaths: evidencePaths.slice(0, 5),
|
|
686
|
-
expectedValue: "Reduce top friction cluster and improve ledger completeness.",
|
|
687
|
-
risk: "low",
|
|
688
|
-
confidence,
|
|
689
|
-
notRecommendedYet,
|
|
690
|
-
redacted: true,
|
|
691
|
-
};
|
|
692
|
-
}
|
|
693
|
-
|
|
694
|
-
function recommendNextPrWithIntelligence(ledger, personaFindings, frictionClusters, intelligenceSignals) {
|
|
695
|
-
// Start with base recommendation
|
|
696
|
-
const base = recommendNextPr(ledger, personaFindings, frictionClusters);
|
|
697
|
-
|
|
698
|
-
if (!intelligenceSignals) return base;
|
|
699
|
-
|
|
700
|
-
const topFriction = intelligenceSignals.topFriction;
|
|
701
|
-
const prelaunchScore = intelligenceSignals.prelaunchScore || 0;
|
|
702
|
-
const tokenLevel = intelligenceSignals.tokenEvidenceLevel;
|
|
703
|
-
const journeyStatus = intelligenceSignals.journeyStatus;
|
|
704
|
-
|
|
705
|
-
// Override with intelligence-backed recommendation
|
|
706
|
-
if (topFriction === "browser_proof_missing") {
|
|
707
|
-
return {
|
|
708
|
-
...base,
|
|
709
|
-
recommendedNextPr: "Browser Proof / Visual QA Bridge",
|
|
710
|
-
whyNow: "Visual proof friction dominates feedback intelligence clusters.",
|
|
711
|
-
confidence: "medium",
|
|
712
|
-
};
|
|
713
|
-
}
|
|
714
|
-
|
|
715
|
-
if (topFriction === "plugin_distribution_unclear") {
|
|
716
|
-
return {
|
|
717
|
-
...base,
|
|
718
|
-
recommendedNextPr: "Plugin / Adapter Technical Readiness",
|
|
719
|
-
whyNow: "Plugin distribution friction dominates feedback intelligence clusters.",
|
|
720
|
-
confidence: "medium",
|
|
721
|
-
};
|
|
722
|
-
}
|
|
723
|
-
|
|
724
|
-
if (topFriction === "install_confusion" || topFriction === "ai_prompt_unclear" || topFriction === "hook_approval_unclear") {
|
|
725
|
-
return {
|
|
726
|
-
...base,
|
|
727
|
-
recommendedNextPr: "Install / activation repair",
|
|
728
|
-
whyNow: `Install confusion (${topFriction}) is the dominant cluster from feedback intelligence.`,
|
|
729
|
-
confidence: "high",
|
|
730
|
-
};
|
|
731
|
-
}
|
|
732
|
-
|
|
733
|
-
if (topFriction === "token_context_unknown" || tokenLevel === "not_available") {
|
|
734
|
-
return {
|
|
735
|
-
...base,
|
|
736
|
-
recommendedNextPr: "Token / cost evidence repair",
|
|
737
|
-
whyNow: "Token/cost evidence missing or unclear per intelligence layer.",
|
|
738
|
-
confidence: "medium",
|
|
739
|
-
};
|
|
740
|
-
}
|
|
741
|
-
|
|
742
|
-
// If intelligence score is strong and journey is ready, recommend Full Readiness Gate
|
|
743
|
-
if (prelaunchScore >= 85 && journeyStatus === "ready") {
|
|
744
|
-
return {
|
|
745
|
-
...base,
|
|
746
|
-
recommendedNextPr: "Full Readiness / Release Candidate Gate",
|
|
747
|
-
whyNow: `Pre-launch intelligence score ${prelaunchScore}/100. Install journey ready. No dominant blocker.`,
|
|
748
|
-
confidence: "medium",
|
|
749
|
-
};
|
|
750
|
-
}
|
|
751
|
-
|
|
752
|
-
// If no intelligence override, use base recommendation
|
|
753
|
-
return base;
|
|
754
|
-
}
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
function recommendNextPrWithFullReadiness(ledger, personaFindings, frictionClusters, intelligenceSignals, fullReadinessSignals) {
|
|
758
|
-
const base = recommendNextPrWithIntelligence(ledger, personaFindings, frictionClusters, intelligenceSignals);
|
|
759
|
-
if (!fullReadinessSignals) return base;
|
|
760
|
-
|
|
761
|
-
const gateStatus = fullReadinessSignals.gateStatus;
|
|
762
|
-
const rcStatus = fullReadinessSignals.releaseCandidateStatus;
|
|
763
|
-
const blockerCount = fullReadinessSignals.blockerCount || 0;
|
|
764
|
-
const safetyBlocker = fullReadinessSignals.safetyBlocker;
|
|
765
|
-
const installDistributionDominates = fullReadinessSignals.installDistributionDominates;
|
|
766
|
-
const browserProofDominates = fullReadinessSignals.browserProofDominates;
|
|
767
|
-
const pluginAdapterDominates = fullReadinessSignals.pluginAdapterDominates;
|
|
768
|
-
const feedbackInsufficient = fullReadinessSignals.feedbackInsufficient;
|
|
769
|
-
const tokenEvidenceMissing = fullReadinessSignals.tokenEvidenceMissing;
|
|
770
|
-
const proofOutcomeMissing = fullReadinessSignals.proofOutcomeMissing;
|
|
771
|
-
|
|
772
|
-
if (safetyBlocker) {
|
|
773
|
-
return { ...base, recommendedNextPr: "Repair: Safety / Support / MCP blocker", whyNow: "Full readiness gate has a safety/MCP hard blocker. Repair before launch.", confidence: "high", notRecommendedYet: [...(base.notRecommendedYet || []), "Website / pricing � deferred until gate passes with no safety blockers."] };
|
|
774
|
-
}
|
|
775
|
-
if (feedbackInsufficient) {
|
|
776
|
-
return { ...base, recommendedNextPr: "Operational: Import real design-partner feedback", whyNow: "Full readiness still lacks qualified redacted feedback evidence.", confidence: "high" };
|
|
777
|
-
}
|
|
778
|
-
if (tokenEvidenceMissing) {
|
|
779
|
-
return { ...base, recommendedNextPr: "Operational: Capture/import real token-cost evidence", whyNow: "Token/cost evidence is still heuristic-only or missing measured usage samples.", confidence: "high" };
|
|
780
|
-
}
|
|
781
|
-
if (proofOutcomeMissing) {
|
|
782
|
-
return { ...base, recommendedNextPr: "Operational: Run proof after a real bounded task", whyNow: "A real proof/value summary artifact is still missing from readiness evidence.", confidence: "medium" };
|
|
783
|
-
}
|
|
784
|
-
if (rcStatus === "candidate_ready" && blockerCount === 0) {
|
|
785
|
-
// If adapter readiness is already verified, move to alpha launch candidate prep
|
|
786
|
-
if (fullReadinessSignals && fullReadinessSignals.adapterReadinessVerified) {
|
|
787
|
-
return { ...base, recommendedNextPr: "Alpha Launch Candidate Prep", whyNow: "Full readiness gate and adapter technical readiness both passed. Ready for alpha launch candidate.", confidence: "high" };
|
|
788
|
-
}
|
|
789
|
-
return { ...base, recommendedNextPr: "Plugin/Adapter Technical Readiness", whyNow: "Full readiness gate passed. Distribution truth verified. Plugin/adapter readiness is next.", confidence: "high" };
|
|
790
|
-
}
|
|
791
|
-
if (rcStatus === "candidate_warn" && blockerCount === 0 && installDistributionDominates) {
|
|
792
|
-
return { ...base, recommendedNextPr: "Repair: Distribution blockers before next PR", whyNow: "Gate warned with distribution blockers. Repair install claims or package content.", confidence: "high" };
|
|
793
|
-
}
|
|
794
|
-
if (browserProofDominates) {
|
|
795
|
-
return { ...base, recommendedNextPr: "Browser Proof / Visual QA Bridge", whyNow: "Browser proof limitation is dominant in full readiness gate.", confidence: "medium" };
|
|
796
|
-
}
|
|
797
|
-
if (pluginAdapterDominates) {
|
|
798
|
-
return { ...base, recommendedNextPr: "Plugin / Adapter Technical Readiness", whyNow: "Plugin/adapter limitation is dominant.", confidence: "medium" };
|
|
799
|
-
}
|
|
800
|
-
if (gateStatus === "blocked" && fullReadinessSignals.gateRecommendedNextPr) {
|
|
801
|
-
return { ...base, recommendedNextPr: fullReadinessSignals.gateRecommendedNextPr, whyNow: "Full readiness gate blocked. Repair required.", confidence: "high" };
|
|
802
|
-
}
|
|
803
|
-
const notRecommendedYet = [...(base.notRecommendedYet || [])];
|
|
804
|
-
if (rcStatus !== "candidate_ready" && !(rcStatus === "candidate_warn" && blockerCount === 0)) {
|
|
805
|
-
if (!notRecommendedYet.includes("Website / pricing � deferred until full readiness gate passes.")) {
|
|
806
|
-
notRecommendedYet.push("Website / pricing � deferred until full readiness gate passes.");
|
|
807
|
-
}
|
|
808
|
-
}
|
|
809
|
-
return { ...base, notRecommendedYet };
|
|
810
|
-
}
|
|
811
|
-
|
|
812
|
-
function buildCompanyLoop(cwd, options = {}) {
|
|
813
|
-
const { buildWorkLedger, writeWorkLedger } = require("./work-ledger");
|
|
814
|
-
const ledger = buildWorkLedger(cwd, options);
|
|
815
|
-
|
|
816
|
-
// Read alpha feedback into ledger friction signals (local only)
|
|
817
|
-
try {
|
|
818
|
-
const { readFeedbackSummary } = require("./alpha-feedback");
|
|
819
|
-
const feedbackSummary = readFeedbackSummary(cwd);
|
|
820
|
-
if (feedbackSummary && feedbackSummary.topFrictionType) {
|
|
821
|
-
const rollupFriction = ledger.rollup?.friction;
|
|
822
|
-
if (Array.isArray(rollupFriction)) {
|
|
823
|
-
rollupFriction.push(`alpha_feedback:${feedbackSummary.topFrictionType}`);
|
|
824
|
-
}
|
|
825
|
-
}
|
|
826
|
-
} catch {}
|
|
827
|
-
|
|
828
|
-
// Consume pre-launch intelligence signals (PR #147)
|
|
829
|
-
let intelligenceSignals = null;
|
|
830
|
-
try {
|
|
831
|
-
const { collectPrelaunchSignals, scorePrelaunchSignals } = require("./prelaunch-intelligence");
|
|
832
|
-
const { buildFeedbackIntelligenceSurface } = require("./feedback-intelligence");
|
|
833
|
-
const { buildTokenCostIntelligenceSurface } = require("./token-cost-intelligence");
|
|
834
|
-
const { buildInstallJourneySurface } = require("./install-journey-intelligence");
|
|
835
|
-
|
|
836
|
-
const signals = collectPrelaunchSignals(cwd, options);
|
|
837
|
-
const scoreData = scorePrelaunchSignals(signals, options);
|
|
838
|
-
const feedbackSurface = buildFeedbackIntelligenceSurface(cwd, options);
|
|
839
|
-
const tokenSurface = buildTokenCostIntelligenceSurface(cwd, options);
|
|
840
|
-
const journeySurface = buildInstallJourneySurface(cwd, options);
|
|
841
|
-
|
|
842
|
-
intelligenceSignals = {
|
|
843
|
-
prelaunchScore: scoreData.score,
|
|
844
|
-
prelaunchStatus: scoreData.score >= 85 ? "strong" : scoreData.score >= 60 ? "moderate" : "weak",
|
|
845
|
-
topFriction: feedbackSurface.topFriction,
|
|
846
|
-
feedbackClusters: feedbackSurface.clustersFound,
|
|
847
|
-
qualifiedFeedbackItemsCount: feedbackSurface.qualifiedFeedbackItemsCount || 0,
|
|
848
|
-
tokenEvidenceLevel: tokenSurface.evidenceLevel,
|
|
849
|
-
tokenRealUsageSamplesCount: tokenSurface.realUsageSamplesCount || 0,
|
|
850
|
-
journeyStatus: journeySurface.status,
|
|
851
|
-
manualStepsAvoided: journeySurface.manualStepsAvoided,
|
|
852
|
-
aiInstallReady: signals.installPrompt?.status === "ready",
|
|
853
|
-
prelaunchReadinessScore: signals.prelaunchReadiness?.score,
|
|
854
|
-
};
|
|
855
|
-
|
|
856
|
-
// Inject intelligence-based friction into ledger
|
|
857
|
-
const rollupFriction = ledger.rollup?.friction;
|
|
858
|
-
if (Array.isArray(rollupFriction)) {
|
|
859
|
-
if (feedbackSurface.topFriction) {
|
|
860
|
-
rollupFriction.push(`intelligence_friction:${feedbackSurface.topFriction}`);
|
|
861
|
-
}
|
|
862
|
-
if (tokenSurface.evidenceLevel === "not_available") {
|
|
863
|
-
rollupFriction.push("intelligence_friction:token_context_unknown");
|
|
864
|
-
}
|
|
865
|
-
if (journeySurface.status !== "ready") {
|
|
866
|
-
rollupFriction.push("intelligence_friction:install_journey_incomplete");
|
|
867
|
-
}
|
|
868
|
-
}
|
|
869
|
-
} catch {}
|
|
870
|
-
|
|
871
|
-
const personaFindings = runInternalPersonaReview(ledger);
|
|
872
|
-
const frictionClusters = clusterFriction(ledger, personaFindings);
|
|
873
|
-
const cogsRollup = buildCostCogsQualityRollup(ledger, personaFindings);
|
|
874
|
-
// Consume full readiness gate signals (PR #148)
|
|
875
|
-
let fullReadinessSignals = null;
|
|
876
|
-
try {
|
|
877
|
-
const { buildFullReadinessSurface } = require("./full-readiness-gate");
|
|
878
|
-
const { buildKnownLimitationsSurface } = require("./known-limitations");
|
|
879
|
-
const { buildProofOutcomeEvidenceSurface } = require("./proof-outcome-evidence");
|
|
880
|
-
const gateSurface = buildFullReadinessSurface(cwd, options);
|
|
881
|
-
const limitationsSurface = buildKnownLimitationsSurface(cwd, options);
|
|
882
|
-
const proofOutcomeSurface = buildProofOutcomeEvidenceSurface(cwd, options);
|
|
883
|
-
if (gateSurface.status !== "not_available") {
|
|
884
|
-
const limitationsList = limitationsSurface?.limitations || [];
|
|
885
|
-
fullReadinessSignals = {
|
|
886
|
-
gateStatus: gateSurface.status,
|
|
887
|
-
releaseCandidateStatus: gateSurface.releaseCandidateStatus,
|
|
888
|
-
blockerCount: gateSurface.blockerCount,
|
|
889
|
-
gateRecommendedNextPr: gateSurface.recommendedNextPr,
|
|
890
|
-
safetyBlocker: (gateSurface.blockerCount || 0) > 0 &&
|
|
891
|
-
["mcp_tool_governance","hook_safety_boundaries","support_bundle_redaction","no_false_claims"].some(
|
|
892
|
-
(id) => (gateSurface.blockers || []).find((b) => b.id === id)
|
|
893
|
-
),
|
|
894
|
-
adapterReadinessVerified: false, // will be updated when adapterReadinessSignals is consumed
|
|
895
|
-
installDistributionDominates:
|
|
896
|
-
(limitationsList).some((l) => l.id === "install_distribution" && l.severity !== "info") &&
|
|
897
|
-
(intelligenceSignals?.qualifiedFeedbackItemsCount || 0) > 0 &&
|
|
898
|
-
(intelligenceSignals?.tokenRealUsageSamplesCount || 0) > 0,
|
|
899
|
-
browserProofDominates:
|
|
900
|
-
intelligenceSignals?.topFriction === "browser_proof_missing" ||
|
|
901
|
-
(limitationsList).some((l) => l.id === "browser_proof_missing" && l.severity === "blocker"),
|
|
902
|
-
pluginAdapterDominates:
|
|
903
|
-
(limitationsList).some((l) => l.id === "plugin_adapter_pending" && l.severity === "blocker"),
|
|
904
|
-
feedbackInsufficient:
|
|
905
|
-
(intelligenceSignals?.qualifiedFeedbackItemsCount || 0) === 0,
|
|
906
|
-
tokenEvidenceMissing:
|
|
907
|
-
(intelligenceSignals?.tokenRealUsageSamplesCount || 0) === 0,
|
|
908
|
-
proofOutcomeMissing:
|
|
909
|
-
proofOutcomeSurface.latestProofAvailable !== true || (proofOutcomeSurface.realTaskProofCount || 0) === 0,
|
|
910
|
-
};
|
|
911
|
-
}
|
|
912
|
-
} catch {}
|
|
913
|
-
|
|
914
|
-
// Consume activation distribution readiness signals (PR #149)
|
|
915
|
-
let activationDistributionSignals = null;
|
|
916
|
-
try {
|
|
917
|
-
const { buildActivationDistributionSurface } = require("./activation-distribution-readiness");
|
|
918
|
-
const adrSurface = buildActivationDistributionSurface(cwd, options);
|
|
919
|
-
if (adrSurface.status !== "not_available") {
|
|
920
|
-
activationDistributionSignals = {
|
|
921
|
-
status: adrSurface.status,
|
|
922
|
-
score: adrSurface.score,
|
|
923
|
-
blockerCount: adrSurface.blockerCount || 0,
|
|
924
|
-
warningCount: adrSurface.warningCount || 0,
|
|
925
|
-
isReady: adrSurface.status === "ready",
|
|
926
|
-
safeNextAction: (adrSurface.safeNextActions || [])[0] || null,
|
|
927
|
-
};
|
|
928
|
-
if (fullReadinessSignals && activationDistributionSignals.blockerCount > 0) {
|
|
929
|
-
fullReadinessSignals.installDistributionDominates = true;
|
|
930
|
-
}
|
|
931
|
-
}
|
|
932
|
-
} catch {}
|
|
933
|
-
|
|
934
|
-
// Consume public distribution gate signals (PR #161)
|
|
935
|
-
let publicDistributionSignals = null;
|
|
936
|
-
try {
|
|
937
|
-
const pdGatePath = path.join(cwd, ".claude/cco/orchestration/public-distribution/latest-gate.json");
|
|
938
|
-
if (fs.existsSync(pdGatePath)) {
|
|
939
|
-
const pdGate = JSON.parse(fs.readFileSync(pdGatePath, "utf8"));
|
|
940
|
-
if (pdGate && pdGate.status) {
|
|
941
|
-
publicDistributionSignals = {
|
|
942
|
-
status: pdGate.status,
|
|
943
|
-
score: pdGate.score,
|
|
944
|
-
blockerCount: (pdGate.blockers || []).length,
|
|
945
|
-
warningCount: (pdGate.warnings || []).length,
|
|
946
|
-
publicInstallStatus: pdGate.publicInstallStatus,
|
|
947
|
-
claimSafetyStatus: pdGate.claimSafetyStatus,
|
|
948
|
-
recommendedNextPr: pdGate.recommendedNextPr,
|
|
949
|
-
isBlocked: pdGate.status === "blocked",
|
|
950
|
-
isLocalOnly: pdGate.status === "local_only",
|
|
951
|
-
};
|
|
952
|
-
// If distribution is blocked (false claims, forbidden files), elevate to full readiness
|
|
953
|
-
if (fullReadinessSignals && pdGate.status === "blocked") {
|
|
954
|
-
fullReadinessSignals.installDistributionDominates = true;
|
|
955
|
-
}
|
|
956
|
-
}
|
|
957
|
-
}
|
|
958
|
-
} catch {}
|
|
959
|
-
|
|
960
|
-
// Consume adapter technical readiness signals (PR #162)
|
|
961
|
-
let adapterReadinessSignals = null;
|
|
962
|
-
try {
|
|
963
|
-
const adapterGatePath = path.join(cwd, ".claude/cco/orchestration/adapter-readiness/latest-technical-gate.json");
|
|
964
|
-
if (fs.existsSync(adapterGatePath)) {
|
|
965
|
-
const adapterGate = JSON.parse(fs.readFileSync(adapterGatePath, "utf8"));
|
|
966
|
-
if (adapterGate && adapterGate.status) {
|
|
967
|
-
adapterReadinessSignals = {
|
|
968
|
-
status: adapterGate.status,
|
|
969
|
-
score: adapterGate.score,
|
|
970
|
-
verdict: adapterGate.verdict,
|
|
971
|
-
blockerCount: adapterGate.blockerCount || 0,
|
|
972
|
-
warningCount: adapterGate.warningCount || 0,
|
|
973
|
-
browserRequired: false,
|
|
974
|
-
noBrowserLaunch: true,
|
|
975
|
-
isReady: adapterGate.verdict === "adapter_ready",
|
|
976
|
-
isBlocked: adapterGate.status === "blocked",
|
|
977
|
-
safeNextAction: adapterGate.safeNextAction || null,
|
|
978
|
-
};
|
|
979
|
-
// If adapter readiness is blocked, elevate to full readiness
|
|
980
|
-
if (fullReadinessSignals && adapterGate.status === "blocked") {
|
|
981
|
-
fullReadinessSignals.pluginAdapterDominates = true;
|
|
982
|
-
}
|
|
983
|
-
// If adapter readiness is ready, clear plugin/adapter friction and mark verified
|
|
984
|
-
if (fullReadinessSignals && adapterGate.verdict === "adapter_ready") {
|
|
985
|
-
fullReadinessSignals.pluginAdapterDominates = false;
|
|
986
|
-
fullReadinessSignals.adapterReadinessVerified = true;
|
|
987
|
-
}
|
|
988
|
-
}
|
|
989
|
-
}
|
|
990
|
-
} catch {}
|
|
991
|
-
|
|
992
|
-
const nextPrRecommendation = recommendNextPrWithFullReadiness(
|
|
993
|
-
ledger, personaFindings, frictionClusters, intelligenceSignals, fullReadinessSignals
|
|
994
|
-
);
|
|
995
|
-
|
|
996
|
-
const warnCount = personaFindings.filter((p) => p.status === "warn").length;
|
|
997
|
-
const failCount = personaFindings.filter((p) => p.status === "fail").length;
|
|
998
|
-
const topFriction = frictionClusters[0]?.type || null;
|
|
999
|
-
|
|
1000
|
-
const reportStatus =
|
|
1001
|
-
failCount > 0 ? "fail" : warnCount > 2 ? "warn" : "pass";
|
|
1002
|
-
|
|
1003
|
-
const report = {
|
|
1004
|
-
contract: CONTRACT,
|
|
1005
|
-
schemaVersion: SCHEMA_VERSION,
|
|
1006
|
-
createdAt: new Date().toISOString(),
|
|
1007
|
-
status: reportStatus,
|
|
1008
|
-
ledger,
|
|
1009
|
-
personaFindings,
|
|
1010
|
-
frictionClusters,
|
|
1011
|
-
cogsRollup,
|
|
1012
|
-
nextPrRecommendation,
|
|
1013
|
-
intelligenceSignals,
|
|
1014
|
-
fullReadinessSignals,
|
|
1015
|
-
activationDistributionSignals,
|
|
1016
|
-
publicDistributionSignals,
|
|
1017
|
-
adapterReadinessSignals,
|
|
1018
|
-
surface: {
|
|
1019
|
-
status: reportStatus,
|
|
1020
|
-
latestReportPath: LATEST_REPORT_REL,
|
|
1021
|
-
personaWarnCount: warnCount,
|
|
1022
|
-
topFriction,
|
|
1023
|
-
recommendedNextPr: nextPrRecommendation.recommendedNextPr,
|
|
1024
|
-
confidence: nextPrRecommendation.confidence,
|
|
1025
|
-
},
|
|
1026
|
-
redacted: true,
|
|
1027
|
-
};
|
|
1028
|
-
|
|
1029
|
-
return report;
|
|
1030
|
-
}
|
|
1031
|
-
|
|
1032
|
-
function writeCompanyLoopReport(cwd, report) {
|
|
1033
|
-
const dir = path.join(cwd, LOOP_DIR_REL);
|
|
1034
|
-
fs.mkdirSync(dir, { recursive: true });
|
|
1035
|
-
const filePath = path.join(cwd, LATEST_REPORT_REL);
|
|
1036
|
-
fs.writeFileSync(filePath, JSON.stringify(report, null, 2), "utf8");
|
|
1037
|
-
return filePath;
|
|
1038
|
-
}
|
|
1039
|
-
|
|
1040
|
-
function buildCompanyLoopSurface(cwd) {
|
|
1041
|
-
const reportPath = path.join(cwd, LATEST_REPORT_REL);
|
|
1042
|
-
if (!fs.existsSync(reportPath)) {
|
|
1043
|
-
return {
|
|
1044
|
-
status: "not_available",
|
|
1045
|
-
latestReportPath: LATEST_REPORT_REL,
|
|
1046
|
-
personaWarnCount: 0,
|
|
1047
|
-
topFriction: null,
|
|
1048
|
-
recommendedNextPr: null,
|
|
1049
|
-
confidence: "low",
|
|
1050
|
-
};
|
|
1051
|
-
}
|
|
1052
|
-
const data = safeReadJson(reportPath);
|
|
1053
|
-
if (!data) return { status: "warn", latestReportPath: LATEST_REPORT_REL };
|
|
1054
|
-
return data.surface || {
|
|
1055
|
-
status: data.status,
|
|
1056
|
-
latestReportPath: LATEST_REPORT_REL,
|
|
1057
|
-
personaWarnCount: (data.personaFindings || []).filter((p) => p.status === "warn").length,
|
|
1058
|
-
topFriction: (data.frictionClusters || [])[0]?.type || null,
|
|
1059
|
-
recommendedNextPr: data.nextPrRecommendation?.recommendedNextPr || null,
|
|
1060
|
-
confidence: data.nextPrRecommendation?.confidence || "low",
|
|
1061
|
-
};
|
|
1062
|
-
}
|
|
1063
|
-
|
|
1064
|
-
function formatCompanyLoopText(report, options = {}) {
|
|
1065
|
-
const debug = options.debug === true;
|
|
1066
|
-
const lines = [];
|
|
1067
|
-
|
|
1068
|
-
lines.push(`Avorelo Company Loop: ${report.status}`);
|
|
1069
|
-
lines.push(`Created: ${report.createdAt}`);
|
|
1070
|
-
lines.push("");
|
|
1071
|
-
|
|
1072
|
-
const { nextPrRecommendation, frictionClusters, cogsRollup } = report;
|
|
1073
|
-
|
|
1074
|
-
if (nextPrRecommendation) {
|
|
1075
|
-
lines.push(`Recommended Next PR:`);
|
|
1076
|
-
lines.push(` ${nextPrRecommendation.recommendedNextPr}`);
|
|
1077
|
-
lines.push(` Why: ${nextPrRecommendation.whyNow}`);
|
|
1078
|
-
lines.push(` Confidence: ${nextPrRecommendation.confidence}`);
|
|
1079
|
-
lines.push("");
|
|
1080
|
-
}
|
|
1081
|
-
|
|
1082
|
-
if (frictionClusters?.length > 0) {
|
|
1083
|
-
lines.push("Top Friction Clusters:");
|
|
1084
|
-
for (const cluster of frictionClusters.slice(0, 5)) {
|
|
1085
|
-
lines.push(
|
|
1086
|
-
` - ${cluster.type} (${cluster.severity}, count: ${cluster.count}): ${cluster.recommendedFix}`
|
|
1087
|
-
);
|
|
1088
|
-
}
|
|
1089
|
-
lines.push("");
|
|
1090
|
-
} else {
|
|
1091
|
-
lines.push("Friction Clusters: none detected");
|
|
1092
|
-
lines.push("");
|
|
1093
|
-
}
|
|
1094
|
-
|
|
1095
|
-
if (cogsRollup) {
|
|
1096
|
-
lines.push("COGS / Quality Rollup:");
|
|
1097
|
-
lines.push(` Local stages used (estimate): ${cogsRollup.estimatedLocalStagesUsed}`);
|
|
1098
|
-
lines.push(` Context tokens saved (estimate): ${cogsRollup.estimatedContextTokensSaved}`);
|
|
1099
|
-
lines.push(` Estimate method: ${cogsRollup.estimateMethod}`);
|
|
1100
|
-
lines.push(` Quality checks verified: ${cogsRollup.qualityChecksVerified}`);
|
|
1101
|
-
lines.push("");
|
|
1102
|
-
}
|
|
1103
|
-
|
|
1104
|
-
if (debug) {
|
|
1105
|
-
lines.push("--- Debug: Persona Findings ---");
|
|
1106
|
-
for (const pf of report.personaFindings || []) {
|
|
1107
|
-
const label = PERSONA_LABELS[pf.persona] || pf.persona;
|
|
1108
|
-
lines.push(`[${pf.status.toUpperCase()}] ${label}:`);
|
|
1109
|
-
lines.push(` ${pf.finding}`);
|
|
1110
|
-
if (pf.evidence) lines.push(` Evidence: ${pf.evidence}`);
|
|
1111
|
-
if (pf.recommendedFix) lines.push(` Fix: ${pf.recommendedFix}`);
|
|
1112
|
-
if (pf.reasonCodes?.length > 0) lines.push(` Codes: ${pf.reasonCodes.join(", ")}`);
|
|
1113
|
-
}
|
|
1114
|
-
lines.push("");
|
|
1115
|
-
|
|
1116
|
-
lines.push("--- Debug: Not Recommended Yet ---");
|
|
1117
|
-
for (const item of nextPrRecommendation?.notRecommendedYet || []) {
|
|
1118
|
-
lines.push(` - ${item}`);
|
|
1119
|
-
}
|
|
1120
|
-
lines.push("");
|
|
1121
|
-
|
|
1122
|
-
lines.push("--- Debug: COGS Caveats ---");
|
|
1123
|
-
for (const caveat of cogsRollup?.caveats || []) {
|
|
1124
|
-
lines.push(` ${caveat}`);
|
|
1125
|
-
}
|
|
1126
|
-
}
|
|
1127
|
-
|
|
1128
|
-
return lines.join("\n");
|
|
1129
|
-
}
|
|
1130
|
-
|
|
1131
|
-
module.exports = {
|
|
1132
|
-
CONTRACT,
|
|
1133
|
-
SCHEMA_VERSION,
|
|
1134
|
-
PERSONAS,
|
|
1135
|
-
PERSONA_LABELS,
|
|
1136
|
-
FRICTION_CLUSTER_TYPES,
|
|
1137
|
-
ROADMAP_CANDIDATES,
|
|
1138
|
-
LATEST_REPORT_REL,
|
|
1139
|
-
runInternalPersonaReview,
|
|
1140
|
-
clusterFriction,
|
|
1141
|
-
buildCostCogsQualityRollup,
|
|
1142
|
-
recommendNextPr,
|
|
1143
|
-
recommendNextPrWithIntelligence,
|
|
1144
|
-
recommendNextPrWithFullReadiness,
|
|
1145
|
-
buildCompanyLoop,
|
|
1146
|
-
writeCompanyLoopReport,
|
|
1147
|
-
buildCompanyLoopSurface,
|
|
1148
|
-
formatCompanyLoopText,
|
|
1149
|
-
};
|