changeledger 0.4.0 → 0.6.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.
@@ -61,6 +61,8 @@
61
61
  </div>
62
62
  </div>
63
63
 
64
+ <div id="toast-container" class="toast-container" aria-live="assertive" aria-atomic="true"></div>
65
+
64
66
  <script type="module" src="/app.js"></script>
65
67
  </body>
66
68
  </html>
@@ -1262,3 +1262,286 @@ body {
1262
1262
  padding: 8px 8px;
1263
1263
  }
1264
1264
  }
1265
+
1266
+ /* config editor tabs and form (113924) */
1267
+ .config-section {
1268
+ border-bottom: 1px solid var(--line);
1269
+ }
1270
+ .config-tabs {
1271
+ display: flex;
1272
+ gap: 2px;
1273
+ padding: 12px 20px 0;
1274
+ border-bottom: 1px solid var(--line);
1275
+ }
1276
+ .config-tab {
1277
+ padding: 6px 14px;
1278
+ border: 1px solid transparent;
1279
+ border-bottom: none;
1280
+ border-radius: 6px 6px 0 0;
1281
+ background: transparent;
1282
+ color: var(--muted);
1283
+ cursor: pointer;
1284
+ font-size: 12px;
1285
+ font-weight: 500;
1286
+ position: relative;
1287
+ bottom: -1px;
1288
+ }
1289
+ .config-tab.active {
1290
+ background: var(--bg);
1291
+ border-color: var(--line);
1292
+ color: var(--text);
1293
+ }
1294
+ .config-form-structured {
1295
+ display: flex;
1296
+ flex-direction: column;
1297
+ gap: 0;
1298
+ }
1299
+ .config-group {
1300
+ margin: 0;
1301
+ padding: 14px 20px;
1302
+ border: none;
1303
+ border-bottom: 1px solid var(--line);
1304
+ }
1305
+ .config-group legend {
1306
+ font-size: 11px;
1307
+ font-weight: 600;
1308
+ color: var(--muted);
1309
+ padding: 0;
1310
+ margin-bottom: 8px;
1311
+ text-transform: uppercase;
1312
+ letter-spacing: 0.05em;
1313
+ }
1314
+ .config-group label {
1315
+ display: flex;
1316
+ flex-direction: column;
1317
+ gap: 4px;
1318
+ font-size: 12px;
1319
+ color: var(--muted);
1320
+ margin-bottom: 8px;
1321
+ }
1322
+ .config-group input[type="text"],
1323
+ .config-group input:not([type]) {
1324
+ padding: 6px 10px;
1325
+ border: 1px solid var(--line);
1326
+ border-radius: 6px;
1327
+ background: var(--bg);
1328
+ color: var(--text);
1329
+ font-size: 13px;
1330
+ }
1331
+ .config-group textarea {
1332
+ padding: 6px 10px;
1333
+ border: 1px solid var(--line);
1334
+ border-radius: 6px;
1335
+ background: var(--bg);
1336
+ color: var(--text);
1337
+ font-size: 12px;
1338
+ font-family: ui-monospace, monospace;
1339
+ resize: vertical;
1340
+ }
1341
+ .config-group label.config-checkbox {
1342
+ flex-direction: row;
1343
+ align-items: center;
1344
+ gap: 8px;
1345
+ color: var(--text);
1346
+ }
1347
+ .config-checkbox input[type="checkbox"] {
1348
+ width: 16px;
1349
+ height: 16px;
1350
+ accent-color: var(--accent);
1351
+ }
1352
+ .config-type-row {
1353
+ display: flex;
1354
+ align-items: center;
1355
+ gap: 16px;
1356
+ padding: 6px 0;
1357
+ margin: 0;
1358
+ border: 0;
1359
+ border-bottom: 1px solid var(--line);
1360
+ flex-wrap: wrap;
1361
+ }
1362
+ .config-type-row:last-child {
1363
+ border-bottom: none;
1364
+ }
1365
+ .config-group .config-type-row legend {
1366
+ min-width: 80px;
1367
+ font-size: 13px;
1368
+ color: var(--text);
1369
+ text-transform: none;
1370
+ letter-spacing: normal;
1371
+ margin: 0;
1372
+ }
1373
+ .config-type-row label:first-of-type {
1374
+ flex: 1 1 240px;
1375
+ }
1376
+ .config-type-row select {
1377
+ padding: 4px 8px;
1378
+ border: 1px solid var(--line);
1379
+ border-radius: 6px;
1380
+ background: var(--bg);
1381
+ color: var(--text);
1382
+ font-size: 12px;
1383
+ }
1384
+ .config-note {
1385
+ font-size: 11px;
1386
+ color: var(--muted);
1387
+ margin: 0 0 6px;
1388
+ }
1389
+ .config-readonly-note {
1390
+ font-style: italic;
1391
+ }
1392
+ .config-group-internal p {
1393
+ display: flex;
1394
+ gap: 12px;
1395
+ margin: 4px 0;
1396
+ font-size: 12px;
1397
+ }
1398
+ .config-readonly-label {
1399
+ color: var(--muted);
1400
+ font-family: ui-monospace, monospace;
1401
+ min-width: 120px;
1402
+ }
1403
+ .config-readonly-value {
1404
+ color: var(--text);
1405
+ }
1406
+ .config-migration-card {
1407
+ padding: 16px 20px;
1408
+ }
1409
+ .config-migration-card h3 {
1410
+ margin: 0 0 8px;
1411
+ font-size: 14px;
1412
+ color: #f7ab57;
1413
+ }
1414
+ .config-migration-preview {
1415
+ margin-top: 12px;
1416
+ }
1417
+ .config-migration-yaml {
1418
+ max-height: 300px;
1419
+ overflow: auto;
1420
+ padding: 10px;
1421
+ background: #0b0d11;
1422
+ border: 1px solid var(--line);
1423
+ border-radius: 6px;
1424
+ font-size: 11px;
1425
+ font-family: ui-monospace, monospace;
1426
+ color: #d9e1ea;
1427
+ margin: 8px 0;
1428
+ }
1429
+ .config-migration-ok {
1430
+ color: #56d364;
1431
+ font-size: 12px;
1432
+ }
1433
+ .config-future-schema p {
1434
+ padding: 0 20px;
1435
+ font-size: 12px;
1436
+ color: var(--muted);
1437
+ }
1438
+ .config-schema-badge {
1439
+ display: inline-block;
1440
+ margin: 12px 20px 4px;
1441
+ padding: 2px 8px;
1442
+ border-radius: 4px;
1443
+ background: rgba(248, 81, 73, 0.15);
1444
+ color: #ff8078;
1445
+ font-size: 11px;
1446
+ font-weight: 600;
1447
+ }
1448
+ .config-section-note {
1449
+ padding: 0 20px;
1450
+ font-size: 11px;
1451
+ color: var(--muted);
1452
+ font-style: italic;
1453
+ }
1454
+
1455
+ /* Native confirm dialog (cl-confirm-dialog) */
1456
+ .cl-confirm-dialog {
1457
+ margin: auto;
1458
+ padding: 28px 28px 24px;
1459
+ min-width: 320px;
1460
+ max-width: 440px;
1461
+ background: var(--panel);
1462
+ border: 1px solid var(--line);
1463
+ border-radius: 14px;
1464
+ box-shadow: 0 24px 72px rgba(0, 0, 0, 0.55);
1465
+ color: var(--text);
1466
+ }
1467
+ .cl-confirm-dialog::backdrop {
1468
+ background: rgba(4, 6, 10, 0.75);
1469
+ backdrop-filter: blur(4px);
1470
+ }
1471
+ .cl-confirm-message {
1472
+ margin: 0 0 20px;
1473
+ font-size: 14px;
1474
+ line-height: 1.55;
1475
+ color: var(--text);
1476
+ }
1477
+ .cl-confirm-actions {
1478
+ display: flex;
1479
+ justify-content: flex-end;
1480
+ gap: 8px;
1481
+ }
1482
+
1483
+ /* Toast notifications */
1484
+ .toast-container {
1485
+ position: fixed;
1486
+ bottom: 24px;
1487
+ right: 24px;
1488
+ z-index: 100;
1489
+ display: flex;
1490
+ flex-direction: column;
1491
+ gap: 8px;
1492
+ pointer-events: none;
1493
+ }
1494
+ .toast {
1495
+ padding: 12px 16px;
1496
+ border-radius: 10px;
1497
+ font-size: 13px;
1498
+ font-weight: 500;
1499
+ max-width: 340px;
1500
+ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.45);
1501
+ animation: toast-in 0.2s ease;
1502
+ pointer-events: auto;
1503
+ }
1504
+ .toast-error {
1505
+ background: #2a1215;
1506
+ border: 1px solid rgba(248, 81, 73, 0.45);
1507
+ color: #ff8078;
1508
+ }
1509
+ .toast-info {
1510
+ background: var(--panel);
1511
+ border: 1px solid var(--line);
1512
+ color: var(--text);
1513
+ }
1514
+ @keyframes toast-in {
1515
+ from {
1516
+ opacity: 0;
1517
+ transform: translateY(8px);
1518
+ }
1519
+ to {
1520
+ opacity: 1;
1521
+ transform: translateY(0);
1522
+ }
1523
+ }
1524
+
1525
+ /* Prompt input inside confirm dialog */
1526
+ .cl-prompt-label {
1527
+ display: block;
1528
+ margin-bottom: 6px;
1529
+ color: var(--muted);
1530
+ font-size: 12px;
1531
+ }
1532
+ .cl-prompt-input {
1533
+ display: block;
1534
+ width: 100%;
1535
+ margin: 0 0 16px;
1536
+ padding: 8px 12px;
1537
+ border: 1px solid var(--line);
1538
+ border-radius: 8px;
1539
+ background: var(--bg);
1540
+ color: var(--text);
1541
+ font-size: 13px;
1542
+ box-sizing: border-box;
1543
+ }
1544
+ .cl-prompt-input:focus {
1545
+ outline: none;
1546
+ border-color: var(--accent);
1547
+ }
@@ -5,8 +5,12 @@ import { gitRefs } from '../../git.mjs';
5
5
  import { publicDir } from '../../paths.mjs';
