avorelo 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +56 -0
- package/bin/avorelo +9 -0
- package/package.json +135 -0
- package/scripts/README.md +40 -0
- package/scripts/cco-dashboard.js +252 -0
- package/scripts/cco-status.js +430 -0
- package/scripts/lib/activation/account-state.js +37 -0
- package/scripts/lib/activation/activation-runner.js +546 -0
- package/scripts/lib/activation/activation-self-healing.js +480 -0
- package/scripts/lib/activation/activation-state.js +83 -0
- package/scripts/lib/activation/activation-summary.js +191 -0
- package/scripts/lib/activation/adapters/claude-code.js +77 -0
- package/scripts/lib/activation/adapters/codex-cli.js +52 -0
- package/scripts/lib/activation/adapters/cursor.js +37 -0
- package/scripts/lib/activation/adapters/github-agent.js +39 -0
- package/scripts/lib/activation/adapters/terminal.js +42 -0
- package/scripts/lib/activation/adapters/vscode.js +39 -0
- package/scripts/lib/activation/adapters/windsurf.js +37 -0
- package/scripts/lib/activation/ai-surface-detector.js +151 -0
- package/scripts/lib/activation/connect-account.js +145 -0
- package/scripts/lib/activation/detect-environment.js +75 -0
- package/scripts/lib/activation/detect-hosts.js +62 -0
- package/scripts/lib/activation/format-activation-output.js +109 -0
- package/scripts/lib/activation/next-action.js +43 -0
- package/scripts/lib/activation/repair-engine.js +219 -0
- package/scripts/lib/activation-distribution-readiness.js +507 -0
- package/scripts/lib/adapter-conformance.js +176 -0
- package/scripts/lib/adapter-readiness.js +417 -0
- package/scripts/lib/adapter-safety-boundaries.js +335 -0
- package/scripts/lib/adapter-technical-readiness-gate.js +205 -0
- package/scripts/lib/agent-access-governance.js +455 -0
- package/scripts/lib/agent-enforcement.js +765 -0
- package/scripts/lib/agent-policy-profile.js +210 -0
- package/scripts/lib/agent-security/action-evaluator.js +507 -0
- package/scripts/lib/agent-security/adapter-registry.js +98 -0
- package/scripts/lib/agent-security/auto-policy.js +139 -0
- package/scripts/lib/agent-security/bounded-scan.js +93 -0
- package/scripts/lib/agent-security/enforcement-adapter.js +174 -0
- package/scripts/lib/agent-security/enforcement-engine.js +1129 -0
- package/scripts/lib/agent-security/file-write-adapter.js +183 -0
- package/scripts/lib/agent-security/file-write-rules.js +178 -0
- package/scripts/lib/agent-security/index.js +3342 -0
- package/scripts/lib/agent-security/instruction-risk.js +181 -0
- package/scripts/lib/agent-security/mcp-action-adapter.js +185 -0
- package/scripts/lib/agent-security/mcp-action-rules.js +184 -0
- package/scripts/lib/agent-security/package-action-adapter.js +175 -0
- package/scripts/lib/agent-security/package-action-rules.js +233 -0
- package/scripts/lib/agent-security/performance.js +148 -0
- package/scripts/lib/agent-security/permission-minimizer.js +403 -0
- package/scripts/lib/agent-security/scan-cache.js +74 -0
- package/scripts/lib/agent-security/source-trust.js +146 -0
- package/scripts/lib/ai-install-prompt.js +288 -0
- package/scripts/lib/ai-workspace-hygiene.js +1499 -0
- package/scripts/lib/alpha-activation.js +520 -0
- package/scripts/lib/alpha-feedback.js +263 -0
- package/scripts/lib/alpha-readiness-gate.js +332 -0
- package/scripts/lib/anti-gaming.js +169 -0
- package/scripts/lib/artifact-health.js +431 -0
- package/scripts/lib/attribution.js +180 -0
- package/scripts/lib/audit.js +289 -0
- package/scripts/lib/avorelo-skill-registry.js +810 -0
- package/scripts/lib/batch-jobs.js +71 -0
- package/scripts/lib/brain-pack.js +578 -0
- package/scripts/lib/brand-boundary.js +424 -0
- package/scripts/lib/brand.js +74 -0
- package/scripts/lib/browser-capability.js +1048 -0
- package/scripts/lib/browser-proof-preflight.js +321 -0
- package/scripts/lib/cache-readiness.js +187 -0
- package/scripts/lib/canonical-reentry.js +162 -0
- package/scripts/lib/capability-packs.js +314 -0
- package/scripts/lib/capability-recommender.js +512 -0
- package/scripts/lib/capability-registry.js +1059 -0
- package/scripts/lib/carry-forward-surfacing.js +194 -0
- package/scripts/lib/ccusage-adapter.js +188 -0
- package/scripts/lib/company-loop.js +1149 -0
- package/scripts/lib/config.js +637 -0
- package/scripts/lib/context-acquisition-plan.js +287 -0
- package/scripts/lib/context-budget-guard.js +170 -0
- package/scripts/lib/context-budget-scanner.js +257 -0
- package/scripts/lib/context-optimizer.js +715 -0
- package/scripts/lib/context-reduction-plan.js +178 -0
- package/scripts/lib/context-safety.js +88 -0
- package/scripts/lib/context-savings-engine.js +158 -0
- package/scripts/lib/cost-evidence.js +254 -0
- package/scripts/lib/cross-host-install-plan.js +308 -0
- package/scripts/lib/cross-host-install-readiness.js +237 -0
- package/scripts/lib/cross-host-value-flow.js +268 -0
- package/scripts/lib/dashboard.js +900 -0
- package/scripts/lib/design-partner-feedback.js +346 -0
- package/scripts/lib/entitlements.js +100 -0
- package/scripts/lib/execution-packet.js +559 -0
- package/scripts/lib/experimentation-events.js +547 -0
- package/scripts/lib/external-capability-compliance.js +107 -0
- package/scripts/lib/external-user-simulation.js +166 -0
- package/scripts/lib/failure-recovery-readiness.js +81 -0
- package/scripts/lib/failure-recovery.js +419 -0
- package/scripts/lib/feedback-intelligence.js +537 -0
- package/scripts/lib/feedback-signals.js +205 -0
- package/scripts/lib/file-integrity.js +68 -0
- package/scripts/lib/fsx.js +127 -0
- package/scripts/lib/full-readiness-gate.js +451 -0
- package/scripts/lib/guidance-builder.js +174 -0
- package/scripts/lib/hook-apply.js +1019 -0
- package/scripts/lib/hook-baseline.js +310 -0
- package/scripts/lib/hook-config-preview.js +275 -0
- package/scripts/lib/hook-contracts.js +290 -0
- package/scripts/lib/hook-safety-boundary-readiness.js +80 -0
- package/scripts/lib/host-capability-matrix.js +351 -0
- package/scripts/lib/host-support-context.js +254 -0
- package/scripts/lib/http-hook-action.js +538 -0
- package/scripts/lib/install-ai-readiness.js +84 -0
- package/scripts/lib/install-intake-risk.js +1037 -0
- package/scripts/lib/install-journey-intelligence.js +329 -0
- package/scripts/lib/intervention-guidance.js +57 -0
- package/scripts/lib/known-limitations.js +115 -0
- package/scripts/lib/l8-path-truth.js +146 -0
- package/scripts/lib/launch-hardening-gate.js +436 -0
- package/scripts/lib/launch-readiness.js +628 -0
- package/scripts/lib/learning-memory.js +686 -0
- package/scripts/lib/lifecycle-hooks.js +802 -0
- package/scripts/lib/local-package-smoke.js +423 -0
- package/scripts/lib/local-pricing.js +299 -0
- package/scripts/lib/mcp-enforcement.js +311 -0
- package/scripts/lib/mcp-least-privilege-policy.js +303 -0
- package/scripts/lib/mcp-tool-inventory.js +388 -0
- package/scripts/lib/mcp-tool-risk.js +0 -0
- package/scripts/lib/memory.js +335 -0
- package/scripts/lib/metrics.js +699 -0
- package/scripts/lib/micro-proof.js +133 -0
- package/scripts/lib/next-run-context.js +436 -0
- package/scripts/lib/operating-value.js +1648 -0
- package/scripts/lib/optimization-v3.js +122 -0
- package/scripts/lib/orchestration/adapters/_shared.js +49 -0
- package/scripts/lib/orchestration/adapters/aider.js +18 -0
- package/scripts/lib/orchestration/adapters/claude-code.js +35 -0
- package/scripts/lib/orchestration/adapters/codex.js +35 -0
- package/scripts/lib/orchestration/adapters/gemini-cli.js +18 -0
- package/scripts/lib/orchestration/adapters/git.js +25 -0
- package/scripts/lib/orchestration/adapters/index.js +31 -0
- package/scripts/lib/orchestration/adapters/lm-studio.js +18 -0
- package/scripts/lib/orchestration/adapters/ollama.js +18 -0
- package/scripts/lib/orchestration/adapters/opencode.js +18 -0
- package/scripts/lib/orchestration/adapters/openrouter.js +18 -0
- package/scripts/lib/orchestration/adapters/test-runner.js +25 -0
- package/scripts/lib/orchestration/cli.js +438 -0
- package/scripts/lib/orchestration/execution-manager.js +279 -0
- package/scripts/lib/orchestration/handoff.js +314 -0
- package/scripts/lib/orchestration/index.js +456 -0
- package/scripts/lib/orchestration/inventory.js +47 -0
- package/scripts/lib/orchestration/model-discovery.js +498 -0
- package/scripts/lib/orchestration/model-profiler.js +170 -0
- package/scripts/lib/orchestration/model-profiles.js +252 -0
- package/scripts/lib/orchestration/model-refresh-policy.js +72 -0
- package/scripts/lib/orchestration/proof-writer.js +349 -0
- package/scripts/lib/orchestration/provider-discovery/aider.js +49 -0
- package/scripts/lib/orchestration/provider-discovery/claude-code.js +56 -0
- package/scripts/lib/orchestration/provider-discovery/codex.js +49 -0
- package/scripts/lib/orchestration/provider-discovery/common.js +186 -0
- package/scripts/lib/orchestration/provider-discovery/gemini.js +106 -0
- package/scripts/lib/orchestration/provider-discovery/lm-studio.js +118 -0
- package/scripts/lib/orchestration/provider-discovery/models-dev.js +12 -0
- package/scripts/lib/orchestration/provider-discovery/ollama.js +100 -0
- package/scripts/lib/orchestration/provider-discovery/opencode.js +47 -0
- package/scripts/lib/orchestration/provider-discovery/openrouter.js +44 -0
- package/scripts/lib/orchestration/risk-classifier.js +130 -0
- package/scripts/lib/orchestration/routing-policy.js +486 -0
- package/scripts/lib/orchestration/settings.js +112 -0
- package/scripts/lib/orchestration/state.js +165 -0
- package/scripts/lib/orchestration/verification-manager.js +138 -0
- package/scripts/lib/output-profiles.js +146 -0
- package/scripts/lib/package-content-audit.js +368 -0
- package/scripts/lib/package-runtime.js +278 -0
- package/scripts/lib/plan-surface.js +53 -0
- package/scripts/lib/plans.js +2318 -0
- package/scripts/lib/policy-provider.js +27 -0
- package/scripts/lib/prelaunch-activation-readiness.js +409 -0
- package/scripts/lib/prelaunch-evidence-store.js +816 -0
- package/scripts/lib/prelaunch-intelligence.js +869 -0
- package/scripts/lib/pricing-experiment.js +118 -0
- package/scripts/lib/pro-moment-events.js +77 -0
- package/scripts/lib/pro-moment-state.js +227 -0
- package/scripts/lib/pro-moments.js +1216 -0
- package/scripts/lib/product-learning-events.js +629 -0
- package/scripts/lib/project-profile.js +555 -0
- package/scripts/lib/prompt-compiler.js +280 -0
- package/scripts/lib/prompt-lint.js +32 -0
- package/scripts/lib/prompt-suggestions.js +52 -0
- package/scripts/lib/proof-canonical.js +398 -0
- package/scripts/lib/proof-drilldown.js +383 -0
- package/scripts/lib/proof-events.js +342 -0
- package/scripts/lib/proof-history.js +243 -0
- package/scripts/lib/proof-metrics.js +296 -0
- package/scripts/lib/proof-outcome-evidence.js +134 -0
- package/scripts/lib/proof-receipt.js +335 -0
- package/scripts/lib/proof-record.js +461 -0
- package/scripts/lib/public-activation-distribution-gate.js +258 -0
- package/scripts/lib/public-cli.js +3891 -0
- package/scripts/lib/public-distribution-truth.js +211 -0
- package/scripts/lib/public-install-claim-checker.js +294 -0
- package/scripts/lib/publish-provenance-readiness.js +283 -0
- package/scripts/lib/readiness-delta.js +218 -0
- package/scripts/lib/readiness-evidence-closure.js +196 -0
- package/scripts/lib/reentry-memory-capture.js +241 -0
- package/scripts/lib/reentry-memory-retrieval.js +302 -0
- package/scripts/lib/reentry-memory-status.js +146 -0
- package/scripts/lib/reentry-memory-store.js +178 -0
- package/scripts/lib/reentry-state.js +66 -0
- package/scripts/lib/release-candidate-bundle.js +166 -0
- package/scripts/lib/remediation.js +81 -0
- package/scripts/lib/repo-map.js +391 -0
- package/scripts/lib/run-improvements-lifecycle.js +330 -0
- package/scripts/lib/run-improvements.js +789 -0
- package/scripts/lib/runtime-decision-policy.js +387 -0
- package/scripts/lib/safe-path-engine.js +705 -0
- package/scripts/lib/safe-run-controller.js +887 -0
- package/scripts/lib/score.js +262 -0
- package/scripts/lib/seamless-enforcement.js +329 -0
- package/scripts/lib/seamless-outcome.js +689 -0
- package/scripts/lib/seamless-reality-gate.js +5043 -0
- package/scripts/lib/security-risk-classifier.js +511 -0
- package/scripts/lib/security-scan.js +384 -0
- package/scripts/lib/session-context-optimizer.js +1211 -0
- package/scripts/lib/session-timing.js +315 -0
- package/scripts/lib/skill-hygiene.js +805 -0
- package/scripts/lib/skill-packs.js +161 -0
- package/scripts/lib/skills-operating-layer.js +580 -0
- package/scripts/lib/smart-work-routing.js +768 -0
- package/scripts/lib/source-catalog.js +700 -0
- package/scripts/lib/status-value-summary.js +32 -0
- package/scripts/lib/support-bundle.js +578 -0
- package/scripts/lib/task-continuation.js +440 -0
- package/scripts/lib/test-helpers.js +15 -0
- package/scripts/lib/tier.js +38 -0
- package/scripts/lib/token-context-quality-gate.js +370 -0
- package/scripts/lib/token-cost-capture.js +187 -0
- package/scripts/lib/token-cost-intelligence.js +358 -0
- package/scripts/lib/token-efficiency-evidence.js +213 -0
- package/scripts/lib/token-evidence.js +699 -0
- package/scripts/lib/tokenish.js +17 -0
- package/scripts/lib/tool-output-sandbox.js +304 -0
- package/scripts/lib/trust-audit.js +136 -0
- package/scripts/lib/unified-events.js +396 -0
- package/scripts/lib/upgrade-interruption-recovery.js +407 -0
- package/scripts/lib/usage-ledger.js +201 -0
- package/scripts/lib/value-ledger.js +130 -0
- package/scripts/lib/value-proof-calibration.js +531 -0
- package/scripts/lib/visual-qa.js +231 -0
- package/scripts/lib/voice-alpha.js +29 -0
- package/scripts/lib/work-aware-orchestration.js +976 -0
- package/scripts/lib/work-control-receipts.js +577 -0
- package/scripts/lib/work-ledger.js +1123 -0
- package/scripts/lib/work-panel-preview.js +352 -0
- package/scripts/lib/workflow-discipline.js +280 -0
- package/scripts/lib/workflow-signals.js +419 -0
- package/scripts/lib/workspace-map.js +281 -0
- package/scripts/lib/workspace-registry.js +1367 -0
- package/scripts/lib/workspace-resolver.js +480 -0
|
@@ -0,0 +1,507 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
// ── Activation Distribution Readiness ────────────────────────────────────────
|
|
4
|
+
// Contract: avorelo.activationDistributionReadiness.v1
|
|
5
|
+
// Answers: "Can a first external user install, activate, see first value,
|
|
6
|
+
// understand limitations, and recover safely without founder hand-holding?"
|
|
7
|
+
// Does NOT claim public launch readiness. Honest about missing evidence.
|
|
8
|
+
|
|
9
|
+
const fs = require("fs");
|
|
10
|
+
const path = require("path");
|
|
11
|
+
const { nowIso } = require("./fsx");
|
|
12
|
+
const { appendProductLearningEvent } = require("./product-learning-events");
|
|
13
|
+
|
|
14
|
+
const CONTRACT = "avorelo.activationDistributionReadiness.v1";
|
|
15
|
+
const SCHEMA_VERSION = 1;
|
|
16
|
+
const ARTIFACT_DIR_REL = ".claude/cco/orchestration/activation-distribution";
|
|
17
|
+
const ARTIFACT_REL = ARTIFACT_DIR_REL + "/latest-activation-distribution-readiness.json";
|
|
18
|
+
|
|
19
|
+
const SCORE_READY = 85;
|
|
20
|
+
const SCORE_WARN = 70;
|
|
21
|
+
|
|
22
|
+
const CHECK_WEIGHTS = {
|
|
23
|
+
install_command_available: 8,
|
|
24
|
+
install_docs_current: 5,
|
|
25
|
+
activation_entrypoint_available: 8,
|
|
26
|
+
doctor_available: 5,
|
|
27
|
+
first_value_surface_available: 8,
|
|
28
|
+
clear_next_action_available: 6,
|
|
29
|
+
recovery_path_available: 7,
|
|
30
|
+
support_bundle_available: 6,
|
|
31
|
+
known_limitations_visible: 5,
|
|
32
|
+
release_candidate_bundle_safe: 6,
|
|
33
|
+
evidence_closure_complete: 6,
|
|
34
|
+
external_user_simulation_covered: 6,
|
|
35
|
+
token_cost_honest: 7,
|
|
36
|
+
feedback_intelligence_honest: 7,
|
|
37
|
+
no_public_launch_claim: 8,
|
|
38
|
+
safe_next_action_exists: 6,
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const TOTAL_WEIGHT = Object.values(CHECK_WEIGHTS).reduce(function(a, b) { return a + b; }, 0);
|
|
42
|
+
|
|
43
|
+
function safeReadJson(absPath) {
|
|
44
|
+
try {
|
|
45
|
+
if (!fs.existsSync(absPath)) return null;
|
|
46
|
+
return JSON.parse(fs.readFileSync(absPath, "utf8").replace(/^/, ""));
|
|
47
|
+
} catch { return null; }
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function pass(id, label, evidence, detail) {
|
|
51
|
+
return { id: id, label: label, status: "pass", evidence: evidence || null, detail: detail || null, safeNextAction: null };
|
|
52
|
+
}
|
|
53
|
+
function warn(id, label, safeNextAction, evidence, detail) {
|
|
54
|
+
return { id: id, label: label, status: "warn", evidence: evidence || null, detail: detail || null, safeNextAction: safeNextAction || "Run readiness closure to identify missing evidence." };
|
|
55
|
+
}
|
|
56
|
+
function blocked(id, label, safeNextAction, evidence, detail) {
|
|
57
|
+
return { id: id, label: label, status: "blocked", evidence: evidence || null, detail: detail || null, safeNextAction: safeNextAction || "Fix blocker before proceeding." };
|
|
58
|
+
}
|
|
59
|
+
function info(id, label, detail) {
|
|
60
|
+
return { id: id, label: label, status: "info", evidence: null, detail: detail || null, safeNextAction: null };
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function checkInstallCommandAvailable(cwd) {
|
|
64
|
+
const binPath = path.join(cwd, "bin", "avorelo");
|
|
65
|
+
const hasBin = fs.existsSync(binPath);
|
|
66
|
+
const pkgPath = path.join(cwd, "package.json");
|
|
67
|
+
const pkg = safeReadJson(pkgPath);
|
|
68
|
+
const hasBinField = pkg && pkg.bin && (typeof pkg.bin === "string" || Object.keys(pkg.bin).length > 0);
|
|
69
|
+
if (!hasBin && !hasBinField) {
|
|
70
|
+
return blocked("install_command_available", "Install command available",
|
|
71
|
+
"Create bin/avorelo entry point. Add bin field to package.json.",
|
|
72
|
+
null, "No bin/avorelo and no bin field in package.json.");
|
|
73
|
+
}
|
|
74
|
+
return pass("install_command_available", "Install command available",
|
|
75
|
+
{ binExists: hasBin, pkgBinField: !!hasBinField }, null);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function checkInstallDocsCurrent(cwd) {
|
|
79
|
+
const docsDir = path.join(cwd, "docs");
|
|
80
|
+
if (!fs.existsSync(docsDir)) {
|
|
81
|
+
return warn("install_docs_current", "Install docs current",
|
|
82
|
+
"Create docs/ directory with install instructions.",
|
|
83
|
+
null, "No docs directory found.");
|
|
84
|
+
}
|
|
85
|
+
const docFiles = fs.readdirSync(docsDir).filter(function(f) {
|
|
86
|
+
return f.toLowerCase().includes("install") || f.toLowerCase().includes("activation") || f.toLowerCase().includes("readiness");
|
|
87
|
+
});
|
|
88
|
+
if (docFiles.length === 0) {
|
|
89
|
+
return warn("install_docs_current", "Install docs current",
|
|
90
|
+
"Add install/activation documentation to docs/ directory.",
|
|
91
|
+
null, "No install or activation docs found in docs/.");
|
|
92
|
+
}
|
|
93
|
+
return pass("install_docs_current", "Install docs current",
|
|
94
|
+
{ docCount: docFiles.length, examples: docFiles.slice(0, 3) }, null);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function checkActivationEntrypointAvailable(cwd) {
|
|
98
|
+
const cliPath = path.join(cwd, "scripts", "lib", "public-cli.js");
|
|
99
|
+
if (!fs.existsSync(cliPath)) {
|
|
100
|
+
return blocked("activation_entrypoint_available", "Activation entrypoint available",
|
|
101
|
+
"Create scripts/lib/public-cli.js with activate command.",
|
|
102
|
+
null, "public-cli.js not found.");
|
|
103
|
+
}
|
|
104
|
+
const content = fs.readFileSync(cliPath, "utf8");
|
|
105
|
+
const hasActivate = content.includes('"activate"') || content.includes("'activate'");
|
|
106
|
+
const hasInstallAi = content.includes('"install-ai"') || content.includes("'install-ai'");
|
|
107
|
+
if (!hasActivate && !hasInstallAi) {
|
|
108
|
+
return warn("activation_entrypoint_available", "Activation entrypoint available",
|
|
109
|
+
"Add activate or install-ai command to public-cli.js.",
|
|
110
|
+
null, "No activate or install-ai command found in public-cli.js.");
|
|
111
|
+
}
|
|
112
|
+
return pass("activation_entrypoint_available", "Activation entrypoint available",
|
|
113
|
+
{ hasActivate: hasActivate, hasInstallAi: hasInstallAi }, null);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function checkDoctorAvailable(cwd) {
|
|
117
|
+
const cliPath = path.join(cwd, "scripts", "lib", "public-cli.js");
|
|
118
|
+
if (!fs.existsSync(cliPath)) {
|
|
119
|
+
return warn("doctor_available", "Doctor/readiness check available",
|
|
120
|
+
"Add doctor command to public-cli.js.",
|
|
121
|
+
null, "public-cli.js not found.");
|
|
122
|
+
}
|
|
123
|
+
const content = fs.readFileSync(cliPath, "utf8");
|
|
124
|
+
const hasDoctor = content.includes('"doctor"') || content.includes("'doctor'");
|
|
125
|
+
const hasReadiness = content.includes('"readiness"') || content.includes("'readiness'");
|
|
126
|
+
const hasPrelaunhReadiness = content.includes('"prelaunch-readiness"') || content.includes("'prelaunch-readiness'");
|
|
127
|
+
if (!hasDoctor && !hasReadiness && !hasPrelaunhReadiness) {
|
|
128
|
+
return warn("doctor_available", "Doctor/readiness check available",
|
|
129
|
+
"Add a doctor or readiness command so users can self-diagnose setup issues.",
|
|
130
|
+
null, "No doctor or readiness command found.");
|
|
131
|
+
}
|
|
132
|
+
return pass("doctor_available", "Doctor/readiness check available",
|
|
133
|
+
{ hasDoctor: hasDoctor, hasReadiness: hasReadiness }, null);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function checkFirstValueSurfaceAvailable(cwd) {
|
|
137
|
+
const firstValueArtifact = safeReadJson(path.join(cwd, ".claude/cco/orchestration/prelaunch-readiness/latest-activation-readiness.json"));
|
|
138
|
+
const valueSummary = safeReadJson(path.join(cwd, ".claude/cco/orchestration/seamless-outcome/latest-value-summary.json"));
|
|
139
|
+
const cliPath = path.join(cwd, "scripts", "lib", "public-cli.js");
|
|
140
|
+
const hasFirstValueCmd = fs.existsSync(cliPath) &&
|
|
141
|
+
(fs.readFileSync(cliPath, "utf8").includes("first-value") || fs.readFileSync(cliPath, "utf8").includes("first_value"));
|
|
142
|
+
if (!firstValueArtifact && !valueSummary && !hasFirstValueCmd) {
|
|
143
|
+
return warn("first_value_surface_available", "First value surface available",
|
|
144
|
+
"Run: node bin/avorelo first-value-check --json to generate first value surface.",
|
|
145
|
+
null, "No first-value artifact or command found.");
|
|
146
|
+
}
|
|
147
|
+
return pass("first_value_surface_available", "First value surface available",
|
|
148
|
+
{ hasActivationArtifact: !!firstValueArtifact, hasValueSummary: !!valueSummary, hasCliCommand: hasFirstValueCmd }, null);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function checkClearNextActionAvailable(cwd) {
|
|
152
|
+
const gate = safeReadJson(path.join(cwd, ".claude/cco/orchestration/full-readiness/latest-gate.json"));
|
|
153
|
+
if (!gate) {
|
|
154
|
+
return warn("clear_next_action_available", "Clear next action available",
|
|
155
|
+
"Run: node bin/avorelo full-readiness --json to generate gate with safeNextAction.",
|
|
156
|
+
null, "Full readiness gate artifact not found.");
|
|
157
|
+
}
|
|
158
|
+
if (!gate.safeNextAction || gate.safeNextAction.length < 10) {
|
|
159
|
+
return warn("clear_next_action_available", "Clear next action available",
|
|
160
|
+
"Re-run full-readiness gate. safeNextAction should be specific and actionable.",
|
|
161
|
+
gate, "Gate has no safeNextAction or it is too vague.");
|
|
162
|
+
}
|
|
163
|
+
return pass("clear_next_action_available", "Clear next action available",
|
|
164
|
+
{ safeNextAction: gate.safeNextAction.slice(0, 80) }, null);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
function checkRecoveryPathAvailable(cwd) {
|
|
168
|
+
const hardening = safeReadJson(path.join(cwd, ".claude/cco/orchestration/launch-hardening/latest-gate.json"));
|
|
169
|
+
const failureRecovery = safeReadJson(path.join(cwd, ".claude/cco/orchestration/launch-hardening/latest-failure-recovery.json"));
|
|
170
|
+
const cliPath = path.join(cwd, "scripts", "lib", "public-cli.js");
|
|
171
|
+
const hasRecoveryCmd = fs.existsSync(cliPath) &&
|
|
172
|
+
(fs.readFileSync(cliPath, "utf8").includes("recovery") || fs.readFileSync(cliPath, "utf8").includes("resume"));
|
|
173
|
+
if (!hardening && !failureRecovery && !hasRecoveryCmd) {
|
|
174
|
+
return warn("recovery_path_available", "Failure/recovery path available",
|
|
175
|
+
"Run: node bin/avorelo launch-hardening --json to verify recovery gates.",
|
|
176
|
+
null, "No hardening or failure recovery artifact found.");
|
|
177
|
+
}
|
|
178
|
+
return pass("recovery_path_available", "Failure/recovery path available",
|
|
179
|
+
{ hasHardening: !!hardening, hasFailureRecovery: !!failureRecovery, hasCli: hasRecoveryCmd }, null);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
function checkSupportBundleAvailable(cwd) {
|
|
183
|
+
const bundle = safeReadJson(path.join(cwd, ".claude/cco/support/latest-support-bundle.json"));
|
|
184
|
+
if (!bundle) {
|
|
185
|
+
return warn("support_bundle_available", "Support bundle available",
|
|
186
|
+
"Run: node bin/avorelo support-bundle --json to generate a redacted support bundle.",
|
|
187
|
+
null, "Support bundle artifact not found.");
|
|
188
|
+
}
|
|
189
|
+
if (bundle.redacted !== true) {
|
|
190
|
+
return blocked("support_bundle_available", "Support bundle available",
|
|
191
|
+
"Regenerate support bundle with redacted: true.",
|
|
192
|
+
null, "Support bundle exists but redacted is not true — safety violation.");
|
|
193
|
+
}
|
|
194
|
+
return pass("support_bundle_available", "Support bundle available",
|
|
195
|
+
{ redacted: bundle.redacted }, null);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
function checkKnownLimitationsVisible(cwd) {
|
|
199
|
+
const kl = safeReadJson(path.join(cwd, ".claude/cco/orchestration/full-readiness/latest-known-limitations.json"));
|
|
200
|
+
if (!kl) {
|
|
201
|
+
return warn("known_limitations_visible", "Known limitations visible",
|
|
202
|
+
"Run: node bin/avorelo known-limitations --json to generate limitations register.",
|
|
203
|
+
null, "Known limitations artifact not found.");
|
|
204
|
+
}
|
|
205
|
+
if (!kl.limitations || kl.limitations.length === 0) {
|
|
206
|
+
return warn("known_limitations_visible", "Known limitations visible",
|
|
207
|
+
"Known limitations register is empty — must document real limitations.",
|
|
208
|
+
null, "Empty limitations register.");
|
|
209
|
+
}
|
|
210
|
+
const blockers = kl.limitations.filter(function(l) { return l.severity === "blocker" && l.status === "needs_fix"; });
|
|
211
|
+
if (blockers.length > 0) {
|
|
212
|
+
return blocked("known_limitations_visible", "Known limitations visible",
|
|
213
|
+
"Resolve blocker limitations before proceeding with distribution.",
|
|
214
|
+
{ blockerIds: blockers.map(function(b) { return b.id; }) },
|
|
215
|
+
blockers.length + " blocker limitation(s) unresolved.");
|
|
216
|
+
}
|
|
217
|
+
return pass("known_limitations_visible", "Known limitations visible",
|
|
218
|
+
{ totalLimitations: kl.limitations.length, blockers: 0 }, null);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
function checkReleaseCandidateBundleSafe(cwd) {
|
|
222
|
+
const rcb = safeReadJson(path.join(cwd, ".claude/cco/orchestration/full-readiness/latest-release-candidate-bundle.json"));
|
|
223
|
+
if (!rcb) {
|
|
224
|
+
return warn("release_candidate_bundle_safe", "Release candidate bundle safe",
|
|
225
|
+
"Run: node bin/avorelo release-candidate-bundle --json",
|
|
226
|
+
null, "Release candidate bundle not found.");
|
|
227
|
+
}
|
|
228
|
+
if (rcb.rawContentExcluded !== true) {
|
|
229
|
+
return blocked("release_candidate_bundle_safe", "Release candidate bundle safe",
|
|
230
|
+
"Regenerate release candidate bundle. rawContentExcluded must be true.",
|
|
231
|
+
null, "rawContentExcluded is not true — raw content may be exposed.");
|
|
232
|
+
}
|
|
233
|
+
return pass("release_candidate_bundle_safe", "Release candidate bundle safe",
|
|
234
|
+
{ rawContentExcluded: rcb.rawContentExcluded, redacted: rcb.redacted }, null);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
function checkEvidenceClosureComplete(cwd) {
|
|
238
|
+
const ec = safeReadJson(path.join(cwd, ".claude/cco/orchestration/full-readiness/latest-evidence-closure.json"));
|
|
239
|
+
if (!ec) {
|
|
240
|
+
return warn("evidence_closure_complete", "Evidence closure complete",
|
|
241
|
+
"Run: node bin/avorelo readiness-closure --json",
|
|
242
|
+
null, "Evidence closure artifact not found.");
|
|
243
|
+
}
|
|
244
|
+
if (ec.status === "complete") {
|
|
245
|
+
return pass("evidence_closure_complete", "Evidence closure complete",
|
|
246
|
+
{ evidencePresentCount: ec.evidencePresentCount, totalChecked: ec.totalChecked }, null);
|
|
247
|
+
}
|
|
248
|
+
if (ec.evidenceMissingCount > 0) {
|
|
249
|
+
return warn("evidence_closure_complete", "Evidence closure complete",
|
|
250
|
+
ec.nextAction || "Follow recoverCommand for each missing artifact.",
|
|
251
|
+
{ presentCount: ec.evidencePresentCount, missingCount: ec.evidenceMissingCount },
|
|
252
|
+
ec.evidenceMissingCount + " artifact(s) still missing.");
|
|
253
|
+
}
|
|
254
|
+
return pass("evidence_closure_complete", "Evidence closure complete",
|
|
255
|
+
{ status: ec.status }, null);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
function checkExternalUserSimulationCovered(cwd) {
|
|
259
|
+
const sim = safeReadJson(path.join(cwd, ".claude/cco/orchestration/full-readiness/latest-external-user-simulation.json"));
|
|
260
|
+
if (!sim) {
|
|
261
|
+
return warn("external_user_simulation_covered", "External user simulation covered",
|
|
262
|
+
"Run: node bin/avorelo external-user-sim --json",
|
|
263
|
+
null, "External user simulation not run.");
|
|
264
|
+
}
|
|
265
|
+
if (sim.blocked > 0) {
|
|
266
|
+
return blocked("external_user_simulation_covered", "External user simulation covered",
|
|
267
|
+
"Fix blocked scenarios. Run: node bin/avorelo external-user-sim --json",
|
|
268
|
+
{ blockedCount: sim.blocked },
|
|
269
|
+
sim.blocked + " scenario(s) blocked in external user simulation.");
|
|
270
|
+
}
|
|
271
|
+
return pass("external_user_simulation_covered", "External user simulation covered",
|
|
272
|
+
{ passed: sim.passed, warned: sim.warned, total: sim.totalScenarios }, null);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
function checkTokenCostHonest(cwd) {
|
|
276
|
+
const tc = safeReadJson(path.join(cwd, ".claude/cco/orchestration/prelaunch-intelligence/latest-token-cost-intelligence.json"));
|
|
277
|
+
if (!tc) {
|
|
278
|
+
return warn("token_cost_honest", "Token cost evidence honest",
|
|
279
|
+
"Run: node bin/avorelo token-cost --json. Status not_available is acceptable.",
|
|
280
|
+
null, "Token cost intelligence artifact not found.");
|
|
281
|
+
}
|
|
282
|
+
if (tc.noExactSavingsClaim !== true) {
|
|
283
|
+
return blocked("token_cost_honest", "Token cost evidence honest",
|
|
284
|
+
"Ensure noExactSavingsClaim=true in token cost intelligence.",
|
|
285
|
+
null, "noExactSavingsClaim is not true — exact savings claim may be made.");
|
|
286
|
+
}
|
|
287
|
+
return pass("token_cost_honest", "Token cost evidence honest",
|
|
288
|
+
{ status: tc.status, evidenceLevel: tc.evidenceLevel, noExactSavingsClaim: tc.noExactSavingsClaim }, null);
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
function checkFeedbackIntelligenceHonest(cwd) {
|
|
292
|
+
const fi = safeReadJson(path.join(cwd, ".claude/cco/orchestration/prelaunch-intelligence/latest-feedback-intelligence.json"));
|
|
293
|
+
if (!fi) {
|
|
294
|
+
return warn("feedback_intelligence_honest", "Feedback intelligence honest",
|
|
295
|
+
"Run: node bin/avorelo feedback insights --json. Insufficient is acceptable; missing is not.",
|
|
296
|
+
null, "Feedback intelligence artifact not found.");
|
|
297
|
+
}
|
|
298
|
+
// As long as the artifact exists and represents the truth, it passes — even if insufficient
|
|
299
|
+
return pass("feedback_intelligence_honest", "Feedback intelligence honest",
|
|
300
|
+
{ status: fi.status, sessionsAnalyzed: fi.sessionsAnalyzed, redacted: fi.redacted }, null);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
function checkNoPublicLaunchClaim(cwd) {
|
|
304
|
+
const gate = safeReadJson(path.join(cwd, ".claude/cco/orchestration/full-readiness/latest-gate.json"));
|
|
305
|
+
const rcb = safeReadJson(path.join(cwd, ".claude/cco/orchestration/full-readiness/latest-release-candidate-bundle.json"));
|
|
306
|
+
var violations = [];
|
|
307
|
+
if (gate && gate.noPublicLaunchClaim !== true) violations.push("full-readiness gate");
|
|
308
|
+
if (rcb && rcb.noPublicLaunchClaim !== true) violations.push("release-candidate-bundle");
|
|
309
|
+
if (violations.length > 0) {
|
|
310
|
+
return blocked("no_public_launch_claim", "No public launch claim on outputs",
|
|
311
|
+
"Set noPublicLaunchClaim: true on all output artifacts.",
|
|
312
|
+
null, "Violations: " + violations.join(", "));
|
|
313
|
+
}
|
|
314
|
+
return pass("no_public_launch_claim", "No public launch claim on outputs",
|
|
315
|
+
{ verified: ["full-readiness gate", "release-candidate-bundle"] }, null);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
function checkSafeNextActionExists(cwd) {
|
|
319
|
+
const gate = safeReadJson(path.join(cwd, ".claude/cco/orchestration/full-readiness/latest-gate.json"));
|
|
320
|
+
if (!gate) {
|
|
321
|
+
return warn("safe_next_action_exists", "Safe next action for every blocker/warning",
|
|
322
|
+
"Run: node bin/avorelo full-readiness --json to generate gate.",
|
|
323
|
+
null, "Gate artifact not found.");
|
|
324
|
+
}
|
|
325
|
+
const blockers = gate.blockers || [];
|
|
326
|
+
const missingSnA = blockers.filter(function(b) { return !b.safeNextAction || b.safeNextAction.length < 5; });
|
|
327
|
+
if (missingSnA.length > 0) {
|
|
328
|
+
return blocked("safe_next_action_exists", "Safe next action for every blocker/warning",
|
|
329
|
+
"Add safeNextAction to all blockers in full-readiness-gate.js.",
|
|
330
|
+
{ missingIds: missingSnA.map(function(b) { return b.id; }) },
|
|
331
|
+
"Blockers without safeNextAction: " + missingSnA.map(function(b) { return b.id; }).join(", "));
|
|
332
|
+
}
|
|
333
|
+
if (!gate.safeNextAction) {
|
|
334
|
+
return warn("safe_next_action_exists", "Safe next action for every blocker/warning",
|
|
335
|
+
"Add top-level safeNextAction to full-readiness gate.",
|
|
336
|
+
null, "Gate has no top-level safeNextAction.");
|
|
337
|
+
}
|
|
338
|
+
return pass("safe_next_action_exists", "Safe next action for every blocker/warning",
|
|
339
|
+
{ blockerCount: blockers.length, allHaveSafeNextAction: true }, null);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
function collectActivationDistributionSignals(cwd) {
|
|
343
|
+
function read(rel) { return safeReadJson(path.join(cwd, rel)); }
|
|
344
|
+
return {
|
|
345
|
+
gate: read(".claude/cco/orchestration/full-readiness/latest-gate.json"),
|
|
346
|
+
evidenceClosure: read(".claude/cco/orchestration/full-readiness/latest-evidence-closure.json"),
|
|
347
|
+
knownLimitations: read(".claude/cco/orchestration/full-readiness/latest-known-limitations.json"),
|
|
348
|
+
externalUserSim: read(".claude/cco/orchestration/full-readiness/latest-external-user-simulation.json"),
|
|
349
|
+
releaseCandidateBundle: read(".claude/cco/orchestration/full-readiness/latest-release-candidate-bundle.json"),
|
|
350
|
+
supportBundle: read(".claude/cco/support/latest-support-bundle.json"),
|
|
351
|
+
tokenCost: read(".claude/cco/orchestration/prelaunch-intelligence/latest-token-cost-intelligence.json"),
|
|
352
|
+
feedbackIntelligence: read(".claude/cco/orchestration/prelaunch-intelligence/latest-feedback-intelligence.json"),
|
|
353
|
+
prelaunchReadiness: read(".claude/cco/orchestration/prelaunch-readiness/latest-activation-readiness.json"),
|
|
354
|
+
valueSummary: read(".claude/cco/orchestration/seamless-outcome/latest-value-summary.json"),
|
|
355
|
+
hardening: read(".claude/cco/orchestration/launch-hardening/latest-gate.json"),
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
function scoreActivationDistributionReadiness(checks) {
|
|
360
|
+
var totalEarned = 0;
|
|
361
|
+
checks.forEach(function(c) {
|
|
362
|
+
var weight = CHECK_WEIGHTS[c.id] || 0;
|
|
363
|
+
if (c.status === "pass" || c.status === "info") totalEarned += weight;
|
|
364
|
+
else if (c.status === "warn") totalEarned += Math.floor(weight * 0.5);
|
|
365
|
+
});
|
|
366
|
+
return Math.round((totalEarned / TOTAL_WEIGHT) * 100);
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
function runActivationDistributionReadiness(cwd, options) {
|
|
370
|
+
options = options || {};
|
|
371
|
+
var checks = [
|
|
372
|
+
checkInstallCommandAvailable(cwd),
|
|
373
|
+
checkInstallDocsCurrent(cwd),
|
|
374
|
+
checkActivationEntrypointAvailable(cwd),
|
|
375
|
+
checkDoctorAvailable(cwd),
|
|
376
|
+
checkFirstValueSurfaceAvailable(cwd),
|
|
377
|
+
checkClearNextActionAvailable(cwd),
|
|
378
|
+
checkRecoveryPathAvailable(cwd),
|
|
379
|
+
checkSupportBundleAvailable(cwd),
|
|
380
|
+
checkKnownLimitationsVisible(cwd),
|
|
381
|
+
checkReleaseCandidateBundleSafe(cwd),
|
|
382
|
+
checkEvidenceClosureComplete(cwd),
|
|
383
|
+
checkExternalUserSimulationCovered(cwd),
|
|
384
|
+
checkTokenCostHonest(cwd),
|
|
385
|
+
checkFeedbackIntelligenceHonest(cwd),
|
|
386
|
+
checkNoPublicLaunchClaim(cwd),
|
|
387
|
+
checkSafeNextActionExists(cwd),
|
|
388
|
+
];
|
|
389
|
+
|
|
390
|
+
var blockers = checks.filter(function(c) { return c.status === "blocked"; });
|
|
391
|
+
var warnings = checks.filter(function(c) { return c.status === "warn"; });
|
|
392
|
+
var passes = checks.filter(function(c) { return c.status === "pass"; });
|
|
393
|
+
var score = scoreActivationDistributionReadiness(checks);
|
|
394
|
+
|
|
395
|
+
var status;
|
|
396
|
+
if (blockers.length > 0) status = "blocked";
|
|
397
|
+
else if (score >= SCORE_READY) status = "ready";
|
|
398
|
+
else if (score >= SCORE_WARN) status = "warn";
|
|
399
|
+
else status = "insufficient_data";
|
|
400
|
+
|
|
401
|
+
var safeNextActions = [];
|
|
402
|
+
blockers.forEach(function(b) { if (b.safeNextAction) safeNextActions.push(b.safeNextAction); });
|
|
403
|
+
warnings.slice(0, 3).forEach(function(w) { if (w.safeNextAction) safeNextActions.push(w.safeNextAction); });
|
|
404
|
+
if (safeNextActions.length === 0) safeNextActions.push("Run: node bin/avorelo readiness-closure --json to identify missing evidence.");
|
|
405
|
+
|
|
406
|
+
var releaseCandidateStatus = (status === "ready") ? "candidate_ready" : (status === "warn") ? "candidate_warn" : "candidate_blocked";
|
|
407
|
+
|
|
408
|
+
var result = {
|
|
409
|
+
contract: CONTRACT,
|
|
410
|
+
schemaVersion: SCHEMA_VERSION,
|
|
411
|
+
createdAt: nowIso(),
|
|
412
|
+
status: status,
|
|
413
|
+
releaseCandidateStatus: releaseCandidateStatus,
|
|
414
|
+
score: score,
|
|
415
|
+
checks: checks,
|
|
416
|
+
blockers: blockers,
|
|
417
|
+
warnings: warnings,
|
|
418
|
+
passes: passes,
|
|
419
|
+
safeNextActions: safeNextActions,
|
|
420
|
+
noPublicLaunchClaim: true,
|
|
421
|
+
noReleaseReadyClaimUnlessPassed: true,
|
|
422
|
+
redacted: true,
|
|
423
|
+
};
|
|
424
|
+
|
|
425
|
+
try { appendProductLearningEvent(cwd, { eventName: "activation_distribution_readiness_run", category: "activation_distribution", status: status, score: score, blockerCount: blockers.length, warnCount: warnings.length }); } catch (e) {}
|
|
426
|
+
return result;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
function writeActivationDistributionReadiness(cwd, result) {
|
|
430
|
+
var dir = path.join(cwd, ARTIFACT_DIR_REL);
|
|
431
|
+
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
|
432
|
+
fs.writeFileSync(path.join(cwd, ARTIFACT_REL), JSON.stringify(result, null, 2));
|
|
433
|
+
return result;
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
function buildActivationDistributionSurface(cwd, options) {
|
|
437
|
+
options = options || {};
|
|
438
|
+
var artifact = safeReadJson(path.join(cwd, ARTIFACT_REL));
|
|
439
|
+
if (!artifact) return { status: "not_available", contract: CONTRACT };
|
|
440
|
+
return {
|
|
441
|
+
contract: artifact.contract,
|
|
442
|
+
status: artifact.status,
|
|
443
|
+
releaseCandidateStatus: artifact.releaseCandidateStatus,
|
|
444
|
+
score: artifact.score,
|
|
445
|
+
blockerCount: (artifact.blockers || []).length,
|
|
446
|
+
warningCount: (artifact.warnings || []).length,
|
|
447
|
+
safeNextActions: (artifact.safeNextActions || []).slice(0, 3),
|
|
448
|
+
noPublicLaunchClaim: artifact.noPublicLaunchClaim,
|
|
449
|
+
redacted: artifact.redacted,
|
|
450
|
+
};
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
function formatActivationDistributionText(result, options) {
|
|
454
|
+
options = options || {};
|
|
455
|
+
var lines = [];
|
|
456
|
+
lines.push("Activation distribution readiness: " + result.status + " (score: " + result.score + "/100)");
|
|
457
|
+
if (result.blockers && result.blockers.length > 0) {
|
|
458
|
+
lines.push("Blockers: " + result.blockers.length);
|
|
459
|
+
result.blockers.forEach(function(b) { lines.push(" [blocked] " + b.label + " — " + (b.safeNextAction || "")); });
|
|
460
|
+
}
|
|
461
|
+
if (result.warnings && result.warnings.length > 0) {
|
|
462
|
+
lines.push("Warnings: " + result.warnings.length);
|
|
463
|
+
if (options.debug) result.warnings.forEach(function(w) { lines.push(" [warn] " + w.label + " — " + (w.safeNextAction || "")); });
|
|
464
|
+
}
|
|
465
|
+
if (result.safeNextActions && result.safeNextActions.length > 0) {
|
|
466
|
+
lines.push("Next: " + result.safeNextActions[0]);
|
|
467
|
+
}
|
|
468
|
+
lines.push("No public launch claim. Redacted.");
|
|
469
|
+
if (options.debug) {
|
|
470
|
+
lines.push("");
|
|
471
|
+
lines.push("Checks:");
|
|
472
|
+
(result.checks || []).forEach(function(c) { lines.push(" [" + c.status + "] " + c.id + (c.detail ? " — " + c.detail : "")); });
|
|
473
|
+
}
|
|
474
|
+
return lines.join("\n");
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
module.exports = {
|
|
478
|
+
CONTRACT,
|
|
479
|
+
SCHEMA_VERSION,
|
|
480
|
+
ARTIFACT_REL,
|
|
481
|
+
SCORE_READY,
|
|
482
|
+
SCORE_WARN,
|
|
483
|
+
CHECK_WEIGHTS,
|
|
484
|
+
collectActivationDistributionSignals,
|
|
485
|
+
scoreActivationDistributionReadiness,
|
|
486
|
+
runActivationDistributionReadiness,
|
|
487
|
+
writeActivationDistributionReadiness,
|
|
488
|
+
buildActivationDistributionSurface,
|
|
489
|
+
formatActivationDistributionText,
|
|
490
|
+
// Individual checks exported for testing
|
|
491
|
+
checkInstallCommandAvailable,
|
|
492
|
+
checkInstallDocsCurrent,
|
|
493
|
+
checkActivationEntrypointAvailable,
|
|
494
|
+
checkDoctorAvailable,
|
|
495
|
+
checkFirstValueSurfaceAvailable,
|
|
496
|
+
checkClearNextActionAvailable,
|
|
497
|
+
checkRecoveryPathAvailable,
|
|
498
|
+
checkSupportBundleAvailable,
|
|
499
|
+
checkKnownLimitationsVisible,
|
|
500
|
+
checkReleaseCandidateBundleSafe,
|
|
501
|
+
checkEvidenceClosureComplete,
|
|
502
|
+
checkExternalUserSimulationCovered,
|
|
503
|
+
checkTokenCostHonest,
|
|
504
|
+
checkFeedbackIntelligenceHonest,
|
|
505
|
+
checkNoPublicLaunchClaim,
|
|
506
|
+
checkSafeNextActionExists,
|
|
507
|
+
};
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const { HOOK_EVENT_NAMES } = require("./hook-contracts");
|
|
4
|
+
|
|
5
|
+
const CAPABILITY_MAP = {
|
|
6
|
+
claude: {
|
|
7
|
+
platform: "claude",
|
|
8
|
+
supportsHooks: [...HOOK_EVENT_NAMES],
|
|
9
|
+
supportsToolOutputReplacement: true,
|
|
10
|
+
supportsPermissionDecision: true,
|
|
11
|
+
supportsPanelLaunch: true,
|
|
12
|
+
supportsRules: false,
|
|
13
|
+
supportsMCPConfig: true,
|
|
14
|
+
supportsExtensionBridge: false,
|
|
15
|
+
supportsPermissionControl: true,
|
|
16
|
+
partialSupportNotes: [],
|
|
17
|
+
},
|
|
18
|
+
cursor: {
|
|
19
|
+
platform: "cursor",
|
|
20
|
+
supportsHooks: ["SessionStart", "UserPromptSubmit", "PreToolUse", "PostToolUse", "Stop", "SessionEnd"],
|
|
21
|
+
supportsToolOutputReplacement: false,
|
|
22
|
+
supportsPermissionDecision: false,
|
|
23
|
+
supportsPanelLaunch: true,
|
|
24
|
+
supportsRules: true,
|
|
25
|
+
supportsMCPConfig: true,
|
|
26
|
+
supportsExtensionBridge: true,
|
|
27
|
+
supportsPermissionControl: false,
|
|
28
|
+
partialSupportNotes: [
|
|
29
|
+
"Cursor does not provide Claude-equivalent hook lifecycle for all 18 events.",
|
|
30
|
+
"Permission decisions are advisory via rules/extension workflow.",
|
|
31
|
+
"Tool output replacement is not directly supported; recommendations are post-action.",
|
|
32
|
+
],
|
|
33
|
+
},
|
|
34
|
+
windsurf: {
|
|
35
|
+
platform: "windsurf",
|
|
36
|
+
supportsHooks: [
|
|
37
|
+
"SessionStart",
|
|
38
|
+
"UserPromptSubmit",
|
|
39
|
+
"PreToolUse",
|
|
40
|
+
"PostToolUse",
|
|
41
|
+
"PostToolUseFailure",
|
|
42
|
+
"Notification",
|
|
43
|
+
"Stop",
|
|
44
|
+
"TaskCompleted",
|
|
45
|
+
"SubagentStart",
|
|
46
|
+
"SubagentStop",
|
|
47
|
+
"ConfigChange",
|
|
48
|
+
"SessionEnd",
|
|
49
|
+
],
|
|
50
|
+
supportsToolOutputReplacement: false,
|
|
51
|
+
supportsPermissionDecision: true,
|
|
52
|
+
supportsPanelLaunch: true,
|
|
53
|
+
supportsRules: false,
|
|
54
|
+
supportsMCPConfig: true,
|
|
55
|
+
supportsExtensionBridge: false,
|
|
56
|
+
supportsPermissionControl: true,
|
|
57
|
+
partialSupportNotes: [
|
|
58
|
+
"Tool output replacement is host-limited; optimizer uses post-action recommendations instead.",
|
|
59
|
+
"Hook names differ by host; mapped through adapter contract.",
|
|
60
|
+
],
|
|
61
|
+
},
|
|
62
|
+
"copilot-coding-agent": {
|
|
63
|
+
platform: "copilot-coding-agent",
|
|
64
|
+
supportsHooks: ["SessionStart", "PreToolUse", "PostToolUse", "Stop", "TaskCompleted", "SessionEnd"],
|
|
65
|
+
supportsToolOutputReplacement: false,
|
|
66
|
+
supportsPermissionDecision: false,
|
|
67
|
+
supportsPanelLaunch: true,
|
|
68
|
+
supportsRules: true,
|
|
69
|
+
supportsMCPConfig: false,
|
|
70
|
+
supportsExtensionBridge: false,
|
|
71
|
+
supportsPermissionControl: false,
|
|
72
|
+
partialSupportNotes: [
|
|
73
|
+
"No first-class permission decision hook parity; guardrails run in advisory mode.",
|
|
74
|
+
"Notification and teammate events are synthesized from available telemetry.",
|
|
75
|
+
],
|
|
76
|
+
},
|
|
77
|
+
continue: {
|
|
78
|
+
platform: "continue",
|
|
79
|
+
supportsHooks: ["SessionStart", "UserPromptSubmit", "PreToolUse", "PostToolUse", "Stop", "SessionEnd"],
|
|
80
|
+
supportsToolOutputReplacement: false,
|
|
81
|
+
supportsPermissionDecision: false,
|
|
82
|
+
supportsPanelLaunch: true,
|
|
83
|
+
supportsRules: true,
|
|
84
|
+
supportsMCPConfig: true,
|
|
85
|
+
supportsExtensionBridge: false,
|
|
86
|
+
supportsPermissionControl: false,
|
|
87
|
+
partialSupportNotes: [
|
|
88
|
+
"Permission decisions are advisory due to host capabilities.",
|
|
89
|
+
"Subagent and worktree lifecycle events are approximated when unavailable.",
|
|
90
|
+
],
|
|
91
|
+
},
|
|
92
|
+
codex: {
|
|
93
|
+
platform: "codex",
|
|
94
|
+
supportsHooks: ["SessionStart", "UserPromptSubmit", "PreToolUse", "PostToolUse", "Stop", "SessionEnd"],
|
|
95
|
+
supportsToolOutputReplacement: false,
|
|
96
|
+
supportsPermissionDecision: true,
|
|
97
|
+
supportsPanelLaunch: true,
|
|
98
|
+
supportsRules: false,
|
|
99
|
+
supportsMCPConfig: true,
|
|
100
|
+
supportsExtensionBridge: false,
|
|
101
|
+
supportsPermissionControl: true,
|
|
102
|
+
partialSupportNotes: ["Hook/event mapping relies on adapter routing and may not expose all Claude-native lifecycle events."],
|
|
103
|
+
},
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
function normalizePlatform(platform) {
|
|
107
|
+
const p = String(platform || "claude").toLowerCase();
|
|
108
|
+
if (p === "copilot" || p === "github-copilot" || p === "github-copilot-coding-agent") return "copilot-coding-agent";
|
|
109
|
+
return CAPABILITY_MAP[p] ? p : "claude";
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function getAdapterCapabilityMap(platform) {
|
|
113
|
+
const key = normalizePlatform(platform);
|
|
114
|
+
return CAPABILITY_MAP[key];
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function normalizeDashboardForPlatform(platform, dashboard) {
|
|
118
|
+
const capabilityMap = getAdapterCapabilityMap(platform);
|
|
119
|
+
const unsupportedHooks = HOOK_EVENT_NAMES.filter((evt) => !capabilityMap.supportsHooks.includes(evt));
|
|
120
|
+
|
|
121
|
+
return {
|
|
122
|
+
platform: capabilityMap.platform,
|
|
123
|
+
capabilityMap,
|
|
124
|
+
partialSupport: unsupportedHooks.length > 0,
|
|
125
|
+
partialSupportNotes: [...capabilityMap.partialSupportNotes],
|
|
126
|
+
unsupportedHooks,
|
|
127
|
+
statusDashboardVersion: dashboard.statusDashboardVersion,
|
|
128
|
+
tier: dashboard.tier,
|
|
129
|
+
dashboardFraming: dashboard.dashboardFraming,
|
|
130
|
+
benefitSummary: dashboard.benefitSummary,
|
|
131
|
+
memorySummary: dashboard.memorySummary,
|
|
132
|
+
contextBudgetPlan: dashboard.contextBudgetPlan,
|
|
133
|
+
recommendationTraces: dashboard.recommendationTraces || [],
|
|
134
|
+
recommendationDecision: dashboard.recommendationDecision || null,
|
|
135
|
+
nextBestAction: dashboard.nextBestAction,
|
|
136
|
+
nextBestPrompt: dashboard.nextBestPrompt,
|
|
137
|
+
simplifyModeStatus: dashboard.simplifyModeStatus,
|
|
138
|
+
teamUnifiedView: dashboard.teamUnifiedView,
|
|
139
|
+
pricingMeter: dashboard.pricingMeter,
|
|
140
|
+
cloudSync: dashboard.cloudSync,
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function hasNormalizedDashboardShape(payload) {
|
|
145
|
+
return Boolean(
|
|
146
|
+
payload &&
|
|
147
|
+
typeof payload === "object" &&
|
|
148
|
+
typeof payload.platform === "string" &&
|
|
149
|
+
payload.capabilityMap &&
|
|
150
|
+
Array.isArray(payload.capabilityMap.supportsHooks) &&
|
|
151
|
+
typeof payload.capabilityMap.supportsToolOutputReplacement === "boolean" &&
|
|
152
|
+
typeof payload.capabilityMap.supportsPermissionDecision === "boolean" &&
|
|
153
|
+
typeof payload.capabilityMap.supportsPanelLaunch === "boolean" &&
|
|
154
|
+
typeof payload.capabilityMap.supportsRules === "boolean" &&
|
|
155
|
+
typeof payload.capabilityMap.supportsMCPConfig === "boolean" &&
|
|
156
|
+
typeof payload.capabilityMap.supportsExtensionBridge === "boolean" &&
|
|
157
|
+
Array.isArray(payload.partialSupportNotes) &&
|
|
158
|
+
payload.benefitSummary &&
|
|
159
|
+
payload.memorySummary &&
|
|
160
|
+
payload.contextBudgetPlan &&
|
|
161
|
+
typeof payload.nextBestAction === "string" &&
|
|
162
|
+
typeof payload.nextBestPrompt === "string" &&
|
|
163
|
+
payload.simplifyModeStatus &&
|
|
164
|
+
payload.pricingMeter &&
|
|
165
|
+
payload.teamUnifiedView &&
|
|
166
|
+
payload.cloudSync
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
module.exports = {
|
|
171
|
+
CAPABILITY_MAP,
|
|
172
|
+
normalizePlatform,
|
|
173
|
+
getAdapterCapabilityMap,
|
|
174
|
+
normalizeDashboardForPlatform,
|
|
175
|
+
hasNormalizedDashboardShape,
|
|
176
|
+
};
|