@dzhechkov/harness-core 0.8.34 → 0.8.36
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/.dz-manifest.json +61 -61
- package/README.md +255 -12
- package/dist/agentdb-index.d.ts +22 -1
- package/dist/agentdb-index.d.ts.map +1 -1
- package/dist/agentdb-index.js +156 -6
- package/dist/agentdb-index.js.map +1 -1
- package/dist/apply-leg.d.ts +180 -2
- package/dist/apply-leg.d.ts.map +1 -1
- package/dist/apply-leg.js +781 -38
- package/dist/apply-leg.js.map +1 -1
- package/dist/codex-hooks-assets.d.ts.map +1 -1
- package/dist/codex-hooks-assets.js +67 -5
- package/dist/codex-hooks-assets.js.map +1 -1
- package/dist/codex-hooks.d.ts +13 -1
- package/dist/codex-hooks.d.ts.map +1 -1
- package/dist/codex-hooks.js +13 -1
- package/dist/codex-hooks.js.map +1 -1
- package/dist/index.d.ts +8 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -4
- package/dist/index.js.map +1 -1
- package/dist/mutation-gate.d.ts +19 -0
- package/dist/mutation-gate.d.ts.map +1 -1
- package/dist/mutation-gate.js +37 -1
- package/dist/mutation-gate.js.map +1 -1
- package/dist/operations.d.ts +17 -1
- package/dist/operations.d.ts.map +1 -1
- package/dist/operations.js +88 -9
- package/dist/operations.js.map +1 -1
- package/dist/publish.d.ts +59 -7
- package/dist/publish.d.ts.map +1 -1
- package/dist/publish.js +205 -32
- package/dist/publish.js.map +1 -1
- package/dist/release-line.d.ts +16 -0
- package/dist/release-line.d.ts.map +1 -1
- package/dist/release-line.js +31 -0
- package/dist/release-line.js.map +1 -1
- package/dist/setup.d.ts.map +1 -1
- package/dist/setup.js +90 -14
- package/dist/setup.js.map +1 -1
- package/dist/skills.d.ts +87 -3
- package/dist/skills.d.ts.map +1 -1
- package/dist/skills.js +266 -15
- package/dist/skills.js.map +1 -1
- package/dist/vector-tier.d.ts +34 -3
- package/dist/vector-tier.d.ts.map +1 -1
- package/dist/vector-tier.js +117 -22
- package/dist/vector-tier.js.map +1 -1
- package/package.json +2 -2
- package/sbom.json +60 -60
- package/src/agentdb-index.ts +158 -7
- package/src/apply-leg.ts +824 -38
- package/src/codex-hooks-assets.ts +67 -5
- package/src/codex-hooks.ts +13 -1
- package/src/index.ts +15 -2
- package/src/mutation-gate.ts +58 -2
- package/src/operations.ts +91 -10
- package/src/publish.ts +247 -30
- package/src/release-line.ts +32 -0
- package/src/setup.ts +81 -16
- package/src/skills.ts +303 -14
- package/src/vector-tier.ts +147 -24
package/README.md
CHANGED
|
@@ -210,7 +210,7 @@ explicit skills-only short circuit. `--no-verify` cannot authorize emission. A C
|
|
|
210
210
|
|
|
211
211
|
| Module | Exports | Purpose |
|
|
212
212
|
|---|---|---|
|
|
213
|
-
| `skills` | `loadSkillFromDir`, `listSkills`, `listSkillsDetailed`, `describeSkillLoadFailure`, `formatSkillLoadFailures`, `formatSkillApplyFailures`, `discoverSkillIds` | Read skill directories into `CanonicalSkill` objects. **Two listing functions, deliberately:** `listSkills` THROWS on the first unloadable skill and always will — it is a published export, and silently turning it into a skip-and-collect function would downgrade every unknown third-party consumer from fail-closed to fail-silent without their consent (an incomplete catalogue reported as complete); a pinned regression test asserts it still throws. `listSkillsDetailed` is the total variant callers ask for BY NAME: it returns `{skills, failures}` with a per-id `try/catch`, so one unparseable `SKILL.md` never hides the ones after it (order-independence is the tested property — the offender first, middle or last yields the same counts). Every failure is NAMED — `describeSkillLoadFailure` is the single place a pathless parser throw becomes `{id, absolute path, verbatim reason, first line}`, because the parser is handed only TEXT and can never supply a path. `formatSkillLoadFailures` renders that list for stderr in one of two modes chosen by the CALLER (absolute paths for `dz list`/`dz sync`; relative-to-package for `dz install`, where a `node_modules/**` path is not actionable) |
|
|
213
|
+
| `skills` | `loadSkillFromDir`, `listSkills`, `listSkillsDetailed`, `describeSkillLoadFailure`, `formatSkillLoadFailures`, `formatSkillApplyFailures`, `discoverSkillIds`, `walkFiles`, `isSkillJunkFile`, `SKILL_JUNK_DIRS`, `SKILL_JUNK_FILES` | Read skill directories into `CanonicalSkill` objects. **Two listing functions, deliberately:** `listSkills` THROWS on the first unloadable skill and always will — it is a published export, and silently turning it into a skip-and-collect function would downgrade every unknown third-party consumer from fail-closed to fail-silent without their consent (an incomplete catalogue reported as complete); a pinned regression test asserts it still throws. `listSkillsDetailed` is the total variant callers ask for BY NAME: it returns `{skills, failures}` with a per-id `try/catch`, so one unparseable `SKILL.md` never hides the ones after it (order-independence is the tested property — the offender first, middle or last yields the same counts). Every failure is NAMED — `describeSkillLoadFailure` is the single place a pathless parser throw becomes `{id, absolute path, verbatim reason, first line}`, because the parser is handed only TEXT and can never supply a path. `formatSkillLoadFailures` renders that list for stderr in one of two modes chosen by the CALLER (absolute paths for `dz list`/`dz sync`; relative-to-package for `dz install`, where a `node_modules/**` path is not actionable). **Symlinks and junk (feature `skills-walk-symlinks-and-junk`):** `walkFiles`, the asset-discovery loop `loadSkillFromDir` and `getSkillInfo` both run on, resolves every symlink with `statSync` before deciding whether it names a file or a directory — a `Dirent` from `readdirSync` answers `false` to BOTH `isDirectory()` and `isFile()` for a symlink entry, so trusting those two checks alone silently drops every symlinked asset (MEASURED: 2 of 4 fixture assets vanished, exit 0, before this fix). A symlink whose target cannot be `stat`'d is a *broken symlink*; a directory (reached directly or through a symlink) whose `realpath` is already on the current ANCESTOR chain ends the walk there instead of recursing — the guard tracks the recursion path, not every directory ever visited, so two non-cyclic aliases of one directory (`alias1 -> shared`, `alias2 -> shared`) are both walked under their own logical paths (Codex r2, lead fix) (`walk-guards-cycles`, its own dedicated mutation entry as of fix-round 1 — the symlink-resolution mutation alone cannot prove the guard, because disabling symlink-following ALSO stops any cycle from ever being reached), which is what stops an `a -> ..` cycle from hanging. **Containment (fix-round 1, lead item AM-8):** a symlink is followed only when its RESOLVED target's real path lies within the skill directory's own real path — `assets/secret -> /etc/hostname`, or a relative `-> ../../..` that escapes upward, is refused with reason `'symlink escapes the skill directory'` and never bundled, whether the escaping target is a file or a directory; only a `..` path COMPONENT counts as an escape — a file legitimately named `..asset` is inside the root (Codex r2, lead fix). `SKILL.md` itself gets the same check BEFORE it is read: a `SKILL.md` that is a symlink escaping the skill directory makes the whole skill REFUSED with a named error (it is mandatory, so it cannot merely be skipped); an in-tree `SKILL.md` symlink still loads (Codex r2 CRITICAL, lead fix) (an escaping directory is not recursed into either — nothing beneath it is walked). **What counts as junk IS THE PUBLISHED CONTRACT** (fix-round 1 HIGH-1 — Codex's finding that this contradicts "never drops a legitimate skill asset" is REFUTED-BY-CONTRACT, not a bug: a skill cannot ship an asset under one of these exact names, on purpose or by accident, and that is the deliberate trade this design makes, not an oversight to be widened into content-sniffing): directories `__pycache__`, `node_modules`, `.git`, `__MACOSX`, `.pytest_cache`, `.mypy_cache` (`SKILL_JUNK_DIRS`); files named exactly `.DS_Store` or `Thumbs.db`, or matching `*.pyc`, `*.pyo`, `*.swp`, `*.swo`, or `.#*` (`SKILL_JUNK_FILES` + `isSkillJunkFile`) — a trailing `~` (editor backup) is deliberately NOT on the list: it is the one pattern a legitimate asset name can plausibly end with (`notes~`), and the list is conservative by contract — a false positive would silently drop a real asset (Codex r2, lead decision). This is NOT a whitelist — any other file (including a skill author's own `notes.local.txt`) is kept as a real asset; filtering someone else's files by name is not this list's job. Every junk entry, broken symlink, escaping symlink, and detected cycle is counted and NAMED, never silently dropped: `walkFiles` returns `{files, skipped}` where `skipped` is `{path, reason}[]` and `reason` NAMES the matched pattern (`'junk file (*.pyc)'`, `'junk directory (__pycache__)'`, not a bare `'junk file'` — fix-round 1 HIGH-1(b)), and `loadSkillFromDir` threads that list onto its `CanonicalSkill` result as an *optional* `skipped` field (present only when something was actually skipped, so every existing consumer that only reads the `CanonicalSkill` shape is unaffected). An unreadable directory (`readdirSync` throwing — fix-round 1 MEDIUM-3) is *also* a named `'unreadable directory (<errno>)'` skip, never a throw out of `loadSkillFromDir`. `dz install` sums the junk-tagged entries across the installed package's skills and prints one line — `skills: skipped N junk entr(y|ies) (…)` — only when N > 0; the count is ENTRIES, not files (a skipped junk directory is one entry regardless of how many files sit underneath it, since `walkFiles` never descends into it to count those), and a directory path in the list is shown with a trailing `/` (fix-round 1 MEDIUM-4) |
|
|
214
214
|
| `apply` | `applyEmitResult` | Write an adapter `EmitResult` to disk — **additively** |
|
|
215
215
|
| `repo-boundary` | `isRepoBoundary`, `RepoBoundaryIo` | A repository boundary is a `.git` directory with a real `HEAD` file or a worktree `gitdir:` redirect; an empty or unrelated `.git` entry is not a boundary, so `dz` run from a directory such as `/tmp` with a stray empty `.git` no longer treats it as a project root (and no longer creates a `.dz` store there). Named locks are unchanged: `<root>/.dz/locks/<name>.lock`, a pure function of the root. |
|
|
216
216
|
| `targets` | `TARGETS`, `TargetName`, `isTargetName`, `resolveTargetName`, `TARGET_ALIASES`, `TARGET_NAMES_SORTED`, `formatTargetProblem`, `formatTargetAliasNote`, `normalizeTargetToken` | `--target` name → platform adapter, plus the resolution layer in front of it. `isTargetName`/`TARGETS`/`TARGET_NAMES` are UNCHANGED: `boundaries.json` names `isTargetName` as the scanned `--target` validation boundary, and every resolution ends in exactly that guard — the boundary is routed THROUGH, never relocated. `resolveTargetName` is total and pure, with fixed precedence: exact canonical → normalised canonical (case/padding/separators: `Claude_Code`, `claudecode`) → an explicit `TARGET_ALIASES` row → unique normalised prefix → Levenshtein ≤ 3 strictly better than the runner-up → nothing. **Aliases ACCEPT; prefix and Levenshtein only SUGGEST** — an alias row is an owner decision recorded in DATA (adding one is one line and zero control flow), while a fuzzy match is a guess, and installing to the wrong target on a guess is worse than one round-trip. An ambiguous prefix (`co` → `codex`/`copilot`) is terminal with NO suggestion, for the same reason. `formatTargetProblem` renders the two-line refusal, keeping the literal `--target must be one of:` substring that shipped assertions pin |
|
|
@@ -556,10 +556,13 @@ hook entry at all).
|
|
|
556
556
|
`@dzhechkov/harness-core`, or the hub's own `harnessCoreDistDir()` for its own copies) — replacing
|
|
557
557
|
a hard-coded `/usr/lib/node_modules/...` guess that failed on any other npm prefix (nvm,
|
|
558
558
|
`/usr/local`, a differently-rooted global install).
|
|
559
|
-
- `applyLegHookEntries()` — the exact `UserPromptSubmit`/`SessionStart` hook-registry
|
|
560
|
-
`runSetup` merges into `.claude/settings.json` (a swallowed non-zero exit on the recall
|
|
561
|
-
broken body never blocks a prompt; a detached `nohup` spawn for the daemon so
|
|
562
|
-
waits on the ~1.5 s model load).
|
|
559
|
+
- `applyLegHookEntries(installRoot?)` — the exact `UserPromptSubmit`/`SessionStart` hook-registry
|
|
560
|
+
entries `runSetup` merges into `.claude/settings.json` (a swallowed non-zero exit on the recall
|
|
561
|
+
hook so a broken body never blocks a prompt; a detached `nohup` spawn for the daemon so
|
|
562
|
+
`SessionStart` never waits on the ~1.5 s model load). `installRoot` — an ABSOLUTE path — bakes both
|
|
563
|
+
commands as `node "<installRoot>/.claude/helpers/<file>" …`; omitting it (every zero-arg caller
|
|
564
|
+
before feature `apply-leg-install-root`) keeps the original `${CLAUDE_PROJECT_DIR:-.}`-relative
|
|
565
|
+
form. See "Install-root resolution" below for why the absolute form exists.
|
|
563
566
|
- `applyLegStatus(root)` — the ONE measurement `dz doctor` and `dz parity` both read: do both helper
|
|
564
567
|
files exist, at what version, and does `settings.json` actually reference them? Neither surface
|
|
565
568
|
may declare the leg "installed" from a static capability table again (ADR-001 Decision 3) — a
|
|
@@ -604,6 +607,13 @@ instead of only ever checking the plain project path. The daemon also now prints
|
|
|
604
607
|
(path N bytes)` and exits non-zero, never a silent "ready" for a socket that was never created
|
|
605
608
|
(`APPLY_LEG_VERSION` bumped 3→4 for this and the resolver change).
|
|
606
609
|
|
|
610
|
+
`probeApplyLeg` (and `probeHookLiveness` beneath it) now report **`groupKillAttempted`** — whether the
|
|
611
|
+
liveness probe actually issued its process-group `SIGKILL` (attempted after EVERY probe outcome — timeout, exit, spawn error; ESRCH still counts as attempted) — as an OBSERVED field,
|
|
612
|
+
set in the `finally` right after the kill attempt and present only on branches that reached a spawn.
|
|
613
|
+
A test can therefore assert "the kill was attempted" separately from "the child is dead" instead of
|
|
614
|
+
inferring the first from the source (feature `full-suite-flake-fixes-3`, Codex HIGH-1; the mutant
|
|
615
|
+
that never reports the attempt is registry entry `probe-group-kill-attempted`).
|
|
616
|
+
|
|
607
617
|
### One recall engine for hook and CLI (`hook-recall-hybrid-parity`, ADR-001, `APPLY_LEG_VERSION` 4→5)
|
|
608
618
|
|
|
609
619
|
The daemon's `op: recall` handler used to run its own brute-force cosine loop over the in-memory
|
|
@@ -635,13 +645,105 @@ simply a second caller of the same contract.
|
|
|
635
645
|
|
|
636
646
|
`pickEngine` (the one seam `recallHybrid`, `mirrorPatternsToVector`, `teachGuard` etc. all resolve
|
|
637
647
|
their engine through) now routes through `getOrOpenEngine(projectRoot)` instead of calling
|
|
638
|
-
`resolveVectorEngine` directly — a per-process cache keyed by `(projectRoot
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
648
|
+
`resolveVectorEngine` directly — a per-process cache keyed by `realpath(projectRoot)`, invalidated
|
|
649
|
+
whenever `.dz/agentdb.db`'s mtime, size, inode, OR write-generation counter (see "Store
|
|
650
|
+
write-generation counter" below) changes, so a long-lived caller (the daemon) pays the
|
|
651
|
+
`isPackageInstalled`/`probeNativeDep` walk once, not once per prompt. A short-lived CLI invocation is
|
|
652
|
+
unaffected (the cache is populated and discarded within one process either way — I-1 parity holds).
|
|
653
|
+
`getOrOpenEngine`'s second parameter is an injectable resolver (default `resolveVectorEngine`) purely
|
|
654
|
+
for spy-testability — two functions in the same ES module cannot be reliably intercepted by
|
|
655
|
+
`vi.spyOn` when one calls the other by its local name.
|
|
656
|
+
|
|
657
|
+
### Install-root resolution (`apply-leg-install-root`, ADR-001, `APPLY_LEG_VERSION` 6→7)
|
|
658
|
+
|
|
659
|
+
Both generated files used to resolve their own store from `CLAUDE_PROJECT_DIR || cwd()` — the
|
|
660
|
+
SESSION's project, never the project the leg was actually installed into. A user-level install
|
|
661
|
+
(`dz setup --target claude-code --memory agentdb --project $HOME` — the owner's own layout, expecting
|
|
662
|
+
the leg everywhere `~/.claude/settings.json` is read) silently looked up a DIFFERENT project's `.dz/`
|
|
663
|
+
from every other session (issue #2, MEASURED on 0.8.25), and when `project === $HOME` the settings
|
|
664
|
+
command (`node "${CLAUDE_PROJECT_DIR:-.}/.claude/helpers/recall-hook.cjs"`) broke down to `Cannot
|
|
665
|
+
find module` from a foreign session, swallowed by `2>/dev/null || true`.
|
|
666
|
+
|
|
667
|
+
- **The hook and daemon now resolve `PROJECT` install-root-first.** `INSTALL_ROOT =
|
|
668
|
+
path.resolve(__dirname, '..', '..')` (the hook, `.cjs`) / `dirname(dirname(fileURLToPath(import.meta.url)))`
|
|
669
|
+
(the daemon, ESM) — the precedent is `claude-hooks-assets.ts`'s own `path.resolve(__dirname, '..',
|
|
670
|
+
'..')` for the destructive-guard hook. Order for the hook: `INSTALL_ROOT` (used when it owns a
|
|
671
|
+
`.dz/`) → `CLAUDE_PROJECT_DIR` → `cwd()`. Order for the daemon is the same shape but
|
|
672
|
+
`DZ_PROJECT_ROOT` stays the TOP override (an explicit project root always wins over the install
|
|
673
|
+
root) → `INSTALL_ROOT` → `cwd()`. The hook's existing `[dz-recall] engine=…` diagnostic line (stderr
|
|
674
|
+
only, never `additionalContext`) now also names `root=<path> (install|env|cwd)`.
|
|
675
|
+
- **`dz setup` now bakes an ABSOLUTE command.** `applyLegHookEntries(opts.projectRoot)` writes
|
|
676
|
+
`node "<installRoot>/.claude/helpers/recall-hook.cjs" …` instead of the
|
|
677
|
+
`${CLAUDE_PROJECT_DIR:-.}`-relative form — the deployed helper already bakes an absolute
|
|
678
|
+
`CORE_DIST_DIR`, so the relative command only masked that non-portability. `hookCommandInvokes` (and
|
|
679
|
+
therefore `applyLegStatus`) recognizes BOTH forms — a command is "ours" once the helper's full
|
|
680
|
+
`.claude/helpers/<file>` path follows a `node` invocation, whatever the prefix. A re-`dz setup` over
|
|
681
|
+
a pre-feature relative entry REPLACES it in place (same array position — `addIfMissing` in
|
|
682
|
+
`setup.ts` is now add-or-replace, never reorders), so an upgrade never leaves two entries for one
|
|
683
|
+
event.
|
|
684
|
+
- **Limits, named plainly.** One store per install: from a foreign project's session the hook injects
|
|
685
|
+
the INSTALL ROOT's lessons, not the session project's — that is the requested behavior (a
|
|
686
|
+
per-project store alongside a user-level one is a separate feature). The Codex host's own hook
|
|
687
|
+
(`codex-hooks-assets.ts:232`/`:373`) resolves its root from `payload.cwd || PWD || cwd()` via a
|
|
688
|
+
single shared `resolveHookRoot(payload)` and now NAMES a not-found root on stderr instead of a
|
|
689
|
+
silent early return (`codex-hook-root-provenance`, below); a live probe (T1, codex-cli 0.154.0,
|
|
690
|
+
re-run correctly in fix-round 1 — see that feature's own change manifest) found `payload.cwd`
|
|
691
|
+
always present and equal to `PWD`/`cwd()` across 3 scenarios / 6 captures, so no explicit-override
|
|
692
|
+
knob was added — a SCOPED finding, not a claim that no producer could ever send a different value.
|
|
693
|
+
|
|
694
|
+
#### Codex hook root provenance (`codex-hook-root-provenance`)
|
|
695
|
+
|
|
696
|
+
Both Codex hooks (`dz-codex-veto`, `dz-codex-recall`) share ONE `resolveHookRoot(payload)` instead of
|
|
697
|
+
two copies of the `payload.cwd || PWD || cwd()` fallback, and a `root === null` early return now
|
|
698
|
+
prints one line to stderr — `[dz-codex-<hook>] skipped reason=no-project-root start=<startDir>
|
|
699
|
+
(<source>)` — so a hook that never found a project is distinguishable from one that is silently dead;
|
|
700
|
+
a found root stays silent unless `DZ_CODEX_HOOK_DEBUG` is set. Interpolated paths are escaped (C0
|
|
701
|
+
control range + DEL) before printing, so a hostile `cwd` cannot turn the "ONE line" promise into
|
|
702
|
+
several — the tradeoff is that the line still discloses the absolute directory the hook was asked
|
|
703
|
+
about (which can embed a username or a project name) to stderr, accepted because it is a diagnostic
|
|
704
|
+
for the person running the hook, not a return value. A live probe (three real `codex exec` sessions —
|
|
705
|
+
project root, a nested subdirectory, a directory with no `.dz` anywhere — each with BOTH hook events,
|
|
706
|
+
`PreToolUse` and `UserPromptSubmit`, captured separately; corrected in fix-round 1 after the original
|
|
707
|
+
reproducer's unexported `BASE` measured the wrong file) found `payload.cwd` always correct in every
|
|
708
|
+
one of the 6 captures, so there is no `DZ_PROJECT_ROOT`-style override — stated as "not observed on
|
|
709
|
+
codex-cli 0.154.0 across 3 scenarios / 6 captures", not as a claim that the "hook read the wrong
|
|
710
|
+
project" class cannot exist elsewhere.
|
|
711
|
+
|
|
712
|
+
### Store write-generation counter (`store-generation-counter`, `agentdb-index.ts`/`vector-tier.ts`)
|
|
713
|
+
|
|
714
|
+
`getOrOpenEngine`'s cache above invalidates on `.dz/agentdb.db`'s mtime/size/inode — AM-6 already
|
|
715
|
+
covers a temp+rename replace that preserves mtime (size or inode still differs), but a write of the
|
|
716
|
+
SAME byte length landing inside the same filesystem-mtime TICK, in place (no rename), could leave
|
|
717
|
+
all three signals coincidentally unchanged, serving the daemon a stale engine that never sees the
|
|
718
|
+
lesson `dz teach` just wrote. `indexPatternsToAgentdb` (`agentdb-index.ts` — the single write seam,
|
|
719
|
+
QR-6, every `dz teach`/consolidate/reindex/brain-mirror write) now bumps a sidecar counter file,
|
|
720
|
+
`<dbFile>.generation` (atomic tmp+`wx`+rename, next to the store itself so it travels with any copy),
|
|
721
|
+
on every successful write: `bumpStoreGeneration(projectRoot, dbPath?)` reads the current value via
|
|
722
|
+
`readStoreGeneration(projectRoot, dbPath?)` (missing/corrupt file degrades to `0` — the compatibility
|
|
723
|
+
floor for a store that predates this feature; a corrupt-but-numeric-looking value like `12junk` also
|
|
724
|
+
degrades to `0` — the parse is strict, `/^\d+$/`, not `Number.parseInt`'s leading-digits tolerance)
|
|
725
|
+
and writes `current + 1`. **Every exported store mutator bumps it** on its success path, not only
|
|
726
|
+
`indexPatternsToAgentdb`: `importVectorsToAgentdb`, `clearAgentdbQuarantine`, `deleteAgentdbByDzIds`,
|
|
727
|
+
`bumpAgentdbUses` and `reindexAgentdbRows` all call the same `bumpStoreGeneration` when they actually
|
|
728
|
+
changed a row (fix-round after independent Codex review, AM-1). The read-modify-write itself runs
|
|
729
|
+
under `withNamedLockSync(dirname(dbFile), 'store-generation', …)` (`named-lock.ts` — the repo's
|
|
730
|
+
advisory lock for a read-modify-write file store, `.claude/rules/cross-runtime-concurrency.md`; same
|
|
731
|
+
`dirname(dbFile)`-addressed pattern as `agentdb-reindex-marker.ts`'s `withAgentdbSnapshotLock`), with
|
|
732
|
+
the counter RE-READ from disk inside the lock — a bare read→compute→rename would let two concurrent
|
|
733
|
+
writers both publish the same `N+1` (one bump silently lost) or let a delayed writer overwrite a
|
|
734
|
+
later value with an earlier one (AM-2). Inside `indexPatternsToAgentdb`/`importVectorsToAgentdb` the
|
|
735
|
+
bump runs IMMEDIATELY after the row commit, BEFORE `writeEmbedManifest` — if the manifest write then
|
|
736
|
+
throws, the generation is already correct for the rows already on disk (AM-3). A write failure (a
|
|
737
|
+
jammed counter path, a full disk, an unresolvable path, or a lock that could not be acquired by its
|
|
738
|
+
deadline) is reported honestly on the index result (`generationBumped: false, generationReason`) but
|
|
739
|
+
NEVER fails the store write it accompanies, and `bumpStoreGeneration` itself never throws — telemetry
|
|
740
|
+
is not a gate (FR-4/AM-2/AM-4).
|
|
741
|
+
|
|
742
|
+
`getOrOpenEngine`'s cache-invalidation stat (`AgentdbDbStat`, `vector-tier.ts`) now carries
|
|
743
|
+
`generation` as a FOURTH independent signal alongside mtime/size/inode — a monotonically increasing
|
|
744
|
+
counter can never coincidentally match a stale cache entry the way mtime/size/inode occasionally can
|
|
745
|
+
on a coarse filesystem. Both public functions are exported from the package root
|
|
746
|
+
(`readStoreGeneration`, `bumpStoreGeneration`).
|
|
645
747
|
|
|
646
748
|
`dz doctor`'s "apply-leg alive (embed daemon)" check now sends one live `op: recall` probe
|
|
647
749
|
(`probeRecallEngine`, `operations.ts`, 1000 ms default — comfortably above the 500 ms production
|
|
@@ -660,6 +762,87 @@ budget. The p95/p50/reproducer script live in
|
|
|
660
762
|
cache is `agentdb-index.ts` work, outside this feature's touched files — named here as a follow-up,
|
|
661
763
|
not silently absorbed into a passing-looking number.
|
|
662
764
|
|
|
765
|
+
### Green means injected, not merely present (`apply-leg-never-silent`, ADR-001, `APPLY_LEG_VERSION` 8→9)
|
|
766
|
+
|
|
767
|
+
Issue #2's second half: the recall hook exited 0 with NO stderr on every early-return path, and
|
|
768
|
+
`dz setup`'s own UserPromptSubmit command swallowed even a `Cannot find module` behind
|
|
769
|
+
`2>/dev/null || true` — a MEASURED state where `dz doctor` printed three green checks
|
|
770
|
+
(`apply-leg installed`, `apply-leg alive`, `memory hooks match config`) and `dz parity` printed
|
|
771
|
+
`✓ Self-learning … via UserPromptSubmit hook (auto recall)` while the leg injected nothing in every
|
|
772
|
+
session but one. Both instruments were reading FILE PRESENCE and STRUCTURAL WIRING as proof of
|
|
773
|
+
FUNCTION — the same class of defect ADR-001 Decision 3 already named for `applyLegStatus`, one layer
|
|
774
|
+
deeper.
|
|
775
|
+
|
|
776
|
+
- **The hook never exits silently now (FR-1).** Every early return in `main()` — `store-not-found`
|
|
777
|
+
(no `.dz/` under the resolved `PROJECT`), `socket-absent` (no daemon listening), `core-unavailable`
|
|
778
|
+
(`recall-hook-policy.js` unresolvable), `empty-prompt`, `no-hits` — prints exactly one line,
|
|
779
|
+
`[dz-recall] skipped reason=<reason> root=<path> (<source>) session=<path>`, on stderr before
|
|
780
|
+
returning. Exit code stays 0 — NEVER-BLOCK is unchanged; only the silence is gone.
|
|
781
|
+
- **`dz setup`'s own command no longer swallows that line (FR-2).** `applyLegHookEntries()`'s
|
|
782
|
+
UserPromptSubmit command dropped `2>/dev/null` (both the legacy relative form and the
|
|
783
|
+
`installRoot`-given absolute form); `|| true` stays, so a broken hook body still never fails a
|
|
784
|
+
prompt. **Where that line actually goes, MEASURED against the real Claude Code binary** (strings
|
|
785
|
+
extracted from `bin/claude.exe`, the `UserPromptSubmit` entry in its own hook-reference table):
|
|
786
|
+
`Exit code 0 - stdout shown to Claude` / `Exit code 2 - block processing, erase original prompt,
|
|
787
|
+
and show stderr to user only` / `Other exit codes - show stderr to user only` — on exit 0
|
|
788
|
+
(NEVER-BLOCK's exit code), stderr is named NOWHERE in that table. So the reason line is NOT for a
|
|
789
|
+
user watching Claude Code's own transcript (that channel does not exist for this hook on exit 0,
|
|
790
|
+
whatever "verbose mode" might suggest) — it is for the two readers who actually read a spawned
|
|
791
|
+
child's stderr directly: `probeApplyLeg`'s own `child_process` call below, and a human running the
|
|
792
|
+
hook by hand from a terminal.
|
|
793
|
+
- **A live, end-to-end probe replaces "files present" as the proof of function (FR-3/FR-4, ADR-001
|
|
794
|
+
Decision 1).** `probeApplyLeg(root, opts?)` — new export — spawns the REAL configured
|
|
795
|
+
UserPromptSubmit command (read back from `.claude/settings.json`, never reconstructed — a
|
|
796
|
+
reconstruction would silently stop testing the legacy relative form's own `${CLAUDE_PROJECT_DIR:-.}`
|
|
797
|
+
shell-expansion dependency) from a TEMPORARY cwd with `CLAUDE_PROJECT_DIR` pointing at that same
|
|
798
|
+
temp dir — the shape of a real session, never the project root itself. It writes a throwaway
|
|
799
|
+
"beacon" lesson into the lexical store via `recordPattern` (the same seam `dz teach` uses — no
|
|
800
|
+
embedding needed; the daemon's `recallHybrid` runs its LEXICAL leg synchronously and always, so an
|
|
801
|
+
exact-token beacon is found even under a starved hybrid budget) immediately before the probe and
|
|
802
|
+
removes it via `removePatternsByIds` in a `finally` — unconditionally, so a probe that throws,
|
|
803
|
+
times out, or never finds the leg alive still leaves the store exactly as it found it (proven by a
|
|
804
|
+
count-before == count-after test, not merely claimed). `ok: true` ONLY when the beacon's own token
|
|
805
|
+
comes back inside `additionalContext`; every other outcome is `ok: false` with a `reason` — taken
|
|
806
|
+
from the hook's own `[dz-recall] skipped reason=…` line when present (FR-1 feeding FR-3 directly),
|
|
807
|
+
else a best-effort description.
|
|
808
|
+
- `dz doctor` gains `apply-leg injects (live probe)`, evaluated whenever the existing
|
|
809
|
+
`apply-leg alive (embed daemon)` row's `applyLegWired` gate is true — green with the elapsed
|
|
810
|
+
time on success, red with the probe's `reason` on failure. A dedicated `try`/`catch`, separate
|
|
811
|
+
from the socket-alive check beside it: a probe failure must never suppress that already-useful
|
|
812
|
+
row, and vice versa.
|
|
813
|
+
- `dz parity`'s Self-learning cell now gates on `probeApplyLeg(cwd).ok`, not
|
|
814
|
+
`applyLegStatus(cwd).installed` alone — `computeParity` itself is untouched (FR-5 of the earlier
|
|
815
|
+
feature). A structurally-installed-but-silent leg reads `◐ … installed but silent: <reason>`,
|
|
816
|
+
never `✓ full`; the SAME `reason` `dz doctor`'s row prints, so the two instruments cannot
|
|
817
|
+
disagree about WHY a leg is dead, matching the fix-round-1 discipline `applyLegReasonMessage`
|
|
818
|
+
already established for `stale-version`/`unreadable`.
|
|
819
|
+
- `probeHookLiveness` (`operations.ts`) gained optional `cwd`/`env`/`timeoutMs` overrides (additive
|
|
820
|
+
— every pre-existing 2-arg call site, the Codex veto-hook liveness checks, is unaffected) and now
|
|
821
|
+
also returns `stdout` alongside `status`/`stderr`, reused by `probeApplyLeg` via a dynamic
|
|
822
|
+
`import()` rather than duplicating a `child_process` surface in `apply-leg.ts` (the core-boundary
|
|
823
|
+
IO ratchet stayed at its pinned `files:63 imports:69` — no new top-level IO import anywhere).
|
|
824
|
+
- `timeoutMs` defaults to 8000 ms. Measured (this environment, 2026-09-14/15): a
|
|
825
|
+
`store-not-found`/`socket-absent` probe returns in well under 200 ms; a live-daemon probe answers
|
|
826
|
+
in ~100-200 ms (matching ADR-001's own estimate) once warm. `dz doctor`/`dz parity` are
|
|
827
|
+
measurably slower by one probe's worth of wall time when the leg is wired — named here, not
|
|
828
|
+
hidden.
|
|
829
|
+
- **A limit, named plainly.** Under HEAVY concurrent load (this repo's own ~2700-test suite run in
|
|
830
|
+
one process), a live probe against a just-spawned daemon can occasionally exceed the hook's own
|
|
831
|
+
hardcoded 800 ms client-side socket timeout even when the daemon itself answers — a CPU-contention
|
|
832
|
+
flake, not a correctness defect; the daemon's own `HOOK_RECALL_BUDGET_MS` is independently
|
|
833
|
+
widenable, and `probeApplyLeg`'s `env` option exists for exactly this in tests. A real single
|
|
834
|
+
`dz doctor`/`dz parity` invocation never contends with 100+ concurrent test files.
|
|
835
|
+
- **Every probe beacon now carries an owner and a TTL (feature `apply-leg-daemon-hygiene`, FR-3).**
|
|
836
|
+
The pre-probe scavenger used to delete EVERY `apply-leg-probe`-domain record unconditionally,
|
|
837
|
+
which was safe against a probe killed mid-flight but WRONG the moment two probes from two
|
|
838
|
+
different sessions run against the same store concurrently — the second probe's scavenge could
|
|
839
|
+
delete the first probe's still-in-flight beacon, producing a false-red `dz doctor`/`dz parity`
|
|
840
|
+
parity check with no real defect behind it. Each beacon now embeds `probe-owner=<pid>:<startedMs>`
|
|
841
|
+
in its own text (no schema change), and `scavengeStaleProbeBeacons` (exported) removes ONLY a
|
|
842
|
+
beacon whose owner is dead (`process.kill(pid, 0)` ⇒ ESRCH) or older than 60 s — a live, in-budget
|
|
843
|
+
beacon from a different concurrent probe is left untouched. A scavenge failure is now a named fact
|
|
844
|
+
(`ApplyLegProbeResult.scavengeError`), never a swallowed exception.
|
|
845
|
+
|
|
663
846
|
## Run a plan without the Claude host
|
|
664
847
|
|
|
665
848
|
`runWorkflow` (`workflow-run.ts`) is the PURE scheduler behind `dz workflow run`: it INTERPRETS a
|
|
@@ -719,6 +902,15 @@ Four changes, each replacing a statement derived from configuration with one der
|
|
|
719
902
|
it REPLACED the lexical one, and exact matches on rare identifiers vanished. The lexical top-1 now
|
|
720
903
|
keeps a reserved seat (taken from the weakest non-`both` place, never from a hit both legs found),
|
|
721
904
|
and ties break by evidence rather than by the id alphabet.
|
|
905
|
+
- **Recall's ordering contract is score DESC → evidence → `dzId` ASC everywhere, via one exported
|
|
906
|
+
`compareHybridHits`** (`feature recall-parity-tie-break`) — `mergeHybridHits`, `dampQuarantined`,
|
|
907
|
+
and `enhance()`'s reinforcement/bandit re-rank (via `orderHitsForReRank`, its pre-sort) all share
|
|
908
|
+
it, and the comparator is total even for `NaN`/±Infinity keys (a `NaN` sorts deterministically
|
|
909
|
+
last, never a coincidental tie). The daemon's own `recall-hit` exposure write stays
|
|
910
|
+
fire-and-forget — awaiting it cost +55–131 ms per recall against a 500 ms hook budget without
|
|
911
|
+
fully closing the race anyway; parity between the daemon and `dz recall` is instead proven with a
|
|
912
|
+
byte-level store snapshot taken before the comparison, so no write can reach the read it's
|
|
913
|
+
compared against.
|
|
722
914
|
- **`HybridRecall` carries `semanticCandidates` and `semanticRanked`** — what the engine returned and
|
|
723
915
|
what actually entered the merge, so a caller can tell "the tier is empty" from "the tier returned
|
|
724
916
|
only stale ids", which need different fixes.
|
|
@@ -1087,6 +1279,17 @@ had NO mutual exclusion, and only the 10-minute grace period above stood between
|
|
|
1087
1279
|
|
|
1088
1280
|
## Status
|
|
1089
1281
|
|
|
1282
|
+
`0.8.36` — this release (night 15→16.09). Three changes live in this package: `recallHybrid` orders equal-scoring
|
|
1283
|
+
hits through ONE comparator (score desc → evidence rank → `dzId` asc, NaN last), so the embed daemon and
|
|
1284
|
+
`dz recall` agree; the apply-leg test helpers prove a daemon stop by OBSERVING `/proc` until nothing serves the
|
|
1285
|
+
root and gate every SIGKILL on a freshly-read identity plus containment under the test root (three-valued —
|
|
1286
|
+
"could not read" is never "does not match"), while the probe beacon carries its own owner, raw start ticks and
|
|
1287
|
+
expiry; and both generated Codex hooks resolve the project root through one `resolveHookRoot`, with
|
|
1288
|
+
`reportRootProvenance` naming the source and start directory on stderr, silent on the success path and with
|
|
1289
|
+
control characters escaped. The environment override originally planned for the hooks was dropped after a live
|
|
1290
|
+
measurement showed the payload's `cwd` present and correct in all six captures (3 scenarios × 2 hook events,
|
|
1291
|
+
codex-cli 0.154.0).
|
|
1292
|
+
|
|
1090
1293
|
`dz guard check --op publish` now warns when either release line disagrees with the core/CLI package versions, and a registry-confirmed live core or CLI publish synchronizes the first such line in both release READMEs: each README is rewritten atomically; the pair is not one transaction (dry-run and bump-only never write them).
|
|
1091
1294
|
|
|
1092
1295
|
`0.8.12` — **staged, not published.** The `/feature-adr` phase panel + per-phase ledger telemetry,
|
|
@@ -1372,6 +1575,46 @@ comment claimed historical notes were safe; they were, except for the one releas
|
|
|
1372
1575
|
cites most — the one it supersedes. A backticked version opening a line before a dash is now treated
|
|
1373
1576
|
as an entry and left alone; footers, badges, install examples and pins still move.
|
|
1374
1577
|
|
|
1578
|
+
**Feature publish-readme-stamp-scope (2026-09-15, fix-round 1 2026-09-15): the sync outside the
|
|
1579
|
+
changelog region is a real POSITIVE ALLOWLIST — not a denylist, and not a denylist that calls itself
|
|
1580
|
+
one.** MEASURED 2026-09-15: a live `dz publish --yes` rewrote five historical lines — a second `##
|
|
1581
|
+
Status` region's own changelog entry (`changelogRegion` protected only the FIRST run, so a `memory`
|
|
1582
|
+
README's later `0.2.21` entry sat bare) and four prose CITATIONS of the outgoing version as a past
|
|
1583
|
+
fact (`MEASURED on 0.8.25`, two `Previous release (vA / v0.8.25)` parentheticals, `on 0.8.10 and
|
|
1584
|
+
0.8.25 alike`). The FIRST fix (same day) replaced that with a denylist of exactly those three phrase
|
|
1585
|
+
shapes (`isCitationContext`) — narrower than the incident, but still a denylist: any FOURTH prose
|
|
1586
|
+
shape citing the outgoing version ("since X", "measured against X", "X behaviour", a bare "X" in a
|
|
1587
|
+
sentence) would have rewritten by default until someone thought to deny it too, and the README
|
|
1588
|
+
documented it as an "allowlist" while the code rewrote by default — a cross-model review caught both.
|
|
1589
|
+
`planReadmeVersionSync(text, old, new)` now inverts the default: outside a changelog region, a token
|
|
1590
|
+
rewrites ONLY when `isAllowlistedRewriteContext` recognises one of six shapes — the lock-step feature
|
|
1591
|
+
this sync exists for, and nothing beyond it:
|
|
1592
|
+
|
|
1593
|
+
1. a release-line token — `` `harness-core vX` · `harness-cli vY` `` and any generalised
|
|
1594
|
+
`` `<name> vX` `` on the same line, including a trailing `` · `memory vZ` `` segment
|
|
1595
|
+
(`release-line.ts` `isReleaseLineToken`/`GENERIC_RELEASE_TOKEN_RE`, unchanged since the earlier fix).
|
|
1596
|
+
2. a current-release FOOTER prefix — `Status:`/`Version:`/`Current release:`/`Current status:`/
|
|
1597
|
+
`Released as` (case-insensitive, optional leading `**`/`-`), POSITION-aware: only the token
|
|
1598
|
+
immediately after the label is allowed, so a footer sentence that also cites an unrelated older
|
|
1599
|
+
release later in the same line (`Current release: X. (Previous release (vA / vB) …)`) allows the
|
|
1600
|
+
first token and still protects the second.
|
|
1601
|
+
3. an install/dependency-pin context — the token immediately follows `@` (`npm i
|
|
1602
|
+
@dzhechkov/harness-core@X`), or sits in a JSON-pin shape `"<package-name>": "X"`.
|
|
1603
|
+
4. the `dz publish: tarball <name>@X sha256:…` example line.
|
|
1604
|
+
5. a `<!-- dz:version -->` marker on the line — forces the rewrite regardless of EVERY other
|
|
1605
|
+
protection, including the changelog region (the author's explicit override, AC-3).
|
|
1606
|
+
6. a shields.io-style badge URL segment — `badge/npm-vX-…` / `badge/version-X-…`.
|
|
1607
|
+
|
|
1608
|
+
Every OTHER shape — whatever prose it is written in, today or in the future — is HISTORY by default,
|
|
1609
|
+
the same as a changelog entry. `syncReadmeVersion` stays a thin, atomic-write wrapper around the
|
|
1610
|
+
plan, returning exactly what it always returned (the pre-sync text, or `undefined` when nothing
|
|
1611
|
+
moved) — every existing caller is byte-compatible. The plan itself is never silent, and locates BOTH
|
|
1612
|
+
sides of its report: `dz publish` prints `readme sync <pkg>: would rewrite N line(s) (L…); M version
|
|
1613
|
+
token(s) kept as history (L…)` on a dry run and `rewrote N line(s) …` on a live publish — attached on
|
|
1614
|
+
every publish path (the main live publish, `--bump-only`, and the packed-transport batch), and
|
|
1615
|
+
`--json` carries the same `readmeSync` summary (`rewrittenLines`, `lines`, `skippedHistorical`,
|
|
1616
|
+
`historyLines`) per package.
|
|
1617
|
+
|
|
1375
1618
|
Also: skill-enrichment ownership is anchored at the skill dir rather than searched across the whole
|
|
1376
1619
|
absolute path, and enrichment is excluded from canonical SELECTION as well as from the destination
|
|
1377
1620
|
set — otherwise a `--auto` canonical could propagate one target's metadata into every copy.
|
package/dist/agentdb-index.d.ts
CHANGED
|
@@ -24,10 +24,14 @@ export interface AgentdbRow {
|
|
|
24
24
|
readonly uses?: number;
|
|
25
25
|
readonly avgReward?: number;
|
|
26
26
|
}
|
|
27
|
-
/** Outcome of {@link indexPatternsToAgentdb}.
|
|
27
|
+
/** Outcome of {@link indexPatternsToAgentdb}. `generationBumped`/`generationReason` are present only
|
|
28
|
+
* when a store write actually happened (`indexed > 0`) — FR-4: a failed counter write NEVER fails
|
|
29
|
+
* the indexing call itself, it is only reported so a caller (`dz doctor`, telemetry) can see it. */
|
|
28
30
|
export interface AgentdbIndexResult {
|
|
29
31
|
readonly indexed: number;
|
|
30
32
|
readonly error?: string | undefined;
|
|
33
|
+
readonly generationBumped?: boolean;
|
|
34
|
+
readonly generationReason?: string;
|
|
31
35
|
}
|
|
32
36
|
/** Resolve the shared store path: explicit opt → AGENTDB_PATH env → `<project>/.dz/agentdb.db`. */
|
|
33
37
|
export declare function resolveAgentdbPath(projectRoot: string, dbPath?: string): string;
|
|
@@ -58,6 +62,23 @@ export declare function ensureAgentdbSchema(projectRoot: string, dbPath?: string
|
|
|
58
62
|
readonly ok: boolean;
|
|
59
63
|
readonly error?: string;
|
|
60
64
|
};
|
|
65
|
+
/**
|
|
66
|
+
* FR-2/FR-3 (`store-generation-counter`): the store's write-generation counter, read back. A
|
|
67
|
+
* missing file (a store that predates this feature, or one that has never been written through
|
|
68
|
+
* {@link bumpStoreGeneration}) reads as `0` — the compatibility floor {@link getOrOpenEngine}'s
|
|
69
|
+
* caller compares against, never an error. A corrupt/non-numeric file degrades the same way (best
|
|
70
|
+
* effort — a bad counter must never crash a read path), never a throw. AM-5: the content must match
|
|
71
|
+
* {@link STRICT_GENERATION} exactly — `Number.parseInt`'s leading-digits-only tolerance is NOT used
|
|
72
|
+
* to decide validity, only to convert an already-validated string.
|
|
73
|
+
*/
|
|
74
|
+
export declare function readStoreGeneration(projectRoot: string, dbPath?: string): number;
|
|
75
|
+
export declare function bumpStoreGeneration(projectRoot: string, dbPath?: string): {
|
|
76
|
+
readonly ok: true;
|
|
77
|
+
readonly generation: number;
|
|
78
|
+
} | {
|
|
79
|
+
readonly ok: false;
|
|
80
|
+
readonly error: string;
|
|
81
|
+
};
|
|
61
82
|
/**
|
|
62
83
|
* Index `rows` into the shared AgentDB vector store. Returns `{indexed:0}` for an empty input and
|
|
63
84
|
* `{indexed:0, error}` when `agentdb`/`better-sqlite3` cannot be resolved from the project.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agentdb-index.d.ts","sourceRoot":"","sources":["../src/agentdb-index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAUH,OAAO,EAAqC,KAAK,sBAAsB,EAAE,MAAM,gCAAgC,CAAC;AAChH,OAAO,EAAiD,KAAK,cAAc,EAAuB,MAAM,uBAAuB,CAAC;AAehI,iGAAiG;AACjG,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,+FAA+F;IAC/F,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC5C,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED
|
|
1
|
+
{"version":3,"file":"agentdb-index.d.ts","sourceRoot":"","sources":["../src/agentdb-index.ts"],"names":[],"mappings":"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"}
|