@mmerterden/multi-agent-pipeline 17.6.0 → 19.0.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 +310 -0
- package/README.md +76 -18
- package/README.tr.md +55 -16
- package/docs/adr/0002-instruction-driven-flag.md +1 -0
- package/docs/adr/0005-lazy-phase-docs.md +11 -1
- package/docs/adr/0008-installer-modularization-and-secret-leak-defense.md +1 -0
- package/docs/adr/0010-own-code-graph.md +1 -0
- package/docs/adr/0011-dormant-ci.md +25 -1
- package/docs/adr/0014-six-phase-consolidation.md +134 -0
- package/docs/adr/README.md +2 -1
- package/docs/architecture.md +37 -38
- package/docs/best-practices.md +1 -1
- package/docs/ecosystem.md +37 -26
- package/docs/engineering.md +1 -1
- package/docs/facts.json +45 -0
- package/docs/features.md +54 -53
- package/docs/performance.md +5 -5
- package/docs/recovery-guide.md +9 -9
- package/docs/server-readiness.md +188 -0
- package/docs/token-budget-history.md +3 -1
- package/index.js +18 -3
- package/install/_codex-agents.mjs +1 -1
- package/install/_common.mjs +42 -17
- package/install/_dev-only-files.mjs +8 -0
- package/install/_unattended-profile.mjs +113 -0
- package/install/index.mjs +48 -0
- package/install/templates/claude-hooks.json +1 -1
- package/install/templates/codex-instructions.md +1 -1
- package/install/templates/copilot-instructions.md +28 -28
- package/manifest.json +1065 -0
- package/package.json +6 -3
- package/pipeline/agents/dev-critic.md +3 -3
- package/pipeline/commands/figma-to-swiftui.md +1 -1
- package/pipeline/commands/multi-agent/SKILL.md +8 -8
- package/pipeline/commands/multi-agent/analysis/SKILL.md +9 -9
- package/pipeline/commands/multi-agent/autopilot/SKILL.md +7 -7
- package/pipeline/commands/multi-agent/channels/SKILL.md +15 -15
- package/pipeline/commands/multi-agent/diff-explain/SKILL.md +6 -6
- package/pipeline/commands/multi-agent/garbage-collect/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/graph/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/help/SKILL.md +62 -62
- package/pipeline/commands/multi-agent/language/SKILL.md +2 -2
- package/pipeline/commands/multi-agent/local/SKILL.md +11 -11
- package/pipeline/commands/multi-agent/local-autopilot/SKILL.md +13 -13
- package/pipeline/commands/multi-agent/log/SKILL.md +2 -2
- package/pipeline/commands/multi-agent/manual-test/SKILL.md +9 -9
- package/pipeline/commands/multi-agent/model/SKILL.md +69 -0
- package/pipeline/commands/multi-agent/refactor/SKILL.md +3 -3
- package/pipeline/commands/multi-agent/resume/SKILL.md +4 -4
- package/pipeline/commands/multi-agent/resume-local/SKILL.md +19 -17
- package/pipeline/commands/multi-agent/review/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/route-off/SKILL.md +36 -0
- package/pipeline/commands/multi-agent/route-on/SKILL.md +74 -0
- package/pipeline/commands/multi-agent/route-status/SKILL.md +56 -0
- package/pipeline/commands/multi-agent/setup/SKILL.md +2 -2
- package/pipeline/commands/multi-agent/status/SKILL.md +54 -23
- package/pipeline/commands/multi-agent/steer/SKILL.md +2 -2
- package/pipeline/commands/multi-agent/sync/SKILL.md +12 -13
- package/pipeline/commands/multi-agent/test/SKILL.md +1 -1
- package/pipeline/lib/_jira-auth.sh +8 -0
- package/pipeline/lib/analysis-jira-write.sh +32 -0
- package/pipeline/lib/ask-choice.sh +13 -2
- package/pipeline/lib/autopilot-state.sh +8 -0
- package/pipeline/lib/credential-inventory.sh +1 -1
- package/pipeline/lib/fatal.mjs +129 -0
- package/pipeline/lib/fetch-fortify.sh +1 -1
- package/pipeline/lib/figma-mcp-refresh.sh +18 -0
- package/pipeline/lib/figma-screenshot.sh +18 -0
- package/pipeline/lib/invoked-directly.mjs +43 -0
- package/pipeline/lib/jira-publish.sh +42 -0
- package/pipeline/lib/md2confluence-v3.py +47 -0
- package/pipeline/lib/model-rung.sh +142 -0
- package/pipeline/lib/outbound-gate.mjs +175 -0
- package/pipeline/lib/phase-schema.mjs +88 -0
- package/pipeline/lib/plan-todos.sh +32 -11
- package/pipeline/lib/post-pr-review.sh +77 -8
- package/pipeline/lib/repo-hygiene.sh +8 -3
- package/pipeline/lib/require-jq.sh +40 -0
- package/pipeline/lib/route-state.sh +161 -0
- package/pipeline/lib/run-paths.sh +335 -0
- package/pipeline/multi-agent-refs/_account-picker.md +1 -1
- package/pipeline/multi-agent-refs/_dev-context.md +1 -1
- package/pipeline/multi-agent-refs/_input-parser.md +1 -1
- package/pipeline/multi-agent-refs/analysis/evidence.md +0 -9
- package/pipeline/multi-agent-refs/analysis/intake.md +1 -1
- package/pipeline/multi-agent-refs/analysis/locked.md +21 -22
- package/pipeline/multi-agent-refs/analysis/render.md +1 -1
- package/pipeline/multi-agent-refs/analysis/synthesis.md +12 -6
- package/pipeline/multi-agent-refs/android-guide.md +1 -1
- package/pipeline/multi-agent-refs/audit-guide.md +13 -13
- package/pipeline/multi-agent-refs/channels/issue-comment.md +2 -2
- package/pipeline/multi-agent-refs/channels/jira.md +3 -3
- package/pipeline/multi-agent-refs/channels/pr.md +4 -4
- package/pipeline/multi-agent-refs/channels/wiki.md +1 -1
- package/pipeline/multi-agent-refs/component-dispatch.md +3 -3
- package/pipeline/multi-agent-refs/cross-cli-contract.md +31 -6
- package/pipeline/multi-agent-refs/features/autopilot-circuit-breaker.md +74 -4
- package/pipeline/multi-agent-refs/features/code-graph.md +5 -5
- package/pipeline/multi-agent-refs/features/cost-analysis.md +93 -0
- package/pipeline/multi-agent-refs/features/design-conformance.md +1 -1
- package/pipeline/multi-agent-refs/features/dev-critic.md +3 -3
- package/pipeline/multi-agent-refs/features/doctor.md +47 -2
- package/pipeline/multi-agent-refs/features/external-context-injection.md +3 -3
- package/pipeline/multi-agent-refs/features/maturity-followup.md +3 -3
- package/pipeline/multi-agent-refs/features/model-fallback.md +5 -5
- package/pipeline/multi-agent-refs/features/plan-todos.md +1 -1
- package/pipeline/multi-agent-refs/features/repo-map.md +1 -1
- package/pipeline/multi-agent-refs/features/review-delta.md +3 -3
- package/pipeline/multi-agent-refs/features/review-multi-repo.md +1 -1
- package/pipeline/multi-agent-refs/features/scope-check.md +4 -4
- package/pipeline/multi-agent-refs/features/skill-conformance.md +2 -2
- package/pipeline/multi-agent-refs/features/stack-skill-routing.md +1 -1
- package/pipeline/multi-agent-refs/features/verify-by-test.md +4 -4
- package/pipeline/multi-agent-refs/features/verify.md +83 -0
- package/pipeline/multi-agent-refs/features/visual-evidence.md +19 -19
- package/pipeline/multi-agent-refs/features/worktree-finalize.md +6 -6
- package/pipeline/multi-agent-refs/issue-jira-triad.md +10 -10
- package/pipeline/multi-agent-refs/knowledge.md +11 -11
- package/pipeline/multi-agent-refs/multi-repo-integration-build.md +13 -13
- package/pipeline/multi-agent-refs/payload-contracts.md +8 -8
- package/pipeline/multi-agent-refs/phases/log-format.md +10 -10
- package/pipeline/multi-agent-refs/phases/modes.md +30 -30
- package/pipeline/multi-agent-refs/phases/operations.md +21 -10
- package/pipeline/multi-agent-refs/phases/phase-0-init.md +25 -25
- package/pipeline/multi-agent-refs/phases/phase-1-plan.md +599 -0
- package/pipeline/multi-agent-refs/phases/{phase-3-dev.md → phase-2-dev.md} +129 -49
- package/pipeline/multi-agent-refs/phases/{phase-4-review.md → phase-3-review.md} +225 -107
- package/pipeline/multi-agent-refs/phases/{phase-6-commit.md → phase-4-commit.md} +23 -23
- package/pipeline/multi-agent-refs/phases/{phase-7-report.md → phase-5-report.md} +29 -29
- package/pipeline/multi-agent-refs/phases.md +44 -48
- package/pipeline/multi-agent-refs/picker-contract.md +1 -1
- package/pipeline/multi-agent-refs/progress-contract.md +6 -6
- package/pipeline/multi-agent-refs/readiness-review.md +1 -1
- package/pipeline/multi-agent-refs/rules.md +7 -7
- package/pipeline/multi-agent-refs/swiftui-guide.md +2 -2
- package/pipeline/multi-agent-refs/tracker-contract.md +31 -32
- package/pipeline/multi-agent-refs/unattended-contract.md +129 -0
- package/pipeline/multi-agent-refs/wiki-capture.md +14 -14
- package/pipeline/preferences-template.json +9 -1
- package/pipeline/rules/outside-the-pipeline.md +1 -1
- package/pipeline/schemas/agent-state.schema.json +50 -50
- package/pipeline/schemas/analysis-output.schema.json +2 -2
- package/pipeline/schemas/autopilot-config.schema.json +1 -1
- package/pipeline/schemas/code-graph.schema.json +1 -1
- package/pipeline/schemas/criteria-manifest.schema.json +1 -1
- package/pipeline/schemas/dev-critic-output.schema.json +1 -1
- package/pipeline/schemas/diff-risk.schema.json +1 -1
- package/pipeline/schemas/migrations/prefs-2.4.0-to-2.5.0.mjs +2 -2
- package/pipeline/schemas/migrations/prefs-2.6.0-to-2.7.0.mjs +31 -0
- package/pipeline/schemas/migrations/state-2.1.0-to-2.2.0.mjs +129 -0
- package/pipeline/schemas/phases.json +105 -0
- package/pipeline/schemas/plan-todos.schema.json +5 -5
- package/pipeline/schemas/planning-output.schema.json +1 -1
- package/pipeline/schemas/prefs.schema.json +100 -56
- package/pipeline/schemas/reviewer-output.schema.json +3 -3
- package/pipeline/schemas/route-config.schema.json +74 -0
- package/pipeline/schemas/scope-check.schema.json +1 -1
- package/pipeline/schemas/test-gap.schema.json +1 -1
- package/pipeline/schemas/token-budget.json +12 -18
- package/pipeline/schemas/triage-output.schema.json +6 -6
- package/pipeline/scripts/README.md +3 -3
- package/pipeline/scripts/_code-graph.mjs +2 -2
- package/pipeline/scripts/_run-paths.mjs +372 -0
- package/pipeline/scripts/_smoke-root.sh +1 -1
- package/pipeline/scripts/aggregate-metrics.mjs +65 -65
- package/pipeline/scripts/autopilot-arming.mjs +2 -1
- package/pipeline/scripts/autopilot-intake.mjs +2 -1
- package/pipeline/scripts/autopilot-runner.mjs +206 -2
- package/pipeline/scripts/build-references.mjs +2 -1
- package/pipeline/scripts/build-stack-plugins.mjs +10 -2
- package/pipeline/scripts/capture-evidence.sh +7 -2
- package/pipeline/scripts/capture-flush.sh +8 -8
- package/pipeline/scripts/capture-resume.sh +3 -3
- package/pipeline/scripts/classify-plan-safety.mjs +3 -2
- package/pipeline/scripts/cost-analyze.mjs +600 -0
- package/pipeline/scripts/cost-budget-check.mjs +4 -12
- package/pipeline/scripts/council-view.mjs +2 -1
- package/pipeline/scripts/crush-json.mjs +2 -1
- package/pipeline/scripts/diff-explain.mjs +7 -10
- package/pipeline/scripts/diff-risk-score.mjs +2 -1
- package/pipeline/scripts/doctor.mjs +140 -6
- package/pipeline/scripts/evidence-gate.mjs +9 -3
- package/pipeline/scripts/feedback-send.mjs +12 -2
- package/pipeline/scripts/gc-abandoned.sh +32 -16
- package/pipeline/scripts/gc-tmp.sh +1 -1
- package/pipeline/scripts/gc-worktrees.sh +12 -5
- package/pipeline/scripts/gen-facts.mjs +175 -0
- package/pipeline/scripts/gen-mode-dispatch.mjs +32 -37
- package/pipeline/scripts/gen-ref-toc.mjs +1 -1
- package/pipeline/scripts/github-ssh-setup.sh +64 -7
- package/pipeline/scripts/graph-mermaid.mjs +4 -2
- package/pipeline/scripts/graph-report.mjs +1 -1
- package/pipeline/scripts/jira-attach.sh +1 -1
- package/pipeline/scripts/keychain-save.sh +101 -30
- package/pipeline/scripts/learn-from-transcripts.mjs +3 -2
- package/pipeline/scripts/learning-curve.mjs +36 -31
- package/pipeline/scripts/log-metric.sh +17 -4
- package/pipeline/scripts/make-manifest.mjs +199 -0
- package/pipeline/scripts/memory-save.sh +1 -1
- package/pipeline/scripts/migrate-prefs.mjs +24 -6
- package/pipeline/scripts/migrate-state.mjs +94 -4
- package/pipeline/scripts/phase-banner.sh +26 -22
- package/pipeline/scripts/phase-tracker.sh +48 -10
- package/pipeline/scripts/plan-coverage-gate.mjs +8 -4
- package/pipeline/scripts/pre-commit-check.sh +7 -0
- package/pipeline/scripts/pre-push-check.sh +7 -0
- package/pipeline/scripts/purge.sh +23 -6
- package/pipeline/scripts/render-agent-log-cost.sh +10 -3
- package/pipeline/scripts/render-cost-summary.sh +9 -2
- package/pipeline/scripts/render-work-summary.sh +14 -7
- package/pipeline/scripts/review-file-filter.mjs +5 -3
- package/pipeline/scripts/review-scope.mjs +2 -1
- package/pipeline/scripts/routine-registry.mjs +2 -1
- package/pipeline/scripts/run-aggregator.mjs +26 -20
- package/pipeline/scripts/run-metrics.mjs +4 -2
- package/pipeline/scripts/runs-index.mjs +353 -0
- package/pipeline/scripts/scorecard-snapshot.mjs +178 -0
- package/pipeline/scripts/search-logs.sh +18 -0
- package/pipeline/scripts/smoke-cross-cli-behavior.sh +6 -6
- package/pipeline/scripts/smoke-schema-validation.sh +26 -7
- package/pipeline/scripts/test-gap-scan.mjs +2 -1
- package/pipeline/scripts/test-integrity-gate.mjs +2 -1
- package/pipeline/scripts/token-budget-report.mjs +13 -2
- package/pipeline/scripts/triage-memory.mjs +2 -2
- package/pipeline/scripts/update-issue-progress.sh +56 -7
- package/pipeline/scripts/usage-report.mjs +12 -1
- package/pipeline/scripts/validate-analysis-doc.mjs +75 -18
- package/pipeline/scripts/validate-code-graph.mjs +6 -3
- package/pipeline/scripts/validate-complaint-doc.mjs +2 -1
- package/pipeline/scripts/validate-diff-risk.mjs +6 -3
- package/pipeline/scripts/validate-planning.mjs +1 -1
- package/pipeline/scripts/validate-reviewer.mjs +1 -1
- package/pipeline/scripts/validate-state.mjs +45 -5
- package/pipeline/scripts/validate-test-gap.mjs +6 -3
- package/pipeline/scripts/validate-triage.mjs +6 -4
- package/pipeline/scripts/verify-citations.mjs +4 -2
- package/pipeline/scripts/verify.mjs +327 -0
- package/pipeline/scripts/worktree-finalize.sh +18 -9
- package/pipeline/scripts/write-state.mjs +154 -15
- package/pipeline/skills/.skill-manifest.json +37 -21
- package/pipeline/skills/.skills-index.json +104 -5
- package/pipeline/skills/shared/README.md +15 -6
- package/pipeline/skills/shared/core/apple-archive-compliance/SKILL.md +2 -2
- package/pipeline/skills/shared/core/google-play-compliance/SKILL.md +2 -2
- package/pipeline/skills/shared/core/multi-agent/SKILL.md +69 -71
- package/pipeline/skills/shared/core/multi-agent-autopilot/SKILL.md +3 -3
- package/pipeline/skills/shared/core/multi-agent-channels/SKILL.md +14 -14
- package/pipeline/skills/shared/core/multi-agent-diff-explain/SKILL.md +5 -5
- package/pipeline/skills/shared/core/multi-agent-graph/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-help/SKILL.md +25 -23
- package/pipeline/skills/shared/core/multi-agent-language/SKILL.md +2 -2
- package/pipeline/skills/shared/core/multi-agent-local/SKILL.md +2 -2
- package/pipeline/skills/shared/core/multi-agent-local-autopilot/SKILL.md +8 -8
- package/pipeline/skills/shared/core/multi-agent-manual-test/SKILL.md +6 -6
- package/pipeline/skills/shared/core/multi-agent-model/SKILL.md +71 -0
- package/pipeline/skills/shared/core/multi-agent-refactor/SKILL.md +3 -3
- package/pipeline/skills/shared/core/multi-agent-resume/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-resume-local/SKILL.md +7 -7
- package/pipeline/skills/shared/core/multi-agent-route-off/SKILL.md +39 -0
- package/pipeline/skills/shared/core/multi-agent-route-on/SKILL.md +76 -0
- package/pipeline/skills/shared/core/multi-agent-route-status/SKILL.md +59 -0
- package/pipeline/skills/shared/core/multi-agent-setup/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-status/SKILL.md +35 -11
- package/pipeline/skills/shared/core/multi-agent-steer/SKILL.md +2 -2
- package/pipeline/skills/shared/core/multi-agent-sync/SKILL.md +6 -5
- package/pipeline/skills/shared/external/macos-spm-app-packaging/assets/templates/package_app.sh +4 -1
- package/pipeline/skills/shared/external/macos-spm-app-packaging/assets/templates/setup_dev_signing.sh +4 -1
- package/pipeline/skills/shared/external/macos-spm-app-packaging/assets/templates/sign-and-notarize.sh +2 -1
- package/pipeline/skills/skills-index.md +13 -4
- package/pipeline/multi-agent-refs/phases/phase-1-analysis.md +0 -263
- package/pipeline/multi-agent-refs/phases/phase-2-planning.md +0 -344
- package/pipeline/multi-agent-refs/phases/phase-5-test.md +0 -182
|
@@ -12,6 +12,10 @@
|
|
|
12
12
|
# $HOME/.claude/logs/multi-agent/<task_id>/tracker-state.json
|
|
13
13
|
# (override with $TRACKER_FILE env var)
|
|
14
14
|
#
|
|
15
|
+
# `init` writes that flat path. READS go through pipeline/lib/run-paths.sh,
|
|
16
|
+
# which also finds a tracker nested under <project>/<task_id>/ - the multi-repo
|
|
17
|
+
# path writes there, and a hard-coded flat lookup used to miss those runs.
|
|
18
|
+
#
|
|
15
19
|
# Commands:
|
|
16
20
|
# init <task_id> Reset tracker for this task
|
|
17
21
|
# add <phase_id> "<name>" Register a phase (status=pending); idempotent - existing id is a no-op
|
|
@@ -39,7 +43,7 @@
|
|
|
39
43
|
#
|
|
40
44
|
# Examples:
|
|
41
45
|
# phase-tracker.sh init "TASK-123"
|
|
42
|
-
# for p in 0:Init 1:
|
|
46
|
+
# for p in 0:Init 1:Plan 2:Dev 3:Review 4:Commit 5:Report; do
|
|
43
47
|
# phase-tracker.sh add "${p%%:*}" "${p#*:}"
|
|
44
48
|
# done
|
|
45
49
|
# phase-tracker.sh update 0 in_progress
|
|
@@ -52,6 +56,12 @@
|
|
|
52
56
|
|
|
53
57
|
set -uo pipefail
|
|
54
58
|
|
|
59
|
+
# Run-state path resolution: pipeline/lib/run-paths.sh owns both layouts.
|
|
60
|
+
_MA_RP_HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
61
|
+
# shellcheck source=/dev/null
|
|
62
|
+
. "$_MA_RP_HERE/../lib/run-paths.sh" 2>/dev/null || . "$HOME/.claude/lib/run-paths.sh"
|
|
63
|
+
|
|
64
|
+
|
|
55
65
|
if [ "$#" -lt 1 ]; then
|
|
56
66
|
cat >&2 <<USAGE
|
|
57
67
|
usage:
|
|
@@ -110,7 +120,13 @@ if [ -z "$TRACKER_FILE" ]; then
|
|
|
110
120
|
exit 64
|
|
111
121
|
fi
|
|
112
122
|
else
|
|
113
|
-
|
|
123
|
+
# Resolve through run-paths.sh: this script writes flat, but 13 of the
|
|
124
|
+
# trackers on a real machine sit nested under a project directory (written
|
|
125
|
+
# by the multi-repo path), and the hard-coded flat path could not see them.
|
|
126
|
+
# A run that does not exist yet resolves to the flat path, which is exactly
|
|
127
|
+
# where `init` will create it - so new-run behaviour is unchanged.
|
|
128
|
+
TRACKER_FILE="$(ma_resolve_run_file "$TASK_ID_FROM_ENV" tracker-state.json 2>/dev/null \
|
|
129
|
+
|| echo "$HOME/.claude/logs/multi-agent/${TASK_ID_FROM_ENV}/tracker-state.json")"
|
|
114
130
|
fi
|
|
115
131
|
fi
|
|
116
132
|
TRACKER_DIR="$(dirname "$TRACKER_FILE")"
|
|
@@ -125,7 +141,7 @@ need_jq() {
|
|
|
125
141
|
# Live usage ping (best-effort). Emits one per-phase update to the private
|
|
126
142
|
# dashboard via usage-report.mjs, always status=running so per-phase updates
|
|
127
143
|
# never fold the run into rollup counters - the terminal fold comes only from
|
|
128
|
-
# the Phase
|
|
144
|
+
# the Phase 5 / halt emit that reads the real run status. The emitter no-ops
|
|
129
145
|
# unless prefs.global.usageLog.enabled; detached so it never blocks a boundary.
|
|
130
146
|
usage_live_ping() {
|
|
131
147
|
# Smoke runs exercise this script's state handling, never the live dashboard -
|
|
@@ -430,13 +446,22 @@ save_state() {
|
|
|
430
446
|
# corrupt document (render exits 65). $$ keeps each writer's temp private; the
|
|
431
447
|
# rename is still atomic, so the last full write wins instead of a torn one.
|
|
432
448
|
local tmp="${TRACKER_FILE}.tmp.$$"
|
|
433
|
-
|
|
449
|
+
local doc="$1"
|
|
450
|
+
# Stamp the unlocked-write count, if there were any. jq is guarded because a
|
|
451
|
+
# machine without it must still get its state written - losing the annotation
|
|
452
|
+
# is acceptable, losing the write is not.
|
|
453
|
+
if [ "${TRACKER_LOCK_LOST:-0}" -gt 0 ] && command -v jq >/dev/null 2>&1; then
|
|
454
|
+
doc=$(printf '%s' "$doc" | jq --argjson n "$TRACKER_LOCK_LOST" \
|
|
455
|
+
'.unlockedWrites = ((.unlockedWrites // 0) + $n)' 2>/dev/null || printf '%s' "$doc")
|
|
456
|
+
TRACKER_LOCK_LOST=0
|
|
457
|
+
fi
|
|
458
|
+
printf '%s\n' "$doc" > "$tmp"
|
|
434
459
|
mv "$tmp" "$TRACKER_FILE"
|
|
435
460
|
}
|
|
436
461
|
|
|
437
462
|
# --- read-modify-write lock ---------------------------------------------------
|
|
438
463
|
# tmp+rename makes each save atomic, but two concurrent invocations (e.g. two
|
|
439
|
-
# parallel Phase
|
|
464
|
+
# parallel Phase 3 reviewers reporting `tokens`) both load the same state and
|
|
440
465
|
# the second save silently drops the first delta. Guard every load->save
|
|
441
466
|
# sequence with a portable mkdir spinlock (macOS bash 3.2: no flock builtin).
|
|
442
467
|
# The wait is bounded and the lock FAILS OPEN with a warning so a stuck lock
|
|
@@ -444,6 +469,9 @@ save_state() {
|
|
|
444
469
|
# reclaimed.
|
|
445
470
|
TRACKER_LOCK_DIR=""
|
|
446
471
|
TRACKER_LOCK_HELD=0
|
|
472
|
+
# How many writes went through WITHOUT the lock in this process. Stamped into
|
|
473
|
+
# the state so a run's own record says its counts may be low.
|
|
474
|
+
TRACKER_LOCK_LOST=0
|
|
447
475
|
|
|
448
476
|
state_lock_stale() {
|
|
449
477
|
local pid mtime now age
|
|
@@ -482,7 +510,17 @@ acquire_state_lock() {
|
|
|
482
510
|
fi
|
|
483
511
|
tries=$((tries + 1))
|
|
484
512
|
if [ "$tries" -ge 50 ]; then
|
|
485
|
-
|
|
513
|
+
# STILL fails open, and that is the right call: a lost tracker write is
|
|
514
|
+
# worse than a lost lock, and a hung pipeline is worse than both.
|
|
515
|
+
#
|
|
516
|
+
# What changes is that it stops being invisible. Two writers in the
|
|
517
|
+
# critical section means one of their token deltas is dropped, and the
|
|
518
|
+
# only trace was a warning on stderr inside a background run nobody
|
|
519
|
+
# reads. The count now lands in the state file, so the run CARRIES the
|
|
520
|
+
# evidence that its numbers are low - which is the difference between an
|
|
521
|
+
# undercount and an undercount you can see.
|
|
522
|
+
TRACKER_LOCK_LOST=$((TRACKER_LOCK_LOST + 1))
|
|
523
|
+
echo "phase-tracker: WARN - state lock busy ($TRACKER_LOCK_DIR); proceeding without it. Token counts for this write may be low; recorded as unlockedWrites in the state." >&2
|
|
486
524
|
return 0
|
|
487
525
|
fi
|
|
488
526
|
sleep 0.1
|
|
@@ -574,7 +612,7 @@ tracker_next_hint() {
|
|
|
574
612
|
# Not every session carries the task tools: Claude Code provides them by
|
|
575
613
|
# default only up to Opus 4.7 / Sonnet 4.6, a default that landed in
|
|
576
614
|
# v2.1.268. Naming the fallback on the same line is what keeps a newer model
|
|
577
|
-
# from advancing
|
|
615
|
+
# from advancing six phases in silence.
|
|
578
616
|
# `subjects` now carries Phase 2's plan steps as indented rows, and
|
|
579
617
|
# update_plan takes the whole list anyway, so re-reading it is what puts
|
|
580
618
|
# those steps on the Codex plan without a second mechanism. Codex has no
|
|
@@ -605,7 +643,7 @@ format_span() {
|
|
|
605
643
|
}
|
|
606
644
|
|
|
607
645
|
# The end-of-run report: what the pipeline spent, phase by phase, and what it
|
|
608
|
-
# has to say about phases it could not price. Printed by Phase
|
|
646
|
+
# has to say about phases it could not price. Printed by Phase 5 next to the
|
|
609
647
|
# work summary, which covers what actually changed on disk.
|
|
610
648
|
report() {
|
|
611
649
|
need_jq
|
|
@@ -762,7 +800,7 @@ subjects() {
|
|
|
762
800
|
#
|
|
763
801
|
# Creation order is the ONLY ordering the native widget has - it renders by the
|
|
764
802
|
# order tiles were made, not by any id inside them - so a plan that arrives at
|
|
765
|
-
# Phase 2 cannot simply be appended: its rows would land after Phase
|
|
803
|
+
# Phase 2 cannot simply be appended: its rows would land after Phase 5. The
|
|
766
804
|
# answer is a rebuild at that one boundary, which is the same thing `:resume`
|
|
767
805
|
# already does for a different reason.
|
|
768
806
|
tiles_script() {
|
|
@@ -773,7 +811,7 @@ tiles_script() {
|
|
|
773
811
|
has_subs=$(echo "$state" | jq '[.phases[]?.subs[]?] | length')
|
|
774
812
|
|
|
775
813
|
# A list carrying sub-steps has to be rebuilt whole, so the rebuild wins over a
|
|
776
|
-
# narrowed batch: appending to it would land the new rows after Phase
|
|
814
|
+
# narrowed batch: appending to it would land the new rows after Phase 5.
|
|
777
815
|
[ "${has_subs:-0}" -gt 0 ] && new_only=""
|
|
778
816
|
|
|
779
817
|
if [ -n "$new_only" ]; then
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
// Phase 4 answers "is what changed correct" and Step 1.45 answers "did every
|
|
5
5
|
// planned TEST land". Nothing answered "did every planned TASK land". The
|
|
6
6
|
// criteria manifest's denominator is rule IDs, not plan steps, and the only
|
|
7
|
-
// place a step's status surfaced was render-work-summary.sh at Phase
|
|
7
|
+
// place a step's status surfaced was render-work-summary.sh at Phase 5 - a
|
|
8
8
|
// report, printed after the commit. So a plan with seven steps could ship five
|
|
9
9
|
// and read as done.
|
|
10
10
|
//
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
//
|
|
30
30
|
// Exit codes: 0 clean, 1 coverage gap, 2 usage / parse error.
|
|
31
31
|
|
|
32
|
-
import { readFileSync, existsSync } from "node:fs";
|
|
32
|
+
import { readFileSync, existsSync, writeFileSync } from "node:fs";
|
|
33
33
|
import { join, isAbsolute } from "node:path";
|
|
34
34
|
import { pathToFileURL } from "node:url";
|
|
35
35
|
|
|
@@ -116,7 +116,7 @@ if (isMain) {
|
|
|
116
116
|
"",
|
|
117
117
|
"Fails when a plan step never reached a terminal status, when a skip or",
|
|
118
118
|
"failure carries no reason, or when an analysis Section 14 `Add new` file",
|
|
119
|
-
"is missing from the tree. Run before Phase
|
|
119
|
+
"is missing from the tree. Run before Phase 4 commit.",
|
|
120
120
|
"",
|
|
121
121
|
].join("\n"),
|
|
122
122
|
);
|
|
@@ -157,8 +157,12 @@ if (isMain) {
|
|
|
157
157
|
const msg = Array.isArray(todos)
|
|
158
158
|
? "the plan has zero steps - that is an unusable plan, not a clean one; skip this gate explicitly for modes with no Phase 2"
|
|
159
159
|
: "no plan todos found - if this mode has no Phase 2, skip this gate explicitly";
|
|
160
|
+
// fd 1 synchronously, then exit. This sits in `if (isMain)` at module scope,
|
|
161
|
+
// not in a function, so there is nothing to return from - and a
|
|
162
|
+
// process.stdout.write followed by process.exit() loses the verdict when
|
|
163
|
+
// stdout is a pipe.
|
|
160
164
|
if (asJson)
|
|
161
|
-
|
|
165
|
+
writeFileSync(1, `${JSON.stringify({ verdict: "unusable", reason: msg }, null, 2)}\n`);
|
|
162
166
|
else process.stderr.write(`plan-coverage-gate: ${msg}\n`);
|
|
163
167
|
process.exit(2);
|
|
164
168
|
}
|
|
@@ -4,6 +4,13 @@
|
|
|
4
4
|
# Exit 0 = clean, Exit 2 = secrets found. The PreToolUse hook contract
|
|
5
5
|
# (install/templates/claude-hooks.json, agent-guard.sh) blocks the tool call
|
|
6
6
|
# only on exit 2, with the reason on stderr.
|
|
7
|
+
#
|
|
8
|
+
# No `-e` here either, and for a sharper reason than in pre-push-check.sh: this
|
|
9
|
+
# file is a PreToolUse hook that fires on every Bash call, and it is built out
|
|
10
|
+
# of greps that are SUPPOSED to find nothing. Under `-e` the first clean
|
|
11
|
+
# detector would end the scan, and a hook that exits early reports "no secrets"
|
|
12
|
+
# for a file it never finished reading - a scanner failing open, on the path
|
|
13
|
+
# that exists to keep secrets out of commits.
|
|
7
14
|
|
|
8
15
|
set -uo pipefail
|
|
9
16
|
|
|
@@ -43,6 +43,13 @@
|
|
|
43
43
|
# 0 - all gates passed, safe to push
|
|
44
44
|
# 1 - a gate failed (test, lint, schema, or personal-data leak)
|
|
45
45
|
# 2 - environment problem (node missing, npm missing, wrong cwd)
|
|
46
|
+
#
|
|
47
|
+
# No `-e`, and that is a decision rather than an omission. This file RUNS the
|
|
48
|
+
# gates and counts how many failed; `-e` would abort at the first one, so a
|
|
49
|
+
# tree with three problems would report one, get fixed, report the next, and
|
|
50
|
+
# take three full runs to learn what one run already knew. The four destructive
|
|
51
|
+
# scripts in this directory DO use `-e`, because there the next command deletes
|
|
52
|
+
# something. Here the next command is another question.
|
|
46
53
|
|
|
47
54
|
set -uo pipefail
|
|
48
55
|
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
# Exit: 0 on success (including "nothing to do"), 2 on usage error or refused
|
|
34
34
|
# repo.
|
|
35
35
|
|
|
36
|
-
set -
|
|
36
|
+
set -euo pipefail
|
|
37
37
|
|
|
38
38
|
REPO="$PWD"
|
|
39
39
|
DELETE=0
|
|
@@ -66,7 +66,11 @@ fi
|
|
|
66
66
|
# Anchor everything on the MAIN worktree (first porcelain entry), so running
|
|
67
67
|
# purge from inside a linked worktree still targets <repo>/.worktrees/.
|
|
68
68
|
MAIN_WT="$(git -C "$REPO" worktree list --porcelain 2>/dev/null | sed -n 's/^worktree //p' | head -1)"
|
|
69
|
-
|
|
69
|
+
# `|| true` on the resolve, not on the cd: an assignment takes the exit status
|
|
70
|
+
# of its command substitution, so under `set -e` a MAIN_WT that no longer exists
|
|
71
|
+
# would kill the script HERE - three lines before the guard whose whole job is
|
|
72
|
+
# to report exactly that, with a message, as exit 2.
|
|
73
|
+
MAIN_WT="$(cd "$MAIN_WT" 2>/dev/null && pwd -P || true)"
|
|
70
74
|
HOME_REAL="$(cd "$HOME" 2>/dev/null && pwd -P || printf '%s' "$HOME")"
|
|
71
75
|
if [ -z "$MAIN_WT" ] || [ "$MAIN_WT" = "/" ] || [ "$MAIN_WT" = "$HOME_REAL" ]; then
|
|
72
76
|
echo "purge: refusing to operate on repo root '$MAIN_WT'" >&2
|
|
@@ -96,7 +100,11 @@ cur_branch=""
|
|
|
96
100
|
flush_block() {
|
|
97
101
|
[ -z "$cur_path" ] && { cur_branch=""; return 0; }
|
|
98
102
|
local resolved
|
|
99
|
-
|
|
103
|
+
# A registered worktree whose directory is GONE is the ordinary case this
|
|
104
|
+
# function exists to handle - `git worktree list` still lists it, and purge is
|
|
105
|
+
# what cleans it up. resolve_dir fails there, and an unforgiven assignment
|
|
106
|
+
# would end the teardown with exit 1 and no output at all.
|
|
107
|
+
resolved="$(resolve_dir "$cur_path" || true)"
|
|
100
108
|
case "$resolved" in
|
|
101
109
|
"$WT_ROOT"/*)
|
|
102
110
|
wt_paths+=("$resolved")
|
|
@@ -184,7 +192,12 @@ while [ "$i" -lt "${#wt_paths[@]}" ]; do
|
|
|
184
192
|
case "$p" in
|
|
185
193
|
"$WT_ROOT"/*)
|
|
186
194
|
rm -rf "$p" 2>/dev/null && wt_gone=1
|
|
187
|
-
|
|
195
|
+
# `|| true` because this branch only runs when `worktree remove --force`
|
|
196
|
+
# ALREADY failed - a locked or damaged worktree - which is exactly when
|
|
197
|
+
# the follow-up prune is likeliest to fail too. Under `set -e` that would
|
|
198
|
+
# abort the teardown mid-loop, leaving the remaining worktrees, the
|
|
199
|
+
# branches, the counter reset and the exclude-block removal undone.
|
|
200
|
+
git -C "$MAIN_WT" worktree prune >/dev/null 2>&1 || true
|
|
188
201
|
;;
|
|
189
202
|
*) echo "purge: skipping worktree outside $WT_ROOT: $p" >&2 ;;
|
|
190
203
|
esac
|
|
@@ -228,8 +241,12 @@ if [ -n "$COUNTER" ]; then
|
|
|
228
241
|
rm -f "$COUNTER" 2>/dev/null && echo "→ reset task counter $COUNTER"
|
|
229
242
|
fi
|
|
230
243
|
|
|
231
|
-
# Drop the now-empty .worktrees/ shell (only when truly empty).
|
|
232
|
-
|
|
244
|
+
# Drop the now-empty .worktrees/ shell (only when truly empty). The `|| true`
|
|
245
|
+
# is the point of the line, not noise on it: a symlink pointing out of the tree
|
|
246
|
+
# is deliberately NOT followed and NOT deleted, so the directory is routinely
|
|
247
|
+
# non-empty here, rmdir routinely fails, and under `set -e` that ordinary
|
|
248
|
+
# outcome would abort the teardown before the exclude block came out.
|
|
249
|
+
[ -d "$WT_ROOT" ] && { rmdir "$WT_ROOT" 2>/dev/null || true; }
|
|
233
250
|
|
|
234
251
|
# purge is the whole-repo teardown, so it is the one place the managed exclude
|
|
235
252
|
# block should come back out - a per-task finalize must not, because other tasks
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
#
|
|
8
8
|
# This is the agent-log counterpart to render-cost-summary.sh (which
|
|
9
9
|
# targets PR/Jira channel bodies). The agent-log version is rendered
|
|
10
|
-
# unconditionally on every Phase
|
|
10
|
+
# unconditionally on every Phase 5 run; the channels version is opt-in
|
|
11
11
|
# via prefs.global.reportContent.costSummary.
|
|
12
12
|
#
|
|
13
13
|
# Usage:
|
|
@@ -19,6 +19,13 @@
|
|
|
19
19
|
|
|
20
20
|
set -euo pipefail
|
|
21
21
|
|
|
22
|
+
# Run-state path resolution: pipeline/lib/run-paths.sh owns the two layouts
|
|
23
|
+
# (nested <root>/<project>/<id>/ and flat <root>/<id>/) and every id spelling.
|
|
24
|
+
_MA_RP_HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
25
|
+
# shellcheck source=/dev/null
|
|
26
|
+
. "$_MA_RP_HERE/../lib/run-paths.sh" 2>/dev/null || . "$HOME/.claude/lib/run-paths.sh"
|
|
27
|
+
|
|
28
|
+
|
|
22
29
|
TASK_ID="${1:?usage: render-agent-log-cost.sh <task-id> [--otel-spans <path>]}"
|
|
23
30
|
shift || true
|
|
24
31
|
|
|
@@ -50,8 +57,8 @@ for candidate in \
|
|
|
50
57
|
"$PWD/.worktrees/$TASK_ID/phase-tracker.json" \
|
|
51
58
|
"$PWD/.worktrees/$task_id_bare/phase-tracker.json" \
|
|
52
59
|
"$PWD/.worktrees/task-$task_id_bare/phase-tracker.json" \
|
|
53
|
-
"$
|
|
54
|
-
"$
|
|
60
|
+
"$(ma_resolve_run_file "$TASK_ID" tracker-state.json 2>/dev/null || echo /nonexistent)" \
|
|
61
|
+
"$(ma_resolve_run_file "$task_id_bare" tracker-state.json 2>/dev/null || echo /nonexistent)"
|
|
55
62
|
do
|
|
56
63
|
[ -f "$candidate" ] && { tracker_file="$candidate"; break; }
|
|
57
64
|
done
|
|
@@ -13,6 +13,13 @@
|
|
|
13
13
|
|
|
14
14
|
set -euo pipefail
|
|
15
15
|
|
|
16
|
+
# Run-state path resolution: pipeline/lib/run-paths.sh owns the two layouts
|
|
17
|
+
# (nested <root>/<project>/<id>/ and flat <root>/<id>/) and every id spelling.
|
|
18
|
+
_MA_RP_HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
19
|
+
# shellcheck source=/dev/null
|
|
20
|
+
. "$_MA_RP_HERE/../lib/run-paths.sh" 2>/dev/null || . "$HOME/.claude/lib/run-paths.sh"
|
|
21
|
+
|
|
22
|
+
|
|
16
23
|
TASK_ID="${1:?usage: render-cost-summary.sh <task-id> [--otel-spans <path>]}"
|
|
17
24
|
shift || true
|
|
18
25
|
|
|
@@ -50,8 +57,8 @@ for candidate in \
|
|
|
50
57
|
"$PWD/.worktrees/$TASK_ID/phase-tracker.json" \
|
|
51
58
|
"$PWD/.worktrees/$task_id_bare/phase-tracker.json" \
|
|
52
59
|
"$PWD/.worktrees/task-$task_id_bare/phase-tracker.json" \
|
|
53
|
-
"$
|
|
54
|
-
"$
|
|
60
|
+
"$(ma_resolve_run_file "$TASK_ID" tracker-state.json 2>/dev/null || echo /nonexistent)" \
|
|
61
|
+
"$(ma_resolve_run_file "$task_id_bare" tracker-state.json 2>/dev/null || echo /nonexistent)"
|
|
55
62
|
do
|
|
56
63
|
[ -f "$candidate" ] && { tracker_file="$candidate"; break; }
|
|
57
64
|
done
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
# render-work-summary.sh - v7.1.0
|
|
3
3
|
#
|
|
4
4
|
# Reads agent-state.json + phase-tracker.json + git diff, emits a concise
|
|
5
|
-
# "### Work Summary" markdown block for Phase
|
|
5
|
+
# "### Work Summary" markdown block for Phase 5 channels dispatch. Intended
|
|
6
6
|
# as an executive-summary companion to the existing Normal Analysis /
|
|
7
7
|
# Technical Details / Test Scenarios sections - gives Jira/Confluence
|
|
8
8
|
# readers and PR reviewers a single-screen answer to "what actually
|
|
@@ -40,6 +40,13 @@
|
|
|
40
40
|
|
|
41
41
|
set -euo pipefail
|
|
42
42
|
|
|
43
|
+
# Run-state path resolution: pipeline/lib/run-paths.sh owns the two layouts
|
|
44
|
+
# (nested <root>/<project>/<id>/ and flat <root>/<id>/) and every id spelling.
|
|
45
|
+
_MA_RP_HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
46
|
+
# shellcheck source=/dev/null
|
|
47
|
+
. "$_MA_RP_HERE/../lib/run-paths.sh" 2>/dev/null || . "$HOME/.claude/lib/run-paths.sh"
|
|
48
|
+
|
|
49
|
+
|
|
43
50
|
TASK_ID="${1:?usage: render-work-summary.sh <task-id>}"
|
|
44
51
|
shift || true
|
|
45
52
|
|
|
@@ -78,18 +85,18 @@ if [ -n "$WORKTREE" ]; then
|
|
|
78
85
|
[ -f "$WORKTREE/triage-output.json" ] && TRIAGE_FILE="$WORKTREE/triage-output.json"
|
|
79
86
|
fi
|
|
80
87
|
|
|
81
|
-
# Fall back to the salvaged artefacts when the worktree is gone. Phase
|
|
88
|
+
# Fall back to the salvaged artefacts when the worktree is gone. Phase 4 removes it
|
|
82
89
|
# once the PR is open (worktree-finalize), and this script used to resolve state
|
|
83
90
|
# ONLY from the worktree - so it exited 2 and the whole Work Summary silently
|
|
84
91
|
# disappeared from the PR body and the Jira comment. render-agent-log-cost.sh has
|
|
85
92
|
# had a log-dir fallback all along; this is the same list.
|
|
86
93
|
if [ -z "$STATE_FILE" ] || [ -z "$TRACKER_FILE" ]; then
|
|
87
94
|
task_bare="${TASK_ID##*-}"
|
|
95
|
+
# The `*/` glob here saw only the nested layout, and an unmatched glob is a
|
|
96
|
+
# literal path in bash - so a flat-layout run fell through silently.
|
|
88
97
|
for base in \
|
|
89
|
-
"$
|
|
90
|
-
"$
|
|
91
|
-
"$HOME"/.claude/logs/multi-agent/*/"$TASK_ID"/artifacts \
|
|
92
|
-
"$HOME"/.claude/logs/multi-agent/*/"$task_bare"/artifacts
|
|
98
|
+
"$(ma_resolve_run_dir_any "$TASK_ID" 2>/dev/null || echo /nonexistent)/artifacts" \
|
|
99
|
+
"$(ma_resolve_run_dir_any "$task_bare" 2>/dev/null || echo /nonexistent)/artifacts"
|
|
93
100
|
do
|
|
94
101
|
[ -d "$base" ] || continue
|
|
95
102
|
[ -z "$STATE_FILE" ] && [ -f "$base/agent-state.json" ] && STATE_FILE="$base/agent-state.json"
|
|
@@ -196,7 +203,7 @@ total_add=0; total_del=0
|
|
|
196
203
|
# repository check. Testing -d "$WORKTREE/.git" would be wrong regardless: in a
|
|
197
204
|
# linked worktree .git is a file, not a directory.
|
|
198
205
|
# Prefer the worktree; fall back to the project root with the branch by name. A
|
|
199
|
-
# finalized task (Phase
|
|
206
|
+
# finalized task (Phase 4 removed the worktree after the PR) has no worktree but
|
|
200
207
|
# the branch is still local, so without this the Changed-files section vanished
|
|
201
208
|
# from the PR body and the Jira comment even though the data was right there.
|
|
202
209
|
DIFF_IN=""; DIFF_TIP=""
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* @file review-file-filter.mjs - decide what the reviewers are asked to read.
|
|
5
5
|
*
|
|
6
6
|
* Phase 4 has a size cap and no exclusion list. When the diff exceeds the
|
|
7
|
-
* budget the cap truncates the LARGEST files first (`phase-
|
|
7
|
+
* budget the cap truncates the LARGEST files first (`phase-3-review.md`, Step
|
|
8
8
|
* 1.9), so a regenerated lockfile or a snapshot dump does not merely waste
|
|
9
9
|
* tokens - it is the thing that survives while real code is cut. The cheapest
|
|
10
10
|
* fix is to decide what is worth reading before the cap decides what fits.
|
|
@@ -44,6 +44,8 @@ import { readFileSync } from "node:fs";
|
|
|
44
44
|
import { join } from "node:path";
|
|
45
45
|
import { globToRegExp } from "./glob-match.mjs";
|
|
46
46
|
import { unquotePathIfNeeded } from "./git-path.mjs";
|
|
47
|
+
import { runMain } from "../lib/fatal.mjs";
|
|
48
|
+
import { invokedDirectly } from "../lib/invoked-directly.mjs";
|
|
47
49
|
|
|
48
50
|
const DEFAULT_PATTERNS = join(import.meta.dirname, "..", "schemas", "review-file-exclusions.json");
|
|
49
51
|
|
|
@@ -175,6 +177,6 @@ function main() {
|
|
|
175
177
|
}
|
|
176
178
|
}
|
|
177
179
|
|
|
178
|
-
if (import.meta.url
|
|
179
|
-
main
|
|
180
|
+
if (invokedDirectly(import.meta.url)) {
|
|
181
|
+
runMain("review-file-filter", main);
|
|
180
182
|
}
|
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
* Exit 0 always. Invalid/empty input → fail SAFE to "full" (never under-review).
|
|
27
27
|
*/
|
|
28
28
|
import { readFileSync } from "node:fs";
|
|
29
|
+
import { runMain } from "../lib/fatal.mjs";
|
|
29
30
|
|
|
30
31
|
const args = process.argv.slice(2);
|
|
31
32
|
const num = (flag, dflt) => {
|
|
@@ -97,4 +98,4 @@ function main() {
|
|
|
97
98
|
emit({ scope: trivial ? "single" : "full", reason, churn, maxScore, blockers });
|
|
98
99
|
}
|
|
99
100
|
|
|
100
|
-
main
|
|
101
|
+
runMain("review-scope", main);
|
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
|
|
28
28
|
import { existsSync, readFileSync, writeFileSync, mkdirSync, rmSync, renameSync } from "node:fs";
|
|
29
29
|
import { join, dirname } from "node:path";
|
|
30
|
+
import { runMain } from "../lib/fatal.mjs";
|
|
30
31
|
|
|
31
32
|
const NAME_RE = /^[a-z0-9][a-z0-9-]*$/;
|
|
32
33
|
const MAX_NAME = 40;
|
|
@@ -218,4 +219,4 @@ function main() {
|
|
|
218
219
|
}
|
|
219
220
|
}
|
|
220
221
|
|
|
221
|
-
main
|
|
222
|
+
runMain("routine-registry", main);
|
|
@@ -38,6 +38,8 @@ import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
|
38
38
|
import { join, dirname } from "node:path";
|
|
39
39
|
import { fileURLToPath } from "node:url";
|
|
40
40
|
import { costUsd } from "./_cost.mjs";
|
|
41
|
+
import { resolveRunFile, canonicalRunDir } from "./_run-paths.mjs";
|
|
42
|
+
import { toCurrentPhase, CURRENT_SCHEMA } from "../lib/phase-schema.mjs";
|
|
41
43
|
|
|
42
44
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
43
45
|
|
|
@@ -82,26 +84,24 @@ function die(msg) {
|
|
|
82
84
|
process.exit(1);
|
|
83
85
|
}
|
|
84
86
|
|
|
85
|
-
//
|
|
86
|
-
//
|
|
87
|
-
//
|
|
88
|
-
//
|
|
89
|
-
//
|
|
87
|
+
// Path resolution lives in _run-paths.mjs: tracker-state.json is written to
|
|
88
|
+
// the flat <root>/<task-id>/ while agent-state.json documents the nested
|
|
89
|
+
// <root>/<project>/<task-id>/, and both layouts are populated in practice.
|
|
90
|
+
// This used to be a hand-rolled candidate list here, a second one in
|
|
91
|
+
// render-cost-summary.sh and a third in render-agent-log-cost.sh.
|
|
90
92
|
function resolveTrackerCandidates() {
|
|
91
93
|
const candidates = [];
|
|
92
94
|
if (flags["task-dir"]) {
|
|
93
95
|
candidates.push(join(flags["task-dir"], "tracker-state.json"));
|
|
94
96
|
}
|
|
95
97
|
if (flags["task-id"]) {
|
|
96
|
-
const
|
|
97
|
-
if (
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
}
|
|
104
|
-
candidates.push(join(HOME, ".claude", "logs", "multi-agent", taskId, "tracker-state.json"));
|
|
98
|
+
const found = resolveRunFile(flags["task-id"], "tracker-state.json", flags.project);
|
|
99
|
+
if (found) candidates.push(found);
|
|
100
|
+
// Keep the canonical path in the list even when nothing exists yet, so the
|
|
101
|
+
// "not found" message names a path instead of an empty candidate set.
|
|
102
|
+
candidates.push(
|
|
103
|
+
join(canonicalRunDir(String(flags["task-id"]), flags.project), "tracker-state.json"),
|
|
104
|
+
);
|
|
105
105
|
}
|
|
106
106
|
if (!candidates.length) die("either --task-dir or --task-id is required");
|
|
107
107
|
return candidates;
|
|
@@ -158,16 +158,22 @@ function computeCost(modelKey, tokensIn, tokensOut, costTable) {
|
|
|
158
158
|
}
|
|
159
159
|
|
|
160
160
|
/**
|
|
161
|
-
* Heuristic:
|
|
162
|
-
* Sonnet by default unless the run is a Short pipeline (Opus)
|
|
163
|
-
* is
|
|
161
|
+
* Heuristic: Plan (1) uses Opus per personas + dev-mode docs; Dev (2) uses
|
|
162
|
+
* Sonnet by default unless the run is a Short pipeline (Opus); Review (3)
|
|
163
|
+
* triage is Opus and the reviewer breakdown comes from spans.
|
|
164
164
|
*
|
|
165
165
|
* This is a fallback when phase-tracker doesn't record the model used. Live
|
|
166
166
|
* runs that emit OTel spans get per-call model attribution from the spans.
|
|
167
|
+
*
|
|
168
|
+
* The phase number is normalised first. The old body compared against the
|
|
169
|
+
* literals "1", "2" and "4", which under the six-phase contract are Plan, Dev
|
|
170
|
+
* and Commit - so a pre-v19 row and a post-v19 row would have been priced
|
|
171
|
+
* against different phases with no error anywhere.
|
|
167
172
|
*/
|
|
168
|
-
function inferModelForPhase(phaseId) {
|
|
169
|
-
|
|
170
|
-
if (
|
|
173
|
+
function inferModelForPhase(phaseId, schema = CURRENT_SCHEMA) {
|
|
174
|
+
const p = toCurrentPhase(phaseId, schema);
|
|
175
|
+
if (p === 1) return "opus";
|
|
176
|
+
if (p === 3) return "opus";
|
|
171
177
|
return "sonnet";
|
|
172
178
|
}
|
|
173
179
|
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
* consensusVerdict - unanimous-* / split / unverified
|
|
25
25
|
* buildPassed - per-repo build outcome
|
|
26
26
|
* diff.filesTouched / locAdded / - size of the change, from state.diffRisk
|
|
27
|
-
* locRemoved / maxScore (Phase
|
|
27
|
+
* locRemoved / maxScore (Phase 3 Step 1.75); null when the
|
|
28
28
|
* run predates the persisted totals
|
|
29
29
|
* reviewDelta.stillPresentFinal / - cross-round classification of the
|
|
30
30
|
* resolvedTotal / tripped last iteration (state.reviewIterations[].delta)
|
|
@@ -215,5 +215,7 @@ const metrics = {
|
|
|
215
215
|
},
|
|
216
216
|
};
|
|
217
217
|
|
|
218
|
+
// No process.exit(0) here. Exit code 0 is already the default, and calling it
|
|
219
|
+
// would terminate before this write drained - stdout to a pipe is asynchronous,
|
|
220
|
+
// so `run-metrics.mjs | jq` would read a payload cut at a buffer boundary.
|
|
218
221
|
console.log(JSON.stringify(metrics, null, 2));
|
|
219
|
-
process.exit(0);
|