6
6
  import { loadRepoAsync } from '../../repo.mjs';
7
7
  import {
8
+ applyConfigMigration,
8
9
  changeStatus,
10
+ patchProjectConfig,
11
+ previewConfigMigration,
9
12
  readProjectConfig,
13
+ readProjectConfigStructured,
10
14
  repairProjectPath,
11
15
  resolveProjects,
12
16
  saveProjectConfig,
@@ -87,12 +91,15 @@ export function createRequestListener(cwd, localOnly, token) {
87
91
  const route = url.pathname;
88
92
  const params = url.searchParams;
89
93
 
90
- if (
91
- req.method === 'POST' &&
92
- ['/api/status', '/api/project-config', '/api/project-path', '/api/project-remove'].includes(
93
- route,
94
- )
95
- ) {
94
+ const WRITE_ROUTES = new Set([
95
+ '/api/status',
96
+ '/api/project-config',
97
+ '/api/project-config-patch',
98
+ '/api/project-config-migrate-apply',
99
+ '/api/project-path',
100
+ '/api/project-remove',
101
+ ]);
102
+ if (req.method === 'POST' && WRITE_ROUTES.has(route)) {
96
103
  if (!isAuthorizedWrite(req, token)) {
97
104
  send(res, 403, MIME['.json'], JSON.stringify({ error: 'unauthorized write' }));
98
105
  req.destroy();
@@ -121,14 +128,17 @@ export function createRequestListener(cwd, localOnly, token) {
121
128
  }
122
129
  const { projects } = resolveProjects(cwd, localOnly);
123
130
  const options = { localOnly };
124
- const result =
125
- route === '/api/status'
126
- ? changeStatus(projects, payload)
127
- : route === '/api/project-config'
128
- ? saveProjectConfig(projects, payload, options)
129
- : route === '/api/project-path'
130
- ? repairProjectPath(projects, payload, options)
131
- : unregisterProject(projects, payload, options);
131
+ let result;
132
+ if (route === '/api/status') result = changeStatus(projects, payload);
133
+ else if (route === '/api/project-config')
134
+ result = saveProjectConfig(projects, payload, options);
135
+ else if (route === '/api/project-config-patch')
136
+ result = patchProjectConfig(projects, payload);
137
+ else if (route === '/api/project-config-migrate-apply')
138
+ result = applyConfigMigration(projects, payload);
139
+ else if (route === '/api/project-path')
140
+ result = repairProjectPath(projects, payload, options);
141
+ else result = unregisterProject(projects, payload, options);
132
142
  const { code, body } = result;
133
143
  send(res, code, MIME['.json'], JSON.stringify(body));
134
144
  } catch (error) {
@@ -154,6 +164,22 @@ export function createRequestListener(cwd, localOnly, token) {
154
164
  send(res, code, MIME['.json'], JSON.stringify(body));
155
165
  return;
156
166
  }
167
+ if (route === '/api/project-config-structured') {
168
+ const { projects } = resolveProjects(cwd, localOnly);
169
+ const { code, body } = readProjectConfigStructured(projects, params.get('project'));
170
+ send(res, code, MIME['.json'], JSON.stringify(body));
171
+ return;
172
+ }
173
+ if (route === '/api/project-config-migrate-preview') {
174
+ const { projects } = resolveProjects(cwd, localOnly);
175
+ const { code, body } = previewConfigMigration(
176
+ projects,
177
+ params.get('project'),
178
+ params.get('revision'),
179
+ );
180
+ send(res, code, MIME['.json'], JSON.stringify(body));
181
+ return;
182
+ }
157
183
  if (route === '/api/git') {
158
184
  const rawId = params.get('id');
159
185
  if (rawId && !/^[0-9]{8}-[0-9]{6}$/.test(rawId)) {
@@ -1,13 +1,17 @@
1
1
  # ChangeLedger — repo configuration
2
2
  # Repo specifics: documentation language, change types and active stages per type.
3
3
 
4
+ # Schema version — used to detect and migrate outdated configurations.
5
+ # Run `changeledger config migrate --dry-run` to inspect available migrations.
6
+ schema_version: 1
7
+
4
8
  # Language for generated documentation CONTENT. Structure (headings, keys, enums)
5
- # is always English. See AGENTS.md §8.
9
+ # is always English. See `changeledger context spec`.
6
10
  language: en
7
11
 
8
12
  # Definition of Ready policy. When true (default), changes are documented
9
13
  # test-grade and implemented via TDD; `changeledger check` warns on criteria ↔ task
10
- # coverage gaps. Set false for exploratory repos. See AGENTS.md §11.
14
+ # coverage gaps. Set false for exploratory repos. See `changeledger context spec`.
11
15
  tdd: true
12
16
 
13
17
  # Default SemVer impact for a completed change. A change may override its type
@@ -38,7 +42,8 @@ stages: [request, investigation, proposal, specification, plan, log]
38
42
 
39
43
  # Active stages per type. The viewer shows only these.
40
44
  # `review_required: true` makes the change pass through `in-review` (an
41
- # independent subagent review) before universal human validation. See AGENTS.md §5/§6.
45
+ # independent subagent review) before universal human validation. See
46
+ # `changeledger context implement` and `changeledger context review`.
42
47
  types:
43
48
  feature:
44
49
  stages: [request, investigation, proposal, specification, plan, log]
@@ -0,0 +1,6 @@
1
+ # Blocked — Resolve Before Implementing
2
+
3
+ Do not resume implementation merely because context was requested. Inspect the
4
+ blocked task and Log. If the impediment is resolved within authorized scope,
5
+ record the decision, restore the task and move `blocked → in-progress`. If it
6
+ requires scope or product judgment, ask the human. Never bypass the block.
@@ -0,0 +1,18 @@
1
+ # Closing Accepted Work
2
+
3
+ The human accepted this change. Graduate persistent truth before archiving:
4
+
5
+ - `changeledger graduate <id> <spec-slug>` creates a new spec.
6
+ - `changeledger graduate <id> <spec-slug> --into` links an existing spec and
7
+ refreshes `updated` without overwriting the spec body (the agent edits the body manually).
8
+ - `changeledger graduate <id> --skip [reason]` records that no persistent truth
9
+ changed.
10
+ - `changeledger graduate --pending` lists unresolved graduation decisions.
11
+ - `changeledger archive <id>` hides the completed record from the default board.
12
+
13
+ Specs have no lifecycle: minimal frontmatter (`title`, `updated`, `tags`) plus
14
+ free Markdown describing current capabilities, architecture or domain truth.
15
+ The change is the journey; the spec is the destination.
16
+
17
+ After closure, share a brief retrospective. New work needs a new authorized
18
+ change; `done` never reopens.
@@ -0,0 +1,71 @@
1
+ # ChangeLedger — Core Contract
2
+
3
+ Documents under `.changeledger/` are the source of truth. Code is their
4
+ reflection. Work is planned and documented before code is written.
5
+
6
+ ## Non-negotiable fast path
7
+
8
+ 1. Work starts with conversation. Read-only investigation may clarify a request,
9
+ but create no change or implementation artifact until there is enough clarity
10
+ to document faithfully **and** the human explicitly authorizes documentation. A direct request such
11
+ as “create the change” is authorization; never invent missing requirements.
12
+ 2. The human authorizes scope, approves drafts and accepts the final result. The
13
+ agent decides how to divide and execute work within that authorized scope.
14
+ 3. Capture every authorized change in `.changeledger/changes/`. The document
15
+ wins when code and documentation disagree.
16
+ 4. Never implement a `draft`. After approval, work one change at a time on a
17
+ non-main branch and commit the approved change document before code.
18
+ 5. Keep lifecycle, tasks, ownership and Log current while working.
19
+ 6. For types that require review, use a fresh clean-context reviewer before
20
+ human validation.
21
+ 7. Stop at `in-validation`. The agent never accepts on the human's behalf.
22
+ 8. After human acceptance, graduate persistent truth or record an explicit skip,
23
+ then archive the done change.
24
+
25
+ Humans consume changes in `changeledger view`; write for the rendered view.
26
+
27
+ ## Lifecycle
28
+
29
+ ```text
30
+ draft → approved → in-progress
31
+ in-progress → in-review → in-validation → done [review required]
32
+ in-progress → in-validation → done [no review required]
33
+ in-review → in-progress [review retry]
34
+ in-review → blocked → in-progress [review escalation]
35
+ in-validation → in-progress [human rejection]
36
+ (draft | approved | in-progress | blocked) → discarded
37
+ ```
38
+
39
+ - `draft`: documentation awaiting human approval; no implementation.
40
+ - `approved`: ready to start after the Git/worktree checks.
41
+ - `in-progress`: implementation underway.
42
+ - `in-review`: independent review required.
43
+ - `in-validation`: stop and wait for human acceptance or rejection.
44
+ - `blocked`: an impediment or decision needs resolution.
45
+ - `done`: terminal; the human accepted the complete result.
46
+ - `discarded`: terminal tombstone; never reopen it.
47
+
48
+ `changeledger status <id> <status>` enforces agent-owned transitions and does not accept `done` or `discarded`.
49
+ Humans approve and validate in the viewer; use
50
+ `changeledger discard <id> "<reason>"` for a discarded change. `done` and `discarded`
51
+ never reopen.
52
+
53
+ ## Context modes
54
+
55
+ Valid modes: implement, review, spec, release.
56
+
57
+ - `changeledger context spec`: author or refine a change.
58
+ - `changeledger context implement`: execute an approved change.
59
+ - `changeledger context review`: independently verify completed work.
60
+ - `changeledger context release`: plan portable delivery metadata.
61
+ - `changeledger context <change-id>`: infer the correct context from lifecycle.
62
+
63
+ ## Operational discovery
64
+
65
+ Prefer structured CLI queries before scanning files:
66
+
67
+ - `changeledger list --status approved`: find approved changes ready to implement.
68
+ - `changeledger graduate --pending`: find accepted changes whose graduation decision is unresolved.
69
+
70
+ Run `changeledger help` or `changeledger <command> --help` for exact CLI syntax.
71
+ Structure is always English; narrative content follows `.changeledger/config.yml`.
@@ -0,0 +1,5 @@
1
+ # Discarded — Terminal
2
+
3
+ This change records work explicitly decided against. Preserve its reason and
4
+ dependencies; do not implement, graduate or reopen it. Any later reconsideration
5
+ requires a new authorized change.
@@ -0,0 +1,52 @@
1
+ # Implementing an Approved Change
2
+
3
+ 1. Keep one concern per change. Work necessary for the authorized objective may
4
+ update Specification, Plan and Log. If related work materially expands observable scope, obtain explicit human
5
+ authorization before adding it; propose independent work separately.
6
+ 2. Never implement approved changes on `main`, `master`, or `dev`. Inspect the
7
+ worktree first. If unrelated changes exist, do not include them silently.
8
+ 3. Commit the approved change documentation before touching implementation code.
9
+ Implement one change at a time.
10
+ 4. Commit a completed unit before continuing when another task or shared edit makes attribution
11
+ ambiguous. Commit messages reference the id. If shared files make a combined commit
12
+ unavoidable, record it explicitly and name every change sharing the surface.
13
+ 5. Keep the change current with `changeledger task`, `changeledger log`,
14
+ `changeledger owner` and `changeledger status`.
15
+ 6. Follow the Specification exactly. Write a failing test from each criterion,
16
+ make it pass, then refactor. Do not silently drift the document.
17
+ 7. Leave no TODO/FIXME, dead code or unrelated residue without explicit agreement.
18
+ 8. When implementation and tasks are complete, move to `in-review` if the type
19
+ requires independent review; otherwise move to `in-validation` and stop.
20
+
21
+ ## Correction isolation
22
+
23
+ After review `fail --retry`, keep the candidate correction uncommitted while a
24
+ fresh clean-context reviewer checks it. If it fails again, iterate on that diff.
25
+ After `pass`, commit the confirmed correction and ledger truth before asking for
26
+ human validation.
27
+
28
+ After human rejection (`in-validation → in-progress`), keep the correction
29
+ uncommitted until the human confirms it. Do not start another task or change
30
+ while a correction waits; the worktree is the isolation boundary.
31
+
32
+ ## Triage friction at handoff; retrospect after completion
33
+
34
+ Before handing the human completed or blocked work, classify discovered
35
+ friction:
36
+
37
+ - If necessary to fulfill the purpose of an active change, update that change.
38
+ - If it is an operational step such as verify, commit, graduate or archive,
39
+ execute or record it in the current flow.
40
+ - If independent or materially larger, propose its type, title, and reason to
41
+ the human. Create the draft only after explicit authorization.
42
+ - If too vague for backlog, mention it without creating a file.
43
+
44
+ When a change reaches `done`, also share a brief retrospective with the human.
45
+
46
+ ## Useful commands
47
+
48
+ - `changeledger status <id> <status>`
49
+ - `changeledger task <id> done|block <n> [reason]`
50
+ - `changeledger log <id> "<message>"`
51
+ - `changeledger owner <id> <name|->`
52
+ - `changeledger check [id]`
@@ -0,0 +1,19 @@
1
+ # Definition of Ready
2
+
3
+ With `tdd: true`, an approved change is ready only when:
4
+
5
+ 1. Every behavioral requirement is a concrete `CRn` with actual inputs, exact
6
+ outputs/effects and literal errors. Edge cases get separate criteria.
7
+ 2. Every implementation task names target file(s)/area(s), verification, and the
8
+ criteria it satisfies. It is sized to one red-green cycle.
9
+ 3. TDD is explicit: write the failing test from the criterion, make it pass, then
10
+ refactor. The implementer chooses how, not what, to test.
11
+
12
+ Repos may configure `readiness.target_patterns` and
13
+ `readiness.verification_patterns`. For manual checks, prefer a structural rule
14
+ such as `verification_patterns: ["verify:"]`, then write evidence like
15
+ `verify: manual Android device check` instead of listing every possible manual phrase.
16
+
17
+ `changeledger check` reports missing Given/When/Then, uncovered or unknown CRs,
18
+ tasks without traceability, and CR-bearing tasks without a configured target and
19
+ verification (`draft` warnings; approved/in-progress errors).
@@ -0,0 +1,25 @@
1
+ # Portable Release Planning
2
+
3
+ - `changeledger release init <version>` adopts release tracking at an existing
4
+ stable SemVer; the baseline contains changes already done.
5
+ - `changeledger release plan [--json]` deterministically selects unreleased done
6
+ changes and calculates the next version without writing.
7
+ - `changeledger release record <version>` records exactly that plan in
8
+ `.changeledger/releases/<version>.yml`.
9
+
10
+ Defaults live under `release.impacts` in `.changeledger/config.yml`; a change may
11
+ override its type with `release_impact` (`none|patch|minor|major`).
12
+
13
+ ChangeLedger owns portable membership and SemVer. The operating agent owns
14
+ stack-specific version files, project gates, commits, tags and publishing.
15
+ Never infer that every ChangeLedger repository uses npm or GitHub.
16
+
17
+ ## Routine release preparation
18
+
19
+ Routine release preparation is operational work.
20
+ Version bumps, release manifests, quality gates, packaging, commits, tags and publishing do not require a ChangeLedger change by themselves.
21
+ Do not create a change only to group those routine steps.
22
+
23
+ If preparation reveals a functional fix, release-workflow change or persistent documentation, capture it as a separate change.
24
+ Complete that change and rerun `changeledger release plan` before `changeledger release record <version>`.
25
+ Keep this workflow stack-agnostic; do not assume npm, GitHub or specific manifest filenames.
@@ -0,0 +1,19 @@
1
+ # Independent Review
2
+
3
+ Review-required work must be checked by a fresh subagent with clean context and
4
+ a model sized to the difficulty. Independence is correctness, not an
5
+ optimization. The reviewer verifies every criterion, every Plan task, tests,
6
+ the actual diff and absence of residue; it does not trust the implementer's
7
+ summary.
8
+
9
+ Delegate for a clear reason and boundary. Do not over-shard by file or tiny edit,
10
+ and do not overlap write surfaces without an explicit integration plan.
11
+
12
+ - Pass: `changeledger review <id> pass` → `in-validation`.
13
+ - Fixable defect: `changeledger review <id> fail --retry "<reason>"` →
14
+ `in-progress`.
15
+ - Scope/decision escalation: `changeledger review <id> fail --block "<reason>"`
16
+ → `blocked` for the human.
17
+
18
+ After a retry, the correction stays uncommitted until another clean reviewer
19
+ passes it. Then commit correction + ledger before asking for human validation.