@event4u/agent-config 14.5.0 → 14.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.
- package/.claude-plugin/marketplace.json +1 -1
- package/CHANGELOG.md +128 -0
- package/dist/agent-src/commands/analyze/decision.md +7 -0
- package/dist/agent-src/commands/optimize/project.md +10 -0
- package/dist/agent-src/commands/roadmap/process-full.md +45 -3
- package/dist/agent-src/contexts/execution/roadmap-process-loop.md +130 -1
- package/dist/agent-src/rules/decision-revisit-gate.md +108 -7
- package/dist/agent-src/skills/adr-create/SKILL.md +25 -3
- package/dist/agent-src/skills/decision-review/SKILL.md +18 -0
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
- package/dist/cli-delegate/{chunk-ZPSXJTLI.js → chunk-P6LQDIWK.js} +15 -1
- package/dist/cli-delegate/cmd_conformance.js +1 -1
- package/dist/cli-delegate/cmd_handoff.js +1 -1
- package/dist/cli-delegate/cmd_session_recycle.js +1 -1
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +8 -8
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +1 -1
- package/dist/discovery/dormancy-report.md +1 -1
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +2 -2
- package/dist/discovery/trust-report.md +1 -1
- package/dist/discovery/workspaces.json +2 -2
- package/dist/hooks/dispatch.js +334 -77
- package/dist/mcp/registry-manifest.json +2 -2
- package/dist/mcp/server.json +2 -2
- package/dist/router.json +1 -1
- package/docs/guidelines/agent-infra/engineering-memory-data-format.md +49 -0
- package/package.json +1 -1
- package/src/config/estate-count-budget.json +29 -1
- package/src/config/pack-size-budget.json +3 -2
- package/src/scripts/_lib/layer_overlap_notice.ts +85 -0
- package/src/scripts/_lib/scope_guard.sh +62 -3
- package/src/scripts/_lib/subagent_capsule.ts +81 -1
- package/src/scripts/adr/regenerate_index.ts +13 -2
- package/src/scripts/adr_cite_check.ts +424 -0
- package/src/scripts/check_adr_frontmatter.ts +187 -1
- package/src/scripts/check_single_delivery.ts +473 -0
- package/src/scripts/hooks/run_continuation_hook.ts +884 -68
- package/src/scripts/install.sh +12 -2
- package/src/scripts/memory_consolidation.ts +189 -0
- package/src/scripts/memory_eviction.ts +384 -0
- package/src/scripts/report_layer_overlap.ts +72 -0
- package/src/scripts/report_memory_pointers.ts +622 -0
- package/src/scripts/session_register_hook.ts +104 -15
|
@@ -354,8 +354,17 @@ export function claim_is_stale(
|
|
|
354
354
|
// roadmaps directory" — and it is the same check for a traversal, an absolute
|
|
355
355
|
// path, and an encoding nobody enumerated. A slug that fails it is reported
|
|
356
356
|
// stale rather than resolved, so no read happens at all.
|
|
357
|
+
// Structural, not textual. Round 6 finding 3: the previous form ANDed a
|
|
358
|
+
// `!rel.includes('..')` substring test onto the prefix check, and round 5
|
|
359
|
+
// finding 10 removed exactly that test from `resolveRoadmap` — one-sided. The
|
|
360
|
+
// two functions then disagreed about one claim string in the opposite
|
|
361
|
+
// direction: for a legal slug like `road-to-a..b` the register rendered a live
|
|
362
|
+
// claim as stale (dropping it from the collision set and disabling the
|
|
363
|
+
// duplicate-work warning) while the hook resolved it and engaged. `path.dirname`
|
|
364
|
+
// asks the only question that matters — is the result a file directly inside the
|
|
365
|
+
// roadmaps directory — and is the same check both sides now make.
|
|
357
366
|
const rel = path.normalize(path.join('agents', 'roadmaps', `${base}.md`));
|
|
358
|
-
const inside =
|
|
367
|
+
const inside = path.dirname(rel) === path.join('agents', 'roadmaps');
|
|
359
368
|
if (!inside || path.isAbsolute(base)) {
|
|
360
369
|
return true; // not a slug this repo can hold; never render it as live work
|
|
361
370
|
}
|
|
@@ -409,29 +418,98 @@ export function claim_is_stale(
|
|
|
409
418
|
* conditions, because a wrong anchor is worse than the fallback:
|
|
410
419
|
*
|
|
411
420
|
* 1. it is an existing directory;
|
|
412
|
-
* 2. it
|
|
413
|
-
*
|
|
414
|
-
*
|
|
415
|
-
*
|
|
416
|
-
* another repo would otherwise write this repo's register with a foreign
|
|
421
|
+
* 2. it resolves to the NEAREST enclosing checkout root, walking up from the
|
|
422
|
+
* reported directory;
|
|
423
|
+
* 3. that root belongs to the SAME repository — identical git common dir. A cwd
|
|
424
|
+
* in another repo would otherwise write this repo's register with a foreign
|
|
417
425
|
* branch, and the register is shared by every worktree here.
|
|
426
|
+
*
|
|
427
|
+
* ## Condition 2 used to reject a subdirectory, and that was wrong here
|
|
428
|
+
*
|
|
429
|
+
* It required the reported directory to BE a checkout root, and defended the
|
|
430
|
+
* rejection as "a session whose cwd is a subdirectory degrades to
|
|
431
|
+
* `workspace_root` — today's behaviour, never something worse". R2 round 3
|
|
432
|
+
* finding 2 measured that claim false in this repository's own layout, where
|
|
433
|
+
* worktrees live at `<parent>/.claude/worktrees/<name>` — NESTED under the
|
|
434
|
+
* parent. For a session standing at `<parent>/.claude/worktrees/wt/src`:
|
|
435
|
+
*
|
|
436
|
+
* - the degraded root is `<parent>`, i.e. equal to `workspace_root`;
|
|
437
|
+
* - so `git_dir` and `git_common_dir` taken from it are both `<parent>/.git`;
|
|
438
|
+
* - and the reported cwd is under `<parent>` as well.
|
|
439
|
+
*
|
|
440
|
+
* Every available signal then reports a healthy same-tree run for a genuine
|
|
441
|
+
* two-tree one. That is not a loss of precision, it is a confident wrong answer,
|
|
442
|
+
* which is strictly worse than the fallback the docblock was defending.
|
|
443
|
+
*
|
|
444
|
+
* The walk is bounded twice over, per the AI council's condition (2026-08-19,
|
|
445
|
+
* 2/2 convergent on this shape): it stops at the FIRST enclosing checkout root,
|
|
446
|
+
* so a nested worktree is found before the parent that contains it, and the
|
|
447
|
+
* same-repository check is retained on whatever it finds — a cwd inside an
|
|
448
|
+
* unrelated repo nested in this tree resolves to that repo's root, fails the
|
|
449
|
+
* identity check, and falls back. Paths are canonicalised before the walk so a
|
|
450
|
+
* symlinked cwd cannot walk a different chain than the one it names.
|
|
418
451
|
*/
|
|
419
452
|
export function session_checkout(
|
|
420
453
|
workspace_root: string,
|
|
421
454
|
payload_cwd: string | null | undefined,
|
|
422
455
|
): string {
|
|
456
|
+
// EVERY branch returns a canonical path, resolve and fallback alike.
|
|
457
|
+
//
|
|
458
|
+
// Round 4 finding 5: the resolve branch realpath-normalised and the four
|
|
459
|
+
// fallback branches returned `workspace_root` verbatim, so under a repo
|
|
460
|
+
// reached through a symlinked ancestor two sessions in the SAME working tree
|
|
461
|
+
// stored different strings for it — `/private/var/…/repo` from the resolver
|
|
462
|
+
// and `/var/…/repo` from the envelope. `foreign_sessions_block` compares the
|
|
463
|
+
// stored forms with `path.resolve`, which does not follow symlinks, so it read
|
|
464
|
+
// them as different worktrees and printed the benign "separate trees" note
|
|
465
|
+
// where the same-worktree COLLISION prompt belongs. The walk-up widened the
|
|
466
|
+
// exposure by moving subdirectory sessions onto the normalising branch.
|
|
467
|
+
const fallback = canonical(workspace_root);
|
|
423
468
|
const cwd = String(payload_cwd ?? '').trim();
|
|
424
|
-
if (cwd === '') return
|
|
469
|
+
if (cwd === '') return fallback;
|
|
470
|
+
let start: string;
|
|
425
471
|
try {
|
|
426
|
-
if (!fs.statSync(cwd).isDirectory()) return
|
|
472
|
+
if (!fs.statSync(cwd).isDirectory()) return fallback;
|
|
473
|
+
start = fs.realpathSync(cwd);
|
|
427
474
|
} catch {
|
|
428
|
-
return
|
|
475
|
+
return fallback;
|
|
429
476
|
}
|
|
430
|
-
|
|
431
|
-
|
|
477
|
+
const root = nearest_checkout_root(start);
|
|
478
|
+
if (root === null) return fallback;
|
|
479
|
+
const mine = git_common_dir(root);
|
|
432
480
|
const theirs = git_common_dir(workspace_root);
|
|
433
|
-
if (mine === null || theirs === null || mine !== theirs) return
|
|
434
|
-
return
|
|
481
|
+
if (mine === null || theirs === null || mine !== theirs) return fallback;
|
|
482
|
+
return root;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
/** `realpath` that falls back to an absolute form when the path is unreadable. */
|
|
486
|
+
function canonical(p: string): string {
|
|
487
|
+
const abs = path.resolve(p);
|
|
488
|
+
try {
|
|
489
|
+
return fs.realpathSync(abs);
|
|
490
|
+
} catch {
|
|
491
|
+
return abs;
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
/**
|
|
496
|
+
* The nearest enclosing directory that is a checkout root, or `null`.
|
|
497
|
+
*
|
|
498
|
+
* The iteration cap is a loop guard, not a policy: `path.dirname` is a fixed
|
|
499
|
+
* point at the filesystem root, so the terminating condition is the unchanged
|
|
500
|
+
* path and the counter only bounds a pathological filesystem. The FIRST hit
|
|
501
|
+
* wins, which is what makes a nested worktree resolve to itself rather than to
|
|
502
|
+
* the checkout it sits inside.
|
|
503
|
+
*/
|
|
504
|
+
function nearest_checkout_root(start: string): string | null {
|
|
505
|
+
let dir = start;
|
|
506
|
+
for (let i = 0; i < 64; i++) {
|
|
507
|
+
if (git_dir(dir) !== null) return dir;
|
|
508
|
+
const up = path.dirname(dir);
|
|
509
|
+
if (up === dir) return null;
|
|
510
|
+
dir = up;
|
|
511
|
+
}
|
|
512
|
+
return null;
|
|
435
513
|
}
|
|
436
514
|
|
|
437
515
|
/**
|
|
@@ -619,8 +697,19 @@ export function foreign_sessions_block(
|
|
|
619
697
|
// `session_checkout`. Before that every record claimed the main checkout, so
|
|
620
698
|
// every collision looked like the dangerous one.
|
|
621
699
|
if (branch_hit !== null) {
|
|
622
|
-
|
|
623
|
-
|
|
700
|
+
// Compared through `canonical`, not `path.resolve`, because resolve does not
|
|
701
|
+
// follow symlinks — round 5 finding 11. Round 4 finding 5 made every
|
|
702
|
+
// `session_checkout` branch canonical, which fixes records written from now
|
|
703
|
+
// on; it does nothing for a record already in the register from before the
|
|
704
|
+
// upgrade, and those live for the whole TTL window. Under a symlinked
|
|
705
|
+
// ancestor such a peer holds `/var/…/repo` while this session holds
|
|
706
|
+
// `/private/var/…/repo`, and comparing the raw strings reads two sessions
|
|
707
|
+
// in ONE working tree as separate trees — printing the benign note where
|
|
708
|
+
// the collision prompt belongs. Canonicalising at the comparison closes the
|
|
709
|
+
// upgrade boundary the writer side cannot reach.
|
|
710
|
+
const peer_tree = canonical(branch_hit.record.worktree ?? '');
|
|
711
|
+
const same_tree =
|
|
712
|
+
(branch_hit.record.worktree ?? '') !== '' && peer_tree === canonical(workspace_root);
|
|
624
713
|
if (same_tree) {
|
|
625
714
|
parts.push(
|
|
626
715
|
'',
|