@dzhechkov/harness-cli 0.7.5 → 0.7.7
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 +15 -15
- package/README.md +51 -3
- package/dist/boolean-flags.d.ts.map +1 -1
- package/dist/boolean-flags.js +1 -0
- package/dist/boolean-flags.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +190 -7
- package/dist/cli.js.map +1 -1
- package/dist/known-flags.d.ts.map +1 -1
- package/dist/known-flags.js +2 -0
- package/dist/known-flags.js.map +1 -1
- package/package.json +9 -9
- package/sbom.json +14 -14
- package/src/boolean-flags.ts +1 -0
- package/src/cli.ts +181 -5
- package/src/known-flags.ts +2 -0
package/.dz-manifest.json
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
},
|
|
10
10
|
{
|
|
11
11
|
"path": "README.md",
|
|
12
|
-
"sha256": "
|
|
12
|
+
"sha256": "3d621db3f7811b174ee46b19fa462316ef13679786a910ac64c65fb05bfd5ef7"
|
|
13
13
|
},
|
|
14
14
|
{
|
|
15
15
|
"path": "dist/bin.d.ts",
|
|
@@ -33,15 +33,15 @@
|
|
|
33
33
|
},
|
|
34
34
|
{
|
|
35
35
|
"path": "dist/boolean-flags.d.ts.map",
|
|
36
|
-
"sha256": "
|
|
36
|
+
"sha256": "bf5eadb6ea3ed4761fbc8206167c86119467d7dfd28d7e0eee7cd21d30099da6"
|
|
37
37
|
},
|
|
38
38
|
{
|
|
39
39
|
"path": "dist/boolean-flags.js",
|
|
40
|
-
"sha256": "
|
|
40
|
+
"sha256": "2cee996fe21ed692135c98b35bf5e56a89f2dc157f681b36c65020fd062b857b"
|
|
41
41
|
},
|
|
42
42
|
{
|
|
43
43
|
"path": "dist/boolean-flags.js.map",
|
|
44
|
-
"sha256": "
|
|
44
|
+
"sha256": "68a41f08452af263f2a378b54e813567b6ba52376f3d0e13567a7eef7dff09e0"
|
|
45
45
|
},
|
|
46
46
|
{
|
|
47
47
|
"path": "dist/cli.d.ts",
|
|
@@ -49,15 +49,15 @@
|
|
|
49
49
|
},
|
|
50
50
|
{
|
|
51
51
|
"path": "dist/cli.d.ts.map",
|
|
52
|
-
"sha256": "
|
|
52
|
+
"sha256": "c7856b79fdf6683fe855268191805ed07b1c68f2ff7ac544d46ac3d93e4c94ef"
|
|
53
53
|
},
|
|
54
54
|
{
|
|
55
55
|
"path": "dist/cli.js",
|
|
56
|
-
"sha256": "
|
|
56
|
+
"sha256": "27741d68ac996a060df7161b49e372f68e31b990a406f0792c79c474ff17eeca"
|
|
57
57
|
},
|
|
58
58
|
{
|
|
59
59
|
"path": "dist/cli.js.map",
|
|
60
|
-
"sha256": "
|
|
60
|
+
"sha256": "bea844c256e8d947464a4690d2224e4f28d61f433d6e50e5fe26bed3b415ae26"
|
|
61
61
|
},
|
|
62
62
|
{
|
|
63
63
|
"path": "dist/core-compat.d.ts",
|
|
@@ -113,15 +113,15 @@
|
|
|
113
113
|
},
|
|
114
114
|
{
|
|
115
115
|
"path": "dist/known-flags.d.ts.map",
|
|
116
|
-
"sha256": "
|
|
116
|
+
"sha256": "1e6f9fd92734216f3cc392fba9e2ec7899492a6892e5891197bc582c886a38fc"
|
|
117
117
|
},
|
|
118
118
|
{
|
|
119
119
|
"path": "dist/known-flags.js",
|
|
120
|
-
"sha256": "
|
|
120
|
+
"sha256": "fea029550cb557c73eea2d53d94ef09ec99ba353126a5090a658dc219e8ae5df"
|
|
121
121
|
},
|
|
122
122
|
{
|
|
123
123
|
"path": "dist/known-flags.js.map",
|
|
124
|
-
"sha256": "
|
|
124
|
+
"sha256": "1b46a6093d0ff5713c870b5b7566623c98a33bb212c7f1ba0c56f336620961a3"
|
|
125
125
|
},
|
|
126
126
|
{
|
|
127
127
|
"path": "keys/README.md",
|
|
@@ -133,7 +133,7 @@
|
|
|
133
133
|
},
|
|
134
134
|
{
|
|
135
135
|
"path": "package.json",
|
|
136
|
-
"sha256": "
|
|
136
|
+
"sha256": "b7c47af8811ca86ee8dd5d4d98cab76c4cceddaafbe09676141bacae92b69b9d"
|
|
137
137
|
},
|
|
138
138
|
{
|
|
139
139
|
"path": "src/bin.ts",
|
|
@@ -141,11 +141,11 @@
|
|
|
141
141
|
},
|
|
142
142
|
{
|
|
143
143
|
"path": "src/boolean-flags.ts",
|
|
144
|
-
"sha256": "
|
|
144
|
+
"sha256": "3ea2dd881198881f94675ce14e465ce007e5d987e25b7786f67d9af13e880e22"
|
|
145
145
|
},
|
|
146
146
|
{
|
|
147
147
|
"path": "src/cli.ts",
|
|
148
|
-
"sha256": "
|
|
148
|
+
"sha256": "d8288240b5420ddca2cabdb7b358c7c18ba59724defda951d0dbc61439b6fc4c"
|
|
149
149
|
},
|
|
150
150
|
{
|
|
151
151
|
"path": "src/core-compat.ts",
|
|
@@ -161,9 +161,9 @@
|
|
|
161
161
|
},
|
|
162
162
|
{
|
|
163
163
|
"path": "src/known-flags.ts",
|
|
164
|
-
"sha256": "
|
|
164
|
+
"sha256": "d123f4f88f51a6b6d283a4fe6d2502bb297ad0de4eb1ef6f99f01b86a7da98a0"
|
|
165
165
|
}
|
|
166
166
|
]
|
|
167
167
|
},
|
|
168
|
-
"signature": "
|
|
168
|
+
"signature": "OQCEpmIWKpZGhU/+x7WMKAFh0U4l40qE6AIVuUfTE5ACGVyVo5kon78Pw2MG2mNhf//gJwd+vAERs41vWR5rAw=="
|
|
169
169
|
}
|
package/README.md
CHANGED
|
@@ -1841,7 +1841,7 @@ dz recap [--day|--week|--month] [--at <ISO date>] [--refresh-publish
|
|
|
1841
1841
|
dz cadence [--window day|week|month|quarter|halfyear|year] [--json] # the RHYTHM view of what shipped: graded-shipment counts bucketed by ISO week, npm-publish cadence (reads `dz recap`'s publish-times cache — run `dz recap --refresh-publishes` to warm it), guard repeat DECAY on the FIXED rule set (a rule joins only with pre-window history, so a newborn rule's zero is youth, not virtue — the no-stubs false-zero class excluded by construction), and recall reuse per week. A window deeper than 2× the record is REFUSED with the measured depth and the largest honest window named (a cadence from under two full windows is scale forgery). Sibling of `dz recap`: recap is the narrative what-was-done report over one window; cadence is the week-by-week rhythm across the window. exit 0 / 2 refused-window / 1 usage
|
|
1842
1842
|
dz provenance-check --manifest <sources.json> [--project <dir>] [--json] # nothing goes out citing a source that may not leave this machine. Checks PROVENANCE, not words: every claim in a draft names its source, and a source is cleared only when it is a KNOWN kind that resolves safely. Repo paths are classified by `git -C <root> check-ignore` over the RESOLVED path — so a symlink into an ignored directory is refused, not cleared (MEASURED: git classifies the string and never dereferences), and the verdict does not change with your working directory. Store records need naming in the git-TRACKED `provenance-public.json`, so declaring one public is a reviewable commit rather than a field inside an ignored store. Anything else is refused: an undeclared kind is never inferred from the path's shape. exit 0 allowed / 1 blocked / 3 NOT ESTABLISHED — an empty manifest, an unreadable one, or an oracle that did not run is never a pass. **What it cannot do, said on the passing path too:** it proves what was CITED. It cannot see a paraphrase with no citation, nor confidential text pasted by hand into an allowed file. Read the draft.
|
|
1843
1843
|
dz name-check [--command <n>] [--module <basename>] [--export <a,b>] [--project <dir>] [--json] # is this name free, BEFORE a line of code? Twice in one day a collision broke the build outright — `dz retro` was already a command, `decideProvenance` already an export — and both were answerable in advance. Scans workspace SOURCE and never `dist`, because a stale build answers 'free' confidently (MEASURED: half an hour of convincing live runs against a previous build while tsc was red). Checks a command name against the dispatcher AND the help block, a module basename against every package's src/, and exported identifiers against every declaration — naming the DECLARING file, not the barrel. exit 0 all free / 1 at least one taken / 2 nothing asked or the scan read nothing — an empty sweep is never a clean bill. **Honest limit, printed on the passing path:** it reads declarations, so a re-export under a different name stays the build's job.
|
|
1844
|
-
dz tg-post --draft <file.html> [--manifest <sources.json>] [--channel <@name>] [--send --yes] [--night] [--json] # the sender for an APPROVED genai-tweets-channel post, held to the channel's own accepted ADRs: HTML mode only (never MarkdownV2 — 18 escapes against 3, one miss is a 400); link preview OFF by default (x.com previews in Telegram are broken since 2022); the 00:00-06:00 MSK quiet window refuses without an explicit --night. THE DEFAULT RUN IS A DRY-RUN: tag balance and allowed-tag checks, bare &/< detection, the 4096 visible-character limit with the overshoot counted — every issue named in one pass, not just the first. The provenance gate runs IN-PROCESS over --manifest, and a draft with no manifest is refused as unchecked when a send is asked. A real send needs --send AND --yes — ADR-004's standing order that publishing stays manual, stated out loud each time. The bot token (TELEGRAM_BOT_TOKEN or telegram.tokenFile) is never printed, and the gates run BEFORE any secret is read. exit 0 sent or clean dry-run / 1 refused / 2 usage
|
|
1844
|
+
dz tg-post --draft <file.html> [--manifest <sources.json>] [--channel <@name>] [--send --yes] [--night] [--max-per-day <n>] [--json] # the sender for an APPROVED genai-tweets-channel post, held to the channel's own accepted ADRs: HTML mode only (never MarkdownV2 — 18 escapes against 3, one miss is a 400); link preview OFF by default (x.com previews in Telegram are broken since 2022); the 00:00-06:00 MSK quiet window refuses without an explicit --night. THE DEFAULT RUN IS A DRY-RUN: tag balance and allowed-tag checks, bare &/< detection, the 4096 visible-character limit with the overshoot counted — every issue named in one pass, not just the first. The provenance gate runs IN-PROCESS over --manifest, and a draft with no manifest is refused as unchecked when a send is asked. A real send needs --send AND --yes — ADR-004's standing order that publishing stays manual, stated out loud each time. Three autopublish guards run FAIL-CLOSED, in a fixed order: the **stop-cord** (`.dz/tg-post/HALT` exists ⇒ nothing publishes, checked FIRST so no bug in a later gate can route around it), **dedup** by the sha256 of the post's VISIBLE text (what the reader sees, not the bytes — a whitespace-different draft is the same post), and the **daily limit** (10 by default, `--max-per-day <n>` to change it), counted over the trailing 24h. The journal is two-phase: a `pending` row is written BEFORE the network call and a `sent` row after Telegram accepts, so a crash between the two is caught by dedup on the next run instead of double-publishing; only `sent` rows eat the daily ceiling. An UNREADABLE journal REFUSES — an unreadable counter does not prove the ceiling is unreached. The provenance gate also clears `kind: url`: a well-formed http(s) URL is public by construction so there is nothing local to protect, while a `file://`, a bare path or a non-URL is refused, never inferred. The bot token (TELEGRAM_BOT_TOKEN or telegram.tokenFile) is never printed, and the gates run BEFORE any secret is read. exit 0 sent or clean dry-run / 1 refused / 2 usage
|
|
1845
1845
|
dz feature-adr-checkpoint (--slug <feature> | --feature-dir <abs>) --stage <s> --input-hash <h> --result <json> [--artifact a,b] [--json]
|
|
1846
1846
|
dz reqe [--slug <feature> [--done --report <f>]] [--project <dir>] [--json] # the re-QE debt ledger: a usage-switched feature-adr run whose Step-8 QE ran on the coder's OWN family (cross-model guard suspended, FR-2.9) records a debt; list debts (also surfaced by dz usage), print the cross-family review brief, settle FAIL-CLOSED against an existing GRADED report (the run's own 08_qe_report.md — even hard-linked — can never settle its own debt); settlement lands in 08_qe_report.md, evidence rotates to reqe-settled.json
|
|
1847
1847
|
dz qe-bridge --family claude --slug <feature> [--coder-family codex|claude] [--model <id>] [--files a,b] [--out <f>] [--timeout <s>] [--allow-same-family] [--json] # the REVERSE QE bridge (Codex-hosted → Claude reviewer): the reviewer runs ISOLATED (an empty temp cwd + --safe-mode --strict-mcp-config --tools '' --no-session-persistence, so no CLAUDE.md/skills/plugins/hooks/MCP load) and its verdict is read from the --output-format json RESULT ENVELOPE, so text a customization printed onto the same stdout can never become a signoff. Probes the model first; sends SCOPED extracts under a loud 200k-char ceiling; the grade must agree across three LAST-anchored channels AND the marker must be the final content — empty/gradeless/mismatched/miscounted output is a named failure with an audit record under features/<slug>/.fa-state/qe-bridge/, never a clean review. exit 0 signoff parsed (ANY grade — it reports, it does not gate) / 1 named failure / 2 usage. DZ_QE_BRIDGE_CLAUDE_BIN is a TEST SEAM (recorded as binOverride:true)
|
|
@@ -4096,10 +4096,58 @@ npx @dzhechkov/p-replicator init
|
|
|
4096
4096
|
|
|
4097
4097
|
## Status
|
|
4098
4098
|
|
|
4099
|
-
`v0.7.
|
|
4099
|
+
`v0.7.7` — **the observability pass, and one new verb.** `dz feature-adr-record --backfill` fills the
|
|
4100
|
+
run-cost ledger from the host's own workflow record — dry-run by default, `--yes` writes atomically.
|
|
4101
|
+
A derived number is MARKED (`filledFrom`/`filledBy`), a number you typed is never overwritten and any
|
|
4102
|
+
disagreement is reported, and every unfillable row comes back NAMED rather than silently skipped.
|
|
4103
|
+
Two ambiguities are REFUSED rather than guessed: a slug matching more than one run, and a run claimed
|
|
4104
|
+
by more than one row — writing the same total into an L/XL feature's `plan` and `full` rows would
|
|
4105
|
+
double-count it for anyone who sums the column. Only `tokens` is derived; minutes and agents stay
|
|
4106
|
+
null because the run record exposes no duration and the ledger's `agents` column means a different
|
|
4107
|
+
quantity than the spend-bearing agent ids.
|
|
4108
|
+
|
|
4109
|
+
Ledger rows now carry a join key at all: the sandboxed workflow cannot know its own run id, so
|
|
4110
|
+
`dz feature-adr-record --kind ledger` resolves it at WRITE time — the only moment the run is
|
|
4111
|
+
unambiguous — and stamps it as `runIdSource: 'resolved-at-write'`, because a resolved id is an
|
|
4112
|
+
inference and not something the pipeline knew.
|
|
4113
|
+
|
|
4114
|
+
`dz feature-adr-checkpoint` stamps the write instant, so "how long did this stage take" becomes
|
|
4115
|
+
answerable for every future run. `dz doctor` reports AQE store integrity from a log that had 1508
|
|
4116
|
+
rows and no readers. `dz score` gains an `observability-declared` discipline: does the architecture
|
|
4117
|
+
artifact say how anyone would know this feature works? Descriptive, never a gate.
|
|
4118
|
+
|
|
4119
|
+
`v0.7.7` — **`dz drift-check` and `dz sync-canonical` stop being a `.claude/skills` gate.** Skill-copy
|
|
4120
|
+
discovery searched `packages/` plus one hardcoded install root, so the four other per-target install
|
|
4121
|
+
trees were ungated — measurably: this repo's own Codex install of `feature-adr` under `.agents/skills`
|
|
4122
|
+
drifted for a day while `dz sync-canonical feature-adr --check` reported "all 3 copies match
|
|
4123
|
+
canonical" and the HARD `no-skill-drift` rule passed. The copy was missing both the K1 section of its
|
|
4124
|
+
`SKILL.md` and the C6 check of its gate script. Discovery is now driven by a target→install-root
|
|
4125
|
+
registry, and the HARD rule runs at a new scope covering generated installs while exempting the
|
|
4126
|
+
hand-edited dev tree (which legitimately lags — three real skills drift there today, so gating it
|
|
4127
|
+
would be red-on-arrival). **The guard legitimately gets STRICTER: a publish that passed before can now
|
|
4128
|
+
be BLOCKED by real drift in a non-`.claude` root — that is the gate working.** Target enrichment
|
|
4129
|
+
written by `dz init --enrich` is exempt from both the drift verdict and the healer, so `sync-canonical`
|
|
4130
|
+
cannot delete it. Also: `dz tg-post` gains `--max-per-day`, previously read by the code but
|
|
4131
|
+
unregistered.
|
|
4132
|
+
|
|
4133
|
+
`v0.7.7` — **the channel sender stops trusting itself.** `dz tg-post` could format-check, provenance-check
|
|
4134
|
+
and time-check a post and still publish it twice, or ten more times, or right through an operator who
|
|
4135
|
+
wanted everything stopped: nothing counted what had already gone out. It now runs three guards FAIL-CLOSED
|
|
4136
|
+
in a fixed order — a **stop-cord** file that halts even a perfect post before any cheaper check, **dedup**
|
|
4137
|
+
keyed on the sha256 of the post's VISIBLE text rather than its bytes, and a **daily limit** (10 by default,
|
|
4138
|
+
`--max-per-day <n>`) counted over the trailing 24h. The send journal is two-phase — `pending` written before
|
|
4139
|
+
the network call, `sent` after Telegram accepts — so a crash in that window is caught by dedup instead of
|
|
4140
|
+
double-publishing, and only accepted sends eat the ceiling. An unreadable journal refuses: an unreadable
|
|
4141
|
+
counter does not prove the ceiling is unreached. The provenance gate additionally clears `kind: url` — a
|
|
4142
|
+
well-formed http(s) URL is public by construction, while a `file://`, a bare path or a non-URL is refused
|
|
4143
|
+
and never inferred from its shape. Also: `dz challenge` is now discoverable from the CLI's own help surface
|
|
4144
|
+
(it existed and was reachable only if you already knew the name), and the adversary it assembles is fed all
|
|
4145
|
+
five calibration documents rather than a subset.
|
|
4146
|
+
|
|
4147
|
+
`v0.7.7` — **a signature-only republish.** `0.7.0` shipped through `pnpm publish` rather than
|
|
4100
4148
|
`dz publish`, so the re-signing step was skipped and 17 of 497 files in the published core did not
|
|
4101
4149
|
match their signed hashes — the content was correct, the manifest was ten hours stale. Nothing in
|
|
4102
|
-
the shipped behaviour changes between `0.7.0` and `0.7.
|
|
4150
|
+
the shipped behaviour changes between `0.7.0` and `0.7.7`; the integrity check stops reporting these
|
|
4103
4151
|
packages as tampered. The one code change is a TEST: the compat case that asserted the workspace
|
|
4104
4152
|
core sits exactly on `MIN_CORE` is split into an integration half and a boundary half, so a patch
|
|
4105
4153
|
bump of core no longer reddens it and `MIN_CORE` need not claim a version the CLI does not require.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"boolean-flags.d.ts","sourceRoot":"","sources":["../src/boolean-flags.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,iBAAiB,EAAE,WAAW,CAAC,MAAM,
|
|
1
|
+
{"version":3,"file":"boolean-flags.d.ts","sourceRoot":"","sources":["../src/boolean-flags.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,iBAAiB,EAAE,WAAW,CAAC,MAAM,CAyFhD,CAAC;AAEH,gGAAgG;AAChG,eAAO,MAAM,qBAAqB,EAAE,SAAS,MAAM,EAAc,CAAC;AAElE,iGAAiG;AACjG,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAGpE"}
|
package/dist/boolean-flags.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"boolean-flags.js","sourceRoot":"","sources":["../src/boolean-flags.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAwB,IAAI,GAAG,CAAC;IAC5D,UAAU;IACV,KAAK;IACL,mBAAmB;IACnB,sBAAsB;IACtB,KAAK;IACL,OAAO;IACP,WAAW;IACX,MAAM;IACN,OAAO;IACP,KAAK;IACL,WAAW;IACX,UAAU;IACV,WAAW;IACX,OAAO;IACP,SAAS;IACT,cAAc;IACd,MAAM;IACN,MAAM;IACN,MAAM;IACN,SAAS;IACT,MAAM;IACN,QAAQ;IACR,WAAW;IACX,oBAAoB;IACpB,UAAU;IACV,OAAO;IACP,MAAM;IACN,OAAO;IACP,OAAO;IACP,QAAQ;IACR,WAAW;IACX,MAAM;IACN,eAAe;IACf,MAAM;IACN,SAAS;IACT,gBAAgB;IAChB,cAAc;IACd,MAAM;IACN,cAAc;IACd,QAAQ;IACR,SAAS;IACT,MAAM;IACN,cAAc;IACd,MAAM;IACN,OAAO;IACP,YAAY;IACZ,UAAU;IACV,UAAU;IACV,UAAU;IACV,WAAW;IACX,WAAW;IACX,eAAe;IACf,WAAW;IACX,aAAa;IACb,UAAU;IACV,WAAW;IACX,MAAM;IACN,UAAU;IACV,SAAS;IACT,YAAY;IACZ,aAAa;IACb,kBAAkB;IAClB,SAAS;IACT,WAAW;IACX,oBAAoB;IACpB,mBAAmB;IACnB,QAAQ;IACR,cAAc;IACd,iBAAiB;IACjB,QAAQ;IACR,QAAQ;IACR,aAAa;IACb,UAAU;IACV,MAAM;IACN,OAAO;IACP,aAAa;IACb,QAAQ;IACR,OAAO;IACP,QAAQ;IACR,KAAK;IACL,OAAO;IACP,OAAO;IACP,UAAU;IACV,MAAM;IACN,YAAY;IACZ,iBAAiB;IACjB,KAAK;CACN,CAAC,CAAC;AAEH,gGAAgG;AAChG,MAAM,CAAC,MAAM,qBAAqB,GAAsB,CAAC,OAAO,CAAC,CAAC;AAElE,iGAAiG;AACjG,MAAM,UAAU,aAAa,CAAC,IAAY,EAAE,OAAe;IACzD,IAAI,IAAI,KAAK,OAAO;QAAE,OAAO,CAAC,qBAAqB,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IACtE,OAAO,iBAAiB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AACrC,CAAC"}
|
|
1
|
+
{"version":3,"file":"boolean-flags.js","sourceRoot":"","sources":["../src/boolean-flags.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAwB,IAAI,GAAG,CAAC;IAC5D,UAAU;IACV,UAAU;IACV,KAAK;IACL,mBAAmB;IACnB,sBAAsB;IACtB,KAAK;IACL,OAAO;IACP,WAAW;IACX,MAAM;IACN,OAAO;IACP,KAAK;IACL,WAAW;IACX,UAAU;IACV,WAAW;IACX,OAAO;IACP,SAAS;IACT,cAAc;IACd,MAAM;IACN,MAAM;IACN,MAAM;IACN,SAAS;IACT,MAAM;IACN,QAAQ;IACR,WAAW;IACX,oBAAoB;IACpB,UAAU;IACV,OAAO;IACP,MAAM;IACN,OAAO;IACP,OAAO;IACP,QAAQ;IACR,WAAW;IACX,MAAM;IACN,eAAe;IACf,MAAM;IACN,SAAS;IACT,gBAAgB;IAChB,cAAc;IACd,MAAM;IACN,cAAc;IACd,QAAQ;IACR,SAAS;IACT,MAAM;IACN,cAAc;IACd,MAAM;IACN,OAAO;IACP,YAAY;IACZ,UAAU;IACV,UAAU;IACV,UAAU;IACV,WAAW;IACX,WAAW;IACX,eAAe;IACf,WAAW;IACX,aAAa;IACb,UAAU;IACV,WAAW;IACX,MAAM;IACN,UAAU;IACV,SAAS;IACT,YAAY;IACZ,aAAa;IACb,kBAAkB;IAClB,SAAS;IACT,WAAW;IACX,oBAAoB;IACpB,mBAAmB;IACnB,QAAQ;IACR,cAAc;IACd,iBAAiB;IACjB,QAAQ;IACR,QAAQ;IACR,aAAa;IACb,UAAU;IACV,MAAM;IACN,OAAO;IACP,aAAa;IACb,QAAQ;IACR,OAAO;IACP,QAAQ;IACR,KAAK;IACL,OAAO;IACP,OAAO;IACP,UAAU;IACV,MAAM;IACN,YAAY;IACZ,iBAAiB;IACjB,KAAK;CACN,CAAC,CAAC;AAEH,gGAAgG;AAChG,MAAM,CAAC,MAAM,qBAAqB,GAAsB,CAAC,OAAO,CAAC,CAAC;AAElE,iGAAiG;AACjG,MAAM,UAAU,aAAa,CAAC,IAAY,EAAE,OAAe;IACzD,IAAI,IAAI,KAAK,OAAO;QAAE,OAAO,CAAC,qBAAqB,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IACtE,OAAO,iBAAiB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AACrC,CAAC"}
|
package/dist/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AASH,OAAO,EAAoC,KAAK,EAAa,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAK3G,OAAO,EA4CL,iBAAiB,EAmBjB,KAAK,oBAAoB,
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.js
CHANGED
|
@@ -16,7 +16,7 @@ import { homedir, tmpdir } from 'node:os';
|
|
|
16
16
|
import { createRequire } from 'node:module';
|
|
17
17
|
import { createSkill, getSkillInfo, listSkillsDetailed, formatSkillLoadFailures, formatSkillApplyFailures, resolveTargetName, formatTargetProblem, formatTargetAliasNote, TARGET_NAMES_SORTED, runDoctor, runInit, resolvePackageSkillRoots, PACKAGE_SKILL_LAYOUTS, benchmarkSkill, benchmarkSkills, scanMcp, reconcileCapabilities, RECONCILE_BANNER, buildRegistry, discoverSkillPackDirs, discoverVerifiablePackDirs, checkUpstream, compareSkills, checkAllUpstream, sweepSkillDrift, syncCanonicalSkill, checkUpgrades, discoverPackages, discoverSourcePackages, fetchAllDownloads, filterByCategory, pretrain, recommend, generatePlugin, publishPackages, runSetup, runMigrate, searchRegistry, runSync, runVerify, runInitAgentsMd, runInitGeminiMd, runSyncAgentsPolicy, runSyncCodexHooks, resolveCodexHome, withNamedLockSync,
|
|
18
18
|
// dz workflow run (feature dz-workflow-run): the pure scheduler + the dispatch adapters.
|
|
19
|
-
TRACE_RUNID_RE, WF_RUN_OWNER_HOST, preflight, runWorkflow, makeClaudePDispatcher, makeCodexExecDispatcher, NamedLockTimeoutError, NamedLockCompromisedError, POLICY_SOURCES, detectPolicyDrift, hasPolicyFence, TARGET_NAMES, buildParityMatrix, downgradeForStaleEvidence, findStaleTranscriptEvidence, TARGET_CAPABILITIES, TARGET_SHORT_LABELS, WORKFLOW_TEMPLATES_RETIRED_MESSAGE, parsePlan, isParseErrors, validatePlan, normalizePlan, planDigest, toTraceProjection, renderPlan, mergeRender, lint, lintExitCode, LOOP_BLOBS, parseTrace, assembleTimeline, runInvariants, deriveAttestation, stampAttestation, corroborate, NOT_WITNESSED, renderTimelineHtml, importEcc, recordPattern, resolveLearningBackend, storeStats, consolidateSessions, pruneNoisePatterns, lessonDeltaReport, removePatternsByIds, snapshotStore, recallHybrid, teachGuard, mirrorPatternsToVector, mirrorEntriesToVector, patternVectorEntry, readMemoryLearningConfig, promotePatterns, quarantineExpiryCandidates, pruneQuarantinePatterns, clearAgentdbQuarantine, vectorMirrorEnabled, vectorTierStatus, resolveVectorEngine, reindexVectorStore, harmonizeVectorStore, importRvfCheckpoint, statuslineData, writeFeatureAdrState, computeUsage, deriveCostLedger, renderCostLedger, verifyCostLedgerReport, writeCostLedgerJsonl, COST_LEDGER_SCOPE, deriveUsageCalibration, normalizeClaudeUsageModelKey, readUsageLimits, parseWeeklyResetAnchor, claimCheck, summarize, queryBookKnowledge, loadStorePatternsSync, patternRecordId, loadStoreRecords, recordToPattern, bundleSkills, brainHome, listBrain, bookKbPath, promoteProjectToBrain, updateBrainSource, queryBrain, groundPrompt, expandKu, reindexBrainVectors, buildPrimer, exportBrainSlice, importBrainSlice, registerKusToBrain, RECALL_USAGE_LOG_RELATIVE, RECALL_USAGE_LOG_MAX_BYTES, parseRecallUsageLog, buildRecallUsageReport, EVENT_CHAIN_TAIL_BYTES, EMPTY_LOG_TAIL, readTailInfo, appendChainedLines, verifyEventChainText, buildManifest, buildSbom, resolveTrustRoot, decideVerifyPolicy, generateSigningKeypair, evaluateGuard, resolveRules, auditRecord, guardExitCode, DEFAULT_RULES, parsePnpmLockImporters, scannableStubPath,
|
|
19
|
+
TRACE_RUNID_RE, WF_RUN_OWNER_HOST, preflight, runWorkflow, makeClaudePDispatcher, makeCodexExecDispatcher, NamedLockTimeoutError, NamedLockCompromisedError, POLICY_SOURCES, detectPolicyDrift, hasPolicyFence, TARGET_NAMES, buildParityMatrix, downgradeForStaleEvidence, findStaleTranscriptEvidence, TARGET_CAPABILITIES, TARGET_SHORT_LABELS, WORKFLOW_TEMPLATES_RETIRED_MESSAGE, parsePlan, isParseErrors, validatePlan, normalizePlan, planDigest, toTraceProjection, renderPlan, mergeRender, lint, lintExitCode, LOOP_BLOBS, parseTrace, assembleTimeline, runInvariants, deriveAttestation, stampAttestation, corroborate, NOT_WITNESSED, renderTimelineHtml, importEcc, recordPattern, resolveLearningBackend, storeStats, consolidateSessions, pruneNoisePatterns, lessonDeltaReport, removePatternsByIds, snapshotStore, recallHybrid, teachGuard, mirrorPatternsToVector, mirrorEntriesToVector, patternVectorEntry, readMemoryLearningConfig, promotePatterns, quarantineExpiryCandidates, pruneQuarantinePatterns, clearAgentdbQuarantine, vectorMirrorEnabled, vectorTierStatus, resolveVectorEngine, reindexVectorStore, harmonizeVectorStore, importRvfCheckpoint, statuslineData, writeFeatureAdrState, computeUsage, deriveCostLedger, planLedgerBackfill, listCostLedgerRuns, resolveLedgerRunId, AMBIGUOUS, stampCheckpointLine, LEDGER_FILL_SOURCE, renderCostLedger, verifyCostLedgerReport, writeCostLedgerJsonl, COST_LEDGER_SCOPE, deriveUsageCalibration, normalizeClaudeUsageModelKey, readUsageLimits, parseWeeklyResetAnchor, claimCheck, summarize, queryBookKnowledge, loadStorePatternsSync, patternRecordId, loadStoreRecords, recordToPattern, bundleSkills, brainHome, listBrain, bookKbPath, promoteProjectToBrain, updateBrainSource, queryBrain, groundPrompt, expandKu, reindexBrainVectors, buildPrimer, exportBrainSlice, importBrainSlice, registerKusToBrain, RECALL_USAGE_LOG_RELATIVE, RECALL_USAGE_LOG_MAX_BYTES, parseRecallUsageLog, buildRecallUsageReport, EVENT_CHAIN_TAIL_BYTES, EMPTY_LOG_TAIL, readTailInfo, appendChainedLines, verifyEventChainText, buildManifest, buildSbom, resolveTrustRoot, decideVerifyPolicy, generateSigningKeypair, evaluateGuard, resolveRules, auditRecord, guardExitCode, DEFAULT_RULES, parsePnpmLockImporters, scannableStubPath,
|
|
20
20
|
// guard-promotion (feature guard-promotion, scout idea #1)
|
|
21
21
|
assembleCandidates, renderPromotionReport, renderPromotionAdr, normalizePromotionState, nextPromotionState, globMatch, promotionAdrRelPath, DEFAULT_WINDOW_DAYS, DEFAULT_PERIODS, MAX_CONTENT_FETCHES, BUILTIN_COVERAGE, decideProvenance, isInsideTree, signManifest, verifyManifest, listSignablePackFiles, assertKeyOutsideTree, decidePublishGate, collectPackageFacts, planReleaseGates, selectAffectedPackages, classifyGateExecutions, buildFailureIssue, buildReleaseNotes, releaseTagName, firstOutputLine, formatPublishError, MANIFEST_NAME, SBOM_NAME, buildArchitectureMap, renderMapHuman, findArchitectureDrift, renderDriftReport, scanWorkspacePackages, loadSubsystemManifest, loadProductVision, checkFeatureAgainstArchitecture, renderArchCheck, planProjectSkills, guidanceForStage, renderInjectionReport, analyzeCorpus, renderRakeReport, renderCriticSection, rakeAsLesson, rakeReward, DEFAULT_RAKE_THRESHOLDS, streamSessionEvents, findLatestTranscript, detectProcessRakes, buildRetro, renderRetro, retroLessonText, PROCESS_SIGNATURES, RETRO_DOMAIN, scanForSetup, buildSetupPlan, scaffoldFromSpec, renderScaffoldPreview, readExistingForScaffold, assembleChallengeContext, buildChallengeBrief, planDiscriminationCheck, classifyDiscrimination, classifyExecutionEvidence, pickAdversaryModel, CHALLENGE_QUESTIONS, loadOutcomes, renderOutcomes, statsForKey, selectAutoCost, recordProvisional, finalizeOutcome, harvestStageOutcomes, recommendModels, planFeed, GRADE_SUCCESS_FLOOR, COST_LADDER, splitScenarios, budgetPlan, selectWinner, proseScopeOk, renderProseDiff, readScenarioIds, DEFAULT_MAX_JUDGE_RUNS, collectDeliveryFacts, planDeliveryCheck, renderDeliveryBrief, classifyDelivery, isUsablePlaneResult, renderDeliveryReview, scanSkillsLayout, declaredPluginSurface, parseInitFacts, verifyRegistration, buildContentProbePrompt, classifyContentProbe, renderContentProbe, findNonRegistrableSkillDirs, assembleCompoundingReport,
|
|
22
22
|
// Cold-vs-warm EPOCH RUNNER (feature epoch-replay) — orchestrates + scores, never calls a model.
|
|
@@ -26,7 +26,7 @@ readBacklogConfig, readIdeas, writeIdeas, ideaId, dedupIdea, readGoalMap, readGo
|
|
|
26
26
|
// qe-bridge (feature qe-bridge-claude, ADR-001): the pure half of the reverse QE bridge.
|
|
27
27
|
KNOWN_CLAUDE, isSafeClaudeId, claudeProbeArgs, claudeReviewArgs, interpretClaudeProbe, modelFamily, buildBridgePrompt, parseBridgeOutput, buildBridgeFailureRecord, buildBridgeSignoffRecord, renderBridgeReport, isSafeSlug, hasUnsafePathChars, hasDotDotSegment, buildReqeBrief, settleReqeDebt, renderReqeList, REQE_SCOPE,
|
|
28
28
|
// Mutation gate (feature ha-mutation-gate) — break each named protection, run the suite, require red.
|
|
29
|
-
parseMutationRegistry, applyMutationToText, countFailingTests, classifyBaseline, classifyRunFailure, classifyMutationOutcome, mutationGateExitCode, summarizeMutationResults, renderMutationReport, TRACE_BUNDLE_LEDGER_PATH, TRACE_BUNDLE_SCHEMA, TRACE_BUNDLE_RUN_META_FILE, buildBundle, serializeBundle, parseBundle, planImport, decideCheckpointWrite, amendmentSection, planSaysNoAmendments, parseAmendments, resolveAmendments, decideAmendmentOutcome, amendmentVerdictLine, amendmentsMissingFromPlan, AMENDMENT_VACUITY_NOTE, decideSignableSet, signableSetLine, decideRecordWrite, decideReadBack, recordVerdictLine, buildCadenceReport, CADENCE_WINDOW_DAYS, } from '@dzhechkov/harness-core';
|
|
29
|
+
parseMutationRegistry, applyMutationToText, countFailingTests, classifyBaseline, classifyRunFailure, classifyMutationOutcome, mutationGateExitCode, summarizeMutationResults, renderMutationReport, TRACE_BUNDLE_LEDGER_PATH, TRACE_BUNDLE_SCHEMA, TRACE_BUNDLE_RUN_META_FILE, buildBundle, serializeBundle, parseBundle, planImport, decideCheckpointWrite, amendmentSection, planSaysNoAmendments, parseAmendments, resolveAmendments, decideAmendmentOutcome, amendmentVerdictLine, amendmentsMissingFromPlan, AMENDMENT_VACUITY_NOTE, decideSignableSet, signableSetLine, decideRecordWrite, decideReadBack, recordVerdictLine, buildCadenceReport, tgVisibleSha256, CADENCE_WINDOW_DAYS, } from '@dzhechkov/harness-core';
|
|
30
30
|
import { getPreset, PRESET_NAMES } from '@dzhechkov/harness-presets';
|
|
31
31
|
import { scanGitHub, analyzeRepo, generateReport, deepAnalyze, scanAllSources, ScoutMemory } from '@dzhechkov/scout';
|
|
32
32
|
const USAGE = `dz - DZ cross-platform harness CLI
|
|
@@ -59,6 +59,7 @@ Usage:
|
|
|
59
59
|
dz release [--filter <name>] [--tag] [--publish] [--json] [--dry-run] [--no-issue] (VERIFIED release: 4 HARD gates in FRONT of dz publish — full package test suites, audit >=high, node --check of every dist/bin file, bin smoke-boot via "node <bin> --help" — any red gate STOPS the release (exit 1) + best-effort gh issue; all green ⇒ re-sign reminder, then prints the ready dz publish command (or chains with --publish); never duplicates publish's own gates)
|
|
60
60
|
dz parity [--target <name>] [--json] (the honest feature×target map, COMPUTED from the capability model — which harness feature is full / manual / absent on each of the ${TARGET_NAMES.length} targets, and via which form)
|
|
61
61
|
dz delivery-check --slug <slug> [--context-only] [--findings <f.json>] [--strict] [--author <model>] [--json] (portable Step-10 Delivery Gate: prints the 4-plane review brief + artifact probes; --findings classifies a fed-back review into a fail-closed ready|blocked hand-off and writes features/<slug>/10_delivery_review.md; --strict exits 1 on blocked)
|
|
62
|
+
dz challenge --plan <plan.md> [--author <model>] (the deterministic cartridge behind the challenge-panel adversarial plan-gate (R6): assembles the wide brief — plan + architecture/vision.md + testing.md + map.json + degradations.md — and prints the C1-C8 adversary prompt naming the cross-family reviewer to dispatch. exit 0 brief printed / 1 plan missing or empty)
|
|
62
63
|
dz skills-verify [--dir <project>] [--expect a,b] [--static] [--strict] [--json] (does .claude/skills/ actually REGISTER? --static = instant layout scan for CI; default reads the authoritative system/init listing from a real session. exit 0 pass / 1 fail / 2 inconclusive — never a false pass)
|
|
63
64
|
dz compounding [--project <dir>] [--json] (honest learning-loop payoff report: pool write-only ratio, guard repeat-violation trajectory, cold-vs-warm replay readiness, instrumentation health — a gate without enough data says INSUFFICIENT_DATA, never a fake verdict)
|
|
64
65
|
dz epoch-replay --mock [--n <N>] [--effect <-1..1>] [--tie-rate <0..1>] [--seed <N>] [--slice <name>] [--json] ($0 synthetic run — exercises the verdict math, NOT evidence)
|
|
@@ -6708,7 +6709,7 @@ function gatherGuardFacts(op, root, text, storeCap) {
|
|
|
6708
6709
|
}
|
|
6709
6710
|
catch { /* unreadable tree — the rule reports nothing rather than inventing a violation */ }
|
|
6710
6711
|
try {
|
|
6711
|
-
facts['drift'] = sweepSkillDrift(root, { scope: '
|
|
6712
|
+
facts['drift'] = sweepSkillDrift(root, { scope: 'installs', allowlist: readDriftAllowlist(root) }).drifted.map((d) => d.name);
|
|
6712
6713
|
}
|
|
6713
6714
|
catch { /* skip */ }
|
|
6714
6715
|
facts['counts'] = gatherReadmeCounts(root);
|
|
@@ -6911,7 +6912,7 @@ function gatherGuardFacts(op, root, text, storeCap) {
|
|
|
6911
6912
|
}
|
|
6912
6913
|
if (op === 'consolidate') {
|
|
6913
6914
|
try {
|
|
6914
|
-
facts['drift'] = sweepSkillDrift(root, { scope: '
|
|
6915
|
+
facts['drift'] = sweepSkillDrift(root, { scope: 'installs', allowlist: readDriftAllowlist(root) }).drifted.map((d) => d.name);
|
|
6915
6916
|
}
|
|
6916
6917
|
catch { /* skip */ }
|
|
6917
6918
|
}
|
|
@@ -10156,12 +10157,42 @@ async function cmdTgPost(options, flags, cwd, write) {
|
|
|
10156
10157
|
for (const line of renderSourceProvenance(decision))
|
|
10157
10158
|
write(line);
|
|
10158
10159
|
}
|
|
10160
|
+
// ADR-005 autopublish guards: read the stop-cord and the send journal as FACTS, then let the pure
|
|
10161
|
+
// decideTgSend judge. An UNREADABLE journal stays undefined ⇒ decideTgSend fails closed on G4/G5.
|
|
10162
|
+
const tgDir = join(repoRoot, '.dz', 'tg-post');
|
|
10163
|
+
const halted = existsSync(join(tgDir, 'HALT'));
|
|
10164
|
+
const sha256 = tgVisibleSha256(draft);
|
|
10165
|
+
let sentLog;
|
|
10166
|
+
const sentLogPath = join(tgDir, 'sent-log.jsonl');
|
|
10167
|
+
if (!existsSync(sentLogPath)) {
|
|
10168
|
+
sentLog = []; // no journal yet is an EMPTY journal, not an unreadable one — a fresh channel sends
|
|
10169
|
+
}
|
|
10170
|
+
else {
|
|
10171
|
+
try {
|
|
10172
|
+
sentLog = [];
|
|
10173
|
+
for (const line of readFileSync(sentLogPath, 'utf-8').split('\n')) {
|
|
10174
|
+
if (line.trim() === '')
|
|
10175
|
+
continue;
|
|
10176
|
+
const r = JSON.parse(line);
|
|
10177
|
+
if (typeof r.sha256 === 'string' && typeof r.ts === 'string') {
|
|
10178
|
+
sentLog.push({ sha256: r.sha256, ts: r.ts, ...(r.status === 'pending' || r.status === 'sent' ? { status: r.status } : {}) });
|
|
10179
|
+
}
|
|
10180
|
+
}
|
|
10181
|
+
}
|
|
10182
|
+
catch {
|
|
10183
|
+
sentLog = undefined; // genuinely unreadable ⇒ fail-closed
|
|
10184
|
+
}
|
|
10185
|
+
}
|
|
10159
10186
|
const decision = decideTgSend({
|
|
10160
10187
|
issues,
|
|
10161
10188
|
provenanceOutcome,
|
|
10162
10189
|
confirmed: flags.has('send') && flags.has('yes'),
|
|
10163
10190
|
nowUtcIso: new Date().toISOString(),
|
|
10164
10191
|
nightOverride: flags.has('night'),
|
|
10192
|
+
halted,
|
|
10193
|
+
sha256,
|
|
10194
|
+
sentLog,
|
|
10195
|
+
maxPostsPerDay: (() => { const n = Number(options.get('max-per-day')); return Number.isFinite(n) && n > 0 ? n : 10; })(),
|
|
10165
10196
|
});
|
|
10166
10197
|
const visible = tgVisibleLength(draft);
|
|
10167
10198
|
if (!json) {
|
|
@@ -10184,6 +10215,17 @@ async function cmdTgPost(options, flags, cwd, write) {
|
|
|
10184
10215
|
write('dz tg-post: --channel @name (or a chat id) is required to send');
|
|
10185
10216
|
return 2;
|
|
10186
10217
|
}
|
|
10218
|
+
// Two-phase journal (Codex A-): write a PENDING row BEFORE the network call. If the process dies
|
|
10219
|
+
// between send and the sent-row, G5 dedup sees this pending row on the next run and refuses to
|
|
10220
|
+
// double-publish. Best-effort — a pending-write failure is warned, not fatal (better to risk one
|
|
10221
|
+
// duplicate than to block a legitimate send on a full disk).
|
|
10222
|
+
try {
|
|
10223
|
+
mkdirSync(tgDir, { recursive: true });
|
|
10224
|
+
appendFileSync(sentLogPath, JSON.stringify({ sha256, ts: new Date().toISOString(), channel, status: 'pending' }) + '\n');
|
|
10225
|
+
}
|
|
10226
|
+
catch (e) {
|
|
10227
|
+
write(`dz tg-post: WARNING — could not write the PENDING journal row (${e.message}); the crash-window dedup guard is degraded for this send`);
|
|
10228
|
+
}
|
|
10187
10229
|
const sent = await tgApi(token, 'sendMessage', {
|
|
10188
10230
|
chat_id: channel,
|
|
10189
10231
|
text: draft,
|
|
@@ -10197,6 +10239,16 @@ async function cmdTgPost(options, flags, cwd, write) {
|
|
|
10197
10239
|
write(JSON.stringify({ ok: false, action: 'send', reason: sent.description ?? 'refused', visible }));
|
|
10198
10240
|
return 1;
|
|
10199
10241
|
}
|
|
10242
|
+
// Record the send AFTER Telegram accepted it (never before — a failed send must not eat the daily
|
|
10243
|
+
// limit or block a retry via dedup). Best-effort append; a journal write failure is logged, not
|
|
10244
|
+
// fatal — the post already went out.
|
|
10245
|
+
try {
|
|
10246
|
+
mkdirSync(tgDir, { recursive: true });
|
|
10247
|
+
appendFileSync(sentLogPath, JSON.stringify({ sha256, ts: new Date().toISOString(), channel, messageId: sent.messageId ?? null, status: 'sent' }) + '\n');
|
|
10248
|
+
}
|
|
10249
|
+
catch (e) {
|
|
10250
|
+
write(`dz tg-post: WARNING — sent, but could not record it in ${sentLogPath} (${e.message}) — the daily limit and dedup may under-count until fixed`);
|
|
10251
|
+
}
|
|
10200
10252
|
write(`dz tg-post: sent to ${channel}${sent.messageId !== undefined ? ` (message ${sent.messageId})` : ''}`);
|
|
10201
10253
|
if (json)
|
|
10202
10254
|
write(JSON.stringify({ ok: true, action: 'send', channel, messageId: sent.messageId ?? null, visible }));
|
|
@@ -10268,8 +10320,111 @@ async function cmdRecap(options, flags, cwd, write) {
|
|
|
10268
10320
|
}
|
|
10269
10321
|
return 0;
|
|
10270
10322
|
}
|
|
10323
|
+
/**
|
|
10324
|
+
* `dz feature-adr-record --backfill` — fill the run-cost ledger from the host workflow records.
|
|
10325
|
+
*
|
|
10326
|
+
* MEASURED 2026-08-25: of 87 ledger rows, all 20 written automatically carried
|
|
10327
|
+
* `tokens:null, minutes:null, agents:null`, so cost-per-feature was answerable only for the 66 rows
|
|
10328
|
+
* a human retyped. The numbers exist in the host record; the sandboxed workflow simply cannot reach
|
|
10329
|
+
* them. This is that join, run afterwards, on the dz side.
|
|
10330
|
+
*/
|
|
10331
|
+
function cmdLedgerBackfill(options, flags, cwd, write) {
|
|
10332
|
+
const json = flags.has('json');
|
|
10333
|
+
const apply = flags.has('yes');
|
|
10334
|
+
const ledgerPath = resolve(options.get('project') ?? cwd, '.dz', 'feature-adr', 'run-cost-ledger.jsonl');
|
|
10335
|
+
if (!existsSync(ledgerPath)) {
|
|
10336
|
+
const msg = `dz feature-adr-record --backfill: no ledger at ${ledgerPath}`;
|
|
10337
|
+
write(json ? JSON.stringify({ ok: false, reason: 'no-ledger', path: ledgerPath }) : msg);
|
|
10338
|
+
return 1;
|
|
10339
|
+
}
|
|
10340
|
+
const raw = readFileSync(ledgerPath, 'utf-8');
|
|
10341
|
+
const lines = raw.split('\n').filter((l) => l !== '');
|
|
10342
|
+
const cache = new Map();
|
|
10343
|
+
// Only `tokens` is derived, and the scope is narrow on purpose:
|
|
10344
|
+
// • minutes — CostLedgerReport exposes startedTs but no run duration; there is nothing to divide.
|
|
10345
|
+
// • agents — the ledger column means TOTAL agent invocations including infra agents, while the
|
|
10346
|
+
// union of row.agentIds counts only agents that SPENT. Writing the second into the first would
|
|
10347
|
+
// quietly redefine the column, which that column's own writer explicitly warns against.
|
|
10348
|
+
const factsFor = (runId) => {
|
|
10349
|
+
try {
|
|
10350
|
+
const report = deriveCostLedger({ runId });
|
|
10351
|
+
if (report === null)
|
|
10352
|
+
return null;
|
|
10353
|
+
const tokens = typeof report.recordTotalTokens === 'number' && Number.isFinite(report.recordTotalTokens)
|
|
10354
|
+
? report.recordTotalTokens
|
|
10355
|
+
: null;
|
|
10356
|
+
return { tokens, minutes: null, agents: null };
|
|
10357
|
+
}
|
|
10358
|
+
catch {
|
|
10359
|
+
return null;
|
|
10360
|
+
}
|
|
10361
|
+
};
|
|
10362
|
+
const facts = (key, value) => {
|
|
10363
|
+
const ck = key + ':' + value;
|
|
10364
|
+
const hit = cache.get(ck);
|
|
10365
|
+
if (hit !== undefined)
|
|
10366
|
+
return hit;
|
|
10367
|
+
let out = null;
|
|
10368
|
+
if (key === 'runId') {
|
|
10369
|
+
out = factsFor(value);
|
|
10370
|
+
}
|
|
10371
|
+
else {
|
|
10372
|
+
// The slug is the fallback because the sandboxed workflow cannot know its own run id. It is
|
|
10373
|
+
// only usable when it names exactly ONE host run: deriveCostLedger resolves a slug with
|
|
10374
|
+
// `runs.find(...)`, which takes the FIRST match SILENTLY, so a feature run twice would have
|
|
10375
|
+
// one run's spend written into the other run's row and called measured. Count first, refuse
|
|
10376
|
+
// on more than one.
|
|
10377
|
+
try {
|
|
10378
|
+
const matches = listCostLedgerRuns().filter((r) => r.slug === value);
|
|
10379
|
+
if (matches.length > 1)
|
|
10380
|
+
out = AMBIGUOUS;
|
|
10381
|
+
else if (matches.length === 1 && matches[0] !== undefined)
|
|
10382
|
+
out = factsFor(matches[0].runId);
|
|
10383
|
+
}
|
|
10384
|
+
catch {
|
|
10385
|
+
out = null;
|
|
10386
|
+
}
|
|
10387
|
+
}
|
|
10388
|
+
cache.set(ck, out);
|
|
10389
|
+
return out;
|
|
10390
|
+
};
|
|
10391
|
+
const plan = planLedgerBackfill({ lines, facts });
|
|
10392
|
+
const unfilled = plan.rows.filter((r) => r.skipped !== null && r.skipped !== 'already-complete');
|
|
10393
|
+
if (apply && plan.filledRows > 0) {
|
|
10394
|
+
// Atomic replace: a torn ledger is worse than an unfilled one.
|
|
10395
|
+
const tmp = ledgerPath + '.backfill-tmp';
|
|
10396
|
+
writeFileSync(tmp, plan.lines.join('\n') + '\n', 'utf-8');
|
|
10397
|
+
renameSync(tmp, ledgerPath);
|
|
10398
|
+
}
|
|
10399
|
+
if (json) {
|
|
10400
|
+
write(JSON.stringify({
|
|
10401
|
+
ok: true, applied: apply && plan.filledRows > 0, filledRows: plan.filledRows,
|
|
10402
|
+
totalRows: lines.length, disagreements: plan.disagreements,
|
|
10403
|
+
unfilled: unfilled.map((r) => ({ index: r.index, runId: r.runId, reason: r.skipped })),
|
|
10404
|
+
source: LEDGER_FILL_SOURCE, path: ledgerPath,
|
|
10405
|
+
}));
|
|
10406
|
+
return 0;
|
|
10407
|
+
}
|
|
10408
|
+
write('dz feature-adr-record --backfill: SCOPE — only tokens is derived; minutes and agents stay null (the run record exposes no duration, and the agents column means a different quantity than the spend-bearing agent ids). A row without a runId is matched by SLUG, and only when the slug names exactly one run.');
|
|
10409
|
+
write(`dz feature-adr-record --backfill: ${plan.filledRows} of ${lines.length} row(s) fillable from the host record${apply ? ' — WRITTEN' : ' (dry run; pass --yes to write)'}`);
|
|
10410
|
+
for (const d of plan.disagreements) {
|
|
10411
|
+
write(` DISAGREEMENT row ${d.index} ${d.field}: ledger says ${d.existing}, host record says ${d.derived} — the typed number stands, look at this`);
|
|
10412
|
+
}
|
|
10413
|
+
const byReason = new Map();
|
|
10414
|
+
for (const r of unfilled)
|
|
10415
|
+
byReason.set(String(r.skipped), (byReason.get(String(r.skipped)) ?? 0) + 1);
|
|
10416
|
+
for (const [reason, n] of byReason)
|
|
10417
|
+
write(` not filled: ${n} row(s) — ${reason}`);
|
|
10418
|
+
return 0;
|
|
10419
|
+
}
|
|
10271
10420
|
function cmdFeatureAdrRecord(options, flags, cwd, write) {
|
|
10272
10421
|
const json = flags.has('json');
|
|
10422
|
+
// `--backfill` is a different verb on the same store: it fills the ledger's null cost fields from
|
|
10423
|
+
// the host's own workflow record. DRY-RUN BY DEFAULT — this rewrites an append-only log, so the
|
|
10424
|
+
// writing form must be asked for (`--yes`), the same contract `dz publish` and `sync-canonical`
|
|
10425
|
+
// already use. See ledger-backfill.ts for the four rules the plan obeys.
|
|
10426
|
+
if (flags.has('backfill'))
|
|
10427
|
+
return cmdLedgerBackfill(options, flags, cwd, write);
|
|
10273
10428
|
const kind = (options.get('kind') ?? '').trim();
|
|
10274
10429
|
const stage = (options.get('stage') ?? '').trim();
|
|
10275
10430
|
const slug = (options.get('slug') ?? '').trim();
|
|
@@ -10310,6 +10465,11 @@ function cmdFeatureAdrRecord(options, flags, cwd, write) {
|
|
|
10310
10465
|
});
|
|
10311
10466
|
if (decision.line === null)
|
|
10312
10467
|
return emit(decision);
|
|
10468
|
+
// Declared out here because the READ-BACK below must verify what was ACTUALLY written, not what
|
|
10469
|
+
// the decision proposed — the ledger path enriches the line with a resolved runId before the
|
|
10470
|
+
// append, and comparing against the pre-enrichment text made every ledger write report
|
|
10471
|
+
// "not-verified" (caught by running it, not by reading it).
|
|
10472
|
+
let lineToWrite = decision.line;
|
|
10313
10473
|
// MEASURE, never assume: an unwritable target is a LOUD refusal, because a swallowed mkdir failure
|
|
10314
10474
|
// is exactly how a write becomes a silent no-op (acid case A4).
|
|
10315
10475
|
try {
|
|
@@ -10331,7 +10491,28 @@ function cmdFeatureAdrRecord(options, flags, cwd, write) {
|
|
|
10331
10491
|
return emit({ verdict: 'refused', exit: 2, reason: `the target could not be prepared: ${err.message}`, blocking: false, line: null });
|
|
10332
10492
|
}
|
|
10333
10493
|
try {
|
|
10334
|
-
|
|
10494
|
+
// WRITE-TIME RUN-ID RESOLUTION. The sandboxed workflow cannot know its own run id — it is not in
|
|
10495
|
+
// `args` and not a sandbox global — so 16 of 20 automatic ledger rows carried no join key at all
|
|
10496
|
+
// and nothing could ever be joined to them (MEASURED 2026-08-25). This command runs on the host,
|
|
10497
|
+
// where the records live, so it answers the question the sandbox cannot. Resolving HERE beats
|
|
10498
|
+
// resolving later: right now the run is in flight and is simply the newest for this slug; an hour
|
|
10499
|
+
// from now the same slug may have several and the choice becomes a guess. Refuses on any tie.
|
|
10500
|
+
lineToWrite = decision.line;
|
|
10501
|
+
if (kind === 'ledger') {
|
|
10502
|
+
try {
|
|
10503
|
+
const parsed = JSON.parse(decision.line);
|
|
10504
|
+
if (parsed !== null && typeof parsed === 'object' && !Array.isArray(parsed)) {
|
|
10505
|
+
const rowObj = parsed;
|
|
10506
|
+
const resolved = resolveLedgerRunId(rowObj, listCostLedgerRuns());
|
|
10507
|
+
if (resolved !== null) {
|
|
10508
|
+
// Marked, because a resolved run id is our inference, not something the pipeline knew.
|
|
10509
|
+
lineToWrite = JSON.stringify({ ...rowObj, runId: resolved, runIdSource: 'resolved-at-write' });
|
|
10510
|
+
}
|
|
10511
|
+
}
|
|
10512
|
+
}
|
|
10513
|
+
catch { /* resolution is an ENRICHMENT; a failure must never cost the row itself */ }
|
|
10514
|
+
}
|
|
10515
|
+
appendFileSync(target, `${lineToWrite}\n`, 'utf-8');
|
|
10335
10516
|
}
|
|
10336
10517
|
catch (err) {
|
|
10337
10518
|
return emit({ verdict: 'refused', exit: 2, reason: `the append failed: ${err.message}`, blocking: false, line: null });
|
|
@@ -10346,7 +10527,7 @@ function cmdFeatureAdrRecord(options, flags, cwd, write) {
|
|
|
10346
10527
|
catch {
|
|
10347
10528
|
lastLine = null;
|
|
10348
10529
|
}
|
|
10349
|
-
return emit(decideReadBack(
|
|
10530
|
+
return emit(decideReadBack(lineToWrite, lastLine), { target });
|
|
10350
10531
|
}
|
|
10351
10532
|
function cmdAmendmentCheck(options, flags, cwd, write) {
|
|
10352
10533
|
const json = flags.has('json');
|
|
@@ -10512,7 +10693,9 @@ function cmdFeatureAdrCheckpoint(options, flags, cwd, write) {
|
|
|
10512
10693
|
const stateDir = join(featureDir, '.fa-state');
|
|
10513
10694
|
try {
|
|
10514
10695
|
mkdirSync(stateDir, { recursive: true });
|
|
10515
|
-
|
|
10696
|
+
// The CLI is the only participant with a clock — the sandboxed workflow has no `Date` — so the
|
|
10697
|
+
// write instant is stamped here, at the append, and nowhere inside the blob-mirrored serializer.
|
|
10698
|
+
appendFileSync(join(stateDir, 'checkpoints.jsonl'), stampCheckpointLine(verdict.line, new Date().toISOString()) + '\n', 'utf-8');
|
|
10516
10699
|
}
|
|
10517
10700
|
catch (err) {
|
|
10518
10701
|
const reason = err instanceof Error ? err.message : String(err);
|