@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 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 `architecture.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 three at session start and append to them; the toolkit only seeds the blank files once. Editing them is expected.
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dalzoubi/dev-agents-sync",
3
- "version": "2.0.26",
3
+ "version": "2.0.28",
4
4
  "type": "module",
5
5
  "description": "CLI that syncs managed dev-agent prompts into consumer repos (.claude/ and/or .cursor/).",
6
6
  "license": "UNLICENSED",
package/src/hooks.mjs CHANGED
@@ -11,8 +11,15 @@
11
11
 
12
12
  import { DEFAULT_HOOK_SCRIPTS, mergeHookSettings } from './settings.mjs';
13
13
 
14
- /** True for a FileMap key that is a managed hook script (claude/hooks/*.sh). */
15
- function isHookKey(relKey) {
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(isHookKey).map(toConsumerHookPath);
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`) are
5
- * a persistent, CONSUMER-OWNED memory layer. Agents read all three at session
6
- * start and append to them; the toolkit seeds blank scaffolds ONCE and then never
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 three steering scaffold files and their blank/minimal seed bodies. */
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 three blank steering scaffold files when .claude/steering/ is absent.
9
- * B2. update writes three blank steering scaffold files when .claude/steering/ is absent.
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 three steering file names the spec requires. */
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 three scaffold files when absent', async () => {
140
- // No steering/ pre-exists. init must create all three.
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 three scaffold files when absent', async () => {
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 three steering files to .claude/steering/', () => {
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 three steering files)`,
554
+ `build must emit .claude/steering/${file} (all four steering files)`,
554
555
  );
555
556
  }
556
557
  });