@sabaiway/agent-workflow-memory 4.7.0 → 5.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 +27 -0
- package/SKILL.md +1 -1
- package/capability.json +1 -1
- package/package.json +1 -1
- package/references/scripts/spec-schema.mjs +5 -1
- package/references/scripts/spec-schema.test.mjs +8 -0
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,33 @@ 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
|
+
## 5.0.0 — the scenario floor: a contract can no longer pin NOTHING (AD-117)
|
|
8
|
+
|
|
9
|
+
The reader enforced a minimum on `## Out of scope` and none on `## Scenarios`. A `kind: spec`
|
|
10
|
+
document could therefore carry an EMPTY scenario section and pass everything — the reader, both
|
|
11
|
+
`spec-check` lanes, the gate row. Measured cost, from writing the layer's first real specs: three
|
|
12
|
+
stub specs would have satisfied every mechanical check of that slice and delivered nothing.
|
|
13
|
+
|
|
14
|
+
> ### ⚠ BREAKING — the reader refuses a document it used to accept
|
|
15
|
+
>
|
|
16
|
+
> `SPEC_SCHEMA.rules` gains ONE frozen rule, **`scenarios-empty`**, in table position between
|
|
17
|
+
> `scenario-path` and `out-of-scope`: a `## Scenarios` section carrying no scenario line is now an
|
|
18
|
+
> error. The rule list is a frozen ordered contract, so a consumer that deep-equals it sees a 34th
|
|
19
|
+
> id, and a deployment's spec gate can turn red with no edit of its own. The remedy is one line per
|
|
20
|
+
> scenario — `- S<N> <name> :: unbound` while no test pins it.
|
|
21
|
+
|
|
22
|
+
- **`*(empty)*` is deliberately NOT an escape here.** Written under `## Scenarios` it still refuses,
|
|
23
|
+
as `scenario-line`, and a fixture now pins that. The asymmetry with `## Out of scope` (where the
|
|
24
|
+
marker IS the decision) is the point: an empty exclusion list is a claim, an empty scenario list is
|
|
25
|
+
an absence, and the grammar already carries the honest form for the absence.
|
|
26
|
+
- **`unbound` accepts on every status** — `draft`, `live` and `retired` alike — so the floor costs a
|
|
27
|
+
spec nothing but the statement that a scenario exists.
|
|
28
|
+
- Measured before shipping: no document in the fixture corpus, the live store or the shipped
|
|
29
|
+
templates carries an empty section, so the floor refuses nothing that already exists.
|
|
30
|
+
- The other 33 rule ids, every existing refusal and the whole `structure` extraction stay
|
|
31
|
+
behaviour-identical. The new arm was red-proofed against the pre-change reader.
|
|
32
|
+
|
|
33
|
+
|
|
7
34
|
## 4.7.0 — the reader's verdict gains the additive `structure` extraction (AD-114)
|
|
8
35
|
|
|
9
36
|
The slice-2 checker (`spec-check`, next release) must read a document's structure through the SAME
|
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: '
|
|
6
|
+
version: '5.0.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
|
+
"version": "5.0.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",
|
|
@@ -38,7 +38,7 @@ export const SPEC_SCHEMA = Object.freeze({
|
|
|
38
38
|
'frontmatter', 'frontmatter-key', 'substrate-key', 'type', 'kind', 'maxlines', 'status', 'revision',
|
|
39
39
|
'root-owns', 'slug', 'kind-path', 'root-uplink', 'title', 'section-missing', 'section-order',
|
|
40
40
|
'section-forbidden', 'fence', 'children-link', 'children-duplicate', 'fan-out', 'scenario-line',
|
|
41
|
-
'scenario-number', 'scenario-marker', 'scenario-path', 'out-of-scope', 'module-line', 'module-empty',
|
|
41
|
+
'scenario-number', 'scenario-marker', 'scenario-path', 'scenarios-empty', 'out-of-scope', 'module-line', 'module-empty',
|
|
42
42
|
'module-traversal', 'module-absolute', 'module-backslash', 'module-glob', 'module-mix', 'parts',
|
|
43
43
|
]),
|
|
44
44
|
});
|
|
@@ -238,6 +238,10 @@ const checkScenarios = (parsed, slug, status, errors, warnings) => {
|
|
|
238
238
|
}
|
|
239
239
|
scenarios.push(scenario);
|
|
240
240
|
}
|
|
241
|
+
if (scenarios.length === 0) {
|
|
242
|
+
errors.push({ rule: 'scenarios-empty', message: `at least one scenario line (\`${SPEC_SCHEMA.unboundMarker}\` while no test pins it)` });
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
241
245
|
const gap = scenarios.findIndex((scenario, i) => scenario.n !== i + 1);
|
|
242
246
|
if (gap !== -1) errors.push({ rule: 'scenario-number', message: `scenario ${gap + 1} is numbered S${scenarios[gap].n} — N runs contiguously from 1` });
|
|
243
247
|
for (const scenario of scenarios) {
|
|
@@ -131,6 +131,14 @@ describe('readSpecDocument — refuse, exactly one rule per defect', () => {
|
|
|
131
131
|
refuses(specDoc({ scenarios: ['- S1 a :: /abs/login.test.mjs :: spec:login/S1'] }), 'login.md', 'scenario-path');
|
|
132
132
|
});
|
|
133
133
|
|
|
134
|
+
it('scenarios-empty / no empty-marker escape', () => {
|
|
135
|
+
refuses(specDoc({ scenarios: [] }), 'login.md', 'scenarios-empty');
|
|
136
|
+
refuses(specDoc({ scenarios: ['*(empty)*'] }), 'login.md', 'scenario-line');
|
|
137
|
+
for (const status of SPEC_SCHEMA.statuses) {
|
|
138
|
+
expect(readSpecDocument(specDoc({ scenarios: ['- S1 x :: unbound'], fields: { status } }), 'login.md').errors).toEqual([]);
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
|
|
134
142
|
it('out-of-scope / module-empty / module-* path refusals / module-mix / parts', () => {
|
|
135
143
|
refuses(specDoc({ outOfScope: '' }), 'login.md', 'out-of-scope');
|
|
136
144
|
refuses(specDoc({ outOfScope: 'nothing excluded' }), 'login.md', 'out-of-scope');
|