avorelo 0.1.0 → 0.3.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 +90 -51
- package/bin/avorelo.mjs +7 -0
- package/dist/avorelo.mjs +19741 -0
- package/package.json +135 -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,537 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
// ── Feedback Intelligence ─────────────────────────────────────────────────────
|
|
4
|
-
//
|
|
5
|
-
// Contract: avorelo.feedbackIntelligence.v1
|
|
6
|
-
//
|
|
7
|
-
// Clusters local feedback entries into actionable friction types.
|
|
8
|
-
// Deterministic, keyword/reason-code based — no LLM calls, no network.
|
|
9
|
-
// No raw user text exposed if it may contain sensitive data.
|
|
10
|
-
|
|
11
|
-
const fs = require("fs");
|
|
12
|
-
const path = require("path");
|
|
13
|
-
const { nowIso } = require("./fsx");
|
|
14
|
-
const { appendProductLearningEvent } = require("./product-learning-events");
|
|
15
|
-
const { readImportedFeedbackEvidence } = require("./prelaunch-evidence-store");
|
|
16
|
-
|
|
17
|
-
const CONTRACT = "avorelo.feedbackIntelligence.v1";
|
|
18
|
-
const SCHEMA_VERSION = 1;
|
|
19
|
-
const INTELLIGENCE_DIR_REL = ".claude/cco/orchestration/prelaunch-intelligence";
|
|
20
|
-
const ARTIFACT_REL = `${INTELLIGENCE_DIR_REL}/latest-feedback-intelligence.json`;
|
|
21
|
-
|
|
22
|
-
const FRICTION_TYPES = Object.freeze([
|
|
23
|
-
"install_confusion",
|
|
24
|
-
"ai_prompt_unclear",
|
|
25
|
-
"hook_approval_unclear",
|
|
26
|
-
"mcp_governance_warn",
|
|
27
|
-
"token_context_unknown",
|
|
28
|
-
"proof_missing",
|
|
29
|
-
"support_bundle_missing",
|
|
30
|
-
"command_noise",
|
|
31
|
-
"recovery_needed",
|
|
32
|
-
"first_value_unclear",
|
|
33
|
-
"verification_missing",
|
|
34
|
-
"missing_evidence",
|
|
35
|
-
"exact_savings_unavailable",
|
|
36
|
-
"browser_proof_missing",
|
|
37
|
-
"plugin_distribution_unclear",
|
|
38
|
-
"unknown",
|
|
39
|
-
]);
|
|
40
|
-
|
|
41
|
-
const FRICTION_KEYWORDS = {
|
|
42
|
-
install_confusion: ["install", "setup", "first_run", "first run", "install-ai", "onboard"],
|
|
43
|
-
ai_prompt_unclear: ["ai_prompt", "ai prompt", "prompt unclear", "ai install", "prompt_unclear"],
|
|
44
|
-
hook_approval_unclear: ["hook", "hook_apply", "approval", "lifecycle"],
|
|
45
|
-
mcp_governance_warn: ["mcp", "tool governance", "mcp_governance", "mcp_warn", "mcp warn"],
|
|
46
|
-
token_context_unknown: ["token", "context", "cost", "token_context", "token context"],
|
|
47
|
-
proof_missing: ["proof", "evidence", "proof_missing", "receipt missing"],
|
|
48
|
-
support_bundle_missing: ["support_bundle", "support bundle", "bundle missing"],
|
|
49
|
-
command_noise: ["noise", "noisy", "verbose", "output_too_noisy", "too many"],
|
|
50
|
-
recovery_needed: ["recovery", "repair", "rollback", "failure", "broken"],
|
|
51
|
-
first_value_unclear: ["first_value", "first value", "value_unclear", "value unclear"],
|
|
52
|
-
verification_missing: ["verification", "verify", "gate", "reality_gate"],
|
|
53
|
-
missing_evidence: ["missing_evidence", "missing evidence", "no receipt", "ledger_incomplete"],
|
|
54
|
-
exact_savings_unavailable: ["savings", "exact savings", "cost savings", "dollar"],
|
|
55
|
-
browser_proof_missing: ["browser_proof", "browser proof", "visual proof", "screenshot"],
|
|
56
|
-
plugin_distribution_unclear: ["plugin", "marketplace", "distribution", "adapter"],
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
// Legacy friction type mapping from alpha-feedback VALID_FRICTION_TYPES
|
|
60
|
-
const LEGACY_FRICTION_MAP = {
|
|
61
|
-
first_run_unclear: "install_confusion",
|
|
62
|
-
hook_apply_friction: "hook_approval_unclear",
|
|
63
|
-
output_too_noisy: "command_noise",
|
|
64
|
-
output_too_sparse: "verification_missing",
|
|
65
|
-
command_not_found: "install_confusion",
|
|
66
|
-
proof_missing: "proof_missing",
|
|
67
|
-
value_unclear: "first_value_unclear",
|
|
68
|
-
safe_run_unclear: "first_value_unclear",
|
|
69
|
-
ledger_incomplete: "missing_evidence",
|
|
70
|
-
doctor_confusing: "install_confusion",
|
|
71
|
-
support_bundle_missing: "support_bundle_missing",
|
|
72
|
-
feedback_path_missing: "missing_evidence",
|
|
73
|
-
other: "unknown",
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
function safeReadJson(absPath) {
|
|
77
|
-
try {
|
|
78
|
-
if (!fs.existsSync(absPath)) return null;
|
|
79
|
-
return JSON.parse(fs.readFileSync(absPath, "utf8").replace(/^/, ""));
|
|
80
|
-
} catch {
|
|
81
|
-
return null;
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
function classifyFriction(entryOrSignal, options = {}) {
|
|
86
|
-
const signal = entryOrSignal || {};
|
|
87
|
-
const frictionType = signal.frictionType || signal.type || "";
|
|
88
|
-
const summary = (signal.summary || signal.finding || "").toLowerCase();
|
|
89
|
-
|
|
90
|
-
// Direct friction type match
|
|
91
|
-
if (FRICTION_TYPES.includes(frictionType)) {
|
|
92
|
-
return frictionType;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
// Legacy mapping
|
|
96
|
-
if (LEGACY_FRICTION_MAP[frictionType]) {
|
|
97
|
-
return LEGACY_FRICTION_MAP[frictionType];
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
// Keyword match on summary
|
|
101
|
-
for (const [type, keywords] of Object.entries(FRICTION_KEYWORDS)) {
|
|
102
|
-
for (const kw of keywords) {
|
|
103
|
-
if (summary.includes(kw.toLowerCase())) {
|
|
104
|
-
return type;
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
return "unknown";
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
function collectFeedbackEntries(cwd, options = {}) {
|
|
113
|
-
const { listFeedback } = require("./alpha-feedback");
|
|
114
|
-
let manualEntries = [];
|
|
115
|
-
try {
|
|
116
|
-
const result = listFeedback(cwd, { limit: 200 });
|
|
117
|
-
manualEntries = result.items || [];
|
|
118
|
-
} catch {}
|
|
119
|
-
|
|
120
|
-
const importedEntries = readImportedFeedbackEvidence(cwd).map((entry) => ({
|
|
121
|
-
contract: entry.contract,
|
|
122
|
-
schemaVersion: entry.schemaVersion,
|
|
123
|
-
id: `import-${entry.importedAt || "unknown"}`,
|
|
124
|
-
source: entry.sourceType || "manual_import",
|
|
125
|
-
persona: entry.persona || "unknown",
|
|
126
|
-
frictionType: entry.theme || entry.issueCategory || "unknown",
|
|
127
|
-
severity: entry.severity || "medium",
|
|
128
|
-
summary: entry.quoteSummary || "",
|
|
129
|
-
desiredBehavior: "",
|
|
130
|
-
evidencePath: "[redacted-path]",
|
|
131
|
-
createdAt: entry.date || entry.importedAt || nowIso(),
|
|
132
|
-
redacted: true,
|
|
133
|
-
imported: true,
|
|
134
|
-
simulated: entry.simulated === true,
|
|
135
|
-
segment: entry.segment || "unknown",
|
|
136
|
-
theme: entry.theme || "unknown",
|
|
137
|
-
issueCategory: entry.issueCategory || "unknown",
|
|
138
|
-
activationStage: entry.activationStage || "unknown",
|
|
139
|
-
trustConcern: entry.trustConcern === true,
|
|
140
|
-
pricingConcern: entry.pricingConcern === true,
|
|
141
|
-
}));
|
|
142
|
-
|
|
143
|
-
let designPartnerEntries = [];
|
|
144
|
-
try {
|
|
145
|
-
const { readAllDesignPartnerSessions } = require("./design-partner-feedback");
|
|
146
|
-
const sessions = readAllDesignPartnerSessions(cwd);
|
|
147
|
-
designPartnerEntries = sessions.map((s) => ({
|
|
148
|
-
contract: s.contract,
|
|
149
|
-
schemaVersion: s.schemaVersion,
|
|
150
|
-
id: s.sessionId,
|
|
151
|
-
source: "design_partner",
|
|
152
|
-
persona: "unknown",
|
|
153
|
-
frictionType: s.frictionType || "unknown",
|
|
154
|
-
severity: s.severity || "medium",
|
|
155
|
-
summary: s.summary || "",
|
|
156
|
-
desiredBehavior: s.desiredBehavior || "",
|
|
157
|
-
createdAt: s.createdAt,
|
|
158
|
-
redacted: true,
|
|
159
|
-
imported: false,
|
|
160
|
-
simulated: s.simulated === true,
|
|
161
|
-
segment: "design_partner",
|
|
162
|
-
theme: s.theme || "unknown",
|
|
163
|
-
issueCategory: s.issueCategory || "unknown",
|
|
164
|
-
activationStage: s.activationStage || "unknown",
|
|
165
|
-
trustConcern: false,
|
|
166
|
-
pricingConcern: false,
|
|
167
|
-
}));
|
|
168
|
-
} catch {}
|
|
169
|
-
|
|
170
|
-
return manualEntries.concat(importedEntries).concat(designPartnerEntries);
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
function buildFrictionClusters(cwd, options = {}) {
|
|
174
|
-
const entries = collectFeedbackEntries(cwd, options);
|
|
175
|
-
|
|
176
|
-
if (entries.length === 0) {
|
|
177
|
-
return {
|
|
178
|
-
status: "insufficient_data",
|
|
179
|
-
clusters: [],
|
|
180
|
-
totalEntries: 0,
|
|
181
|
-
message: "No feedback entries found. Add dogfood feedback to build friction clusters.",
|
|
182
|
-
};
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
const clusterMap = {};
|
|
186
|
-
|
|
187
|
-
for (const entry of entries) {
|
|
188
|
-
const type = classifyFriction(entry, options);
|
|
189
|
-
if (!clusterMap[type]) {
|
|
190
|
-
clusterMap[type] = {
|
|
191
|
-
frictionType: type,
|
|
192
|
-
count: 0,
|
|
193
|
-
severity: "low",
|
|
194
|
-
evidenceRefs: [],
|
|
195
|
-
evidenceRefCount: 0,
|
|
196
|
-
representativeSummaries: [],
|
|
197
|
-
recommendedAction: null,
|
|
198
|
-
mappedNextPr: null,
|
|
199
|
-
redacted: true,
|
|
200
|
-
};
|
|
201
|
-
}
|
|
202
|
-
const cluster = clusterMap[type];
|
|
203
|
-
cluster.count += 1;
|
|
204
|
-
|
|
205
|
-
// Track max severity
|
|
206
|
-
const sevOrder = { low: 0, medium: 1, high: 2, blocker: 3 };
|
|
207
|
-
if ((sevOrder[entry.severity] || 0) > (sevOrder[cluster.severity] || 0)) {
|
|
208
|
-
cluster.severity = entry.severity;
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
// Add evidence ref (path, not raw content)
|
|
212
|
-
if (entry.evidencePath) {
|
|
213
|
-
cluster.evidenceRefCount += 1;
|
|
214
|
-
if (cluster.evidenceRefs.length < 3) {
|
|
215
|
-
cluster.evidenceRefs.push("[redacted-path]");
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
// Bounded representative summaries (max 3, max 120 chars each, redacted)
|
|
220
|
-
if (cluster.representativeSummaries.length < 3 && entry.summary) {
|
|
221
|
-
const truncated = String(entry.summary).slice(0, 120).replace(/[\x00-\x08\x0b\x0c\x0e-\x1f]/g, "");
|
|
222
|
-
cluster.representativeSummaries.push(truncated);
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
// Assign recommended actions and PR mappings
|
|
227
|
-
for (const cluster of Object.values(clusterMap)) {
|
|
228
|
-
cluster.recommendedAction = getRecommendedAction(cluster.frictionType);
|
|
229
|
-
cluster.mappedNextPr = getMappedNextPr(cluster.frictionType);
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
const clusters = Object.values(clusterMap).sort((a, b) => b.count - a.count);
|
|
233
|
-
|
|
234
|
-
return {
|
|
235
|
-
status: "ready",
|
|
236
|
-
clusters,
|
|
237
|
-
totalEntries: entries.length,
|
|
238
|
-
message: null,
|
|
239
|
-
};
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
function getRecommendedAction(frictionType) {
|
|
243
|
-
const actions = {
|
|
244
|
-
install_confusion: "Improve install-ai prompt clarity and first-run docs.",
|
|
245
|
-
ai_prompt_unclear: "Review AI install prompt text for ambiguity.",
|
|
246
|
-
hook_approval_unclear: "Add approval boundary clarification to hook apply docs.",
|
|
247
|
-
mcp_governance_warn: "Run avorelo mcp doctor and review policy warnings.",
|
|
248
|
-
token_context_unknown: "Run avorelo token-efficiency --json and add caveat clarity.",
|
|
249
|
-
proof_missing: "Run avorelo proof after task completion.",
|
|
250
|
-
support_bundle_missing: "Run avorelo support-bundle --json.",
|
|
251
|
-
command_noise: "Audit default CLI output for verbosity.",
|
|
252
|
-
recovery_needed: "Run avorelo doctor --json and review failure-recovery plan.",
|
|
253
|
-
first_value_unclear: "Run avorelo first-value-check and improve first-value docs.",
|
|
254
|
-
verification_missing: "Run avorelo outcome --gate --json.",
|
|
255
|
-
missing_evidence: "Run full Avorelo sequence to populate ledger receipts.",
|
|
256
|
-
exact_savings_unavailable: "Token cost evidence is estimated. No exact savings claim will be made.",
|
|
257
|
-
browser_proof_missing: "Browser Proof deferred until visual friction is dominant.",
|
|
258
|
-
plugin_distribution_unclear: "Plugin/adapter readiness deferred until distribution friction is dominant.",
|
|
259
|
-
unknown: "Review feedback entry manually and re-classify.",
|
|
260
|
-
};
|
|
261
|
-
return actions[frictionType] || "Review and address this friction type.";
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
function getMappedNextPr(frictionType) {
|
|
265
|
-
const map = {
|
|
266
|
-
install_confusion: "Install / activation repair",
|
|
267
|
-
ai_prompt_unclear: "Install / activation repair",
|
|
268
|
-
hook_approval_unclear: "Install / activation repair",
|
|
269
|
-
mcp_governance_warn: "MCP governance repair",
|
|
270
|
-
token_context_unknown: "Token / cost evidence repair",
|
|
271
|
-
proof_missing: "Full Readiness / Release Candidate Gate",
|
|
272
|
-
support_bundle_missing: "Support bundle repair",
|
|
273
|
-
command_noise: "Full Readiness / Release Candidate Gate",
|
|
274
|
-
recovery_needed: "Full Readiness / Release Candidate Gate",
|
|
275
|
-
first_value_unclear: "Install / activation repair",
|
|
276
|
-
verification_missing: "Full Readiness / Release Candidate Gate",
|
|
277
|
-
missing_evidence: "Full Readiness / Release Candidate Gate",
|
|
278
|
-
exact_savings_unavailable: "Token / cost evidence repair",
|
|
279
|
-
browser_proof_missing: "Browser Proof / Visual QA Bridge",
|
|
280
|
-
plugin_distribution_unclear: "Plugin / Adapter Technical Readiness",
|
|
281
|
-
unknown: null,
|
|
282
|
-
};
|
|
283
|
-
return map[frictionType] || null;
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
function scoreFeedbackCoverage(entries, clusters) {
|
|
287
|
-
const qualifiedEntries = entries.filter((entry) => entry.simulated !== true && entry.summary && entry.summary.trim().length > 0);
|
|
288
|
-
const realEntries = qualifiedEntries.length;
|
|
289
|
-
const sourceCount = new Set(qualifiedEntries.map((entry) => entry.source || entry.sourceType || "unknown")).size;
|
|
290
|
-
const themeCount = new Set(qualifiedEntries.map((entry) => classifyFriction(entry))).size;
|
|
291
|
-
const severityCoverage = new Set(qualifiedEntries.map((entry) => entry.severity || "medium")).size;
|
|
292
|
-
const simulatedEntries = entries.filter((entry) => entry.simulated === true).length;
|
|
293
|
-
|
|
294
|
-
let score = 0;
|
|
295
|
-
score += Math.min(realEntries, 6) * 10;
|
|
296
|
-
score += Math.min(sourceCount, 3) * 8;
|
|
297
|
-
score += Math.min(themeCount, 4) * 5;
|
|
298
|
-
score += Math.min(severityCoverage, 3) * 3;
|
|
299
|
-
if (clusters.some((cluster) => cluster.severity === "blocker")) score -= 10;
|
|
300
|
-
score = Math.max(0, Math.min(100, score));
|
|
301
|
-
|
|
302
|
-
let readinessStatus = "warn";
|
|
303
|
-
if (realEntries === 0) readinessStatus = simulatedEntries > 0 ? "info" : "warn";
|
|
304
|
-
else if (realEntries >= 3 && sourceCount >= 1) readinessStatus = "pass";
|
|
305
|
-
|
|
306
|
-
let evidenceQuality = "missing";
|
|
307
|
-
if (realEntries >= 5 && sourceCount >= 2 && themeCount >= 2) evidenceQuality = "strong";
|
|
308
|
-
else if (realEntries >= 3) evidenceQuality = "moderate";
|
|
309
|
-
else if (realEntries >= 1) evidenceQuality = "weak";
|
|
310
|
-
|
|
311
|
-
return {
|
|
312
|
-
score,
|
|
313
|
-
readinessStatus,
|
|
314
|
-
evidenceQuality,
|
|
315
|
-
qualifiedEntries,
|
|
316
|
-
simulatedEntries,
|
|
317
|
-
sourceCount,
|
|
318
|
-
themeCount,
|
|
319
|
-
};
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
function buildFeedbackIntelligence(cwd, options = {}) {
|
|
323
|
-
const entries = collectFeedbackEntries(cwd, options);
|
|
324
|
-
const clusterResult = buildFrictionClusters(cwd, options);
|
|
325
|
-
const { status, clusters, totalEntries, message } = clusterResult;
|
|
326
|
-
|
|
327
|
-
const topFriction = clusters[0] || null;
|
|
328
|
-
const hasBlockers = clusters.some((c) => c.severity === "blocker");
|
|
329
|
-
const coverage = scoreFeedbackCoverage(entries, clusters);
|
|
330
|
-
const topThemes = clusters.slice(0, 5).map((cluster) => ({
|
|
331
|
-
theme: cluster.frictionType,
|
|
332
|
-
count: cluster.count,
|
|
333
|
-
severity: cluster.severity,
|
|
334
|
-
}));
|
|
335
|
-
const objections = entries
|
|
336
|
-
.filter((entry) => entry.pricingConcern === true)
|
|
337
|
-
.slice(0, 5)
|
|
338
|
-
.map((entry) => ({
|
|
339
|
-
theme: classifyFriction(entry),
|
|
340
|
-
severity: entry.severity || "medium",
|
|
341
|
-
}));
|
|
342
|
-
const activationIssues = entries
|
|
343
|
-
.filter((entry) => (entry.activationStage || "").toLowerCase() !== "unknown")
|
|
344
|
-
.slice(0, 10)
|
|
345
|
-
.map((entry) => ({
|
|
346
|
-
activationStage: entry.activationStage,
|
|
347
|
-
theme: classifyFriction(entry),
|
|
348
|
-
severity: entry.severity || "medium",
|
|
349
|
-
}));
|
|
350
|
-
const trustConcerns = entries
|
|
351
|
-
.filter((entry) => entry.trustConcern === true)
|
|
352
|
-
.slice(0, 10)
|
|
353
|
-
.map((entry) => ({
|
|
354
|
-
theme: classifyFriction(entry),
|
|
355
|
-
severity: entry.severity || "medium",
|
|
356
|
-
}));
|
|
357
|
-
const pricingConcerns = entries
|
|
358
|
-
.filter((entry) => entry.pricingConcern === true)
|
|
359
|
-
.slice(0, 10)
|
|
360
|
-
.map((entry) => ({
|
|
361
|
-
theme: classifyFriction(entry),
|
|
362
|
-
severity: entry.severity || "medium",
|
|
363
|
-
}));
|
|
364
|
-
const sources = entries.reduce((acc, entry) => {
|
|
365
|
-
const source = entry.source || entry.sourceType || "unknown";
|
|
366
|
-
acc[source] = (acc[source] || 0) + 1;
|
|
367
|
-
return acc;
|
|
368
|
-
}, {});
|
|
369
|
-
const hasStructuredEvidence = entries.some((entry) => (
|
|
370
|
-
entry.imported === true
|
|
371
|
-
|| entry.source === "manual_import"
|
|
372
|
-
|| entry.source === "design_partner"
|
|
373
|
-
|| entry.sourceType === "design_partner"
|
|
374
|
-
|| (entry.activationStage && entry.activationStage !== "unknown")
|
|
375
|
-
|| entry.trustConcern === true
|
|
376
|
-
|| entry.pricingConcern === true
|
|
377
|
-
|| (entry.segment && entry.segment !== "unknown")
|
|
378
|
-
));
|
|
379
|
-
const missingEvidence = [];
|
|
380
|
-
if (coverage.qualifiedEntries.length === 0) {
|
|
381
|
-
missingEvidence.push("No redacted real feedback evidence imported or captured locally.");
|
|
382
|
-
}
|
|
383
|
-
if (!hasStructuredEvidence) {
|
|
384
|
-
missingEvidence.push("No structured design-partner feedback evidence is present.");
|
|
385
|
-
}
|
|
386
|
-
if (!entries.some((entry) => entry.activationStage && entry.activationStage !== "unknown")) {
|
|
387
|
-
missingEvidence.push("No activation-stage-tagged feedback evidence present.");
|
|
388
|
-
}
|
|
389
|
-
const safeNextActions = coverage.qualifiedEntries.length === 0
|
|
390
|
-
? [
|
|
391
|
-
"Run: node bin/avorelo feedback intake-pack --json",
|
|
392
|
-
"Run: node bin/avorelo feedback add --source dogfood --summary \"...\"",
|
|
393
|
-
"Run: node bin/avorelo feedback import --file <redacted-json-or-jsonl> --json",
|
|
394
|
-
"Run: node bin/avorelo feedback session --partner <alias> --summary \"...\" --consent not_recorded",
|
|
395
|
-
]
|
|
396
|
-
: [
|
|
397
|
-
"Run: node bin/avorelo feedback insights --json",
|
|
398
|
-
"Run: node bin/avorelo feedback summary --json",
|
|
399
|
-
"Import additional structured feedback if external evidence exists.",
|
|
400
|
-
];
|
|
401
|
-
|
|
402
|
-
return {
|
|
403
|
-
contract: CONTRACT,
|
|
404
|
-
schemaVersion: SCHEMA_VERSION,
|
|
405
|
-
createdAt: nowIso(),
|
|
406
|
-
status: coverage.qualifiedEntries.length === 0 ? "insufficient_data" : status,
|
|
407
|
-
readinessStatus: coverage.readinessStatus,
|
|
408
|
-
score: coverage.score,
|
|
409
|
-
feedbackItemsCount: totalEntries,
|
|
410
|
-
qualifiedFeedbackItemsCount: coverage.qualifiedEntries.length,
|
|
411
|
-
simulatedFeedbackItemsCount: coverage.simulatedEntries,
|
|
412
|
-
sources,
|
|
413
|
-
coverage: {
|
|
414
|
-
sourceCount: coverage.sourceCount,
|
|
415
|
-
themeCount: coverage.themeCount,
|
|
416
|
-
activationStagesTagged: activationIssues.length,
|
|
417
|
-
trustConcernCount: trustConcerns.length,
|
|
418
|
-
pricingConcernCount: pricingConcerns.length,
|
|
419
|
-
},
|
|
420
|
-
topThemes,
|
|
421
|
-
objections,
|
|
422
|
-
activationIssues,
|
|
423
|
-
trustConcerns,
|
|
424
|
-
pricingConcerns,
|
|
425
|
-
evidenceQuality: coverage.evidenceQuality,
|
|
426
|
-
missingEvidence,
|
|
427
|
-
safeNextActions,
|
|
428
|
-
totalFeedbackEntries: totalEntries,
|
|
429
|
-
clustersFound: clusters.length,
|
|
430
|
-
topFriction: topFriction ? topFriction.frictionType : null,
|
|
431
|
-
topFrictionCount: topFriction ? topFriction.count : 0,
|
|
432
|
-
clusters,
|
|
433
|
-
hasBlockerSeverity: hasBlockers,
|
|
434
|
-
message,
|
|
435
|
-
simulatedDataExcluded: true,
|
|
436
|
-
sourceArtifacts: {
|
|
437
|
-
manualFeedbackDir: ".claude/cco/feedback",
|
|
438
|
-
importedFeedbackEvidence: ".claude/cco/evidence/feedback/feedback.jsonl",
|
|
439
|
-
intakePackDir: ".claude/cco/evidence/feedback/intake-pack",
|
|
440
|
-
},
|
|
441
|
-
noRawFeedbackExposed: true,
|
|
442
|
-
redacted: true,
|
|
443
|
-
};
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
function writeFeedbackIntelligence(cwd, intelligence) {
|
|
447
|
-
const dirAbs = path.join(cwd, INTELLIGENCE_DIR_REL);
|
|
448
|
-
fs.mkdirSync(dirAbs, { recursive: true });
|
|
449
|
-
const absPath = path.join(cwd, ARTIFACT_REL);
|
|
450
|
-
fs.writeFileSync(absPath, JSON.stringify(intelligence, null, 2), "utf8");
|
|
451
|
-
return absPath;
|
|
452
|
-
}
|
|
453
|
-
|
|
454
|
-
function buildFeedbackIntelligenceSurface(cwd, options = {}) {
|
|
455
|
-
const absPath = path.join(cwd, ARTIFACT_REL);
|
|
456
|
-
const existing = safeReadJson(absPath);
|
|
457
|
-
if (existing) {
|
|
458
|
-
return {
|
|
459
|
-
status: existing.status,
|
|
460
|
-
readinessStatus: existing.readinessStatus,
|
|
461
|
-
topFriction: existing.topFriction,
|
|
462
|
-
clustersFound: existing.clustersFound,
|
|
463
|
-
totalEntries: existing.totalFeedbackEntries,
|
|
464
|
-
qualifiedFeedbackItemsCount: existing.qualifiedFeedbackItemsCount || 0,
|
|
465
|
-
artifactPath: ARTIFACT_REL,
|
|
466
|
-
};
|
|
467
|
-
}
|
|
468
|
-
const intel = buildFeedbackIntelligence(cwd, options);
|
|
469
|
-
writeFeedbackIntelligence(cwd, intel);
|
|
470
|
-
return {
|
|
471
|
-
status: intel.status,
|
|
472
|
-
readinessStatus: intel.readinessStatus,
|
|
473
|
-
topFriction: intel.topFriction,
|
|
474
|
-
clustersFound: intel.clustersFound,
|
|
475
|
-
totalEntries: intel.totalFeedbackEntries,
|
|
476
|
-
qualifiedFeedbackItemsCount: intel.qualifiedFeedbackItemsCount || 0,
|
|
477
|
-
artifactPath: ARTIFACT_REL,
|
|
478
|
-
};
|
|
479
|
-
}
|
|
480
|
-
|
|
481
|
-
function formatFeedbackIntelligenceText(intelligence, options = {}) {
|
|
482
|
-
const debug = options.debug === true;
|
|
483
|
-
const lines = [];
|
|
484
|
-
|
|
485
|
-
lines.push(`Feedback intelligence: ${intelligence.status}`);
|
|
486
|
-
lines.push(` Readiness: ${intelligence.readinessStatus}`);
|
|
487
|
-
lines.push(` Score: ${intelligence.score}`);
|
|
488
|
-
lines.push(` Entries: ${intelligence.totalFeedbackEntries}`);
|
|
489
|
-
lines.push(` Qualified: ${intelligence.qualifiedFeedbackItemsCount}`);
|
|
490
|
-
lines.push(` Clusters: ${intelligence.clustersFound}`);
|
|
491
|
-
|
|
492
|
-
if (intelligence.topFriction) {
|
|
493
|
-
lines.push(` Top friction: ${intelligence.topFriction} (${intelligence.topFrictionCount})`);
|
|
494
|
-
} else {
|
|
495
|
-
lines.push(` Top friction: none`);
|
|
496
|
-
}
|
|
497
|
-
|
|
498
|
-
if (intelligence.message) {
|
|
499
|
-
lines.push(` Note: ${intelligence.message}`);
|
|
500
|
-
}
|
|
501
|
-
|
|
502
|
-
if (debug && intelligence.clusters && intelligence.clusters.length > 0) {
|
|
503
|
-
lines.push("");
|
|
504
|
-
lines.push("Friction clusters:");
|
|
505
|
-
for (const cluster of intelligence.clusters) {
|
|
506
|
-
lines.push(` - ${cluster.frictionType} (${cluster.severity}, x${cluster.count})`);
|
|
507
|
-
lines.push(` Action: ${cluster.recommendedAction}`);
|
|
508
|
-
if (cluster.mappedNextPr) {
|
|
509
|
-
lines.push(` Next PR: ${cluster.mappedNextPr}`);
|
|
510
|
-
}
|
|
511
|
-
}
|
|
512
|
-
}
|
|
513
|
-
|
|
514
|
-
if (debug && intelligence.safeNextActions && intelligence.safeNextActions.length > 0) {
|
|
515
|
-
lines.push("");
|
|
516
|
-
lines.push("Next:");
|
|
517
|
-
intelligence.safeNextActions.slice(0, 3).forEach((action) => lines.push(` - ${action}`));
|
|
518
|
-
}
|
|
519
|
-
|
|
520
|
-
return lines.join("\n");
|
|
521
|
-
}
|
|
522
|
-
|
|
523
|
-
module.exports = {
|
|
524
|
-
CONTRACT,
|
|
525
|
-
SCHEMA_VERSION,
|
|
526
|
-
ARTIFACT_REL,
|
|
527
|
-
FRICTION_TYPES,
|
|
528
|
-
FRICTION_KEYWORDS,
|
|
529
|
-
LEGACY_FRICTION_MAP,
|
|
530
|
-
classifyFriction,
|
|
531
|
-
collectFeedbackEntries,
|
|
532
|
-
buildFrictionClusters,
|
|
533
|
-
buildFeedbackIntelligence,
|
|
534
|
-
writeFeedbackIntelligence,
|
|
535
|
-
buildFeedbackIntelligenceSurface,
|
|
536
|
-
formatFeedbackIntelligenceText,
|
|
537
|
-
};
|