@sabaiway/agent-workflow-memory 3.1.0 → 3.2.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,17 @@ All notable changes to the memory substrate. Versions are this **package's** npm
|
|
|
4
4
|
they are distinct from the **deployment-lineage** stamp written into a project's
|
|
5
5
|
`docs/ai/.memory-version` (which tracks the shared `agent-workflow` lineage, head `3.0.0`).
|
|
6
6
|
|
|
7
|
+
## 3.2.0 — the ADR rotation can be asked whether a seed is safe, without seeding (AD-083)
|
|
8
|
+
|
|
9
|
+
`archive-decisions.mjs --write-navigator` now honours `--dry-run`. It runs exactly the checks the
|
|
10
|
+
real write runs — the heading parse, the half-migrated guard, and the store-integrity check — and
|
|
11
|
+
then stops before touching anything, reporting how many decisions it validated.
|
|
12
|
+
|
|
13
|
+
Why it exists: a guarded caller (the kit's ADR-store migration) had no way to find out whether
|
|
14
|
+
seeding the store would succeed except by seeding it. A tree with a malformed decisions file could
|
|
15
|
+
therefore be told «go ahead», and only discover the problem after files had been written. The same
|
|
16
|
+
code now answers that question first. Nothing about the normal `--write-navigator` behaviour changes.
|
|
17
|
+
|
|
7
18
|
## 3.1.0 — plain-language communication bar in §2.5 of the agent_rules template (AD-061)
|
|
8
19
|
|
|
9
20
|
The `agent_rules.md` template's **§2.5 Communication** section gains a plain-language bar: every
|
package/SKILL.md
CHANGED
|
@@ -3,7 +3,7 @@ name: agent-workflow-memory
|
|
|
3
3
|
description: Deploy or upgrade a portable AI-agent memory substrate in any project — an entry-point `AGENTS.md` (+ `CLAUDE.md` alias) and a structured `docs/ai/` context store with cap/archive/index enforcement. Use when the user wants to bootstrap `docs/ai/`, set up the Memory Map and session protocols, install the docs-rotation pre-commit hook, or run `/agent-workflow-memory` / `/agent-workflow-memory upgrade`. Triggers on "set up the memory system", "deploy the AI memory here", "bootstrap docs/ai", "upgrade the memory substrate". This is the substrate only — the workflow methodology (plan→execute→review, queue, Cleanup) is owned elsewhere and injected into AGENTS.md by the family composition root.
|
|
4
4
|
disable-model-invocation: true
|
|
5
5
|
metadata:
|
|
6
|
-
version: '3.
|
|
6
|
+
version: '3.2.0'
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
# agent-workflow-memory
|
package/capability.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sabaiway/agent-workflow-memory",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.2.0",
|
|
4
4
|
"description": "Portable, cross-agent memory substrate for AI coding agents — an AGENTS.md entry point + docs/ai context with cap/archive/index enforcement, deployable standalone or as part of the agent-workflow family. The memory layer of the agent-workflow family.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai-agents",
|
|
@@ -29,7 +29,10 @@
|
|
|
29
29
|
// HOT preamble, and only THEN removes the monoliths — gated on conservation AND
|
|
30
30
|
// the snapshot. Re-run skips byte-identical records (crash-resumable).
|
|
31
31
|
// --write-navigator regenerate docs/ai/adr/log.md AND re-trigger the index regen (the authoring /
|
|
32
|
-
// supersession write-side; the --write-index analog).
|
|
32
|
+
// supersession write-side; the --write-index analog). With --dry-run it runs
|
|
33
|
+
// EXACTLY the same validation (parse, half-migrated guard, store integrity) and
|
|
34
|
+
// stops before every write — the read-only preflight a guarded caller needs to
|
|
35
|
+
// earn a go-ahead without risking a partial write.
|
|
33
36
|
// --dry-run print the planned rotation move-set, change nothing.
|
|
34
37
|
// --today=YYYY-MM-DD pin the lastUpdated stamp (tests / reproducible runs).
|
|
35
38
|
//
|
|
@@ -693,7 +696,7 @@ const runMigrate = (root, flags, today, deps, log, logError) => {
|
|
|
693
696
|
return 0;
|
|
694
697
|
};
|
|
695
698
|
|
|
696
|
-
const runWriteNavigator = (root, today, deps, log, logError) => {
|
|
699
|
+
const runWriteNavigator = (root, flags, today, deps, log, logError) => {
|
|
697
700
|
if (!existsSync(resolve(root, HOT_REL)) && !existsSync(resolve(root, ADR_DIR_REL))) {
|
|
698
701
|
log(`[archive-decisions] SKIP — no ADR substrate (neither ${HOT_REL} nor ${ADR_DIR_REL}); nothing to write.`);
|
|
699
702
|
return 0;
|
|
@@ -704,6 +707,14 @@ const runWriteNavigator = (root, today, deps, log, logError) => {
|
|
|
704
707
|
const adrEntries = loadAdrStore(root);
|
|
705
708
|
assertStoreIntegrity(hotEntries, adrEntries); // never emit a duplicate-row / corrupt navigator
|
|
706
709
|
const corpus = [...hotEntries, ...adrEntries];
|
|
710
|
+
// --dry-run runs EXACTLY the validation above and stops before every write: the parse, the
|
|
711
|
+
// half-migrated guard and the store-integrity check are the same code the write path uses, so a
|
|
712
|
+
// caller (the guarded ADR-store crossing) can earn a go-ahead without a partial write. A separate
|
|
713
|
+
// re-implementation of these checks would be an approximation that can disagree with the writer.
|
|
714
|
+
if (flags.dryRun) {
|
|
715
|
+
log(`[archive-decisions] --write-navigator DRY-RUN — no files will be changed; ${corpus.length} ADR(s) validated.`);
|
|
716
|
+
return 0;
|
|
717
|
+
}
|
|
707
718
|
writeNavigatorFile(root, corpus, today);
|
|
708
719
|
const regen = (deps.regenerateIndex ?? defaultRegenerateIndex)(root, today);
|
|
709
720
|
log(`[archive-decisions] wrote ${NAV_REL} (${corpus.length} ADRs in the corpus).`);
|
|
@@ -828,7 +839,7 @@ export const runCli = (argv, deps = {}) => {
|
|
|
828
839
|
const today = todayOpt ?? new Date().toISOString().slice(0, 10);
|
|
829
840
|
|
|
830
841
|
if (flags.migrate) return runMigrate(root, flags, today, deps, log, logError);
|
|
831
|
-
if (flags.writeNavigator) return runWriteNavigator(root, today, deps, log, logError);
|
|
842
|
+
if (flags.writeNavigator) return runWriteNavigator(root, flags, today, deps, log, logError);
|
|
832
843
|
if (flags.check) return runCheck(root, today, log, logError);
|
|
833
844
|
|
|
834
845
|
if (!existsSync(resolve(root, HOT_REL))) {
|
|
@@ -643,6 +643,33 @@ describe('1.5 navigator — governing heads (computed), superseded drop out but
|
|
|
643
643
|
assert.doesNotMatch(gov, /\| AD-002 \|/, 'the Proposed ADR is NOT a governing head (accepted & not-superseded only)');
|
|
644
644
|
});
|
|
645
645
|
|
|
646
|
+
// The read-only preflight a guarded caller needs: the SAME parse / half-migrated guard / store
|
|
647
|
+
// integrity the writer runs, stopping before every write. Without it a caller can only learn that
|
|
648
|
+
// seeding is safe by seeding.
|
|
649
|
+
it('--write-navigator --dry-run validates and writes NOTHING', () => {
|
|
650
|
+
const root = makeRoot();
|
|
651
|
+
seedMigrated(root, { hotIds: ['005', '006'], storeIds: ['001'] });
|
|
652
|
+
const navBefore = readFileSync(join(root, NAV_REL), 'utf8');
|
|
653
|
+
rmSync(join(root, NAV_REL));
|
|
654
|
+
const r = run(['--write-navigator', '--dry-run', '--today=2026-07-09'], root);
|
|
655
|
+
assert.equal(r.code, 0);
|
|
656
|
+
assert.match(r.out.join('\n'), /DRY-RUN/, 'the run states it changed nothing');
|
|
657
|
+
assert.equal(existsSync(join(root, NAV_REL)), false, 'the navigator was NOT written by the dry-run');
|
|
658
|
+
// and the real run still produces exactly what the dry-run validated
|
|
659
|
+
assert.equal(run(['--write-navigator', '--today=2026-07-09'], root).code, 0);
|
|
660
|
+
assert.equal(readFileSync(join(root, NAV_REL), 'utf8'), navBefore);
|
|
661
|
+
});
|
|
662
|
+
|
|
663
|
+
it('--write-navigator --dry-run REFUSES a corrupt store instead of green-lighting it', () => {
|
|
664
|
+
const root = makeRoot();
|
|
665
|
+
seedMigrated(root, { hotIds: ['005', '006'], storeIds: ['001'] });
|
|
666
|
+
// a record whose id also lives in the HOT window — the store would hold the ADR twice
|
|
667
|
+
writeFileSync(join(root, ADR_DIR_REL, 'AD-005-dup.md'), '---\n---\n\n## AD-005 — Dup\n\nBody.\n');
|
|
668
|
+
const r = run(['--write-navigator', '--dry-run', '--today=2026-07-09'], root);
|
|
669
|
+
assert.notEqual(r.code, 0, 'a corrupt store fails the preflight');
|
|
670
|
+
assert.doesNotMatch(r.out.join('\n'), /DRY-RUN/, 'no go-ahead is printed for a tree that cannot converge');
|
|
671
|
+
});
|
|
672
|
+
|
|
646
673
|
it('authoring a new HOT ADR then --write-navigator keeps --check green; a stale nav with NO write → exit 1, then --write-navigator fixes it', () => {
|
|
647
674
|
const root = makeRoot();
|
|
648
675
|
seedMigrated(root, { hotIds: ['005', '006'], storeIds: ['001'] });
|