@mmerterden/multi-agent-pipeline 12.6.0 → 12.7.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/CHANGELOG.md +83 -0
- package/README.md +18 -18
- package/docs/FIGMA_PIPELINE.md +34 -34
- package/docs/adr/0001-three-model-triage.md +12 -12
- package/docs/adr/0002-instruction-driven-flag.md +5 -5
- package/docs/adr/0003-unified-shared-skills.md +5 -5
- package/docs/adr/0004-zero-dependency-philosophy.md +5 -5
- package/docs/adr/0005-lazy-phase-docs.md +2 -2
- package/docs/adr/0006-skills-core-external-split.md +6 -6
- package/docs/adr/0007-multi-tool-adapter-framework.md +19 -19
- package/docs/adr/0008-installer-modularization-and-secret-leak-defense.md +19 -19
- package/docs/adr/README.md +1 -1
- package/docs/best-practices.md +3 -3
- package/docs/features.md +28 -28
- package/docs/performance.md +16 -16
- package/docs/recovery-guide.md +39 -39
- package/index.js +4 -4
- package/install/_common.mjs +5 -11
- package/install/_copilot-instructions.mjs +2 -2
- package/install/_dev-only-files.mjs +1 -1
- package/install/_platform-filter.mjs +1 -1
- package/install/_telemetry.mjs +1 -1
- package/install/claude.mjs +10 -9
- package/install/copilot.mjs +10 -19
- package/install/index.mjs +7 -15
- package/install/templates/copilot-instructions.md +54 -54
- package/install.js +1 -1
- package/package.json +13 -10
- package/pipeline/commands/multi-agent/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/analysis/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/analysis-resolve/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/autopilot/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/build-optimize/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/create-jira/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/design-check/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/dev/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/dev-autopilot/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/dev-local/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/dev-local-autopilot/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/diff-explain/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/finish/SKILL.md +6 -6
- package/pipeline/commands/multi-agent/forget/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/garbage-collect/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/help/SKILL.md +3 -3
- package/pipeline/commands/multi-agent/issue/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/jira/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/kill/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/language/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/local/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/local-autopilot/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/log/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/manual-test/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/prune-logs/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/purge/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/refactor/SKILL.md +16 -8
- package/pipeline/commands/multi-agent/resume/SKILL.md +2 -2
- package/pipeline/commands/multi-agent/review/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/review-issue/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/review-jira/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/routines/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/save/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/scan/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/search/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/setup/SKILL.md +2 -2
- package/pipeline/commands/multi-agent/stack/SKILL.md +3 -3
- package/pipeline/commands/multi-agent/status/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/sync/SKILL.md +5 -5
- package/pipeline/commands/multi-agent/test/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/uninstall/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/update/SKILL.md +3 -3
- package/pipeline/eval/run-metrics-fixture.json +60 -13
- package/pipeline/lib/account-resolver.sh +1 -1
- package/pipeline/lib/channels-multi-repo.sh +1 -1
- package/pipeline/lib/context-link-extractor.sh +1 -1
- package/pipeline/lib/credential-store.sh +1 -1
- package/pipeline/lib/fetch-confluence.sh +1 -1
- package/pipeline/lib/fetch-crashlytics.sh +1 -1
- package/pipeline/lib/fetch-fortify.sh +1 -1
- package/pipeline/lib/fetch-graylog.sh +1 -1
- package/pipeline/lib/fetch-swagger.sh +1 -1
- package/pipeline/lib/issue-fetcher.sh +1 -1
- package/pipeline/lib/multi-repo-pipeline.sh +1 -1
- package/pipeline/lib/repo-cache.sh +1 -1
- package/pipeline/lib/submodule-detector.sh +1 -1
- package/pipeline/multi-agent-refs/component-dispatch.md +1 -1
- package/pipeline/multi-agent-refs/component-generation.md +121 -0
- package/pipeline/multi-agent-refs/cross-cli-contract.md +1 -1
- package/pipeline/multi-agent-refs/features/model-fallback.md +2 -2
- package/pipeline/multi-agent-refs/phases/phase-4-review.md +1 -1
- package/pipeline/preferences-template.json +5 -11
- package/pipeline/schemas/agent-state.schema.json +39 -9
- package/pipeline/schemas/analysis-output.schema.json +18 -4
- package/pipeline/schemas/analysis-spec.schema.json +120 -32
- package/pipeline/schemas/clarify-output.schema.json +15 -5
- package/pipeline/schemas/design-check-config.schema.json +32 -11
- package/pipeline/schemas/dev-critic-output.schema.json +20 -5
- package/pipeline/schemas/figma-project-config.schema.json +42 -10
- package/pipeline/schemas/learnings-ledger.schema.json +10 -2
- package/pipeline/schemas/migrations/figma-config-1.0.0-to-2.0.0.mjs +1 -4
- package/pipeline/schemas/migrations/prefs-2.0.0-to-2.1.0.mjs +24 -7
- package/pipeline/schemas/plan-todos.schema.json +6 -3
- package/pipeline/schemas/planning-output.schema.json +5 -1
- package/pipeline/schemas/prefs.schema.json +91 -229
- package/pipeline/schemas/test-gap.schema.json +5 -5
- package/pipeline/schemas/token-budget.json +8 -8
- package/pipeline/schemas/triage-corpus.schema.json +1 -1
- package/pipeline/scripts/aggregate-metrics.mjs +18 -6
- package/pipeline/scripts/build-skills-index.mjs +6 -2
- package/pipeline/scripts/build-stack-plugins.mjs +142 -39
- package/pipeline/scripts/check-derived-drift.mjs +196 -0
- package/pipeline/scripts/check-md-links.mjs +6 -2
- package/pipeline/scripts/classify-plan-safety.mjs +20 -7
- package/pipeline/scripts/cost-budget-check.mjs +2 -1
- package/pipeline/scripts/cost-table.json +1 -1
- package/pipeline/scripts/diff-explain.mjs +7 -3
- package/pipeline/scripts/diff-risk-score.mjs +13 -3
- package/pipeline/scripts/eval-golden-tasks-live.mjs +8 -3
- package/pipeline/scripts/eval-golden-tasks.mjs +21 -9
- package/pipeline/scripts/eval-intent.mjs +8 -4
- package/pipeline/scripts/eval-mine-corpus.mjs +14 -4
- package/pipeline/scripts/evidence-gate.mjs +7 -2
- package/pipeline/scripts/fixtures/install-layout.tsv +3 -3
- package/pipeline/scripts/gen-mode-dispatch.mjs +38 -21
- package/pipeline/scripts/gen-skills-index.mjs +18 -3
- package/pipeline/scripts/learning-curve.mjs +13 -3
- package/pipeline/scripts/learnings-ledger.mjs +103 -36
- package/pipeline/scripts/lint-mcp-refs.mjs +13 -2
- package/pipeline/scripts/lint-skills.mjs +20 -9
- package/pipeline/scripts/localize-commands.mjs +6 -1
- package/pipeline/scripts/match-skills.mjs +15 -4
- package/pipeline/scripts/migrate-prefs.mjs +33 -16
- package/pipeline/scripts/phase-tracker.sh +3 -1
- package/pipeline/scripts/repo-map.mjs +110 -64
- package/pipeline/scripts/review-scope.mjs +7 -1
- package/pipeline/scripts/routine-registry.mjs +4 -9
- package/pipeline/scripts/run-aggregator.mjs +11 -5
- package/pipeline/scripts/run-metrics.mjs +13 -8
- package/pipeline/scripts/run-smokes.mjs +57 -3
- package/pipeline/scripts/scorecard.mjs +258 -0
- package/pipeline/scripts/smoke-context-budget.sh +72 -0
- package/pipeline/scripts/smoke-model-fallback.sh +1 -1
- package/pipeline/scripts/smoke-no-mcp-in-dev-phases.sh +86 -7
- package/pipeline/scripts/smoke-own-punctuation.sh +103 -0
- package/pipeline/scripts/smoke-workflow-audit.sh +43 -11
- package/pipeline/scripts/smoke-write-state.sh +49 -5
- package/pipeline/scripts/test-gap-rules/android.json +11 -11
- package/pipeline/scripts/test-gap-rules/ios.json +16 -11
- package/pipeline/scripts/test-gap-rules/node.json +19 -7
- package/pipeline/scripts/test-gap-rules/python.json +10 -4
- package/pipeline/scripts/test-gap-scan.mjs +44 -12
- package/pipeline/scripts/test-integrity-gate.mjs +5 -1
- package/pipeline/scripts/token-budget-report.mjs +44 -21
- package/pipeline/scripts/triage-memory.mjs +126 -34
- package/pipeline/scripts/uninstall.mjs +74 -30
- package/pipeline/scripts/validate-analysis-doc.mjs +15 -5
- package/pipeline/scripts/validate-diff-risk.mjs +32 -18
- package/pipeline/scripts/validate-test-gap.mjs +17 -7
- package/pipeline/scripts/validate-triage.mjs +17 -5
- package/pipeline/scripts/write-state.mjs +32 -9
- package/pipeline/skills/.skills-index.json +91 -91
- package/pipeline/skills/shared/README.md +57 -57
- package/pipeline/skills/shared/core/apple-archive-compliance/SKILL.md +1 -1
- package/pipeline/skills/shared/core/google-play-compliance/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent/SKILL.md +26 -279
- package/pipeline/skills/shared/core/multi-agent-analysis/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-analysis-resolve/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-autopilot/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-build-optimize/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-create-jira/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-design-check/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-dev/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-dev-autopilot/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-dev-local/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-dev-local-autopilot/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-diff-explain/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-finish/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-forget/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-garbage-collect/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-help/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-issue/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-jira/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-kill/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-language/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-local/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-local-autopilot/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-log/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-manual-test/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-prune-logs/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-purge/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-refactor/SKILL.md +16 -8
- package/pipeline/skills/shared/core/multi-agent-resume/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-review/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-review-issue/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-review-jira/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-routines/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-save/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-scan/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-search/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-setup/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-stack/SKILL.md +3 -3
- package/pipeline/skills/shared/core/multi-agent-status/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-sync/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-test/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-uninstall/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-update/SKILL.md +1 -1
- package/pipeline/skills/shared/external/accessibility-compliance-accessibility-audit/SKILL.md +1 -1
- package/pipeline/skills/shared/external/agent-introspection-debugging/SKILL.md +4 -4
- package/pipeline/skills/shared/external/agentflow/SKILL.md +1 -1
- package/pipeline/skills/shared/external/android-jetpack-compose-expert/SKILL.md +1 -1
- package/pipeline/skills/shared/external/android_ui_verification/SKILL.md +1 -1
- package/pipeline/skills/shared/external/api-patterns/SKILL.md +1 -1
- package/pipeline/skills/shared/external/api-security-best-practices/SKILL.md +1 -1
- package/pipeline/skills/shared/external/app-store-changelog/SKILL.md +1 -1
- package/pipeline/skills/shared/external/backlog/BACKLOG.md +1 -1
- package/pipeline/skills/shared/external/backlog/SKILL.md +12 -12
- package/pipeline/skills/shared/external/ci-cd-pipelines/SKILL.md +1 -1
- package/pipeline/skills/shared/external/context-compression/SKILL.md +1 -1
- package/pipeline/skills/shared/external/council/SKILL.md +3 -3
- package/pipeline/skills/shared/external/css-modern/SKILL.md +1 -1
- package/pipeline/skills/shared/external/database-patterns/SKILL.md +1 -1
- package/pipeline/skills/shared/external/debugging-strategies/SKILL.md +1 -1
- package/pipeline/skills/shared/external/docker-expert/SKILL.md +1 -1
- package/pipeline/skills/shared/external/fastapi-pro/SKILL.md +1 -1
- package/pipeline/skills/shared/external/firebase/SKILL.md +1 -1
- package/pipeline/skills/shared/external/github-actions-templates/SKILL.md +1 -1
- package/pipeline/skills/shared/external/help-skills/SKILL.md +1 -1
- package/pipeline/skills/shared/external/hig-components-content/SKILL.md +1 -1
- package/pipeline/skills/shared/external/hig-components-layout/SKILL.md +1 -1
- package/pipeline/skills/shared/external/hig-components-status/SKILL.md +1 -1
- package/pipeline/skills/shared/external/hig-components-system/SKILL.md +1 -1
- package/pipeline/skills/shared/external/hig-foundations/SKILL.md +1 -1
- package/pipeline/skills/shared/external/hig-inputs/SKILL.md +1 -1
- package/pipeline/skills/shared/external/hig-patterns/SKILL.md +1 -1
- package/pipeline/skills/shared/external/hig-platforms/SKILL.md +1 -1
- package/pipeline/skills/shared/external/hig-technologies/SKILL.md +1 -1
- package/pipeline/skills/shared/external/html-semantic/SKILL.md +1 -1
- package/pipeline/skills/shared/external/humanizer/SKILL.md +1 -1
- package/pipeline/skills/shared/external/ios-debugger-agent/SKILL.md +1 -1
- package/pipeline/skills/shared/external/ios-developer/SKILL.md +1 -1
- package/pipeline/skills/shared/external/kotlin-coroutines-expert/SKILL.md +1 -1
- package/pipeline/skills/shared/external/macos-menubar-tuist-app/SKILL.md +1 -1
- package/pipeline/skills/shared/external/macos-spm-app-packaging/SKILL.md +1 -1
- package/pipeline/skills/shared/external/monorepo-architect/SKILL.md +1 -1
- package/pipeline/skills/shared/external/nextjs-app-router/SKILL.md +1 -1
- package/pipeline/skills/shared/external/nodejs-backend-patterns/SKILL.md +1 -1
- package/pipeline/skills/shared/external/observability-engineer/SKILL.md +1 -1
- package/pipeline/skills/shared/external/python-patterns/SKILL.md +1 -1
- package/pipeline/skills/shared/external/react-best-practices/SKILL.md +1 -1
- package/pipeline/skills/shared/external/rest-api-design/SKILL.md +1 -1
- package/pipeline/skills/shared/external/search-first/SKILL.md +2 -2
- package/pipeline/skills/shared/external/skill-creator/SKILL.md +12 -12
- package/pipeline/skills/shared/external/skill-creator/audit.md +21 -21
- package/pipeline/skills/shared/external/skill-creator/checklist.md +3 -3
- package/pipeline/skills/shared/external/skill-creator/examples.md +10 -10
- package/pipeline/skills/shared/external/skill-creator/label-check.md +17 -17
- package/pipeline/skills/shared/external/skill-creator/scripts/audit-panel.js +86 -50
- package/pipeline/skills/shared/external/skill-creator/template.md +9 -9
- package/pipeline/skills/shared/external/swift-concurrency-expert/SKILL.md +1 -1
- package/pipeline/skills/shared/external/swiftui-performance-audit/SKILL.md +1 -1
- package/pipeline/skills/shared/external/swiftui-ui-patterns/SKILL.md +1 -1
- package/pipeline/skills/shared/external/swiftui-view-refactor/SKILL.md +1 -1
- package/pipeline/skills/shared/external/tailwind-css/SKILL.md +1 -1
- package/pipeline/skills/shared/external/testing-backend/SKILL.md +1 -1
- package/pipeline/skills/shared/external/typescript-patterns/SKILL.md +1 -1
- package/pipeline/skills/shared/external/vue-composition/SKILL.md +1 -1
- package/pipeline/skills/shared/external/web-accessibility/SKILL.md +1 -1
- package/pipeline/skills/shared/external/web-performance/SKILL.md +1 -1
- package/pipeline/skills/shared/external/web-testing/SKILL.md +1 -1
- package/pipeline/skills/shared/external/xcode-build-benchmark/schemas/build-benchmark.schema.json +9 -49
- package/pipeline/skills/skills-index.md +57 -57
- package/pipeline/scripts/smoke-plugin-validate.sh +0 -64
|
@@ -74,9 +74,17 @@ const reasons = [];
|
|
|
74
74
|
// --- file-count ---
|
|
75
75
|
const fileCount = allFiles.size;
|
|
76
76
|
if (fileCount > 15) {
|
|
77
|
-
reasons.push({
|
|
77
|
+
reasons.push({
|
|
78
|
+
rule: "file-count-high",
|
|
79
|
+
weight: 30,
|
|
80
|
+
detail: `plan touches ${fileCount} files (threshold 15)`,
|
|
81
|
+
});
|
|
78
82
|
} else if (fileCount >= 8) {
|
|
79
|
-
reasons.push({
|
|
83
|
+
reasons.push({
|
|
84
|
+
rule: "file-count-medium",
|
|
85
|
+
weight: 10,
|
|
86
|
+
detail: `plan touches ${fileCount} files`,
|
|
87
|
+
});
|
|
80
88
|
}
|
|
81
89
|
|
|
82
90
|
// --- destructive verb ---
|
|
@@ -102,7 +110,8 @@ if (destructiveHits.length > 0) {
|
|
|
102
110
|
// mid-word hits like "Reauthorize" do not. A trailing anchor here would miss
|
|
103
111
|
// the common "AuthManager"/"TokenStore" suffix-naming and let sensitive files
|
|
104
112
|
// slip past the autopilot pause heuristic.
|
|
105
|
-
const securityRe =
|
|
113
|
+
const securityRe =
|
|
114
|
+
/(\/|^)(auth|keychain|credentials?|secret|security|tokens?|cert|encrypt|signing|privacy)/i;
|
|
106
115
|
const securityHits = [];
|
|
107
116
|
for (const f of allFiles) if (securityRe.test(f)) securityHits.push(f);
|
|
108
117
|
if (securityHits.length > 0) {
|
|
@@ -130,7 +139,11 @@ for (const t of tasks) {
|
|
|
130
139
|
if (!destructiveRe.test(t.title || "")) continue;
|
|
131
140
|
const taskDirs = new Set((t.files || []).map((f) => f.split("/").slice(0, -1).join("/")));
|
|
132
141
|
let covered = false;
|
|
133
|
-
for (const d of taskDirs)
|
|
142
|
+
for (const d of taskDirs)
|
|
143
|
+
if (testFileDirs.has(d)) {
|
|
144
|
+
covered = true;
|
|
145
|
+
break;
|
|
146
|
+
}
|
|
134
147
|
if (!covered) deleteWithoutTest.push(t.id || t.title);
|
|
135
148
|
}
|
|
136
149
|
if (deleteWithoutTest.length > 0) {
|
|
@@ -157,7 +170,8 @@ if (schemaHits.length > 0) {
|
|
|
157
170
|
}
|
|
158
171
|
|
|
159
172
|
// --- infrastructure ---
|
|
160
|
-
const infraRe =
|
|
173
|
+
const infraRe =
|
|
174
|
+
/(^|\/)(Dockerfile|install\.js|package\.json|build\.gradle|settings\.gradle|Gemfile|pyproject\.toml|\.github\/workflows\/.*\.ya?ml|vercel\.(json|ts))$/i;
|
|
161
175
|
const infraHits = [];
|
|
162
176
|
for (const f of allFiles) if (infraRe.test(f)) infraHits.push(f);
|
|
163
177
|
if (infraHits.length > 0) {
|
|
@@ -172,8 +186,7 @@ if (infraHits.length > 0) {
|
|
|
172
186
|
const score = reasons.reduce((s, r) => s + r.weight, 0);
|
|
173
187
|
const heavyHits = reasons.filter((r) => r.weight >= 30);
|
|
174
188
|
const mediumOrAboveHits = reasons.filter((r) => r.weight >= 20);
|
|
175
|
-
const recommendPause =
|
|
176
|
-
heavyHits.length >= 1 || mediumOrAboveHits.length >= 2 || score >= 50;
|
|
189
|
+
const recommendPause = heavyHits.length >= 1 || mediumOrAboveHits.length >= 2 || score >= 50;
|
|
177
190
|
|
|
178
191
|
let summary;
|
|
179
192
|
if (recommendPause) {
|
|
@@ -153,7 +153,8 @@ const base =
|
|
|
153
153
|
`(${pctOfMax.toFixed(0)}%, ${totalTok.toLocaleString("en-US")} tok @ ${cfg.pricingModel})`;
|
|
154
154
|
|
|
155
155
|
if (usd > cfg.maxUsd) {
|
|
156
|
-
const action =
|
|
156
|
+
const action =
|
|
157
|
+
cfg.onExceed === "halt" ? "HALT - run multi-agent:resume to continue" : "over budget";
|
|
157
158
|
process.stdout.write(`EXCEEDED: ${base} - ${action}\n`);
|
|
158
159
|
process.exit(11);
|
|
159
160
|
}
|
|
@@ -83,7 +83,7 @@ function loadTriage() {
|
|
|
83
83
|
if (flags["task-id"]) {
|
|
84
84
|
die(
|
|
85
85
|
"--task-id resolution not implemented in this script - use --triage or --state directly. " +
|
|
86
|
-
|
|
86
|
+
"The slash command resolves task IDs via the orchestrator and passes --state to this script.",
|
|
87
87
|
);
|
|
88
88
|
}
|
|
89
89
|
die("one of --triage, --state, or --task-id is required");
|
|
@@ -239,7 +239,9 @@ lines.push("# Phase 4 Triage Diff Bridge");
|
|
|
239
239
|
lines.push("");
|
|
240
240
|
lines.push("## Summary");
|
|
241
241
|
lines.push("");
|
|
242
|
-
lines.push(
|
|
242
|
+
lines.push(
|
|
243
|
+
`- **Accepted:** ${counts.accepted} (🚫 ${counts.blocking} blocking · ⚠️ ${counts.important} important · 💡 ${counts.suggestion} suggestion)`,
|
|
244
|
+
);
|
|
243
245
|
lines.push(`- **Deferred:** ${counts.deferred} · **Rejected:** ${counts.rejected}`);
|
|
244
246
|
lines.push(`- **Approved:** ${triage.approved === true ? "✅ yes" : "❌ no"}`);
|
|
245
247
|
lines.push("");
|
|
@@ -252,7 +254,9 @@ for (const [file, items] of byFile) {
|
|
|
252
254
|
const icon = severityIcon(item.severity);
|
|
253
255
|
const bucketTag = bucketIcon(item._bucket);
|
|
254
256
|
const reviewer = item.reviewer ? ` _(${item.reviewer})_` : "";
|
|
255
|
-
lines.push(
|
|
257
|
+
lines.push(
|
|
258
|
+
`### ${bucketTag} ${icon} ${severityLabel(item.severity)} - line ${item.line ?? "?"}${reviewer}`,
|
|
259
|
+
);
|
|
256
260
|
lines.push("");
|
|
257
261
|
if (item._reason) lines.push(`> _${item._bucket}: ${item._reason}_`);
|
|
258
262
|
lines.push(`> ${item.issue}`);
|
|
@@ -71,11 +71,20 @@ function git(args) {
|
|
|
71
71
|
|
|
72
72
|
function resolveBase() {
|
|
73
73
|
if (BASE) return BASE;
|
|
74
|
-
for (const ref of [
|
|
74
|
+
for (const ref of [
|
|
75
|
+
"origin/main",
|
|
76
|
+
"main",
|
|
77
|
+
"origin/master",
|
|
78
|
+
"master",
|
|
79
|
+
"develop",
|
|
80
|
+
"origin/develop",
|
|
81
|
+
]) {
|
|
75
82
|
try {
|
|
76
83
|
execFileSync("git", ["-C", ROOT, "rev-parse", "--verify", ref], { stdio: "ignore" });
|
|
77
84
|
return ref;
|
|
78
|
-
} catch {
|
|
85
|
+
} catch {
|
|
86
|
+
/* try next */
|
|
87
|
+
}
|
|
79
88
|
}
|
|
80
89
|
throw new Error("no base ref found (tried origin/main, main, master, develop)");
|
|
81
90
|
}
|
|
@@ -210,7 +219,8 @@ function complexitySignal(addedLines) {
|
|
|
210
219
|
let count = 0;
|
|
211
220
|
for (const l of addedLines) {
|
|
212
221
|
if (/^\s*(if|guard|switch|case\s|while|for|do|try)\b/.test(l)) count++;
|
|
213
|
-
else if (/\b\?\s*:/.test(l))
|
|
222
|
+
else if (/\b\?\s*:/.test(l))
|
|
223
|
+
count++; // ternary
|
|
214
224
|
else if (/&&|\|\|/.test(l)) count++;
|
|
215
225
|
}
|
|
216
226
|
return count;
|
|
@@ -269,7 +269,8 @@ const summary = {
|
|
|
269
269
|
cases_run: results.length,
|
|
270
270
|
cases_passed: results.filter((r) => r.pass === true).length,
|
|
271
271
|
cases_failed: results.filter((r) => r.pass === false).length,
|
|
272
|
-
cases_skipped: results.filter((r) => typeof r.pass === "string" && r.pass.startsWith("skipped"))
|
|
272
|
+
cases_skipped: results.filter((r) => typeof r.pass === "string" && r.pass.startsWith("skipped"))
|
|
273
|
+
.length,
|
|
273
274
|
budget_per_case: budget,
|
|
274
275
|
total_budget: totalBudget,
|
|
275
276
|
projected_spend: projectedSpend,
|
|
@@ -280,8 +281,12 @@ if (asJson) {
|
|
|
280
281
|
} else {
|
|
281
282
|
console.log("");
|
|
282
283
|
console.log(`eval-golden-tasks-live (${summary.mode})`);
|
|
283
|
-
console.log(
|
|
284
|
-
|
|
284
|
+
console.log(
|
|
285
|
+
` cases: ${summary.cases_run}/${summary.cases_total} run, ${summary.cases_passed} passed, ${summary.cases_failed} failed, ${summary.cases_skipped} skipped`,
|
|
286
|
+
);
|
|
287
|
+
console.log(
|
|
288
|
+
` budget: $${budget.toFixed(2)}/case · total cap $${totalBudget.toFixed(2)} · projected spend $${projectedSpend.toFixed(2)}`,
|
|
289
|
+
);
|
|
285
290
|
console.log("");
|
|
286
291
|
for (const r of results) {
|
|
287
292
|
const icon = r.pass === true ? "✓" : r.pass === false ? "✗" : "·";
|
|
@@ -44,7 +44,7 @@ const validators = {
|
|
|
44
44
|
analysis: join(root, "pipeline", "scripts", "validate-analysis.mjs"),
|
|
45
45
|
planning: join(root, "pipeline", "scripts", "validate-planning.mjs"),
|
|
46
46
|
reviewer: join(root, "pipeline", "scripts", "validate-reviewer.mjs"),
|
|
47
|
-
triage:
|
|
47
|
+
triage: join(root, "pipeline", "scripts", "validate-triage.mjs"),
|
|
48
48
|
};
|
|
49
49
|
|
|
50
50
|
const args = process.argv.slice(2);
|
|
@@ -108,10 +108,12 @@ function runCase(name) {
|
|
|
108
108
|
|
|
109
109
|
// --- schema checks ---
|
|
110
110
|
const a = runValidator(validators.analysis, analysisPath);
|
|
111
|
-
if (a.code !== 0)
|
|
111
|
+
if (a.code !== 0)
|
|
112
|
+
errors.push(`phase-1-analysis fails validate-analysis (exit ${a.code}): ${a.stderr.trim()}`);
|
|
112
113
|
|
|
113
114
|
const p = runValidator(validators.planning, planPath);
|
|
114
|
-
if (p.code !== 0)
|
|
115
|
+
if (p.code !== 0)
|
|
116
|
+
errors.push(`phase-2-plan fails validate-planning (exit ${p.code}): ${p.stderr.trim()}`);
|
|
115
117
|
|
|
116
118
|
// phase-4-review is an array (one entry per reviewer) - validate each
|
|
117
119
|
if (!Array.isArray(review)) {
|
|
@@ -124,20 +126,26 @@ function runCase(name) {
|
|
|
124
126
|
input: tmpPayload,
|
|
125
127
|
encoding: "utf-8",
|
|
126
128
|
});
|
|
127
|
-
if (r.status !== 0)
|
|
129
|
+
if (r.status !== 0)
|
|
130
|
+
errors.push(
|
|
131
|
+
`phase-4-review[${idx}] fails validate-reviewer (exit ${r.status}): ${(r.stderr || "").trim()}`,
|
|
132
|
+
);
|
|
128
133
|
});
|
|
129
134
|
}
|
|
130
135
|
|
|
131
136
|
const t = runValidator(validators.triage, triagePath);
|
|
132
137
|
// validate-triage exit codes: 0 valid+clean, 2 contradiction, 3 correction.
|
|
133
138
|
// For fixtures we accept 0 only.
|
|
134
|
-
if (t.code !== 0)
|
|
139
|
+
if (t.code !== 0)
|
|
140
|
+
errors.push(`phase-4-triage fails validate-triage (exit ${t.code}): ${t.stderr.trim()}`);
|
|
135
141
|
|
|
136
142
|
// --- cross-file consistency ---
|
|
137
143
|
|
|
138
144
|
// 1. Stack match
|
|
139
145
|
if (analysis.stack?.primary !== task.expectedStack) {
|
|
140
|
-
errors.push(
|
|
146
|
+
errors.push(
|
|
147
|
+
`stack mismatch: task.expectedStack=${task.expectedStack}, phase-1.stack.primary=${analysis.stack?.primary}`,
|
|
148
|
+
);
|
|
141
149
|
}
|
|
142
150
|
|
|
143
151
|
// 2. plan files ⊆ analysis touchedAreas paths
|
|
@@ -162,7 +170,7 @@ function runCase(name) {
|
|
|
162
170
|
].filter((f) => f && typeof f === "object");
|
|
163
171
|
const triageKeys = new Set(triageAll.map((f) => `${f.file}::${f.line}::${f.issue}`));
|
|
164
172
|
|
|
165
|
-
for (const rev of
|
|
173
|
+
for (const rev of Array.isArray(review) ? review : []) {
|
|
166
174
|
for (const f of rev.findings || []) {
|
|
167
175
|
const key = `${f.file}::${f.line}::${f.issue}`;
|
|
168
176
|
const inPlan = plannedFiles.has(f.file);
|
|
@@ -176,11 +184,15 @@ function runCase(name) {
|
|
|
176
184
|
// 4. blocker + deferral counts match task.expected*
|
|
177
185
|
const acceptedBlockers = (triage.accepted || []).filter((x) => x.severity === "blocking").length;
|
|
178
186
|
if (typeof task.expectedBlockers === "number" && acceptedBlockers !== task.expectedBlockers) {
|
|
179
|
-
errors.push(
|
|
187
|
+
errors.push(
|
|
188
|
+
`expectedBlockers=${task.expectedBlockers}, triage.accepted blocking count=${acceptedBlockers}`,
|
|
189
|
+
);
|
|
180
190
|
}
|
|
181
191
|
const deferredCount = (triage.deferred || []).length;
|
|
182
192
|
if (typeof task.expectedDeferrals === "number" && deferredCount !== task.expectedDeferrals) {
|
|
183
|
-
errors.push(
|
|
193
|
+
errors.push(
|
|
194
|
+
`expectedDeferrals=${task.expectedDeferrals}, triage.deferred count=${deferredCount}`,
|
|
195
|
+
);
|
|
184
196
|
}
|
|
185
197
|
|
|
186
198
|
return { name, ok: errors.length === 0, errors };
|
|
@@ -70,8 +70,8 @@ function isSafe(expected, got) {
|
|
|
70
70
|
return false;
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
-
const mismatches = [];
|
|
74
|
-
const exactMisses = [];
|
|
73
|
+
const mismatches = []; // operationally unsafe (gate-failing)
|
|
74
|
+
const exactMisses = []; // not exact, but operationally safe (informational)
|
|
75
75
|
let safe = 0;
|
|
76
76
|
let exact = 0;
|
|
77
77
|
for (const c of cases) {
|
|
@@ -96,8 +96,12 @@ const summary = {
|
|
|
96
96
|
console.log(JSON.stringify(summary, null, 2));
|
|
97
97
|
|
|
98
98
|
if (accuracy < minAccuracy) {
|
|
99
|
-
console.error(
|
|
99
|
+
console.error(
|
|
100
|
+
`\neval-intent: safe accuracy ${(accuracy * 100).toFixed(1)}% < required ${(minAccuracy * 100).toFixed(0)}% (${mismatches.length} dangerous misclassification(s))`,
|
|
101
|
+
);
|
|
100
102
|
process.exit(1);
|
|
101
103
|
}
|
|
102
|
-
console.error(
|
|
104
|
+
console.error(
|
|
105
|
+
`\neval-intent: safe ${(accuracy * 100).toFixed(1)}% (${safe}/${cases.length}), exact ${((exact / cases.length) * 100).toFixed(1)}% - pass`,
|
|
106
|
+
);
|
|
103
107
|
process.exit(0);
|
|
@@ -45,7 +45,9 @@ for (let i = 0; i < args.length; i++) {
|
|
|
45
45
|
else if (args[i] === "--limit") opts.limit = Number(args[++i]) || Infinity;
|
|
46
46
|
else if (args[i] === "--dry-run") opts.dryRun = true;
|
|
47
47
|
else if (args[i] === "-h" || args[i] === "--help") {
|
|
48
|
-
console.log(
|
|
48
|
+
console.log(
|
|
49
|
+
"Usage: eval-mine-corpus.mjs [--corpus <path>] [--repo-slug <slug>] [--limit N] [--dry-run]",
|
|
50
|
+
);
|
|
49
51
|
process.exit(0);
|
|
50
52
|
}
|
|
51
53
|
}
|
|
@@ -182,19 +184,27 @@ for (const c of selected) {
|
|
|
182
184
|
writeFileSync(join(dir, "expected.json"), JSON.stringify(c.expected, null, 2) + "\n");
|
|
183
185
|
writeFileSync(
|
|
184
186
|
join(dir, "meta.json"),
|
|
185
|
-
JSON.stringify(
|
|
187
|
+
JSON.stringify(
|
|
188
|
+
{ task_id: c.taskId, source: "eval-mine-corpus", hasHumanSignal: c.hasHumanSignal },
|
|
189
|
+
null,
|
|
190
|
+
2,
|
|
191
|
+
) + "\n",
|
|
186
192
|
);
|
|
187
193
|
// Validate the emitted expected.json against the triage contract; flag if bad.
|
|
188
194
|
const res = spawnSync("node", [validator, join(dir, "expected.json")], { encoding: "utf-8" });
|
|
189
195
|
const ok = res.status === 0;
|
|
190
196
|
if (!ok) invalid++;
|
|
191
|
-
console.log(
|
|
197
|
+
console.log(
|
|
198
|
+
` emitted: triage-candidates/${safe}${tag} ${ok ? "(schema OK)" : "(SCHEMA FAIL - review)"}`,
|
|
199
|
+
);
|
|
192
200
|
written++;
|
|
193
201
|
}
|
|
194
202
|
|
|
195
203
|
if (!opts.dryRun) {
|
|
196
204
|
console.log("");
|
|
197
|
-
console.log(
|
|
205
|
+
console.log(
|
|
206
|
+
`eval-mine-corpus: ${written} candidate(s) written to pipeline/eval/triage-candidates/`,
|
|
207
|
+
);
|
|
198
208
|
if (invalid > 0) console.log(` ${invalid} failed schema validation - fix before adopting.`);
|
|
199
209
|
console.log(" Review each, fill scope/diffSummary, then move good ones into");
|
|
200
210
|
console.log(" pipeline/eval/triage/<NN>-<name>/ to add them to the eval suite.");
|
|
@@ -72,7 +72,10 @@ function parseArgs(argv) {
|
|
|
72
72
|
const body = a.slice(2);
|
|
73
73
|
// --key=value form accepts a value starting with "--" too.
|
|
74
74
|
const eq = body.indexOf("=");
|
|
75
|
-
if (eq !== -1) {
|
|
75
|
+
if (eq !== -1) {
|
|
76
|
+
out[body.slice(0, eq)] = body.slice(eq + 1);
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
76
79
|
const key = body;
|
|
77
80
|
const next = argv[i + 1];
|
|
78
81
|
if (next === undefined || next.startsWith("--")) {
|
|
@@ -158,7 +161,9 @@ if (showsFailure) {
|
|
|
158
161
|
}
|
|
159
162
|
// No failure, but also no success marker -> unproven -> default-FAIL.
|
|
160
163
|
if (!showsSuccess) {
|
|
161
|
-
fail(
|
|
164
|
+
fail(
|
|
165
|
+
`${claim} evidence does not contain a success marker - pass claim unverified by ${evidence}`,
|
|
166
|
+
);
|
|
162
167
|
}
|
|
163
168
|
|
|
164
169
|
ok(`${claim} pass claim substantiated by ${evidence}`);
|
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
.claude/commands 48
|
|
5
5
|
.claude/lib 27
|
|
6
6
|
.claude/multi-agent-preferences.json 1
|
|
7
|
-
.claude/multi-agent-refs
|
|
7
|
+
.claude/multi-agent-refs 53
|
|
8
8
|
.claude/rules 12
|
|
9
9
|
.claude/schemas 25
|
|
10
|
-
.claude/scripts
|
|
10
|
+
.claude/scripts 204
|
|
11
11
|
.claude/settings.json 1
|
|
12
12
|
.claude/skills 428
|
|
13
13
|
.copilot/.pipeline-version 1
|
|
@@ -15,5 +15,5 @@
|
|
|
15
15
|
.copilot/copilot-instructions.md 1
|
|
16
16
|
.copilot/lib 27
|
|
17
17
|
.copilot/schemas 25
|
|
18
|
-
.copilot/scripts
|
|
18
|
+
.copilot/scripts 204
|
|
19
19
|
.copilot/skills 471
|
|
@@ -53,15 +53,31 @@ const PHASE_NAMES_NO_TEST = PHASE_NAMES.filter((p) => p !== "5:Test");
|
|
|
53
53
|
* against its generator output.
|
|
54
54
|
*/
|
|
55
55
|
const MODES = {
|
|
56
|
-
dev:
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
56
|
+
dev: {
|
|
57
|
+
phases: ["0:Init", "3:Dev", "5:Test", "6:Commit", "7:Report"],
|
|
58
|
+
local: false,
|
|
59
|
+
autopilot: false,
|
|
60
|
+
},
|
|
61
|
+
"dev-autopilot": {
|
|
62
|
+
phases: ["0:Init", "3:Dev", "6:Commit", "7:Report"],
|
|
63
|
+
local: false,
|
|
64
|
+
autopilot: true,
|
|
65
|
+
},
|
|
66
|
+
"dev-local": {
|
|
67
|
+
phases: ["0:Init", "3:Dev", "6:Commit", "7:Report"],
|
|
68
|
+
local: true,
|
|
69
|
+
autopilot: false,
|
|
70
|
+
},
|
|
71
|
+
"dev-local-autopilot": {
|
|
72
|
+
phases: ["0:Init", "3:Dev", "6:Commit", "7:Report"],
|
|
73
|
+
local: true,
|
|
74
|
+
autopilot: true,
|
|
75
|
+
},
|
|
76
|
+
autopilot: { phases: PHASE_NAMES_NO_TEST, local: false, autopilot: true },
|
|
77
|
+
full: { phases: PHASE_NAMES, local: false, autopilot: false },
|
|
78
|
+
local: { phases: PHASE_NAMES_NO_TEST, local: true, autopilot: false },
|
|
79
|
+
"local-autopilot": { phases: PHASE_NAMES_NO_TEST, local: true, autopilot: true },
|
|
80
|
+
"full-local": { phases: PHASE_NAMES_NO_TEST, local: true, autopilot: false },
|
|
65
81
|
};
|
|
66
82
|
|
|
67
83
|
const spec = MODES[MODE];
|
|
@@ -80,22 +96,23 @@ const phaseSequence = activeIds.map((id) => `Phase ${id}`).join(" → ");
|
|
|
80
96
|
|
|
81
97
|
// Mode label for prose - how to refer to the mode in the TaskCreate paragraph.
|
|
82
98
|
const MODE_LABELS = {
|
|
83
|
-
|
|
84
|
-
"dev-autopilot":
|
|
85
|
-
"dev-local":
|
|
86
|
-
"dev-local-autopilot":
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
"local-autopilot":
|
|
91
|
-
"full-local":
|
|
99
|
+
dev: "`--dev`",
|
|
100
|
+
"dev-autopilot": "`--dev autopilot`",
|
|
101
|
+
"dev-local": "`--dev local`",
|
|
102
|
+
"dev-local-autopilot": "`--dev local autopilot`",
|
|
103
|
+
autopilot: "`autopilot`",
|
|
104
|
+
full: "full-pipeline",
|
|
105
|
+
local: "`--local`",
|
|
106
|
+
"local-autopilot": "`--local autopilot`",
|
|
107
|
+
"full-local": "full-pipeline + `--local`",
|
|
92
108
|
};
|
|
93
109
|
const modeLabel = MODE_LABELS[MODE] ?? `\`${MODE}\``;
|
|
94
110
|
|
|
95
111
|
// Prose for the skip-set + ordering paragraphs.
|
|
96
|
-
const skipNote =
|
|
97
|
-
|
|
98
|
-
|
|
112
|
+
const skipNote =
|
|
113
|
+
skippedIds.length > 0
|
|
114
|
+
? `${modeLabel} mode does NOT TaskCreate phases ${skippedIds.join("/")} - those are not part of the ${modeLabel} phase set (\`${spec.phases.join(" ")}\`). Only register tiles for the active set.`
|
|
115
|
+
: `${modeLabel} mode TaskCreates all 8 phases (no phase is skipped).`;
|
|
99
116
|
|
|
100
117
|
const orderingNote = `**All TaskCreate calls fire in strict phase-number order BEFORE any TaskUpdate is applied.** For ${modeLabel} that means: ${phaseSequence}. The native widget renders by creation order, not by phase number - out-of-order calls produce visually scrambled tile stacks. Full ordering contract in \`$HOME/.claude/multi-agent-refs/tracker-contract.md\` section "TaskCreate ordering (strict)".`;
|
|
101
118
|
|
|
@@ -28,11 +28,26 @@ function parseFrontmatter(md) {
|
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
function categorize(name) {
|
|
31
|
-
if (
|
|
32
|
-
|
|
31
|
+
if (
|
|
32
|
+
name.startsWith("multi-agent") ||
|
|
33
|
+
name === "apple-archive-compliance" ||
|
|
34
|
+
name === "google-play-compliance"
|
|
35
|
+
)
|
|
36
|
+
return "pipeline";
|
|
37
|
+
if (
|
|
38
|
+
/^(swift|swiftui|swiftdata|ios|storekit|healthkit|mapkit|callkit|weatherkit|musickit|passkit|pencilkit|realitykit|cloudkit|apple-on-device-ai|permissionkit|metrickit|homekit-matter|coreml|core-bluetooth|core-motion|core-nfc|speech-recognition|natural-language|vision-framework|contacts-framework|eventkit|energykit|shareplay|background-processing|live-activities|push-notifications|tipkit|widgetkit|authentication|app-clips|app-intents|app-store|alarmkit|macos-|hig-|photos-camera|accessibility-compliance|firebase|device-integrity)/.test(
|
|
39
|
+
name,
|
|
40
|
+
)
|
|
41
|
+
)
|
|
42
|
+
return "ios";
|
|
33
43
|
if (/^(android|compose|gradle|kotlin|retrofit|room|play-store)/.test(name)) return "android";
|
|
34
44
|
if (/^(react|nextjs|vue|tailwind|css|html|typescript|web-|figma)/.test(name)) return "web";
|
|
35
|
-
if (
|
|
45
|
+
if (
|
|
46
|
+
/^(fastapi|nodejs|python|docker|rest-api|api-|database|testing-backend|observability|monorepo)/.test(
|
|
47
|
+
name,
|
|
48
|
+
)
|
|
49
|
+
)
|
|
50
|
+
return "backend";
|
|
36
51
|
return "misc";
|
|
37
52
|
}
|
|
38
53
|
|
|
@@ -66,12 +66,20 @@ for (const e of events) {
|
|
|
66
66
|
if (!id) continue;
|
|
67
67
|
let t = tasks.get(id);
|
|
68
68
|
if (!t) {
|
|
69
|
-
t = {
|
|
69
|
+
t = {
|
|
70
|
+
firstTs: e.ts,
|
|
71
|
+
reviewCycles: null,
|
|
72
|
+
rework: 0,
|
|
73
|
+
tokensIn: 0,
|
|
74
|
+
tokensOut: 0,
|
|
75
|
+
tokensCached: 0,
|
|
76
|
+
};
|
|
70
77
|
tasks.set(id, t);
|
|
71
78
|
}
|
|
72
79
|
if (e.ts && (!t.firstTs || e.ts < t.firstTs)) t.firstTs = e.ts;
|
|
73
80
|
const d = e.details || {};
|
|
74
|
-
if (e.event === "review.completed" && d.review_cycles != null)
|
|
81
|
+
if (e.event === "review.completed" && d.review_cycles != null)
|
|
82
|
+
t.reviewCycles = num(d.review_cycles);
|
|
75
83
|
if (e.event === "rework.started") t.rework += 1;
|
|
76
84
|
t.tokensIn += num(d.tokens_in);
|
|
77
85
|
t.tokensOut += num(d.tokens_out);
|
|
@@ -149,7 +157,9 @@ const arrow = (v, goodIsUp) => {
|
|
|
149
157
|
return `${up ? "+" : ""}${v} ${good ? "(better)" : "(worse)"}`;
|
|
150
158
|
};
|
|
151
159
|
console.log(`# Learning curve (${opts.bucketDays}-day buckets)\n`);
|
|
152
|
-
console.log(
|
|
160
|
+
console.log(
|
|
161
|
+
"| Bucket | Tasks | First-pass clean | Avg review cycles | Rework/task | Tokens/task | Cache ratio |",
|
|
162
|
+
);
|
|
153
163
|
console.log("|---|---|---|---|---|---|---|");
|
|
154
164
|
for (const b of buckets) {
|
|
155
165
|
console.log(
|