@dalzoubi/dev-agents-sync 2.0.26 → 2.0.28
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/README.md +3 -1
- package/package.json +1 -1
- package/src/hooks.mjs +10 -3
- package/src/steering.mjs +17 -5
- package/tests/steering-seed.test.mjs +10 -9
package/README.md
CHANGED
|
@@ -105,7 +105,9 @@ For the `claude` target, `init` and `update` set up two extra pieces of project
|
|
|
105
105
|
|
|
106
106
|
### Steering scaffold (consumer-owned)
|
|
107
107
|
|
|
108
|
-
The CLI seeds a blank steering scaffold under `.claude/steering/` — `decisions.md`, `glossary.md`, and `
|
|
108
|
+
The CLI seeds a blank steering scaffold under `.claude/steering/` — `decisions.md`, `glossary.md`, `architecture.md`, and `delivery-log.md` — on first run. These files are **consumer-owned**: they carry no managed-by marker, are never tracked in the lockfile, and are **never overwritten** once they exist. Agents read all four at session start and append to them; the toolkit only seeds the blank files once. Editing them is expected.
|
|
109
|
+
|
|
110
|
+
`delivery-log.md` is the feedback channel between the two agent namespaces: `deliver-document` appends one dated retrospective per shipped feature, and `define` reads that history to calibrate future estimates and cycle budgets.
|
|
109
111
|
|
|
110
112
|
### Hook scripts (managed)
|
|
111
113
|
|
package/package.json
CHANGED
package/src/hooks.mjs
CHANGED
|
@@ -11,8 +11,15 @@
|
|
|
11
11
|
|
|
12
12
|
import { DEFAULT_HOOK_SCRIPTS, mergeHookSettings } from './settings.mjs';
|
|
13
13
|
|
|
14
|
-
/**
|
|
15
|
-
|
|
14
|
+
/**
|
|
15
|
+
* True for a FileMap key that is a managed hook script (claude/hooks/*.sh).
|
|
16
|
+
*
|
|
17
|
+
* Exported so the content repo's hook-delivery contract test can assert against
|
|
18
|
+
* THIS predicate rather than a copy of the regex. The build and the CLI once
|
|
19
|
+
* held separate, silently divergent hook-path assumptions; binding the test to
|
|
20
|
+
* the real predicate is what keeps them from drifting apart again.
|
|
21
|
+
*/
|
|
22
|
+
export function isManagedHookKey(relKey) {
|
|
16
23
|
const norm = relKey.replace(/\\/g, '/');
|
|
17
24
|
return /^claude\/hooks\/.+\.sh$/.test(norm);
|
|
18
25
|
}
|
|
@@ -32,7 +39,7 @@ function toConsumerHookPath(relKey) {
|
|
|
32
39
|
* given FileMap keys. Used to record installed hooks in the lockfile.
|
|
33
40
|
*/
|
|
34
41
|
export function collectHookPaths(relKeys) {
|
|
35
|
-
const paths = relKeys.filter(
|
|
42
|
+
const paths = relKeys.filter(isManagedHookKey).map(toConsumerHookPath);
|
|
36
43
|
return [...new Set(paths)].sort();
|
|
37
44
|
}
|
|
38
45
|
|
package/src/steering.mjs
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Steering scaffold seeding.
|
|
3
3
|
*
|
|
4
|
-
* Steering files (`steering/decisions.md`, `glossary.md`, `architecture.md
|
|
5
|
-
* a persistent, CONSUMER-OWNED memory layer. Agents read
|
|
6
|
-
* start and append to them; the toolkit seeds blank
|
|
7
|
-
* rewrites them.
|
|
4
|
+
* Steering files (`steering/decisions.md`, `glossary.md`, `architecture.md`,
|
|
5
|
+
* `delivery-log.md`) are a persistent, CONSUMER-OWNED memory layer. Agents read
|
|
6
|
+
* all four at session start and append to them; the toolkit seeds blank
|
|
7
|
+
* scaffolds ONCE and then never rewrites them.
|
|
8
|
+
*
|
|
9
|
+
* This list must stay in step with `.agents/steering/` in the content repo. It
|
|
10
|
+
* is inlined rather than derived, so adding a canonical steering file without
|
|
11
|
+
* adding it here leaves consumers un-seeded — which is how `delivery-log.md`
|
|
12
|
+
* shipped to the agents but not to the CLI.
|
|
8
13
|
*
|
|
9
14
|
* Invariants enforced here:
|
|
10
15
|
* - Seed-if-absent: a file is written only when it does not already exist. An
|
|
@@ -26,7 +31,7 @@
|
|
|
26
31
|
import { existsSync, mkdirSync, writeFileSync } from 'node:fs';
|
|
27
32
|
import path from 'node:path';
|
|
28
33
|
|
|
29
|
-
/** The
|
|
34
|
+
/** The four steering scaffold files and their blank/minimal seed bodies. */
|
|
30
35
|
export const STEERING_SCAFFOLDS = {
|
|
31
36
|
'decisions.md':
|
|
32
37
|
'# Decisions\n\n' +
|
|
@@ -40,6 +45,13 @@ export const STEERING_SCAFFOLDS = {
|
|
|
40
45
|
'# Architecture\n\n' +
|
|
41
46
|
'<!-- What goes here: load-bearing architecture notes, core patterns, and constraints ' +
|
|
42
47
|
'agents should respect. Consumer-owned; keep it current. -->\n',
|
|
48
|
+
'delivery-log.md':
|
|
49
|
+
'# Delivery log\n\n' +
|
|
50
|
+
'<!-- What goes here: one dated, append-only retrospective entry per shipped feature, ' +
|
|
51
|
+
'appended by deliver-document at end-of-feature finalization. Records estimated vs actual ' +
|
|
52
|
+
'effort, pauses, recurring findings, and deferred Minor/Low findings so Define can calibrate ' +
|
|
53
|
+
'future estimates and cycle budgets against history. Consumer-owned; agents append, never ' +
|
|
54
|
+
'rewrite. -->\n',
|
|
43
55
|
};
|
|
44
56
|
|
|
45
57
|
class SteeringWriteError extends Error {
|
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
*
|
|
6
6
|
* What these tests prove (one named test per criterion — §7):
|
|
7
7
|
*
|
|
8
|
-
* B1. init writes
|
|
9
|
-
* B2. update writes
|
|
8
|
+
* B1. init writes four blank steering scaffold files when .claude/steering/ is absent.
|
|
9
|
+
* B2. update writes four blank steering scaffold files when .claude/steering/ is absent.
|
|
10
10
|
* B3. update leaves an already-edited steering/decisions.md byte-identical (seed-if-absent).
|
|
11
11
|
* B4. update leaves an already-edited steering/glossary.md byte-identical (seed-if-absent).
|
|
12
12
|
* B5. update leaves an already-edited steering/architecture.md byte-identical (seed-if-absent).
|
|
@@ -118,8 +118,8 @@ async function setupInitializedRepo(consumerDir, opts = {}) {
|
|
|
118
118
|
writeFileSync(path.join(agentsDir, 'define.md'), fixtureContent, 'utf8');
|
|
119
119
|
}
|
|
120
120
|
|
|
121
|
-
/** The
|
|
122
|
-
const STEERING_FILES = ['decisions.md', 'glossary.md', 'architecture.md'];
|
|
121
|
+
/** The four steering file names the spec requires. */
|
|
122
|
+
const STEERING_FILES = ['decisions.md', 'glossary.md', 'architecture.md', 'delivery-log.md'];
|
|
123
123
|
|
|
124
124
|
// ---------------------------------------------------------------------------
|
|
125
125
|
// B1 — init seeds steering when absent
|
|
@@ -136,8 +136,8 @@ describe('S1 steering seed — init', () => {
|
|
|
136
136
|
rmSync(consumerDir, { recursive: true, force: true });
|
|
137
137
|
});
|
|
138
138
|
|
|
139
|
-
it('B1: init creates .claude/steering/ with
|
|
140
|
-
// No steering/ pre-exists. init must create all
|
|
139
|
+
it('B1: init creates .claude/steering/ with four scaffold files when absent', async () => {
|
|
140
|
+
// No steering/ pre-exists. init must create all four.
|
|
141
141
|
await runInit(consumerDir, {
|
|
142
142
|
targets: ['claude'],
|
|
143
143
|
fetcher: makeFixtureFetcher(),
|
|
@@ -175,7 +175,7 @@ describe('S1 steering seed — update', () => {
|
|
|
175
175
|
rmSync(consumerDir, { recursive: true, force: true });
|
|
176
176
|
});
|
|
177
177
|
|
|
178
|
-
it('B2: update creates .claude/steering/ with
|
|
178
|
+
it('B2: update creates .claude/steering/ with four scaffold files when absent', async () => {
|
|
179
179
|
await setupInitializedRepo(consumerDir);
|
|
180
180
|
// The lockfile resolvedVersion is 1.0.0, but we supply 1.2.0 as the latest
|
|
181
181
|
// tag so update will run (not short-circuit as up-to-date).
|
|
@@ -529,7 +529,7 @@ describe('S1 steering seed — build.mjs emits steering to mirror without marker
|
|
|
529
529
|
);
|
|
530
530
|
});
|
|
531
531
|
|
|
532
|
-
it('B8b: build emits all
|
|
532
|
+
it('B8b: build emits all four steering files to .claude/steering/', () => {
|
|
533
533
|
const agentsDir = path.join(tmpRoot, '.agents');
|
|
534
534
|
const mirrorRoot = path.join(tmpRoot, 'mirror');
|
|
535
535
|
mkdirSync(mirrorRoot, { recursive: true });
|
|
@@ -540,6 +540,7 @@ describe('S1 steering seed — build.mjs emits steering to mirror without marker
|
|
|
540
540
|
'decisions.md': '# Decisions\n',
|
|
541
541
|
'glossary.md': '# Glossary\n',
|
|
542
542
|
'architecture.md': '# Architecture\n',
|
|
543
|
+
'delivery-log.md': '# Delivery log\n',
|
|
543
544
|
},
|
|
544
545
|
mirrorRoot,
|
|
545
546
|
);
|
|
@@ -550,7 +551,7 @@ describe('S1 steering seed — build.mjs emits steering to mirror without marker
|
|
|
550
551
|
const dest = path.join(mirrorRoot, '.claude', 'steering', file);
|
|
551
552
|
assert.ok(
|
|
552
553
|
existsSync(dest),
|
|
553
|
-
`build must emit .claude/steering/${file} (all
|
|
554
|
+
`build must emit .claude/steering/${file} (all four steering files)`,
|
|
554
555
|
);
|
|
555
556
|
}
|
|
556
557
|
});
|