@sabaiway/agent-workflow-kit 1.21.0 → 1.23.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 CHANGED
@@ -4,6 +4,45 @@ Semantically versioned ([semver](https://semver.org)), newest first. The `versio
4
4
  is the current release. `upgrade` mode reads a project's `docs/ai/.workflow-version` and applies
5
5
  every `migrations/<version>-<slug>.md` newer than it, in semver order.
6
6
 
7
+ ## 1.23.0 — Surface the review-loop economics + the resolved backend set in the procedures advisor
8
+
9
+ A **feature** release. `/agent-workflow-kit procedures <activity>` now makes the review-loop discipline
10
+ mechanical at the point of use:
11
+
12
+ - **Backend-set aid.** Each resolved recipe prints its EXPLICIT wrapper set beside the recipe name
13
+ (`review: council → run every backend every round: codex-review + agy-review`; `reviewed → codex-review`;
14
+ `delegated → codex-exec`; solo prints none), so recipe fidelity is visible where the advisor is invoked.
15
+ Sourced from `planRecipe().dispatch` + a new role-keyed `detect-backends.wrapperCmdFor` (reading
16
+ `KNOWN_BACKENDS[].roleCmds`, now the source of truth; the deduped `wrapperCmds` readiness list is derived
17
+ from it). Drift-guarded against each bridge manifest `roles[role].cmd`.
18
+ - **Review-loop economics block.** For a review slot resolving reviewed|council (omitted for solo) the
19
+ advisor prints the ≤2-round cap, the bar-met-by-raising-a-major rule, the backend-divergence crossover
20
+ stop, the thin-plan/diff-review carve-out, a self-consistency read, and the required per-round emission
21
+ {round N · finding-origin · per-backend verdict}. `--json` carries per-slot `backends` + a top-level
22
+ `reviewLoop`.
23
+ - The fallback `agent_rules.md` **§2.5** lens mirror gains the same review-loop disciplines (byte-identical
24
+ to memory's §2.6).
25
+
26
+ Read-only; no resolution behaviour change. Deployment-lineage head stays `1.3.0`.
27
+
28
+ ## 1.22.0 — Harden the planning canon: two-set lens drift guard + the deployed lens
29
+
30
+ A **feature** release. The kit's fallback `agent_rules.md` **§2.5** lens is generalized from *Right-altitude
31
+ & code-grounded* to **Planning, review & process-fidelity invariants** (byte-identical to memory's §2.6
32
+ block) and now carries all **seven** methodology invariants. The cross-package **`test/lens-mirror.test.mjs`**
33
+ is extended to **two scoped, non-vacuous token sets**:
34
+
35
+ - **Set 1 (cross-all-four)** pins the §9-native review/fold + convergence disciplines in EVERY region —
36
+ planning §9, procedures (`## plan-authoring` onward), and both template lens blocks: `0 blockers + 0
37
+ majors`, `test-as-spec`, `no code-mechanics`, `at the diff`, `characterize-first` (alongside the
38
+ existing `fold by code` / `file:line` / `altitude`).
39
+ - **Set 2 (template-scoped)** pins the process-fidelity invariants A1/A2 (`ExitPlanMode`, recipe-fidelity
40
+ `every round`) PRESENT in both template lens blocks — closing the gap the byte-identical check alone
41
+ cannot (it only proves the two templates AGREE, so both could drop A1/A2 and stay green).
42
+
43
+ The lens heading + the `extractLensBlock` regex move in lockstep. The deployment-lineage head stays
44
+ **`1.3.0`** (no `docs/ai` structural change, no migration); the kit **package** version is a separate axis.
45
+
7
46
  ## 1.21.0 — Ships the antigravity-cli-bridge 2.0.0 mirror (grounded agy-review)
8
47
 
9
48
  A **feature** release. The kit now bundles the **antigravity-cli-bridge 2.0.0** byte-identical mirror —
package/SKILL.md CHANGED
@@ -3,7 +3,7 @@ name: agent-workflow-kit
3
3
  description: Deploy or upgrade a portable AI-agent memory-and-workflow system in any project. Use when the user wants to bootstrap `docs/ai/` + an entry-point `AGENTS.md` (+ `CLAUDE.md` alias) + cap/archive/index enforcement in a new or existing repo, set up the Memory Map and session protocols, install the docs-rotation pre-commit hook, or run `/agent-workflow-kit` / `/agent-workflow-kit upgrade`. Triggers on phrases like "set up the memory system", "deploy the AI workflow here", "bootstrap docs/ai", "upgrade the workflow".
4
4
  disable-model-invocation: true
5
5
  metadata:
6
- version: '1.21.0'
6
+ version: '1.23.0'
7
7
  ---
8
8
 
9
9
  # agent-workflow-kit
package/capability.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "schema": 1,
4
4
  "name": "agent-workflow-kit",
5
5
  "kind": "composition-root",
6
- "version": "1.21.0",
6
+ "version": "1.23.0",
7
7
  "provides": [],
8
8
  "roles": {},
9
9
  "detect": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sabaiway/agent-workflow-kit",
3
- "version": "1.21.0",
3
+ "version": "1.23.0",
4
4
  "description": "Portable, cross-agent memory & workflow for AI coding agents — Claude Code, Codex, Cursor, Devin Desktop. One command deploys an AGENTS.md entry point + docs/ai context with cap/archive/index enforcement into any repo.",
5
5
  "keywords": [
6
6
  "ai-agents",
@@ -61,10 +61,19 @@ Before proposing changes or committing, review against:
61
61
  ### 2.4. Quality Gates
62
62
  - Always run type-checker, linter, and all tests before committing.
63
63
 
64
- ### 2.5. Right-altitude & code-grounded (planning + review)
64
+ ### 2.5. Planning, review & process-fidelity invariants
65
+ Apply these when authoring a plan, reviewing, folding a finding, or editing code — the layer read **before any code change**. (Full canon: the project's planning / workflow-methodology + orchestration canon.)
65
66
  - **Fold by code, not prose.** Before folding a code-touching finding into a plan or change, read the cited `file:line` and cite it — a prose fold drifts from the code and seeds the next bug.
66
67
  - **Right altitude.** Pin intent + invariants + acceptance criteria (named tests); leave fine code-mechanics to Execute, where prose cannot diverge from reality.
67
- - **Convergence heuristic.** When a review round keeps finding mechanism issues on a stable architecture, stop refining prose raise the altitude or hand it to Execute. (Full canon: the project's planning methodology / workflow-methodology canon.)
68
+ - **No code-mechanics in the plan.** A Step still carries its exact paths + commands (the plan-structure / self-review canon); the ceiling is on *fold-bred* detail — a review fold must not push fine code-mechanics (`cd`, an env default, a flag) into prose. A fold that needs a mechanic is the trigger to write the test instead.
69
+ - **Test-as-spec.** Fold a code-touching finding into a red→green TEST, not a prose paragraph — the gate is the only deterministic checker; a paragraph cannot self-check.
70
+ - **Characterize-first.** Before editing UNCOVERED code, pin its current behavior in a green test, then edit — any unintended change goes red. Never edit what has no checker; first give it one. Keep edits atomic/reversible; prefer SUBTRACTIVE folds.
71
+ - **Fold minimally — prose has no checker.** An ephemeral, gitignored plan is prose with no executable checker; fold **minimally, in ONE place** and run a **self-consistency** read across the plan before every re-review — a fold that drifts several prose spots is what turns a 2-round review into churn.
72
+ - **Heavy review at the diff.** Plan-review settles architecture only (≤2 rounds, stop at the pre-existing→fold-induced crossover); the exhaustive per-Step review runs against real compiling code + the full suite, where a regression fails a gate immediately. **Backend divergence** (one backend grounded-ships while another keeps revising mechanics) IS that crossover — resolve at altitude, don't exhaust the strictest backend; route an all-mechanics/CI or prose-only artifact to a **thin plan + diff-review**.
73
+ - **Convergence bar.** A review loop is CLEAN only when one round returns **0 blockers + 0 majors** from EVERY backend the recipe names (nits + a ship verdict is the stop). Folding ≠ convergence — re-review after folding.
74
+ - **Per-round emission.** Every review round emits **{round N · finding-origin tally · per-backend verdict}** so the crossover is a computed, visible signal, not a remembered rule.
75
+ - **Recipe fidelity.** Council runs every backend the recipe names, **every round**; silently dropping a ready backend for quota/convenience is a forbidden downgrade — an unavailable backend is a LOUD, stated degrade, never a quiet drop.
76
+ - **ExitPlanMode ≠ execute.** A harness "approved — start coding" prompt authorizes the PLAN only; this methodology overrides it. Continue into execution only as a DELIBERATE transition after the plan + cold-start prompt exist, never an implicit slide.
68
77
 
69
78
  ---
70
79
 
@@ -51,13 +51,15 @@ const EXPECTED_KIND = 'execution-backend';
51
51
  // The kit-owned registry: the per-backend facts the detector needs even when a bridge is NOT
52
52
  // installed (no manifest on disk to read). Kept in lockstep with the in-repo manifests by the
53
53
  // drift-guard test. `credential.env: null` → no env override exists (do not invent one).
54
- // `wrapperCmds` is the EXPECTED deduped roles[].cmd set the CURRENT kit bundles readiness probes
55
- // THIS set (not the installed manifest's), so a stale install missing a wrapper surfaces DEGRADED.
56
- export const KNOWN_BACKENDS = [
54
+ // `roleCmds` is the role-keyed source of truth (role → the PATH wrapper cmd), mirroring each bridge
55
+ // manifest `roles[role].cmd`, drift-guarded. Two derivations ride on it, both drift-guarded against the
56
+ // manifests: `wrapperCmds` (the deduped set the readiness probe checks — a stale install missing one
57
+ // surfaces DEGRADED) and `wrapperCmdFor(backend, role)` (which concrete wrapper the backend-set aid prints).
58
+ const RAW_BACKENDS = [
57
59
  {
58
60
  name: 'codex-cli-bridge',
59
61
  installed: { env: 'CODEX_CLI_BRIDGE_DIR', default: '~/.claude/skills/codex-cli-bridge', file: 'SKILL.md' },
60
- wrapperCmds: ['codex-exec', 'codex-review'],
62
+ roleCmds: { execute: 'codex-exec', review: 'codex-review' },
61
63
  bin: 'codex',
62
64
  credential: { env: 'CODEX_HOME', default: '~/.codex', file: 'auth.json' },
63
65
  setupUrl: 'https://github.com/sabaiway/agent-workflow/blob/main/codex-cli-bridge/setup/README.md',
@@ -69,7 +71,7 @@ export const KNOWN_BACKENDS = [
69
71
  {
70
72
  name: 'antigravity-cli-bridge',
71
73
  installed: { env: 'ANTIGRAVITY_CLI_BRIDGE_DIR', default: '~/.claude/skills/antigravity-cli-bridge', file: 'SKILL.md' },
72
- wrapperCmds: ['agy-review', 'agy-run'],
74
+ roleCmds: { review: 'agy-review', probe: 'agy-run' },
73
75
  bin: 'agy',
74
76
  credential: { env: null, default: '~/.gemini/antigravity-cli', file: 'antigravity-oauth-token' },
75
77
  setupUrl: 'https://github.com/sabaiway/agent-workflow/blob/main/antigravity-cli-bridge/setup/README.md',
@@ -78,6 +80,17 @@ export const KNOWN_BACKENDS = [
78
80
  },
79
81
  ];
80
82
 
83
+ // The deduped roles[].cmd set the CURRENT kit bundles, derived from roleCmds in first-seen order — one
84
+ // source, so the readiness-probe list can never drift from the role-keyed map.
85
+ const wrapperCmdsFromRoles = (roleCmds) => [...new Set(Object.values(roleCmds ?? {}))];
86
+ export const KNOWN_BACKENDS = RAW_BACKENDS.map((entry) => ({ ...entry, wrapperCmds: wrapperCmdsFromRoles(entry.roleCmds) }));
87
+
88
+ // Resolve a dispatched (backend manifest name, role) to its concrete PATH wrapper cmd (e.g.
89
+ // codex-cli-bridge + review → "codex-review") from the role-keyed registry — the backend-set aid
90
+ // consumes this to print WHICH wrapper each dispatched backend runs. `null` when the pair is unknown.
91
+ export const wrapperCmdFor = (backendName, role) =>
92
+ KNOWN_BACKENDS.find((b) => b.name === backendName)?.roleCmds?.[role] ?? null;
93
+
81
94
  // ── pure helpers ─────────────────────────────────────────────────────────────
82
95
 
83
96
  // Expand a leading "~" / "~/x" against home; absolute and relative paths pass through untouched.
@@ -19,8 +19,8 @@
19
19
  import { readFileSync, lstatSync } from 'node:fs';
20
20
  import { homedir } from 'node:os';
21
21
  import { pathToFileURL } from 'node:url';
22
- import { detectBackends } from './detect-backends.mjs';
23
- import { ACTIVITIES, resolveActivityRecipe } from './recipes.mjs';
22
+ import { detectBackends, wrapperCmdFor } from './detect-backends.mjs';
23
+ import { ACTIVITIES, resolveActivityRecipe, planRecipe } from './recipes.mjs';
24
24
  import { resolveEngineDir, readEngineFragment, PROCEDURES_FRAGMENT_REL } from './engine-source.mjs';
25
25
  // The config schema/read core lives in orchestration-config.mjs (the single config contract). procedures
26
26
  // is READ-ONLY: it imports the reader + the SHARED slot/recipe validity, never the fs-writer
@@ -126,10 +126,16 @@ export const extractSection = (text, activity) => {
126
126
  // ── resolution + rendering ─────────────────────────────────────────────────────────
127
127
 
128
128
  const resolveAllSlots = ({ activity, config, detection, overrides }) =>
129
- Object.keys(ACTIVITIES[activity].slots).map((slot) => ({
130
- slot,
131
- ...resolveActivityRecipe({ config: config ?? {}, readiness: detection, activity, slot, override: overrides[slot] }),
132
- }));
129
+ Object.keys(ACTIVITIES[activity].slots).map((slot) => {
130
+ const resolved = resolveActivityRecipe({ config: config ?? {}, readiness: detection, activity, slot, override: overrides[slot] });
131
+ // The concrete wrapper set this slot's EFFECTIVE recipe dispatches (empty for solo). Reuse
132
+ // planRecipe's drift-guarded dispatch for WHICH backends, then resolve each (backend, role) to its
133
+ // manifest wrapper cmd via the bridge registry — no wrapper name is hand-composed here.
134
+ const backends = planRecipe(resolved.recipe, detection).dispatch
135
+ .map((d) => wrapperCmdFor(d.backend, d.role))
136
+ .filter(Boolean);
137
+ return { slot, ...resolved, backends };
138
+ });
133
139
 
134
140
  // An unsatisfiable EXPLICIT override is the only "warning" (loud, flagged for the agent to relay). A
135
141
  // graceful config/default degradation is reported as a per-slot reason, not a warning.
@@ -147,6 +153,35 @@ const SOURCE_LABEL = {
147
153
  override: 'from --override',
148
154
  };
149
155
 
156
+ // The explicit wrapper set a review/execute recipe dispatches, printed beside the recipe name so the A2
157
+ // recipe-fidelity obligation ("run every named backend, every round") is mechanical at the point of use.
158
+ // ≥2 backends (Council) → the every-round reminder; exactly 1 → the lone wrapper; Solo dispatches none → ''.
159
+ const backendSetLabel = (backends) =>
160
+ !backends || backends.length === 0
161
+ ? ''
162
+ : backends.length >= 2
163
+ ? ` → run every backend every round: ${backends.join(' + ')}`
164
+ : ` → ${backends[0]}`;
165
+
166
+ // The review-loop economics block (M1 + M6's firing half) — printed when the activity engages a review
167
+ // backend (a slot resolving reviewed | council) and OMITTED for solo. It paraphrases the §9 +
168
+ // orchestration §4 canon (no rival rule): the ≤2-round architecture cap, the bar met by RAISING a
169
+ // surviving major to an acceptance invariant (not exhausting prose), backend divergence = the crossover
170
+ // stop, the thin-plan/diff-review carve-out, a self-consistency read before every re-review, and the
171
+ // REQUIRED per-round structured emission {round N · finding-origin tally · per-backend verdict}. Only a
172
+ // review slot can resolve reviewed|council (execute floors at solo|delegated), so gate on the recipe.
173
+ const REVIEW_RECIPES = new Set(['reviewed', 'council']);
174
+ const reviewLoopAdvice = (slots) =>
175
+ slots.some((s) => REVIEW_RECIPES.has(s.recipe))
176
+ ? [
177
+ 'Review-loop economics (planning.md §9 · orchestration.md §4) — the review this recipe runs:',
178
+ ' • Cap architecture plan-review at ≤2 rounds; the bar is met by RAISING a surviving major to an acceptance invariant (or handing it to Execute/diff-review), never by exhausting the strictest backend.',
179
+ ' • Backend divergence (one backend grounded-ships while another keeps revising mechanics) IS the crossover stop.',
180
+ ' • Route an all-mechanics/CI or prose-only artifact to a thin plan + diff-review; run a self-consistency read before every re-review.',
181
+ ' • Each round MUST emit {round N · finding-origin tally (first-draft / fold-induced / mechanics) · per-backend verdict} so the crossover is a computed signal.',
182
+ ]
183
+ : [];
184
+
150
185
  const formatHuman = ({ activity, section, slots, warnings }) => {
151
186
  const lines = [
152
187
  section,
@@ -155,9 +190,11 @@ const formatHuman = ({ activity, section, slots, warnings }) => {
155
190
  ];
156
191
  for (const s of slots) {
157
192
  const arrow = s.degradedFrom ? ` (requested ${s.degradedFrom} → degraded)` : '';
158
- lines.push(` ${s.slot}: ${s.recipe} — ${SOURCE_LABEL[s.source]}${arrow}`);
193
+ lines.push(` ${s.slot}: ${s.recipe} — ${SOURCE_LABEL[s.source]}${arrow}${backendSetLabel(s.backends)}`);
159
194
  if (s.reason) lines.push(` ↳ ${s.reason}`);
160
195
  }
196
+ const advice = reviewLoopAdvice(slots);
197
+ if (advice.length) lines.push('', ...advice);
161
198
  if (warnings.length) {
162
199
  lines.push('', 'warnings:');
163
200
  for (const w of warnings) lines.push(` ⚠ ${w}`);
@@ -169,8 +206,9 @@ const buildJson = ({ activity, section, slots, configSource, warnings }) => ({
169
206
  activity,
170
207
  section,
171
208
  slots: Object.fromEntries(
172
- slots.map((s) => [s.slot, { recipe: s.recipe, source: s.source, degradedFrom: s.degradedFrom, reason: s.reason }]),
209
+ slots.map((s) => [s.slot, { recipe: s.recipe, source: s.source, degradedFrom: s.degradedFrom, reason: s.reason, backends: s.backends }]),
173
210
  ),
211
+ reviewLoop: reviewLoopAdvice(slots),
174
212
  configSource,
175
213
  warnings,
176
214
  });