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,352 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
// ── Work Panel Preview ────────────────────────────────────────────────────────
|
|
4
|
-
//
|
|
5
|
-
// Contract: avorelo.workPanelPreview.v1
|
|
6
|
-
//
|
|
7
|
-
// Generates a local-only compact preview of the current execution packet.
|
|
8
|
-
// V1: JSON preview artifact + compact CLI-rendered preview.
|
|
9
|
-
//
|
|
10
|
-
// Not a permanent dashboard. Not a CSS editor. Not browser injection.
|
|
11
|
-
// Local-only artifacts. No network. No auto-apply.
|
|
12
|
-
|
|
13
|
-
const fs = require("fs");
|
|
14
|
-
const path = require("path");
|
|
15
|
-
const { ensureCcoDirs } = require("./fsx");
|
|
16
|
-
const { appendProductLearningEvent } = require("./product-learning-events");
|
|
17
|
-
|
|
18
|
-
const CONTRACT = "avorelo.workPanelPreview.v1";
|
|
19
|
-
const SCHEMA_VERSION = 1;
|
|
20
|
-
|
|
21
|
-
const LATEST_PREVIEW_JSON_REL = ".claude/cco/orchestration/work-panel/latest-preview.json";
|
|
22
|
-
const LATEST_PREVIEW_HTML_REL = ".claude/cco/orchestration/work-panel/latest-preview.html";
|
|
23
|
-
|
|
24
|
-
function safeReadJson(absPath) {
|
|
25
|
-
try {
|
|
26
|
-
if (!fs.existsSync(absPath)) return null;
|
|
27
|
-
return JSON.parse(fs.readFileSync(absPath, "utf8").replace(/^/, ""));
|
|
28
|
-
} catch {
|
|
29
|
-
return null;
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
function nowIso() {
|
|
34
|
-
return new Date().toISOString();
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
// ── Panel content builder ─────────────────────────────────────────────────────
|
|
38
|
-
|
|
39
|
-
function buildPanelContent(packet, projectProfile) {
|
|
40
|
-
if (!packet) {
|
|
41
|
-
return {
|
|
42
|
-
status: "no_packet",
|
|
43
|
-
message: "No execution packet found. Run `avorelo execution-packet <task>` first.",
|
|
44
|
-
goal: null,
|
|
45
|
-
mode: null,
|
|
46
|
-
riskLevel: null,
|
|
47
|
-
approvalRequired: false,
|
|
48
|
-
proofRequired: [],
|
|
49
|
-
allowedScopeSummary: null,
|
|
50
|
-
blockedScopeSummary: null,
|
|
51
|
-
makeSaferSuggestion: null,
|
|
52
|
-
cancelInstruction: null,
|
|
53
|
-
};
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
const riskLevel = packet.risk?.level || "unknown";
|
|
57
|
-
|
|
58
|
-
// Make safer suggestion based on mode and risk
|
|
59
|
-
let makeSaferSuggestion = null;
|
|
60
|
-
if (riskLevel === "high" || riskLevel === "critical") {
|
|
61
|
-
makeSaferSuggestion = "Switch to 'refactor_plan' mode to scope changes before executing, or request manual approval.";
|
|
62
|
-
} else if (packet.mode === "fast_prototype") {
|
|
63
|
-
makeSaferSuggestion = "Switch to 'safe_patch' mode for diff-first, proof-first execution.";
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
return {
|
|
67
|
-
status: "ready",
|
|
68
|
-
goal: packet.goal,
|
|
69
|
-
mode: packet.mode,
|
|
70
|
-
riskLevel,
|
|
71
|
-
approvalRequired: packet.userApproval || false,
|
|
72
|
-
proofRequired: (packet.requiredAfterWrite || []),
|
|
73
|
-
diffRequired: packet.diffRequired || false,
|
|
74
|
-
allowedScopeSummary: {
|
|
75
|
-
actions: (packet.allowedScope?.actions || []).slice(0, 6),
|
|
76
|
-
areas: (packet.allowedScope?.areas || []).slice(0, 4),
|
|
77
|
-
},
|
|
78
|
-
blockedScopeSummary: {
|
|
79
|
-
filePatternCount: (packet.blockedScope?.files || []).length,
|
|
80
|
-
dirCount: (packet.blockedScope?.dirs || []).length,
|
|
81
|
-
actionCount: (packet.blockedScope?.actions || []).length,
|
|
82
|
-
topBlocked: (packet.blockedScope?.files || []).slice(0, 5),
|
|
83
|
-
},
|
|
84
|
-
makeSaferSuggestion,
|
|
85
|
-
cancelInstruction: "To cancel: discard the execution packet and do not proceed with the task.",
|
|
86
|
-
safeNextAction: packet.safeNextAction || null,
|
|
87
|
-
packetId: packet.packetId || null,
|
|
88
|
-
packetPath: LATEST_PACKET_REL_FROM_PANEL,
|
|
89
|
-
promptAvailable: true,
|
|
90
|
-
projectFramework: projectProfile?.framework || null,
|
|
91
|
-
projectPackageManager: projectProfile?.packageManager || null,
|
|
92
|
-
};
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
const LATEST_PACKET_REL_FROM_PANEL = ".claude/cco/orchestration/execution-packet/latest-packet.json";
|
|
96
|
-
|
|
97
|
-
// ── HTML preview (static local artifact) ─────────────────────────────────────
|
|
98
|
-
|
|
99
|
-
function buildPreviewHtml(panel) {
|
|
100
|
-
const riskColor = {
|
|
101
|
-
low: "#2d8c4e",
|
|
102
|
-
medium: "#b58900",
|
|
103
|
-
high: "#dc3545",
|
|
104
|
-
critical: "#7b0000",
|
|
105
|
-
unknown: "#6c757d",
|
|
106
|
-
}[panel.riskLevel || "unknown"] || "#6c757d";
|
|
107
|
-
|
|
108
|
-
const proofList = (panel.proofRequired || []).length > 0
|
|
109
|
-
? panel.proofRequired.map((s) => `<li>${escHtml(s)}</li>`).join("\n")
|
|
110
|
-
: "<li>Manual review</li>";
|
|
111
|
-
|
|
112
|
-
const topBlocked = (panel.blockedScopeSummary?.topBlocked || []).map((f) => `<code>${escHtml(f)}</code>`).join(", ");
|
|
113
|
-
|
|
114
|
-
return `<!DOCTYPE html>
|
|
115
|
-
<html lang="en">
|
|
116
|
-
<head>
|
|
117
|
-
<meta charset="UTF-8">
|
|
118
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
119
|
-
<title>Avorelo Work Panel</title>
|
|
120
|
-
<style>
|
|
121
|
-
body { font-family: system-ui, sans-serif; max-width: 680px; margin: 2rem auto; padding: 1rem; color: #222; background: #fafafa; }
|
|
122
|
-
h1 { font-size: 1.1rem; font-weight: 700; margin-bottom: 0.5rem; }
|
|
123
|
-
.badge { display: inline-block; padding: 0.2em 0.7em; border-radius: 4px; font-size: 0.85rem; font-weight: 600; color: #fff; background: ${riskColor}; }
|
|
124
|
-
.section { margin: 1rem 0; padding: 0.75rem 1rem; background: #fff; border: 1px solid #e0e0e0; border-radius: 6px; }
|
|
125
|
-
.section h2 { font-size: 0.9rem; font-weight: 600; margin: 0 0 0.4rem; color: #555; text-transform: uppercase; letter-spacing: 0.03em; }
|
|
126
|
-
.goal { font-size: 1rem; font-weight: 500; }
|
|
127
|
-
.meta { font-size: 0.85rem; color: #444; }
|
|
128
|
-
.warning { background: #fff3cd; border-color: #ffc107; }
|
|
129
|
-
.warning h2 { color: #856404; }
|
|
130
|
-
code { background: #f0f0f0; border-radius: 3px; padding: 0.1em 0.3em; font-size: 0.85em; }
|
|
131
|
-
ul { margin: 0.3rem 0; padding-left: 1.2rem; }
|
|
132
|
-
.footer { font-size: 0.75rem; color: #888; margin-top: 1.5rem; border-top: 1px solid #eee; padding-top: 0.75rem; }
|
|
133
|
-
.copy-hint { font-size: 0.8rem; color: #555; font-style: italic; }
|
|
134
|
-
</style>
|
|
135
|
-
</head>
|
|
136
|
-
<body>
|
|
137
|
-
<h1>Avorelo Work Panel <span class="badge">${escHtml(panel.riskLevel || "unknown")} risk</span></h1>
|
|
138
|
-
|
|
139
|
-
<div class="section">
|
|
140
|
-
<h2>Goal</h2>
|
|
141
|
-
<div class="goal">${escHtml(panel.goal || "No goal set.")}</div>
|
|
142
|
-
<div class="meta">Mode: <strong>${escHtml(panel.mode || "—")}</strong> | Worker: claude_code</div>
|
|
143
|
-
</div>
|
|
144
|
-
|
|
145
|
-
${panel.approvalRequired ? `<div class="section warning">
|
|
146
|
-
<h2>⚠ Approval Required</h2>
|
|
147
|
-
<p>This packet requires human approval before executing. Do not proceed without explicit sign-off.</p>
|
|
148
|
-
</div>` : ""}
|
|
149
|
-
|
|
150
|
-
<div class="section">
|
|
151
|
-
<h2>Allowed Scope</h2>
|
|
152
|
-
<div class="meta">Actions: ${escHtml((panel.allowedScopeSummary?.actions || []).join(", ") || "file_read, file_write_with_diff")}</div>
|
|
153
|
-
${panel.allowedScopeSummary?.areas?.length > 0 ? `<div class="meta">Areas: ${escHtml(panel.allowedScopeSummary.areas.join(", "))}</div>` : ""}
|
|
154
|
-
</div>
|
|
155
|
-
|
|
156
|
-
<div class="section">
|
|
157
|
-
<h2>Blocked Scope</h2>
|
|
158
|
-
<div class="meta">
|
|
159
|
-
${(panel.blockedScopeSummary?.filePatternCount || 0)} file patterns blocked |
|
|
160
|
-
${(panel.blockedScopeSummary?.dirCount || 0)} sensitive dirs |
|
|
161
|
-
${(panel.blockedScopeSummary?.actionCount || 0)} actions blocked
|
|
162
|
-
</div>
|
|
163
|
-
${topBlocked ? `<div class="meta">Top blocked: ${topBlocked}</div>` : ""}
|
|
164
|
-
<div class="meta"><em>Secrets, auth, billing, deploy are always blocked.</em></div>
|
|
165
|
-
</div>
|
|
166
|
-
|
|
167
|
-
<div class="section">
|
|
168
|
-
<h2>Proof Required</h2>
|
|
169
|
-
<ul>${proofList}</ul>
|
|
170
|
-
${panel.diffRequired ? `<div class="meta">Diff required before any write.</div>` : ""}
|
|
171
|
-
</div>
|
|
172
|
-
|
|
173
|
-
${panel.makeSaferSuggestion ? `<div class="section">
|
|
174
|
-
<h2>Make Safer</h2>
|
|
175
|
-
<div class="meta">${escHtml(panel.makeSaferSuggestion)}</div>
|
|
176
|
-
</div>` : ""}
|
|
177
|
-
|
|
178
|
-
<div class="section">
|
|
179
|
-
<h2>Next Action</h2>
|
|
180
|
-
<div class="meta">${escHtml(panel.safeNextAction || "Review the packet before proceeding.")}</div>
|
|
181
|
-
</div>
|
|
182
|
-
|
|
183
|
-
<div class="section">
|
|
184
|
-
<h2>Copy</h2>
|
|
185
|
-
<div class="copy-hint">Execution packet: <code>${escHtml(panel.packetPath || "")}</code></div>
|
|
186
|
-
<div class="copy-hint">Agent prompt: run <code>avorelo execution-packet --debug</code> to view compiled prompt.</div>
|
|
187
|
-
</div>
|
|
188
|
-
|
|
189
|
-
<div class="footer">
|
|
190
|
-
Local-only preview. No network. No browser injection. No auto-apply.
|
|
191
|
-
Packet: ${escHtml(panel.packetId || "—")} | Generated: ${escHtml(nowIso())}
|
|
192
|
-
</div>
|
|
193
|
-
</body>
|
|
194
|
-
</html>`;
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
function escHtml(str) {
|
|
198
|
-
return String(str || "").replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
function nowIso() {
|
|
202
|
-
return new Date().toISOString();
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
// ── Build and write ───────────────────────────────────────────────────────────
|
|
206
|
-
|
|
207
|
-
function buildWorkPanelPreview(cwd, options = {}) {
|
|
208
|
-
const packet = safeReadJson(path.join(cwd, ".claude", "cco", "orchestration", "execution-packet", "latest-packet.json"));
|
|
209
|
-
const projectProfile = safeReadJson(path.join(cwd, ".claude", "cco", "orchestration", "project-profile", "latest-profile.json"));
|
|
210
|
-
|
|
211
|
-
const panel = buildPanelContent(packet, projectProfile);
|
|
212
|
-
|
|
213
|
-
const preview = {
|
|
214
|
-
contract: CONTRACT,
|
|
215
|
-
schemaVersion: SCHEMA_VERSION,
|
|
216
|
-
createdAt: nowIso(),
|
|
217
|
-
customerVisible: false,
|
|
218
|
-
debugAvailable: true,
|
|
219
|
-
localOnly: true,
|
|
220
|
-
panel,
|
|
221
|
-
artifacts: {
|
|
222
|
-
jsonPath: LATEST_PREVIEW_JSON_REL,
|
|
223
|
-
htmlPath: LATEST_PREVIEW_HTML_REL,
|
|
224
|
-
},
|
|
225
|
-
caveats: [
|
|
226
|
-
"Local-only preview. No network calls.",
|
|
227
|
-
"No browser injection or auto-apply.",
|
|
228
|
-
"Not a CSS editor or Visual QA full implementation.",
|
|
229
|
-
"Execution packet must be compiled first.",
|
|
230
|
-
],
|
|
231
|
-
redacted: true,
|
|
232
|
-
};
|
|
233
|
-
|
|
234
|
-
return preview;
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
function writeWorkPanelPreview(cwd, preview) {
|
|
238
|
-
ensureCcoDirs(cwd);
|
|
239
|
-
const dir = path.join(cwd, ".claude", "cco", "orchestration", "work-panel");
|
|
240
|
-
fs.mkdirSync(dir, { recursive: true });
|
|
241
|
-
|
|
242
|
-
// Write JSON preview
|
|
243
|
-
const jsonPath = path.join(cwd, LATEST_PREVIEW_JSON_REL);
|
|
244
|
-
fs.writeFileSync(jsonPath, JSON.stringify(preview, null, 2), "utf8");
|
|
245
|
-
|
|
246
|
-
// Write HTML preview
|
|
247
|
-
const htmlContent = buildPreviewHtml(preview.panel || {});
|
|
248
|
-
const htmlPath = path.join(cwd, LATEST_PREVIEW_HTML_REL);
|
|
249
|
-
fs.writeFileSync(htmlPath, htmlContent, "utf8");
|
|
250
|
-
|
|
251
|
-
try {
|
|
252
|
-
appendProductLearningEvent(cwd, {
|
|
253
|
-
eventName: "work_panel_preview_generated",
|
|
254
|
-
category: "work_panel",
|
|
255
|
-
surface: "local",
|
|
256
|
-
status: "observed",
|
|
257
|
-
payload: {
|
|
258
|
-
panelStatus: preview.panel?.status || "unknown",
|
|
259
|
-
riskLevel: preview.panel?.riskLevel || "unknown",
|
|
260
|
-
approvalRequired: preview.panel?.approvalRequired || false,
|
|
261
|
-
proofStepCount: (preview.panel?.proofRequired || []).length,
|
|
262
|
-
htmlGenerated: true,
|
|
263
|
-
localOnly: true,
|
|
264
|
-
},
|
|
265
|
-
});
|
|
266
|
-
} catch {
|
|
267
|
-
// non-blocking
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
return {
|
|
271
|
-
jsonPath: LATEST_PREVIEW_JSON_REL,
|
|
272
|
-
htmlPath: LATEST_PREVIEW_HTML_REL,
|
|
273
|
-
};
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
function buildWorkPanelSurface(cwd, options = {}) {
|
|
277
|
-
const absPath = path.join(cwd, LATEST_PREVIEW_JSON_REL);
|
|
278
|
-
const preview = safeReadJson(absPath);
|
|
279
|
-
if (!preview) {
|
|
280
|
-
return {
|
|
281
|
-
status: "not_run",
|
|
282
|
-
latestPreviewPath: null,
|
|
283
|
-
customerVisible: false,
|
|
284
|
-
debugAvailable: false,
|
|
285
|
-
nextAction: "Run `avorelo work-panel <task>` to generate a work panel preview.",
|
|
286
|
-
};
|
|
287
|
-
}
|
|
288
|
-
return {
|
|
289
|
-
status: preview.panel?.status || "ready",
|
|
290
|
-
latestPreviewPath: LATEST_PREVIEW_JSON_REL,
|
|
291
|
-
latestHtmlPath: LATEST_PREVIEW_HTML_REL,
|
|
292
|
-
customerVisible: false,
|
|
293
|
-
debugAvailable: true,
|
|
294
|
-
riskLevel: preview.panel?.riskLevel || null,
|
|
295
|
-
approvalRequired: preview.panel?.approvalRequired || false,
|
|
296
|
-
nextAction: null,
|
|
297
|
-
};
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
function formatWorkPanelText(preview, options = {}) {
|
|
301
|
-
const panel = preview?.panel || {};
|
|
302
|
-
const debug = options.debug || false;
|
|
303
|
-
|
|
304
|
-
const lines = [
|
|
305
|
-
"Avorelo Work Panel Preview",
|
|
306
|
-
"",
|
|
307
|
-
panel.status === "no_packet"
|
|
308
|
-
? panel.message
|
|
309
|
-
: [
|
|
310
|
-
`Goal: ${panel.goal || "—"}`,
|
|
311
|
-
`Mode: ${panel.mode || "—"}`,
|
|
312
|
-
`Risk: ${panel.riskLevel || "—"}`,
|
|
313
|
-
panel.approvalRequired ? "⚠ APPROVAL REQUIRED" : null,
|
|
314
|
-
"",
|
|
315
|
-
`Allowed: ${(panel.allowedScopeSummary?.actions || []).join(", ")}`,
|
|
316
|
-
`Blocked: ${panel.blockedScopeSummary?.filePatternCount || 0} file patterns · ${panel.blockedScopeSummary?.actionCount || 0} actions`,
|
|
317
|
-
"",
|
|
318
|
-
`Proof required: ${(panel.proofRequired || []).join(", ") || "manual review"}`,
|
|
319
|
-
panel.diffRequired ? "Diff before write: yes" : null,
|
|
320
|
-
"",
|
|
321
|
-
panel.makeSaferSuggestion ? `Make safer: ${panel.makeSaferSuggestion}` : null,
|
|
322
|
-
`Next: ${panel.safeNextAction || "Review the packet."}`,
|
|
323
|
-
].filter((l) => l !== null).join("\n"),
|
|
324
|
-
"",
|
|
325
|
-
`JSON: ${LATEST_PREVIEW_JSON_REL}`,
|
|
326
|
-
`HTML: ${LATEST_PREVIEW_HTML_REL}`,
|
|
327
|
-
].filter((l) => l !== null);
|
|
328
|
-
|
|
329
|
-
if (debug && panel.status !== "no_packet") {
|
|
330
|
-
lines.push(
|
|
331
|
-
"",
|
|
332
|
-
"--- Debug ---",
|
|
333
|
-
`Packet ID: ${panel.packetId || "—"}`,
|
|
334
|
-
`Blocked top files: ${(panel.blockedScopeSummary?.topBlocked || []).join(", ")}`,
|
|
335
|
-
`Allowed areas: ${(panel.allowedScopeSummary?.areas || []).join(", ")}`,
|
|
336
|
-
`Cancel: ${panel.cancelInstruction || "—"}`,
|
|
337
|
-
);
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
return lines.join("\n") + "\n";
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
module.exports = {
|
|
344
|
-
CONTRACT,
|
|
345
|
-
SCHEMA_VERSION,
|
|
346
|
-
LATEST_PREVIEW_JSON_REL,
|
|
347
|
-
LATEST_PREVIEW_HTML_REL,
|
|
348
|
-
buildWorkPanelPreview,
|
|
349
|
-
writeWorkPanelPreview,
|
|
350
|
-
buildWorkPanelSurface,
|
|
351
|
-
formatWorkPanelText,
|
|
352
|
-
};
|
|
@@ -1,280 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
// Workflow discipline: deterministic recommendation engine for AI-coding workflows.
|
|
4
|
-
// Input signals → infer work mode → return ordered recommendations with reason codes.
|
|
5
|
-
|
|
6
|
-
const WORKFLOW_IDS = {
|
|
7
|
-
PLAN_FIRST: "WF_PLAN_FIRST",
|
|
8
|
-
PLAN_REFACTOR: "WF_PLAN_REFACTOR",
|
|
9
|
-
DIAGNOSE_FIRST: "WF_DIAGNOSE_FIRST",
|
|
10
|
-
RISK_REVIEW: "WF_RISK_REVIEW",
|
|
11
|
-
HANDOFF_COMPRESS: "WF_HANDOFF_COMPRESS",
|
|
12
|
-
PROOF_BUNDLE: "WF_PROOF_BUNDLE",
|
|
13
|
-
REFRAME_AGENT: "WF_REFRAME_AGENT",
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
const WORKFLOW_CATALOG = {
|
|
17
|
-
[WORKFLOW_IDS.PLAN_FIRST]: {
|
|
18
|
-
id: WORKFLOW_IDS.PLAN_FIRST,
|
|
19
|
-
label: "Plan before coding",
|
|
20
|
-
description: "Break the work into scoped slices with acceptance criteria before starting implementation.",
|
|
21
|
-
nextAction: "Define scope, success criteria, and a slice plan before writing code.",
|
|
22
|
-
severity: "warn",
|
|
23
|
-
},
|
|
24
|
-
[WORKFLOW_IDS.PLAN_REFACTOR]: {
|
|
25
|
-
id: WORKFLOW_IDS.PLAN_REFACTOR,
|
|
26
|
-
label: "Plan the refactor boundary",
|
|
27
|
-
description: "Define what changes and what stays the same before touching existing code.",
|
|
28
|
-
nextAction: "Define change boundaries, protect behavior with tests, then refactor incrementally with a diff review.",
|
|
29
|
-
severity: "warn",
|
|
30
|
-
},
|
|
31
|
-
[WORKFLOW_IDS.DIAGNOSE_FIRST]: {
|
|
32
|
-
id: WORKFLOW_IDS.DIAGNOSE_FIRST,
|
|
33
|
-
label: "Diagnose before patching",
|
|
34
|
-
description: "Identify the root cause using logs, tests, or runtime evidence before applying a fix.",
|
|
35
|
-
nextAction: "Reproduce the failure, identify root cause, then patch minimally.",
|
|
36
|
-
severity: "warn",
|
|
37
|
-
},
|
|
38
|
-
[WORKFLOW_IDS.RISK_REVIEW]: {
|
|
39
|
-
id: WORKFLOW_IDS.RISK_REVIEW,
|
|
40
|
-
label: "Review risk before acting",
|
|
41
|
-
description: "Limit tool/action scope and confirm risk posture before proceeding with risky changes.",
|
|
42
|
-
nextAction: "Check what could go wrong, limit blast radius, require confirmation where appropriate.",
|
|
43
|
-
severity: "warn",
|
|
44
|
-
},
|
|
45
|
-
[WORKFLOW_IDS.HANDOFF_COMPRESS]: {
|
|
46
|
-
id: WORKFLOW_IDS.HANDOFF_COMPRESS,
|
|
47
|
-
label: "Compress and hand off",
|
|
48
|
-
description: "Summarize session state, store reentry memory, and reduce context before continuing.",
|
|
49
|
-
nextAction: "Save a session summary to reentry memory before the context window fills.",
|
|
50
|
-
severity: "info",
|
|
51
|
-
},
|
|
52
|
-
[WORKFLOW_IDS.PROOF_BUNDLE]: {
|
|
53
|
-
id: WORKFLOW_IDS.PROOF_BUNDLE,
|
|
54
|
-
label: "Produce proof before shipping",
|
|
55
|
-
description: "Bundle tests, git diff review, and a clean PR summary before merging.",
|
|
56
|
-
nextAction: "Run tests, review the diff, and write a clear PR summary with proof of correctness.",
|
|
57
|
-
severity: "info",
|
|
58
|
-
},
|
|
59
|
-
[WORKFLOW_IDS.REFRAME_AGENT]: {
|
|
60
|
-
id: WORKFLOW_IDS.REFRAME_AGENT,
|
|
61
|
-
label: "Reframe before re-running",
|
|
62
|
-
description: "Stop repetitive or unclear agent behavior. Ask for a plan or options before re-executing.",
|
|
63
|
-
nextAction: "Ask the agent to produce a plan, options, or tradeoffs before running implementation again.",
|
|
64
|
-
severity: "warn",
|
|
65
|
-
},
|
|
66
|
-
};
|
|
67
|
-
|
|
68
|
-
const VALID_TASK_TYPES = ["feature", "bug", "refactor", "pr", "unknown"];
|
|
69
|
-
const VALID_RISK_LEVELS = ["low", "medium", "high"];
|
|
70
|
-
const VALID_REPO_STATES = ["clean", "modified", "unknown"];
|
|
71
|
-
const VALID_CONTEXT_PRESSURES = ["ok", "warn", "critical"];
|
|
72
|
-
const VALID_REENTRY_STATES = ["available", "missing"];
|
|
73
|
-
const VALID_VALIDATION_STATES = ["missing", "partial", "passed"];
|
|
74
|
-
const VALID_AGENT_SECURITY_STATES = ["off", "visibility", "warn", "approve", "enforce"];
|
|
75
|
-
|
|
76
|
-
const DEFAULT_INPUT = {
|
|
77
|
-
taskType: "unknown",
|
|
78
|
-
riskLevel: "low",
|
|
79
|
-
repoState: "unknown",
|
|
80
|
-
contextPressure: "ok",
|
|
81
|
-
reentryState: "missing",
|
|
82
|
-
validationState: "missing",
|
|
83
|
-
agentSecurityState: "off",
|
|
84
|
-
ambiguous: false,
|
|
85
|
-
repetitiveAgent: false,
|
|
86
|
-
};
|
|
87
|
-
|
|
88
|
-
const VALID_MODES = ["off", "suggest", "warn"];
|
|
89
|
-
|
|
90
|
-
const DEFAULT_WORKFLOW_DISCIPLINE_CONFIG = {
|
|
91
|
-
enabled: true,
|
|
92
|
-
mode: "suggest",
|
|
93
|
-
maxRecommendations: 3,
|
|
94
|
-
};
|
|
95
|
-
|
|
96
|
-
function normalizeWorkflowDisciplineConfig(raw) {
|
|
97
|
-
const cfg = { ...DEFAULT_WORKFLOW_DISCIPLINE_CONFIG, ...(raw || {}) };
|
|
98
|
-
cfg.enabled = cfg.enabled !== false;
|
|
99
|
-
if (!VALID_MODES.includes(cfg.mode)) cfg.mode = DEFAULT_WORKFLOW_DISCIPLINE_CONFIG.mode;
|
|
100
|
-
cfg.maxRecommendations = Number.isFinite(Number(cfg.maxRecommendations))
|
|
101
|
-
? Math.max(1, Math.min(10, Number(cfg.maxRecommendations)))
|
|
102
|
-
: DEFAULT_WORKFLOW_DISCIPLINE_CONFIG.maxRecommendations;
|
|
103
|
-
return cfg;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
function normalizeInput(raw) {
|
|
107
|
-
const input = { ...DEFAULT_INPUT, ...(raw || {}) };
|
|
108
|
-
if (!VALID_TASK_TYPES.includes(input.taskType)) input.taskType = "unknown";
|
|
109
|
-
if (!VALID_RISK_LEVELS.includes(input.riskLevel)) input.riskLevel = "low";
|
|
110
|
-
if (!VALID_REPO_STATES.includes(input.repoState)) input.repoState = "unknown";
|
|
111
|
-
if (!VALID_CONTEXT_PRESSURES.includes(input.contextPressure)) input.contextPressure = "ok";
|
|
112
|
-
if (!VALID_REENTRY_STATES.includes(input.reentryState)) input.reentryState = "missing";
|
|
113
|
-
if (!VALID_VALIDATION_STATES.includes(input.validationState)) input.validationState = "missing";
|
|
114
|
-
if (!VALID_AGENT_SECURITY_STATES.includes(input.agentSecurityState)) input.agentSecurityState = "off";
|
|
115
|
-
input.ambiguous = input.ambiguous === true;
|
|
116
|
-
input.repetitiveAgent = input.repetitiveAgent === true;
|
|
117
|
-
return input;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
// Returns a stable label for the dominant work mode. Used in status surfacing.
|
|
121
|
-
function inferWorkflowMode(rawInput) {
|
|
122
|
-
const input = normalizeInput(rawInput);
|
|
123
|
-
const { taskType, riskLevel, contextPressure, repetitiveAgent } = input;
|
|
124
|
-
|
|
125
|
-
if (repetitiveAgent) return "reframe";
|
|
126
|
-
if (contextPressure === "critical") return "handoff";
|
|
127
|
-
if (taskType === "pr") return "finalize";
|
|
128
|
-
if (taskType === "bug") return "diagnose";
|
|
129
|
-
if (riskLevel === "high") return "risk-review";
|
|
130
|
-
if (taskType === "feature" || input.ambiguous) return "plan";
|
|
131
|
-
if (contextPressure === "warn") return "handoff";
|
|
132
|
-
if (taskType === "refactor") return "plan";
|
|
133
|
-
return "steady";
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
// Returns an ordered list of workflow recommendation objects with reason codes.
|
|
137
|
-
function recommendWorkflows(rawInput, rawConfig) {
|
|
138
|
-
const input = normalizeInput(rawInput);
|
|
139
|
-
const cfg = normalizeWorkflowDisciplineConfig(rawConfig);
|
|
140
|
-
|
|
141
|
-
if (!cfg.enabled || cfg.mode === "off") {
|
|
142
|
-
return [];
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
const candidates = [];
|
|
146
|
-
|
|
147
|
-
// Repetitive/unclear agent → reframe first
|
|
148
|
-
if (input.repetitiveAgent) {
|
|
149
|
-
candidates.push({
|
|
150
|
-
...WORKFLOW_CATALOG[WORKFLOW_IDS.REFRAME_AGENT],
|
|
151
|
-
reasonCodes: ["REPETITIVE_AGENT"],
|
|
152
|
-
});
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
// Context pressure → handoff/compress
|
|
156
|
-
if (input.contextPressure === "critical" || input.contextPressure === "warn") {
|
|
157
|
-
candidates.push({
|
|
158
|
-
...WORKFLOW_CATALOG[WORKFLOW_IDS.HANDOFF_COMPRESS],
|
|
159
|
-
reasonCodes: [`CONTEXT_PRESSURE_${input.contextPressure.toUpperCase()}`, input.reentryState === "missing" ? "REENTRY_MISSING" : null].filter(Boolean),
|
|
160
|
-
});
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
// Bug/failure → diagnose first
|
|
164
|
-
if (input.taskType === "bug") {
|
|
165
|
-
candidates.push({
|
|
166
|
-
...WORKFLOW_CATALOG[WORKFLOW_IDS.DIAGNOSE_FIRST],
|
|
167
|
-
reasonCodes: ["TASK_TYPE_BUG", input.validationState === "missing" ? "VALIDATION_MISSING" : null].filter(Boolean),
|
|
168
|
-
});
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
// High risk → risk review
|
|
172
|
-
if (input.riskLevel === "high") {
|
|
173
|
-
candidates.push({
|
|
174
|
-
...WORKFLOW_CATALOG[WORKFLOW_IDS.RISK_REVIEW],
|
|
175
|
-
reasonCodes: ["RISK_LEVEL_HIGH", input.repoState === "modified" ? "REPO_MODIFIED" : null].filter(Boolean),
|
|
176
|
-
});
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
// Medium risk with modified repo → risk review (lower priority)
|
|
180
|
-
if (input.riskLevel === "medium" && input.repoState === "modified" && !candidates.find((c) => c.id === WORKFLOW_IDS.RISK_REVIEW)) {
|
|
181
|
-
candidates.push({
|
|
182
|
-
...WORKFLOW_CATALOG[WORKFLOW_IDS.RISK_REVIEW],
|
|
183
|
-
reasonCodes: ["RISK_LEVEL_MEDIUM", "REPO_MODIFIED"],
|
|
184
|
-
});
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
// Feature or ambiguous → plan first
|
|
188
|
-
if (input.taskType === "feature" || (input.taskType === "unknown" && input.ambiguous)) {
|
|
189
|
-
candidates.push({
|
|
190
|
-
...WORKFLOW_CATALOG[WORKFLOW_IDS.PLAN_FIRST],
|
|
191
|
-
reasonCodes: [`TASK_TYPE_${input.taskType.toUpperCase()}`, input.ambiguous ? "AMBIGUOUS_REQUEST" : null].filter(Boolean),
|
|
192
|
-
});
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
// Refactor → plan the refactor boundary (distinct from feature planning)
|
|
196
|
-
if (input.taskType === "refactor") {
|
|
197
|
-
candidates.push({
|
|
198
|
-
...WORKFLOW_CATALOG[WORKFLOW_IDS.PLAN_REFACTOR],
|
|
199
|
-
reasonCodes: ["TASK_TYPE_REFACTOR"],
|
|
200
|
-
});
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
// PR/finalization stage → proof bundle
|
|
204
|
-
if (input.taskType === "pr") {
|
|
205
|
-
candidates.push({
|
|
206
|
-
...WORKFLOW_CATALOG[WORKFLOW_IDS.PROOF_BUNDLE],
|
|
207
|
-
reasonCodes: ["TASK_TYPE_PR", input.validationState !== "passed" ? "VALIDATION_NOT_PASSED" : null].filter(Boolean),
|
|
208
|
-
});
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
// Deduplicate by id (keep first occurrence)
|
|
212
|
-
const seen = new Set();
|
|
213
|
-
const deduped = [];
|
|
214
|
-
for (const c of candidates) {
|
|
215
|
-
if (!seen.has(c.id)) {
|
|
216
|
-
seen.add(c.id);
|
|
217
|
-
deduped.push(c);
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
return deduped.slice(0, cfg.maxRecommendations);
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
function buildWorkflowDisciplineStatus(rawInput, rawConfig) {
|
|
225
|
-
const cfg = normalizeWorkflowDisciplineConfig(rawConfig);
|
|
226
|
-
const mode = inferWorkflowMode(rawInput);
|
|
227
|
-
const recommendations = recommendWorkflows(rawInput, rawConfig);
|
|
228
|
-
const top = recommendations[0] || null;
|
|
229
|
-
|
|
230
|
-
return {
|
|
231
|
-
enabled: cfg.enabled,
|
|
232
|
-
mode: cfg.mode,
|
|
233
|
-
currentWorkflow: mode,
|
|
234
|
-
topRecommendation: top
|
|
235
|
-
? {
|
|
236
|
-
id: top.id,
|
|
237
|
-
label: top.label,
|
|
238
|
-
nextAction: top.nextAction,
|
|
239
|
-
reasonCodes: top.reasonCodes,
|
|
240
|
-
severity: top.severity,
|
|
241
|
-
}
|
|
242
|
-
: null,
|
|
243
|
-
recommendations: recommendations.map((r) => ({
|
|
244
|
-
id: r.id,
|
|
245
|
-
label: r.label,
|
|
246
|
-
reasonCodes: r.reasonCodes,
|
|
247
|
-
nextAction: r.nextAction,
|
|
248
|
-
severity: r.severity,
|
|
249
|
-
})),
|
|
250
|
-
};
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
function formatWorkflowDisciplineText(status) {
|
|
254
|
-
if (!status || !status.enabled || status.mode === "off") {
|
|
255
|
-
return null;
|
|
256
|
-
}
|
|
257
|
-
const top = status.topRecommendation;
|
|
258
|
-
if (!top) {
|
|
259
|
-
return `Workflow discipline: ${status.mode} (no active recommendation)`;
|
|
260
|
-
}
|
|
261
|
-
const why = top.reasonCodes && top.reasonCodes.length
|
|
262
|
-
? top.reasonCodes.join(", ")
|
|
263
|
-
: "workflow signal detected";
|
|
264
|
-
return [
|
|
265
|
-
`Workflow discipline: ${status.mode}`,
|
|
266
|
-
` Recommended next step: ${top.nextAction}`,
|
|
267
|
-
` Why: ${why}`,
|
|
268
|
-
].join("\n");
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
module.exports = {
|
|
272
|
-
normalizeWorkflowDisciplineConfig,
|
|
273
|
-
inferWorkflowMode,
|
|
274
|
-
recommendWorkflows,
|
|
275
|
-
buildWorkflowDisciplineStatus,
|
|
276
|
-
formatWorkflowDisciplineText,
|
|
277
|
-
DEFAULT_WORKFLOW_DISCIPLINE_CONFIG,
|
|
278
|
-
WORKFLOW_IDS,
|
|
279
|
-
WORKFLOW_CATALOG,
|
|
280
|
-
};
|