@sabaiway/agent-workflow-kit 1.25.0 → 1.27.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 +75 -0
- package/README.md +13 -7
- package/SKILL.md +88 -28
- package/bin/install.mjs +74 -29
- package/capability.json +1 -1
- package/package.json +1 -1
- package/references/agents/changelog-skeleton.md +23 -0
- package/references/agents/gate-triage.md +23 -0
- package/references/agents/mechanical-sweep.md +20 -0
- package/references/contracts.md +1 -0
- package/references/scripts/archive-decisions.mjs +424 -0
- package/references/scripts/archive-decisions.test.mjs +365 -0
- package/references/scripts/install-git-hooks.mjs +1 -0
- package/references/templates/agent_rules.md +1 -0
- package/references/templates/gates.json +4 -0
- package/tools/cheap-agents.mjs +239 -0
- package/tools/commands.mjs +29 -6
- package/tools/family-members.mjs +2 -1
- package/tools/family-registry.mjs +111 -13
- package/tools/known-footprint.mjs +3 -0
- package/tools/labels.mjs +13 -0
- package/tools/procedures.mjs +19 -0
- package/tools/recipes.mjs +56 -17
- package/tools/renderers.mjs +12 -1
- package/tools/run-gates.mjs +299 -0
- package/tools/semver-lite.mjs +23 -0
- package/tools/setup-backends.mjs +143 -6
- package/tools/view-model.mjs +11 -1
package/bin/install.mjs
CHANGED
|
@@ -23,8 +23,10 @@
|
|
|
23
23
|
// member — the memory substrate (`npx @sabaiway/agent-workflow-memory@latest init`, best-effort: a
|
|
24
24
|
// failure is a loud DEGRADED success, never silent — skippable with `--no-memory`) and the
|
|
25
25
|
// methodology engine the kit reads live (`npx @sabaiway/agent-workflow-engine@latest init`, fatal —
|
|
26
|
-
// the live read STOPs without it — skippable with `--no-engine`). The bridges are
|
|
27
|
-
// `init` (
|
|
26
|
+
// the live read STOPs without it — skippable with `--no-engine`). The bridges are never PLACED by
|
|
27
|
+
// `init` (first placement stays `/agent-workflow-kit setup`, opt-in); once placed, `init` REFRESHES
|
|
28
|
+
// them from this package's own bundled copies — a purely LOCAL copy, no third server contact —
|
|
29
|
+
// skippable with `--no-bridges`. No tracking either way.
|
|
28
30
|
//
|
|
29
31
|
// Dependency-free, Node >= 18.
|
|
30
32
|
|
|
@@ -35,11 +37,22 @@ import { fileURLToPath } from 'node:url';
|
|
|
35
37
|
import { homedir } from 'node:os';
|
|
36
38
|
import { spawnSync } from 'node:child_process';
|
|
37
39
|
import { copyTreeRefresh } from '../tools/fs-safe.mjs';
|
|
40
|
+
// Dependency-free semver, shared with the family registry's bridge freshness probe (one leaf, no
|
|
41
|
+
// second drifting copy). The null-on-unparseable contract is load-bearing here: legacy installs
|
|
42
|
+
// predate any version stamp, so an unparseable side means "no gate", never a false ordering.
|
|
43
|
+
import { compareSemver } from '../tools/semver-lite.mjs';
|
|
38
44
|
// The ONE registry of family members (npm packages, kinds). The init-refresh cascade derives its
|
|
39
45
|
// membership from this table — no second source of "who gets refreshed" — so it can't drift from the
|
|
40
46
|
// manifests (a drift-guard test pins the derivation). Imported from the DATA LEAF (family-members.mjs),
|
|
41
|
-
// NOT family-registry.mjs
|
|
47
|
+
// NOT family-registry.mjs. Leanness note: the bridge-refresh driver below does pull in the backend
|
|
48
|
+
// detector + the manifest validator (setup-backends' imports), but still NOT the status/presenter
|
|
49
|
+
// graph (family-registry, renderers, recipes) — the npx cold-start path stays presenter-free.
|
|
42
50
|
import { FAMILY_MEMBERS } from '../tools/family-members.mjs';
|
|
51
|
+
// The refresh-only bridge driver (shared with `/agent-workflow-kit setup --refresh-placed` and the
|
|
52
|
+
// upgrade reconcile): refreshes ONLY a bridge `setup` already placed — an absent bridge is a stated
|
|
53
|
+
// skip (never a first placement, AD-009/AD-011) and a placed bridge newer than this kit's bundled
|
|
54
|
+
// mirror is a stated skip too (never a downgrade). Every line it returns is tool-composed.
|
|
55
|
+
import { refreshPlacedBridges } from '../tools/setup-backends.mjs';
|
|
43
56
|
|
|
44
57
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
45
58
|
const PKG_ROOT = resolve(__dirname, '..');
|
|
@@ -81,22 +94,6 @@ const readVersion = async () => {
|
|
|
81
94
|
}
|
|
82
95
|
};
|
|
83
96
|
|
|
84
|
-
// Dependency-free semver: parse the leading `x.y.z` (prerelease/build ignored — kit versions are
|
|
85
|
-
// plain). compareSemver returns -1 | 0 | 1, or null when either side is unparseable (legacy installs
|
|
86
|
-
// predate any version stamp). No `let`: a small functional comparison (AGENTS.md §2.3).
|
|
87
|
-
const parseSemver = (str) => {
|
|
88
|
-
const m = typeof str === 'string' ? str.trim().match(/^(\d+)\.(\d+)\.(\d+)/) : null;
|
|
89
|
-
return m ? [Number(m[1]), Number(m[2]), Number(m[3])] : null;
|
|
90
|
-
};
|
|
91
|
-
|
|
92
|
-
const compareSemver = (a, b) => {
|
|
93
|
-
const pa = parseSemver(a);
|
|
94
|
-
const pb = parseSemver(b);
|
|
95
|
-
if (!pa || !pb) return null;
|
|
96
|
-
const firstDiff = [0, 1, 2].map((i) => (pa[i] === pb[i] ? 0 : pa[i] < pb[i] ? -1 : 1)).find((c) => c !== 0);
|
|
97
|
-
return firstDiff ?? 0;
|
|
98
|
-
};
|
|
99
|
-
|
|
100
97
|
// Extract the version that is a DIRECT child of the top-level `metadata:` key — never a top-level
|
|
101
98
|
// or deeper-nested decoy `version:` (mirrors the manifest validator's rigor; the kit ships manifest
|
|
102
99
|
// fixtures that probe exactly those decoys). Pure string walk over the frontmatter block, no deps.
|
|
@@ -157,6 +154,7 @@ const parseArgs = (argv) => {
|
|
|
157
154
|
noLaunchers: argv.includes('--no-launchers'),
|
|
158
155
|
noMemory: argv.includes('--no-memory'),
|
|
159
156
|
noEngine: argv.includes('--no-engine'),
|
|
157
|
+
noBridges: argv.includes('--no-bridges'),
|
|
160
158
|
force: argv.includes('--force'),
|
|
161
159
|
allowDowngrade: argv.includes('--allow-downgrade'),
|
|
162
160
|
dir: dirFlag >= 0 ? argv[dirFlag + 1] : undefined,
|
|
@@ -278,7 +276,7 @@ const printHelp = (version) => {
|
|
|
278
276
|
console.log(`agent-workflow-kit ${version}
|
|
279
277
|
|
|
280
278
|
Usage:
|
|
281
|
-
npx @sabaiway/agent-workflow-kit@latest init [--dir <path>] [--no-launchers] [--no-memory] [--no-engine] [--force] [--allow-downgrade]
|
|
279
|
+
npx @sabaiway/agent-workflow-kit@latest init [--dir <path>] [--no-launchers] [--no-memory] [--no-engine] [--no-bridges] [--force] [--allow-downgrade]
|
|
282
280
|
npx @sabaiway/agent-workflow-kit@latest --version
|
|
283
281
|
npx @sabaiway/agent-workflow-kit@latest --help
|
|
284
282
|
|
|
@@ -294,8 +292,10 @@ Installs/refreshes the kit at ~/.claude/skills/agent-workflow-kit
|
|
|
294
292
|
stale, refresh it yourself + restart — a miss is otherwise a non-fatal degraded success,
|
|
295
293
|
never the engine's hard STOP); --no-engine skips the engine install (the live methodology
|
|
296
294
|
read then STOPs until you install it by hand); --force replaces a pre-existing non-kit
|
|
297
|
-
launcher file (backed up first). The bridges are
|
|
298
|
-
/agent-workflow-kit setup)
|
|
295
|
+
launcher file (backed up first). The bridges are never PLACED by init (first placement
|
|
296
|
+
stays /agent-workflow-kit setup, opt-in); once placed, init refreshes them from the kit's
|
|
297
|
+
own bundled copies — local files only, never a downgrade — and --no-bridges skips that
|
|
298
|
+
refresh. init is additive — it never deletes your settings. If the
|
|
299
299
|
installed kit is newer than the version you ran, init refuses (no network — it compares
|
|
300
300
|
the version on disk) and points you at @latest; --allow-downgrade overrides that
|
|
301
301
|
refusal (distinct from --force, which is launcher-only).
|
|
@@ -376,15 +376,26 @@ const main = async () => {
|
|
|
376
376
|
console.log(`[agent-workflow-kit] removed retired file ${tildify(retired)} (now read live from the engine).`);
|
|
377
377
|
}
|
|
378
378
|
}
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
//
|
|
382
|
-
//
|
|
383
|
-
//
|
|
379
|
+
// Verb keyed on the OBSERVED version relation (cmp), never on mere presence: null (fresh install,
|
|
380
|
+
// or a legacy/unstamped one whose prior version is unknowable) → "installed"; -1 → a real update;
|
|
381
|
+
// 0 → already current (the copy still ran — see the note below); 1 is reachable only under
|
|
382
|
+
// --allow-downgrade (the gate above refused otherwise) and says so plainly. One message contract
|
|
383
|
+
// with the engine installer (same shapes, member noun differs).
|
|
384
|
+
const verb =
|
|
385
|
+
cmp === 0 ? 'refreshed the already-current kit'
|
|
386
|
+
: cmp === 1 ? 'downgraded the kit to'
|
|
387
|
+
: cmp === -1 ? 'updated the kit to'
|
|
388
|
+
: 'installed';
|
|
389
|
+
console.log(`[agent-workflow-kit] ${verb} v${version} -> ${tildify(target)}`);
|
|
390
|
+
|
|
391
|
+
// Same-version re-run: state observable facts only. The copy DID run (repair-on-rerun is a feature —
|
|
392
|
+
// it restores locally modified/deleted files), and whether npx served a cached build is NOT
|
|
393
|
+
// observable here (no network), so the note never claims it; the @latest hint is conditional.
|
|
384
394
|
if (cmp === 0) {
|
|
385
395
|
console.log(
|
|
386
|
-
`[agent-workflow-kit] note:
|
|
387
|
-
`
|
|
396
|
+
`[agent-workflow-kit] note: the kit was already v${version} — the copy still ran, restoring ` +
|
|
397
|
+
`any locally modified or deleted kit file to this version's packaged contents. If you ` +
|
|
398
|
+
`expected a NEWER version, invoke the @latest tag explicitly:\n` +
|
|
388
399
|
` npx @sabaiway/agent-workflow-kit@latest init`,
|
|
389
400
|
);
|
|
390
401
|
}
|
|
@@ -404,6 +415,40 @@ const main = async () => {
|
|
|
404
415
|
}
|
|
405
416
|
}
|
|
406
417
|
|
|
418
|
+
// Placed-bridge refresh — AFTER the kit copy (the bundled bridges/ just landed), BEFORE the two
|
|
419
|
+
// network cascade steps (this one is LOCAL files only: bundle → placed copy). Refresh-only, so the
|
|
420
|
+
// AD-009/AD-011 honesty claim survives as "init never PLACES bridges; it refreshes what setup
|
|
421
|
+
// already placed" — an absent bridge is a stated skip, a placed-newer one a stated skip too (never
|
|
422
|
+
// a downgrade). Best-effort in the memory DEGRADED shape: any miss is a loud warning + a
|
|
423
|
+
// host-runnable recovery composed from the RESOLVED target (a --dir / AGENT_WORKFLOW_KIT_DIR
|
|
424
|
+
// install must get a line that runs) + exit 0 — never silent, never the engine's hard STOP.
|
|
425
|
+
const bridgeRefreshCmd = `node ${tildify(resolve(target, 'tools/setup-backends.mjs'))} --refresh-placed`;
|
|
426
|
+
if (args.noBridges) {
|
|
427
|
+
console.log(
|
|
428
|
+
`[agent-workflow-kit] --no-bridges: skipped refreshing the placed bridges. If one is stale, ` +
|
|
429
|
+
`refresh it yourself:\n ${bridgeRefreshCmd}`,
|
|
430
|
+
);
|
|
431
|
+
} else if (process.platform === 'win32') {
|
|
432
|
+
console.log('[agent-workflow-kit] Windows: skipped the placed-bridge refresh (POSIX wrappers — refresh under WSL).');
|
|
433
|
+
} else {
|
|
434
|
+
console.log('[agent-workflow-kit] refreshing the bridges setup already placed (an absent bridge is never placed here):');
|
|
435
|
+
try {
|
|
436
|
+
const results = refreshPlacedBridges();
|
|
437
|
+
for (const r of results) console.log(r.line);
|
|
438
|
+
if (results.some((r) => r.outcome === 'failed')) {
|
|
439
|
+
console.warn(
|
|
440
|
+
`[agent-workflow-kit] could not refresh every placed bridge — continuing; the kit itself IS ` +
|
|
441
|
+
`installed and works. Re-run the refresh yourself:\n ${bridgeRefreshCmd}`,
|
|
442
|
+
);
|
|
443
|
+
}
|
|
444
|
+
} catch (err) {
|
|
445
|
+
console.warn(
|
|
446
|
+
`[agent-workflow-kit] could not refresh the placed bridges (${err.message}) — continuing; the ` +
|
|
447
|
+
`kit itself IS installed and works. Re-run the refresh yourself:\n ${bridgeRefreshCmd}`,
|
|
448
|
+
);
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
|
|
407
452
|
// Memory substrate refresh — AFTER the kit + launchers, BEFORE the (fatal) engine and the success
|
|
408
453
|
// block, so a returning `init` leaves no stale memory. Unlike the engine, a memory miss is a
|
|
409
454
|
// DEGRADED success: warn with the exact recovery command + the on-disk version (read crash-proof)
|
package/capability.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sabaiway/agent-workflow-kit",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.27.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",
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: changelog-skeleton
|
|
3
|
+
description: Cheap-lane changelog fact-skeleton — drafts the factual bones of a changelog or release-notes entry from diff/log facts. The orchestrator (frontier) writes the lead and owns the final text; use only for the mechanical draft, never for persuasive copy.
|
|
4
|
+
model: haiku
|
|
5
|
+
effort: low
|
|
6
|
+
tools: Read, Grep, Glob
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
You are a changelog-skeleton drafter on the cheap lane (L1). You turn diff facts the orchestrator
|
|
10
|
+
gives you (changed files, commit subjects, version bumps, test counts) into the FACTUAL BONES of
|
|
11
|
+
a changelog entry. The orchestrator writes the lead sentence and all user-facing framing — the
|
|
12
|
+
final wording is never yours (asymmetric pairing: cheap drafts, frontier signs).
|
|
13
|
+
|
|
14
|
+
Rules:
|
|
15
|
+
- Only facts present in the provided input or the files you are pointed at; every claim must be
|
|
16
|
+
traceable to a named file, commit, or diff hunk. Never invent a feature, a motivation, or an
|
|
17
|
+
impact statement.
|
|
18
|
+
- Structure: grouped bullet lists (Added / Changed / Fixed / Internal), each bullet naming the
|
|
19
|
+
artifact (`path`, tool, mode, version) it describes.
|
|
20
|
+
- Versions, package names, commands, and paths are quoted verbatim from the input.
|
|
21
|
+
- Mark anything uncertain as `VERIFY:` rather than asserting it.
|
|
22
|
+
- No superlatives, no persuasion, no summary paragraph — that is the frontier's red-line work.
|
|
23
|
+
- Read-only: you never modify files.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: gate-triage
|
|
3
|
+
description: Cheap-lane gate-failure triage — reads failing gate/test output and produces a structured classification (which gate, first real error, implicated files) for the orchestrator to act on. Use to digest long failing output, never to fix code or decide what to do.
|
|
4
|
+
model: haiku
|
|
5
|
+
effort: low
|
|
6
|
+
tools: Read, Grep, Glob
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
You are a gate-triage agent on the cheap lane (L1). You digest FAILING verification output (a
|
|
10
|
+
gate runner table, a test-suite log, a validator report) into a compact, structured triage the
|
|
11
|
+
orchestrator can act on. You never fix anything and never decide what to do next.
|
|
12
|
+
|
|
13
|
+
Rules:
|
|
14
|
+
- For each failing gate/test, report: the gate/test id · the FIRST real error line (quoted
|
|
15
|
+
verbatim) · the implicated `file:line` if the output names one · the failure class
|
|
16
|
+
(assertion / crash / timeout / missing-file / config).
|
|
17
|
+
- Separate signal from noise: strip repeated stack frames and progress spam; keep the shortest
|
|
18
|
+
quote that still identifies the failure.
|
|
19
|
+
- Preserve counts exactly as printed (`N passed, M failed`) — never recompute or estimate.
|
|
20
|
+
- If output is truncated or ambiguous, say so (`TRUNCATED` / `AMBIGUOUS`) — never guess a cause.
|
|
21
|
+
- Output: one section per failing gate, ordered as the run reported them. No fix suggestions,
|
|
22
|
+
no root-cause speculation beyond the failure class, no code.
|
|
23
|
+
- Read-only: you never modify files, never re-run commands.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: mechanical-sweep
|
|
3
|
+
description: Cheap-lane extraction sweeps — inventories, session-record extraction, doc checklists, multi-file fact collection. Use for mechanical reading at scale, never for judgment, code review, or writing code.
|
|
4
|
+
model: haiku
|
|
5
|
+
effort: low
|
|
6
|
+
tools: Read, Grep, Glob
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
You are a mechanical extraction agent on the cheap lane (L1). Your job is READING AT SCALE and
|
|
10
|
+
returning structured facts — never conclusions, never opinions, never code.
|
|
11
|
+
|
|
12
|
+
Rules:
|
|
13
|
+
- Extract exactly what was asked: inventories, lists, counts, quoted lines, checklist states.
|
|
14
|
+
- Cite every fact as `file:line` (or `file` for whole-file facts) so the orchestrator can verify
|
|
15
|
+
it deterministically. A fact you cannot cite does not go in the output.
|
|
16
|
+
- Quote verbatim; never paraphrase an identifier, version, command, or path.
|
|
17
|
+
- If a requested item is absent, say `ABSENT` explicitly — never guess, never fill gaps.
|
|
18
|
+
- Output format: the structure the prompt asks for (list / table / JSON). No preamble, no
|
|
19
|
+
commentary, no recommendations — the orchestrator applies judgment, you supply facts.
|
|
20
|
+
- Read-only: you never modify files, never run commands, never propose edits.
|
package/references/contracts.md
CHANGED
|
@@ -26,6 +26,7 @@ diverge:
|
|
|
26
26
|
| Pattern | Owner | Kind | Commit-risk name? | Note |
|
|
27
27
|
|---|---|---|---|---|
|
|
28
28
|
| `/.claude/skills/` | Claude Code | dir | no | local-dev skills; absorbs the AD-013 one-off |
|
|
29
|
+
| `/.claude/agents/` | Claude Code | dir | no | project subagent definitions (incl. the kit-placed cheap-lane vehicles) |
|
|
29
30
|
| `/.cursor/rules/` | Cursor | dir | no | project rule files |
|
|
30
31
|
| `/.cursorrules` | Cursor (legacy) | file | **yes** | legacy single-file rules |
|
|
31
32
|
| `/.codeium/` | Codeium/Windsurf | dir | no | home-scoped launchers live under `~/`, out of scope |
|