@aperant/framework 0.7.3 → 0.8.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 +66 -0
- package/agents/apt-executor.md +12 -0
- package/agents/apt-team-docs-narrator.md +11 -0
- package/dist/cli/ci-watch/stop-matrix.d.mts +17 -4
- package/dist/cli/ci-watch/stop-matrix.d.mts.map +1 -1
- package/dist/cli/ci-watch/stop-matrix.mjs +41 -4
- package/dist/cli/ci-watch/stop-matrix.mjs.map +1 -1
- package/dist/cli/commands/fan-out.d.mts +2 -0
- package/dist/cli/commands/fan-out.d.mts.map +1 -0
- package/dist/cli/commands/fan-out.mjs +123 -0
- package/dist/cli/commands/fan-out.mjs.map +1 -0
- package/dist/cli/commands/modes.d.mts +22 -0
- package/dist/cli/commands/modes.d.mts.map +1 -1
- package/dist/cli/commands/modes.mjs +4 -1
- package/dist/cli/commands/modes.mjs.map +1 -1
- package/dist/cli/commands/pr-review-audit-fixer.d.mts.map +1 -1
- package/dist/cli/commands/pr-review-audit-fixer.mjs +86 -6
- package/dist/cli/commands/pr-review-audit-fixer.mjs.map +1 -1
- package/dist/cli/commands/roadmap.d.mts +1 -1
- package/dist/cli/commands/roadmap.d.mts.map +1 -1
- package/dist/cli/commands/roadmap.mjs +47 -4
- package/dist/cli/commands/roadmap.mjs.map +1 -1
- package/dist/cli/commands/task.d.mts.map +1 -1
- package/dist/cli/commands/task.mjs +15 -0
- package/dist/cli/commands/task.mjs.map +1 -1
- package/dist/cli/commands/validate-evidence.d.mts +1 -1
- package/dist/cli/commands/validate-evidence.d.mts.map +1 -1
- package/dist/cli/commands/validate-evidence.mjs +72 -47
- package/dist/cli/commands/validate-evidence.mjs.map +1 -1
- package/dist/cli/commands/wave.d.mts.map +1 -1
- package/dist/cli/commands/wave.mjs +91 -61
- package/dist/cli/commands/wave.mjs.map +1 -1
- package/dist/cli/commands/worktree.mjs +62 -3
- package/dist/cli/commands/worktree.mjs.map +1 -1
- package/dist/cli/config/load.mjs +1 -1
- package/dist/cli/config/load.mjs.map +1 -1
- package/dist/cli/config/parallelization.d.mts +14 -0
- package/dist/cli/config/parallelization.d.mts.map +1 -0
- package/dist/cli/config/parallelization.mjs +19 -0
- package/dist/cli/config/parallelization.mjs.map +1 -0
- package/dist/cli/coordination/agent-identity.d.mts.map +1 -1
- package/dist/cli/coordination/agent-identity.mjs +7 -1
- package/dist/cli/coordination/agent-identity.mjs.map +1 -1
- package/dist/cli/dispatch.d.mts.map +1 -1
- package/dist/cli/dispatch.mjs +2 -0
- package/dist/cli/dispatch.mjs.map +1 -1
- package/dist/cli/roadmap/convex-mirror.d.mts +21 -0
- package/dist/cli/roadmap/convex-mirror.d.mts.map +1 -0
- package/dist/cli/roadmap/convex-mirror.mjs +133 -0
- package/dist/cli/roadmap/convex-mirror.mjs.map +1 -0
- package/dist/cli/roadmap/lifecycle.d.mts +1 -1
- package/dist/cli/roadmap/lifecycle.d.mts.map +1 -1
- package/dist/cli/roadmap/lifecycle.mjs +54 -0
- package/dist/cli/roadmap/lifecycle.mjs.map +1 -1
- package/dist/cli/wfrun/unit-shape.d.mts +27 -0
- package/dist/cli/wfrun/unit-shape.d.mts.map +1 -0
- package/dist/cli/wfrun/unit-shape.mjs +38 -0
- package/dist/cli/wfrun/unit-shape.mjs.map +1 -0
- package/package.json +1 -1
- package/skills/apt-execute/SKILL.md +13 -0
- package/skills/apt-fan-out/SKILL.md +124 -0
- package/skills/apt-pr-review/SKILL.md +8 -1
- package/skills/apt-review/SKILL.md +4 -0
- package/skills/apt-run/SKILL.md +20 -5
- package/skills/apt-spar/SKILL.md +12 -9
- package/skills/apt-verify/SKILL.md +11 -0
- package/skills/apt-watch-ci/SKILL.md +2 -2
- package/src/cli/ci-watch/stop-matrix.mjs +44 -4
- package/src/cli/commands/fan-out.mjs +129 -0
- package/src/cli/commands/modes.mjs +4 -1
- package/src/cli/commands/pr-review-audit-fixer.mjs +82 -6
- package/src/cli/commands/roadmap.mjs +48 -4
- package/src/cli/commands/task.mjs +15 -0
- package/src/cli/commands/validate-evidence.mjs +75 -50
- package/src/cli/commands/wave.mjs +91 -58
- package/src/cli/commands/worktree.mjs +56 -3
- package/src/cli/config/load.mjs +1 -1
- package/src/cli/config/parallelization.mjs +18 -0
- package/src/cli/coordination/agent-identity.mjs +9 -1
- package/src/cli/dispatch.mjs +2 -0
- package/src/cli/roadmap/convex-mirror.mjs +131 -0
- package/src/cli/roadmap/lifecycle.mjs +48 -0
- package/src/cli/wfrun/unit-shape.mjs +39 -0
- package/templates/config.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,72 @@ All notable changes to `@aperant/framework` are documented here. See
|
|
|
5
5
|
|
|
6
6
|
## [Unreleased]
|
|
7
7
|
|
|
8
|
+
## 0.8.0 — 2026-05-20 — cross-task fan-out + 5 framework defects (BUG-033..038)
|
|
9
|
+
|
|
10
|
+
Minor release. Ships the new `/apt:fan-out` skill (cross-task parallelization from a single conductor terminal) and closes five framework defects surfaced during real `/apt:run` pipelines. Includes one behavioral default change (`task_isolation.from_branch` now defaults to `main`, not `current`).
|
|
11
|
+
|
|
12
|
+
### New capability: `/apt:fan-out`
|
|
13
|
+
|
|
14
|
+
Cross-task parallelization from one conductor terminal. The host CLI's main thread spawns N `apt-executor` sub-agents via Task tool `run_in_background: true`, each pinned to its own task-level worktree. Accepts `--tasks <id-list>` (canonical), `--phases <m/p>` (policy front), `--unblocked` (auto-pick from roadmap ready-state). Default concurrency cap `parallelization.max_tasks: 4`.
|
|
15
|
+
|
|
16
|
+
Built on the **generalized wave engine**: `wave.mjs` + `wfrun/dag.mjs` now accept `unit_kind: "subtask" | "task"` so task-level fan-out reuses the same primitives (`apt-tools lock`, JSONL event log, `max_agents` quota) as the existing subtask wave-parallel mode. Subtask path is bit-equivalent (locked by snapshot test).
|
|
17
|
+
|
|
18
|
+
ADRs documenting the locked decisions:
|
|
19
|
+
- ADR-0001 worker subagent topology (host CLI Task tool background spawn)
|
|
20
|
+
- ADR-0002 paired skill surface (mechanism + policy split)
|
|
21
|
+
- ADR-0003 conductor identity (host CLI main thread; never daemon)
|
|
22
|
+
|
|
23
|
+
### Defects fixed
|
|
24
|
+
|
|
25
|
+
- **FRAMEWORK-BUG-033** — cross-task fan-out gap (the umbrella above) bundled the four lifecycle/identity sub-defects:
|
|
26
|
+
- Phase auto-completion sibling-guard bug in `lifecycle.mjs` (16-task phase flipping to `completed` on first close)
|
|
27
|
+
- Durable `assigned_to` field on task records
|
|
28
|
+
- `APT_AGENT_ID=fanout-${batch_id}-${task_id}` export from `apt-executor` for stable per-worker identity
|
|
29
|
+
- Wave engine generalization to accept either subtask or task as `unit_id`
|
|
30
|
+
- **FRAMEWORK-BUG-034** — `validate-evidence` parser self-reference. Stamper inserted `- **Validation Status**: ...` using the same `- **...**:` field-form shape its own regex matched; on subsequent passes the parser dismissed 88% of LLM-validated findings as `evidence_not_literal` by reading its own stamped text as the cited evidence. Fix: writer emits trailing `### Validation Metadata` section; reader strips legacy field-form Status/Note before evidence extraction. Dual-shape reader for back-compat.
|
|
31
|
+
- **FRAMEWORK-BUG-035** — `pr-review-audit-fixer` parser only matched `### {ID}` finding headers, not the canonical `## Fix N` shape per FRAMEWORK-BUG-030. Returned `<none parsed>` + false-positive `hallucinated` verdict despite real commits. Fix: new `parseFixNEntries` with finding-ID extraction via priority chain `**Finding ID**:` → `**Fix**:` → `**ID**:` → synthetic.
|
|
32
|
+
- **FRAMEWORK-BUG-036** — lifecycle phase didn't auto-advance through `apt:execute` / `apt:verify` / `apt:review` SKILL.md success-paths. Only `/apt:ship` flipped the phase (and only from `reviewing`, which never happened). Fix: each skill adds ONE `task update --lifecycle-phase` call at success-end, advancing `executing` → `verifying` → `reviewing`. `/apt:ship` atomic `reviewing → shipped-pending-merge` flip now fires reliably.
|
|
33
|
+
- **FRAMEWORK-BUG-037** — `task_isolation.from_branch: "current"` default silently chained WIP commits into new task PRs. **Behavioral default change**: now `"main"` with main-detection chain (`origin/HEAD` → `origin/main` → `origin/master` → local `main` / `master`). Explicit `--from-branch current` / `--from-branch HEAD` preserved for power users who want chaining. Projects with explicit `from_branch` in their own `.aperant/config.json` are unaffected.
|
|
34
|
+
- **FRAMEWORK-BUG-038** — `/apt:spar` Round-1 `verdict=cede` terminated unilaterally, collapsing every multi-round session to one round. Two SKILL.md edits: partner prompt template now requires `NEXT_WEAKEST_POINT`; Step 8 splits cede semantics — `--rounds 1` explicit terminates, `--rounds >= 2` (default) emits `next-round` regardless and requires two consecutive same-disposition rounds for convergence. No new flags, no new skills.
|
|
35
|
+
|
|
36
|
+
### Version
|
|
37
|
+
|
|
38
|
+
- `packages/framework/package.json`: 0.7.4 → 0.8.0
|
|
39
|
+
- `cli-baseline-version.txt` + `cli-baseline-help.txt` fixtures bumped
|
|
40
|
+
|
|
41
|
+
### Commits
|
|
42
|
+
|
|
43
|
+
- feat(framework): cross-task fan-out + 4 lifecycle/identity fixes (#208) — bd099c8f
|
|
44
|
+
- fix(framework): apt:spar Round-1 collapse (#210) — 567a63d0
|
|
45
|
+
- fix(framework): validate-evidence + audit-fixer parsers (#211) — 0f28a1af
|
|
46
|
+
- fix(framework): lifecycle auto-advance + from-branch default (#214) — b1abcb65
|
|
47
|
+
- (this one) — chore(framework): 0.8.0 — cross-task fan-out + 5 framework defects (BUG-033..038)
|
|
48
|
+
|
|
49
|
+
## 0.7.4 — 2026-05-18 — apt-pr-review context-budget skip prohibition
|
|
50
|
+
|
|
51
|
+
Docs-only patch release hardening the `apt-pr-review` "Fix Everything" contract against a live failure pattern where an orchestrator dropped confirmed minor findings mid-Phase-6 because its own context window felt heavy ("my orchestrator window was getting heavy after 6 specialist rounds + Round 1 work"). Pre-existing rule 5 in §Context Budget Rules already forbade skipping *phases*; this release closes the per-finding gap inside Phase 6.
|
|
52
|
+
|
|
53
|
+
### apt-pr-review SKILL.md
|
|
54
|
+
|
|
55
|
+
Three reading depths now carry the prohibition:
|
|
56
|
+
|
|
57
|
+
- **§Principle: Fix Everything (Phase 6)** — new "Hard rule" paragraph. Orchestrator context pressure, "many fixes already done," and marginal-value judgment are explicitly NOT valid skip reasons. Reminds the orchestrator that fix work runs in fixer windows, so orchestrator pressure does not justify cutting fixer inputs.
|
|
58
|
+
- **§Key Principles → 2. Fix Everything Found** — invalid-reason list extended to include "my context window is heavy" / "I've already done a lot this run."
|
|
59
|
+
- **§Common Mistakes → new 7a (Dropping Findings Because Orchestrator Context Feels Heavy)** — names the failure pattern verbatim, labels it an unauthorized policy deviation, prescribes spawning fixers in smallest batches possible (and filing a framework bug) rather than shipping a partial fix.
|
|
60
|
+
|
|
61
|
+
Only valid skip authorities remain the three in Key Principle #2: `fixable: false`, critical finding without user approval, file assigned to another fixer.
|
|
62
|
+
|
|
63
|
+
### Version
|
|
64
|
+
|
|
65
|
+
- `packages/framework/package.json`: 0.7.3 → 0.7.4
|
|
66
|
+
- `cli-baseline-version.txt` fixture bumped
|
|
67
|
+
|
|
68
|
+
### Commits
|
|
69
|
+
|
|
70
|
+
- chore(framework): forbid context-budget skips in apt-pr-review (a1eb033d)
|
|
71
|
+
- docs(framework): changelog entry for pr-review context-budget skip fix (43c98286)
|
|
72
|
+
- (this one) — chore(framework): 0.7.4 — apt-pr-review context-budget skip prohibition
|
|
73
|
+
|
|
8
74
|
## 0.7.3 — 2026-05-17 — C56 roadmap reconciliation + operator-blocked notes
|
|
9
75
|
|
|
10
76
|
Docs-only patch release reconciling the roadmap with reality. No code changes.
|
package/agents/apt-executor.md
CHANGED
|
@@ -46,6 +46,18 @@ node packages/framework/bin/apt-tools.mjs gate check . --task-id {task-id} --ski
|
|
|
46
46
|
|
|
47
47
|
If `status == "fail"`, STOP. Report the failed gates verbatim and exit — do NOT auto-apply `--force`. Forcing is a human decision; the user can re-invoke with `--force --reason "<explanation>"` to bypass (the override is logged to `.aperant/events/{today}.jsonl`).
|
|
48
48
|
|
|
49
|
+
## 0a. Fan-out worker identity (FRAMEWORK-BUG-033 defect 3)
|
|
50
|
+
|
|
51
|
+
If your spawn prompt contains both `batch_id` and `task_id` (i.e. you are a fan-out worker subagent dispatched by `/apt:fan-out`), export `APT_AGENT_ID` in EVERY `Bash` invocation that runs `apt-tools ...`:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
APT_AGENT_ID=fanout-${batch_id}-${task_id} node packages/framework/bin/apt-tools.mjs <command> ...
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
This pins your `team-status/{agentId}.json` file across short-lived CLI invocations. Without it, each `apt-tools` call gets a fresh `hostname-pid` agentId (per `agent-identity.mjs:86`), the previous pid dies, and `listTeamStatus({ includeStale: false })` filters healthy workers out between invocations — the team-status dashboard flickers into emptiness instead of showing 4 stable fan-out workers.
|
|
58
|
+
|
|
59
|
+
Non-fan-out invocations of this agent receive no `batch_id` and skip this export — the legacy `hostname-pid` path remains correct for single-task work.
|
|
60
|
+
|
|
49
61
|
## 1. Load Context
|
|
50
62
|
|
|
51
63
|
1. Read `CLAUDE.md` and `AGENTS.md` if they exist
|
|
@@ -72,6 +72,17 @@ If the parent spawned you without a mode you recognize, write an error line to `
|
|
|
72
72
|
rendered table. If present, REPLACE the content between anchors (never
|
|
73
73
|
append — this is how re-runs stay idempotent).
|
|
74
74
|
7. Call `apt-tools roadmap sync . --reason 'narrator:phase-ship:<phase_id>'`.
|
|
75
|
+
8. **Slice 5 / AC14 / ADR-0006 dual-write.** Write the rendered prose
|
|
76
|
+
block to a temp file (e.g. `mktemp -t narrator-prose-XXXXXX.md`), then
|
|
77
|
+
run
|
|
78
|
+
`apt-tools roadmap convex-mirror . --scope <scope> --phase <phase_id> --anchor-id phase-ship:<phase_id> --prose-path <tempfile>`
|
|
79
|
+
(add `--merged-pr <pr-number>` when known). The markdown write from
|
|
80
|
+
step 7 is canonical (ADR-0006); this step is the Convex mirror.
|
|
81
|
+
Fail-soft contract:
|
|
82
|
+
- exit 0 with `status:ok` or `status:queued` → continue normally
|
|
83
|
+
- exit non-zero with `status:error` → append the error message to
|
|
84
|
+
`.aperant/digests/errors.log` and continue (do NOT block on Convex
|
|
85
|
+
failures; the in-process cron drainer reconciles within 5 min)
|
|
75
86
|
|
|
76
87
|
## Mode 2: `decision-merge` — merge a recorded decision into the roadmap
|
|
77
88
|
|
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @typedef {Object} CheckRow
|
|
3
3
|
* @property {string} [name]
|
|
4
|
-
* @property {string} [
|
|
5
|
-
*
|
|
4
|
+
* @property {string} [state] Primary per-check status (gh-CLI uppercase enum):
|
|
5
|
+
* 'SUCCESS' | 'FAILURE' | 'CANCELLED' | 'TIMED_OUT' | 'SKIPPED' |
|
|
6
|
+
* 'IN_PROGRESS' | 'QUEUED' | 'PENDING' | 'NEUTRAL'.
|
|
7
|
+
* @property {string} [conclusion] Legacy lowercase per-check field
|
|
8
|
+
* (deprecated — gh dropped it from `pr checks --json` schema circa 2.65).
|
|
9
|
+
* Retained only as a soft fallback for in-memory test fixtures
|
|
10
|
+
* (FRAMEWORK-BUG-016).
|
|
6
11
|
* @property {string} [bucket]
|
|
7
12
|
* @property {string} [failure_class] — optional pre-classified hint (test-only seam)
|
|
8
13
|
* @property {string} [log_fingerprint] — optional digest for identical-log detection
|
|
@@ -25,10 +30,18 @@ export function isFailing(check: any): boolean;
|
|
|
25
30
|
export type CheckRow = {
|
|
26
31
|
name?: string | undefined;
|
|
27
32
|
/**
|
|
28
|
-
*
|
|
33
|
+
* Primary per-check status (gh-CLI uppercase enum):
|
|
34
|
+
* 'SUCCESS' | 'FAILURE' | 'CANCELLED' | 'TIMED_OUT' | 'SKIPPED' |
|
|
35
|
+
* 'IN_PROGRESS' | 'QUEUED' | 'PENDING' | 'NEUTRAL'.
|
|
29
36
|
*/
|
|
30
|
-
conclusion?: string | undefined;
|
|
31
37
|
state?: string | undefined;
|
|
38
|
+
/**
|
|
39
|
+
* Legacy lowercase per-check field
|
|
40
|
+
* (deprecated — gh dropped it from `pr checks --json` schema circa 2.65).
|
|
41
|
+
* Retained only as a soft fallback for in-memory test fixtures
|
|
42
|
+
* (FRAMEWORK-BUG-016).
|
|
43
|
+
*/
|
|
44
|
+
conclusion?: string | undefined;
|
|
32
45
|
bucket?: string | undefined;
|
|
33
46
|
/**
|
|
34
47
|
* — optional pre-classified hint (test-only seam)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stop-matrix.d.mts","sourceRoot":"","sources":["../../../src/cli/ci-watch/stop-matrix.mjs"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"stop-matrix.d.mts","sourceRoot":"","sources":["../../../src/cli/ci-watch/stop-matrix.mjs"],"names":[],"mappings":"AAoCA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wDAHW,aAAa,GACX,cAAc,CAuJ1B;AAED,+CAuBC;;;;;;;;;;;;;;;;;;;;;;;;;;;YA1La,QAAQ,EAAE;;;;WACV,MAAM;;;;gBACN,MAAM;;;YAGN,MAAM;0BACN,OAAO;YACP,MAAM"}
|
|
@@ -5,11 +5,17 @@
|
|
|
5
5
|
* { action, counts_toward_budget, reason }
|
|
6
6
|
*
|
|
7
7
|
* No I/O, no fs, no gh CLI shell-outs — caller pre-fetches `checks` (the
|
|
8
|
-
* payload from `gh pr checks --json name,bucket,state,
|
|
8
|
+
* payload from `gh pr checks --json name,bucket,state,link,workflow,completedAt`)
|
|
9
9
|
* and `prMetadata` (`gh pr view --json state,reviewDecision`) and passes them
|
|
10
10
|
* in. The orchestrator in commands/ci-watch.mjs handles the side effects
|
|
11
11
|
* implied by the action.
|
|
12
12
|
*
|
|
13
|
+
* Primary per-check signal is `state` (uppercase per gh-CLI: SUCCESS,
|
|
14
|
+
* FAILURE, CANCELLED, TIMED_OUT, SKIPPED, IN_PROGRESS, QUEUED, PENDING,
|
|
15
|
+
* NEUTRAL). The legacy lowercase per-check field that gh dropped circa
|
|
16
|
+
* 2.65 is kept as a soft fallback for in-memory test fixtures only —
|
|
17
|
+
* production gh payloads no longer expose it (FRAMEWORK-BUG-016).
|
|
18
|
+
*
|
|
13
19
|
* Predicate order matters — short-circuits go first (merged/closed/green/cap
|
|
14
20
|
* fire before any per-check inspection). See spec.md §9 table for the full
|
|
15
21
|
* ordering.
|
|
@@ -28,8 +34,13 @@ const INFRA_FAILURE_CLASSES = new Set(['runner-oom', 'runner-cancelled', 'gh-5xx
|
|
|
28
34
|
/**
|
|
29
35
|
* @typedef {Object} CheckRow
|
|
30
36
|
* @property {string} [name]
|
|
31
|
-
* @property {string} [
|
|
32
|
-
*
|
|
37
|
+
* @property {string} [state] Primary per-check status (gh-CLI uppercase enum):
|
|
38
|
+
* 'SUCCESS' | 'FAILURE' | 'CANCELLED' | 'TIMED_OUT' | 'SKIPPED' |
|
|
39
|
+
* 'IN_PROGRESS' | 'QUEUED' | 'PENDING' | 'NEUTRAL'.
|
|
40
|
+
* @property {string} [conclusion] Legacy lowercase per-check field
|
|
41
|
+
* (deprecated — gh dropped it from `pr checks --json` schema circa 2.65).
|
|
42
|
+
* Retained only as a soft fallback for in-memory test fixtures
|
|
43
|
+
* (FRAMEWORK-BUG-016).
|
|
33
44
|
* @property {string} [bucket]
|
|
34
45
|
* @property {string} [failure_class] — optional pre-classified hint (test-only seam)
|
|
35
46
|
* @property {string} [log_fingerprint] — optional digest for identical-log detection
|
|
@@ -60,7 +71,15 @@ export function classify({ checks, state, prMetadata }) {
|
|
|
60
71
|
return { action: 'closed', counts_toward_budget: false, reason: 'pr is closed unmerged' };
|
|
61
72
|
}
|
|
62
73
|
const failed = rows.filter((c) => isFailing(c));
|
|
63
|
-
|
|
74
|
+
// FRAMEWORK-BUG-016: `state` is gh-CLI's primary per-check field post-2.65.
|
|
75
|
+
// SKIPPED rows (workflow `if:` guards that didn't trip) are
|
|
76
|
+
// success-equivalent — they intentionally did not run and that is OK.
|
|
77
|
+
// Soft fallback to the legacy lowercase field keeps the in-memory test
|
|
78
|
+
// fixtures green (production gh payloads never hit it).
|
|
79
|
+
const isGreenRow = (c) => c.state === 'SUCCESS' ||
|
|
80
|
+
c.state === 'SKIPPED' ||
|
|
81
|
+
(c.state == null && c.conclusion === 'success');
|
|
82
|
+
const allGreen = rows.length > 0 && rows.every(isGreenRow);
|
|
64
83
|
// 3. All checks green.
|
|
65
84
|
if (allGreen) {
|
|
66
85
|
return { action: 'green', counts_toward_budget: false, reason: 'all checks succeeded' };
|
|
@@ -174,6 +193,24 @@ export function classify({ checks, state, prMetadata }) {
|
|
|
174
193
|
};
|
|
175
194
|
}
|
|
176
195
|
export function isFailing(check) {
|
|
196
|
+
// FRAMEWORK-BUG-016 / BUG-025: prefer the uppercase `state` field that gh
|
|
197
|
+
// 2.65+ exposes. SKIPPED / NEUTRAL / IN_PROGRESS / QUEUED / PENDING /
|
|
198
|
+
// SUCCESS are explicitly NOT red — SKIPPED in particular must never
|
|
199
|
+
// burn a fix attempt (workflow `if:` guards routinely skip jobs on PRs
|
|
200
|
+
// that don't trip them). The legacy lowercase field is a soft fallback
|
|
201
|
+
// for in-memory test fixtures only.
|
|
202
|
+
const s = check.state;
|
|
203
|
+
if (s === 'SUCCESS' ||
|
|
204
|
+
s === 'SKIPPED' ||
|
|
205
|
+
s === 'NEUTRAL' ||
|
|
206
|
+
s === 'IN_PROGRESS' ||
|
|
207
|
+
s === 'QUEUED' ||
|
|
208
|
+
s === 'PENDING') {
|
|
209
|
+
return false;
|
|
210
|
+
}
|
|
211
|
+
if (s === 'FAILURE' || s === 'CANCELLED' || s === 'TIMED_OUT') {
|
|
212
|
+
return true;
|
|
213
|
+
}
|
|
177
214
|
const c = check.conclusion;
|
|
178
215
|
return c === 'failure' || c === 'cancelled' || c === 'timed_out' || c === 'action_required';
|
|
179
216
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stop-matrix.mjs","sourceRoot":"","sources":["../../../src/cli/ci-watch/stop-matrix.mjs"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"stop-matrix.mjs","sourceRoot":"","sources":["../../../src/cli/ci-watch/stop-matrix.mjs"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fan-out.d.mts","sourceRoot":"","sources":["../../../src/cli/commands/fan-out.mjs"],"names":[],"mappings":"AAmEA,wHA6DC"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* commands/fan-out.mjs — FRAMEWORK-BUG-033 capability gap (ID-04 / ID-05).
|
|
3
|
+
*
|
|
4
|
+
* Single resolver helper for the `/apt:fan-out` SKILL body. Three input
|
|
5
|
+
* forms accepted (`--tasks`, `--phases`, `--unblocked`); all resolve to
|
|
6
|
+
* the canonical `{task_ids, source, batch_id}` shape. The actual
|
|
7
|
+
* orchestration loop (worktree create, worker spawn, polling) lives in
|
|
8
|
+
* the SKILL body — this CLI just materializes the batch.
|
|
9
|
+
*
|
|
10
|
+
* Subcommands: `resolve`.
|
|
11
|
+
*/
|
|
12
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
13
|
+
import { join, resolve } from 'node:path';
|
|
14
|
+
import { parseFlags } from '../util/args.mjs';
|
|
15
|
+
import { err, ok } from '../util/result.mjs';
|
|
16
|
+
const ID_PATTERN = /^[a-z0-9_-]+$/i;
|
|
17
|
+
function generateBatchId() {
|
|
18
|
+
const d = new Date();
|
|
19
|
+
const yyyy = d.getUTCFullYear();
|
|
20
|
+
const mm = String(d.getUTCMonth() + 1).padStart(2, '0');
|
|
21
|
+
const dd = String(d.getUTCDate()).padStart(2, '0');
|
|
22
|
+
const hex = Math.random().toString(16).slice(2, 8);
|
|
23
|
+
return `fanout-${yyyy}${mm}${dd}-${hex}`;
|
|
24
|
+
}
|
|
25
|
+
function parseIdList(raw) {
|
|
26
|
+
if (typeof raw !== 'string')
|
|
27
|
+
return [];
|
|
28
|
+
return raw
|
|
29
|
+
.split(',')
|
|
30
|
+
.map((s) => s.trim())
|
|
31
|
+
.filter(Boolean);
|
|
32
|
+
}
|
|
33
|
+
function readState(targetDir) {
|
|
34
|
+
const statePath = join(targetDir, '.aperant', 'state.json');
|
|
35
|
+
if (!existsSync(statePath))
|
|
36
|
+
return null;
|
|
37
|
+
try {
|
|
38
|
+
return JSON.parse(readFileSync(statePath, 'utf-8'));
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
function resolveFromPhases(state, phases) {
|
|
45
|
+
const wanted = new Set(phases);
|
|
46
|
+
const ids = [];
|
|
47
|
+
for (const [id, task] of Object.entries(state?.active_tasks || {})) {
|
|
48
|
+
if (!task)
|
|
49
|
+
continue;
|
|
50
|
+
const key = `${task.milestone_id ?? ''}/${task.phase_id ?? ''}`;
|
|
51
|
+
if (wanted.has(key) && task.lifecycle_phase !== 'closed') {
|
|
52
|
+
ids.push(id);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return ids;
|
|
56
|
+
}
|
|
57
|
+
function resolveUnblocked(state) {
|
|
58
|
+
const ids = [];
|
|
59
|
+
for (const [id, task] of Object.entries(state?.active_tasks || {})) {
|
|
60
|
+
if (task?.lifecycle_phase === 'ready-for-agent')
|
|
61
|
+
ids.push(id);
|
|
62
|
+
}
|
|
63
|
+
return ids;
|
|
64
|
+
}
|
|
65
|
+
export function cmdFanOut(subcommand, projectDir, extraArgs) {
|
|
66
|
+
if (!subcommand) {
|
|
67
|
+
return err('Usage: apt-tools fan-out <resolve> <project-dir> [--tasks <ids> | --phases <m/p,m/p> | --unblocked]');
|
|
68
|
+
}
|
|
69
|
+
switch (subcommand) {
|
|
70
|
+
case 'resolve': {
|
|
71
|
+
if (!projectDir) {
|
|
72
|
+
return err('Usage: apt-tools fan-out resolve <project-dir> [--tasks <ids> | --phases <m/p,m/p> | --unblocked]');
|
|
73
|
+
}
|
|
74
|
+
const targetDir = resolve(projectDir);
|
|
75
|
+
const flags = parseFlags(extraArgs);
|
|
76
|
+
const hasTasks = flags.has('tasks');
|
|
77
|
+
const hasPhases = flags.has('phases');
|
|
78
|
+
const hasUnblocked = flags.has('unblocked');
|
|
79
|
+
const inputForms = [hasTasks, hasPhases, hasUnblocked].filter(Boolean).length;
|
|
80
|
+
if (inputForms === 0) {
|
|
81
|
+
return err('One of --tasks, --phases, or --unblocked is required');
|
|
82
|
+
}
|
|
83
|
+
if (inputForms > 1) {
|
|
84
|
+
return err('Only one of --tasks, --phases, or --unblocked may be passed at a time');
|
|
85
|
+
}
|
|
86
|
+
let taskIds = [];
|
|
87
|
+
let source = '';
|
|
88
|
+
if (hasTasks) {
|
|
89
|
+
taskIds = parseIdList(flags.get('tasks'));
|
|
90
|
+
source = 'tasks';
|
|
91
|
+
for (const id of taskIds) {
|
|
92
|
+
if (!ID_PATTERN.test(id)) {
|
|
93
|
+
return err(`Invalid task id in --tasks: "${id}" (must match /^[a-z0-9_-]+$/i)`);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
else if (hasPhases) {
|
|
98
|
+
const state = readState(targetDir);
|
|
99
|
+
if (!state)
|
|
100
|
+
return err('No state.json found — cannot resolve --phases');
|
|
101
|
+
taskIds = resolveFromPhases(state, parseIdList(flags.get('phases')));
|
|
102
|
+
source = 'phases';
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
const state = readState(targetDir);
|
|
106
|
+
if (!state)
|
|
107
|
+
return err('No state.json found — cannot resolve --unblocked');
|
|
108
|
+
taskIds = resolveUnblocked(state);
|
|
109
|
+
source = 'unblocked';
|
|
110
|
+
}
|
|
111
|
+
return ok({
|
|
112
|
+
status: 'ok',
|
|
113
|
+
command: 'fan-out-resolve',
|
|
114
|
+
source,
|
|
115
|
+
task_ids: taskIds,
|
|
116
|
+
batch_id: generateBatchId(),
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
default:
|
|
120
|
+
return err(`Unknown fan-out subcommand: ${subcommand}. Available: resolve`);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=fan-out.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fan-out.mjs","sourceRoot":"","sources":["../../../src/cli/commands/fan-out.mjs"],"names":[],"mappings":"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"}
|
|
@@ -10,4 +10,26 @@
|
|
|
10
10
|
* tree is also scanned when present.
|
|
11
11
|
*/
|
|
12
12
|
export function cmdModes(subcommand: any, projectDir: any, _extraArgs: any): import("../util/result.mjs").CommandResult;
|
|
13
|
+
/**
|
|
14
|
+
* Hardcoded skill→config-paths map. Maintained inline so adding a new
|
|
15
|
+
* config-dependent skill is a one-line change.
|
|
16
|
+
*
|
|
17
|
+
* Per AC12, this is the mapping `modes list` consumes to enumerate
|
|
18
|
+
* which config keys a skill cares about. Skills that don't touch
|
|
19
|
+
* config are omitted (their config_keys is `[]`).
|
|
20
|
+
*
|
|
21
|
+
* AUDIT-001 (0.7.2): all dotted paths below resolve against the MERGED
|
|
22
|
+
* config (`loadMergedProjectConfig()` — shared `config.json` + local
|
|
23
|
+
* `config.local.json` overlay). The five per-device fields enumerated by
|
|
24
|
+
* `AUDIT_001_LOCAL_FIELDS` in `cli/config/load.mjs` (currently
|
|
25
|
+
* `verification.open_report`, `multi_model.cross_verification.tools`,
|
|
26
|
+
* `preferences.{date_format,time_format,quick_task_post_verify}`)
|
|
27
|
+
* physically live in `config.local.json`; the wildcard `'*'` surface for
|
|
28
|
+
* `apt:setup` covers both files. Consumers MUST go through the merged
|
|
29
|
+
* loader — never raw `JSON.parse(readFileSync('.aperant/config.json'))` —
|
|
30
|
+
* to honor per-device overrides correctly.
|
|
31
|
+
*
|
|
32
|
+
* @type {Record<string, string[]>}
|
|
33
|
+
*/
|
|
34
|
+
export const SKILL_CONFIG_KEYS: Record<string, string[]>;
|
|
13
35
|
//# sourceMappingURL=modes.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"modes.d.mts","sourceRoot":"","sources":["../../../src/cli/commands/modes.mjs"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"modes.d.mts","sourceRoot":"","sources":["../../../src/cli/commands/modes.mjs"],"names":[],"mappings":"AA2KA;;;;;;;;;;GAUG;AACH,wHA+CC;AAlMD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,gCAFU,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAoBjC"}
|
|
@@ -51,7 +51,7 @@ const FRONTMATTER_RE = /^---\s*([\s\S]*?)\s*---/;
|
|
|
51
51
|
*
|
|
52
52
|
* @type {Record<string, string[]>}
|
|
53
53
|
*/
|
|
54
|
-
const SKILL_CONFIG_KEYS = {
|
|
54
|
+
export const SKILL_CONFIG_KEYS = {
|
|
55
55
|
'apt:execute': ['coding.tdd_default', 'tdd.iron_law'],
|
|
56
56
|
'apt:triage': [
|
|
57
57
|
'task_tracking.backend',
|
|
@@ -66,6 +66,9 @@ const SKILL_CONFIG_KEYS = {
|
|
|
66
66
|
'apt:ship': ['pipeline.auto_branch', 'pipeline.branch_prefix'],
|
|
67
67
|
'apt:setup': ['*'], // setup edits config — wildcard surface
|
|
68
68
|
'apt:run': ['parallelization.enabled', 'parallelization.max_agents'],
|
|
69
|
+
// FRAMEWORK-BUG-033 capability gap (AC10) — fan-out concurrency cap.
|
|
70
|
+
// Consumed by the /apt:fan-out SKILL body via cli/config/parallelization.mjs.
|
|
71
|
+
'apt:fan-out': ['parallelization.max_tasks', 'parallelization.max_agents'],
|
|
69
72
|
};
|
|
70
73
|
/**
|
|
71
74
|
* Parse the `argument-hint` frontmatter field for `--flag` tokens.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"modes.mjs","sourceRoot":"","sources":["../../../src/cli/commands/modes.mjs"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AACzE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACzC,OAAO,EAAE,KAAK,IAAI,SAAS,EAAE,MAAM,MAAM,CAAA;AACzC,OAAO,EAAE,8BAA8B,EAAE,MAAM,+BAA+B,CAAA;AAC9E,OAAO,EAAE,EAAE,EAAE,MAAM,oBAAoB,CAAA;AAEvC,MAAM,cAAc,GAAG,yBAAyB,CAAA;AAEhD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,iBAAiB,GAAG;
|
|
1
|
+
{"version":3,"file":"modes.mjs","sourceRoot":"","sources":["../../../src/cli/commands/modes.mjs"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pr-review-audit-fixer.d.mts","sourceRoot":"","sources":["../../../src/cli/commands/pr-review-audit-fixer.mjs"],"names":[],"mappings":"AA+EA;;;;;GAKG;AACH;;;;;SAgBC;AAiBD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"pr-review-audit-fixer.d.mts","sourceRoot":"","sources":["../../../src/cli/commands/pr-review-audit-fixer.mjs"],"names":[],"mappings":"AA+EA;;;;;GAKG;AACH;;;;;SAgBC;AAiBD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH;;;;;;;;;;;;;;EA0BC;AA8XD;;;;;;;;;GASG;AACH;;;EAoBC;AAED;;;;GAIG;AACH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA6JC;AAED;;;;;;;;;;;;EAiCC;AAmDD;;GAEG;AACH,mHAmOC"}
|
|
@@ -143,13 +143,28 @@ export function parseFixesAppliedMarkdown(md) {
|
|
|
143
143
|
const fixesSection = extractTopLevelSection(md, 'Fixes Applied');
|
|
144
144
|
const selfReviewerSection = extractTopLevelSection(md, 'Fixes Applied by Self-Reviewer');
|
|
145
145
|
const skippedSection = extractTopLevelSection(md, 'Skipped');
|
|
146
|
-
const
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
146
|
+
const legacyFixerEntries = parseFixEntries(fixesSection);
|
|
147
|
+
const selfReviewerEntries = parseSelfReviewerFixEntries(selfReviewerSection);
|
|
148
|
+
// FRAMEWORK-BUG-035: additive `## Fix N` parser path. Scans the whole
|
|
149
|
+
// document — NOT a `## Fixes Applied` body — so it catches fixer reports
|
|
150
|
+
// shaped as numbered top-level blocks. Union, not substitution, per spec
|
|
151
|
+
// ID-03 so legacy `### {ID}` reports keep parsing unchanged.
|
|
152
|
+
const fixNEntries = parseFixNEntries(md);
|
|
153
|
+
const fixes = [...legacyFixerEntries, ...selfReviewerEntries, ...fixNEntries];
|
|
150
154
|
const skipped = parseSkippedEntries(skippedSection);
|
|
151
|
-
//
|
|
152
|
-
|
|
155
|
+
// Schema discriminator: when the ONLY entries came from the `## Fix N`
|
|
156
|
+
// parser path, label it `'fix-n'` so downstream code / debugging can
|
|
157
|
+
// tell which shape was on disk. Fall back to existing fixer / self-
|
|
158
|
+
// reviewer labels when those sections were present.
|
|
159
|
+
let schema;
|
|
160
|
+
if (fixesSection)
|
|
161
|
+
schema = 'fixer';
|
|
162
|
+
else if (selfReviewerSection)
|
|
163
|
+
schema = 'self-reviewer';
|
|
164
|
+
else if (fixNEntries.length > 0)
|
|
165
|
+
schema = 'fix-n';
|
|
166
|
+
else
|
|
167
|
+
schema = 'fixer';
|
|
153
168
|
return { exists: true, fixes, skipped, schema };
|
|
154
169
|
}
|
|
155
170
|
/**
|
|
@@ -231,6 +246,71 @@ function parseFixEntries(section) {
|
|
|
231
246
|
}
|
|
232
247
|
return entries;
|
|
233
248
|
}
|
|
249
|
+
/**
|
|
250
|
+
* FRAMEWORK-BUG-035 — parse `## Fix N` top-level blocks into entries shaped
|
|
251
|
+
* like `parseFixEntries` output. The bug narrative documents `## Fix N`
|
|
252
|
+
* as the canonical shape going forward for fixes-applied-fixer-N.md, but
|
|
253
|
+
* the legacy `### {ID} — title` parser silently dropped every entry on
|
|
254
|
+
* those reports, surfacing `<none parsed>` and false-positive flipping
|
|
255
|
+
* the gate to `hallucinated`.
|
|
256
|
+
*
|
|
257
|
+
* This parser scans the WHOLE document (not a `## Fixes Applied` body)
|
|
258
|
+
* because the new shape uses `## Fix N` directly as top-level headers.
|
|
259
|
+
* Finding-ID extraction priority chain (per spec ID-04):
|
|
260
|
+
* 1. `- **Finding ID**:` field line
|
|
261
|
+
* 2. `- **Fix**:` field line
|
|
262
|
+
* 3. `- **ID**:` field line
|
|
263
|
+
* 4. synthetic `fix-N` fallback (matches `parseSelfReviewerFixEntries`'s
|
|
264
|
+
* `self-reviewer-fix-N` convention; the diff-intersect step in
|
|
265
|
+
* `decideVerdict` is the real check, not the id)
|
|
266
|
+
*
|
|
267
|
+
* Returns the same `{id, title, file, files, verification}` shape as
|
|
268
|
+
* `parseFixEntries` so downstream consumers see a uniform array.
|
|
269
|
+
*/
|
|
270
|
+
function parseFixNEntries(markdown) {
|
|
271
|
+
if (!markdown)
|
|
272
|
+
return [];
|
|
273
|
+
const entries = [];
|
|
274
|
+
// `^## Fix N$` — top-level heading with the literal word "Fix" + a
|
|
275
|
+
// number. No trailing description in the header (the canonical shape
|
|
276
|
+
// per the BUG-034 narrative puts the description inside the body).
|
|
277
|
+
const headerRx = /^##\s+Fix\s+(\d+)\s*$/gm;
|
|
278
|
+
const matches = [...markdown.matchAll(headerRx)];
|
|
279
|
+
for (let i = 0; i < matches.length; i++) {
|
|
280
|
+
const m = matches[i];
|
|
281
|
+
const start = m.index + m[0].length;
|
|
282
|
+
// Terminate at the next top-level `## ` heading OR EOF. Mirrors
|
|
283
|
+
// `extractTopLevelSection`'s body slicing.
|
|
284
|
+
const rest = markdown.slice(start);
|
|
285
|
+
const nextTopRx = /\n##\s+/m;
|
|
286
|
+
const nxt = nextTopRx.exec(rest);
|
|
287
|
+
const body = (nxt ? rest.slice(0, nxt.index) : rest).trim();
|
|
288
|
+
const findingId = extractFindingIdField(body) ?? `fix-${m[1]}`;
|
|
289
|
+
const files = extractFileFields(body);
|
|
290
|
+
entries.push({
|
|
291
|
+
id: findingId,
|
|
292
|
+
title: null,
|
|
293
|
+
file: files[0] ?? null,
|
|
294
|
+
files,
|
|
295
|
+
verification: extractVerificationField(body),
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
return entries;
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* Extract the finding ID from a `## Fix N` block body via the priority
|
|
302
|
+
* chain documented in `parseFixNEntries`. Returns `null` if no field
|
|
303
|
+
* matched — caller falls back to the synthetic `fix-N` id.
|
|
304
|
+
*/
|
|
305
|
+
function extractFindingIdField(body) {
|
|
306
|
+
for (const key of ['Finding ID', 'Fix', 'ID']) {
|
|
307
|
+
const rx = new RegExp(`-\\s*\\*\\*${key}\\*\\*:\\s*([^\\n]+)`, 'i');
|
|
308
|
+
const m = rx.exec(body);
|
|
309
|
+
if (m)
|
|
310
|
+
return m[1].trim();
|
|
311
|
+
}
|
|
312
|
+
return null;
|
|
313
|
+
}
|
|
234
314
|
function parseSkippedEntries(section) {
|
|
235
315
|
if (!section)
|
|
236
316
|
return [];
|