@dzhechkov/harness-cli 0.7.5 → 0.7.6
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 +11 -11
- package/README.md +31 -3
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +55 -3
- package/dist/cli.js.map +1 -1
- package/dist/known-flags.d.ts.map +1 -1
- package/dist/known-flags.js +1 -0
- package/dist/known-flags.js.map +1 -1
- package/package.json +9 -9
- package/sbom.json +10 -10
- package/src/cli.ts +47 -2
- package/src/known-flags.ts +1 -0
package/.dz-manifest.json
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
},
|
|
10
10
|
{
|
|
11
11
|
"path": "README.md",
|
|
12
|
-
"sha256": "
|
|
12
|
+
"sha256": "ba98f7078023a6202a8bf809b83ae20ef44b3d2e1ca14ce0ae5aac83ffd8d51e"
|
|
13
13
|
},
|
|
14
14
|
{
|
|
15
15
|
"path": "dist/bin.d.ts",
|
|
@@ -49,15 +49,15 @@
|
|
|
49
49
|
},
|
|
50
50
|
{
|
|
51
51
|
"path": "dist/cli.d.ts.map",
|
|
52
|
-
"sha256": "
|
|
52
|
+
"sha256": "3c0a60e8d8528e1b7df6bf5678388ce14d3ac3d0362bde42bc8e7e712d914dbd"
|
|
53
53
|
},
|
|
54
54
|
{
|
|
55
55
|
"path": "dist/cli.js",
|
|
56
|
-
"sha256": "
|
|
56
|
+
"sha256": "f117e676f0a120e1314f3cc6416901931d9b389d97052985e1150fa75322b221"
|
|
57
57
|
},
|
|
58
58
|
{
|
|
59
59
|
"path": "dist/cli.js.map",
|
|
60
|
-
"sha256": "
|
|
60
|
+
"sha256": "718f0380983cb995fad2a30b87af79feb3b0c85656449957bada67956e7e8854"
|
|
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": "93d7a002824ed631f1459e922ac2cad08772e06a21777b64eed095933dd0e889"
|
|
117
117
|
},
|
|
118
118
|
{
|
|
119
119
|
"path": "dist/known-flags.js",
|
|
120
|
-
"sha256": "
|
|
120
|
+
"sha256": "64928f5f20cc647f86323b4d179c614613635eeb6a553fd7733bf5ebad653d70"
|
|
121
121
|
},
|
|
122
122
|
{
|
|
123
123
|
"path": "dist/known-flags.js.map",
|
|
124
|
-
"sha256": "
|
|
124
|
+
"sha256": "3cb9b072c57a3d9562cfb919c11c2b242db215169a4675b9940de46b67e0ccfa"
|
|
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": "4831c7b0121cb2a62464bc4d4844e6037a80f9e2d1e6e0934836bde14a1bffdb"
|
|
137
137
|
},
|
|
138
138
|
{
|
|
139
139
|
"path": "src/bin.ts",
|
|
@@ -145,7 +145,7 @@
|
|
|
145
145
|
},
|
|
146
146
|
{
|
|
147
147
|
"path": "src/cli.ts",
|
|
148
|
-
"sha256": "
|
|
148
|
+
"sha256": "f30fb7c6b0795758578a90de19b870c4cde42eb2009fa246051023f499374c09"
|
|
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": "b08dc5d28795419f642df56fbf5cd036a43a06bb1bec5e864f4e538b0a025b13"
|
|
165
165
|
}
|
|
166
166
|
]
|
|
167
167
|
},
|
|
168
|
-
"signature": "
|
|
168
|
+
"signature": "az3T9G53JK8QzlVMBBMgoXLUN0Awpx4vfe19JJVYkbN67X5FDWUn8nVhe8IRAIKogxxbmp9lgnLkeYOj/b2YCg=="
|
|
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,38 @@ npx @dzhechkov/p-replicator init
|
|
|
4096
4096
|
|
|
4097
4097
|
## Status
|
|
4098
4098
|
|
|
4099
|
-
`v0.7.
|
|
4099
|
+
`v0.7.6` — **`dz drift-check` and `dz sync-canonical` stop being a `.claude/skills` gate.** Skill-copy
|
|
4100
|
+
discovery searched `packages/` plus one hardcoded install root, so the four other per-target install
|
|
4101
|
+
trees were ungated — measurably: this repo's own Codex install of `feature-adr` under `.agents/skills`
|
|
4102
|
+
drifted for a day while `dz sync-canonical feature-adr --check` reported "all 3 copies match
|
|
4103
|
+
canonical" and the HARD `no-skill-drift` rule passed. The copy was missing both the K1 section of its
|
|
4104
|
+
`SKILL.md` and the C6 check of its gate script. Discovery is now driven by a target→install-root
|
|
4105
|
+
registry, and the HARD rule runs at a new scope covering generated installs while exempting the
|
|
4106
|
+
hand-edited dev tree (which legitimately lags — three real skills drift there today, so gating it
|
|
4107
|
+
would be red-on-arrival). **The guard legitimately gets STRICTER: a publish that passed before can now
|
|
4108
|
+
be BLOCKED by real drift in a non-`.claude` root — that is the gate working.** Target enrichment
|
|
4109
|
+
written by `dz init --enrich` is exempt from both the drift verdict and the healer, so `sync-canonical`
|
|
4110
|
+
cannot delete it. Also: `dz tg-post` gains `--max-per-day`, previously read by the code but
|
|
4111
|
+
unregistered.
|
|
4112
|
+
|
|
4113
|
+
`v0.7.6` — **the channel sender stops trusting itself.** `dz tg-post` could format-check, provenance-check
|
|
4114
|
+
and time-check a post and still publish it twice, or ten more times, or right through an operator who
|
|
4115
|
+
wanted everything stopped: nothing counted what had already gone out. It now runs three guards FAIL-CLOSED
|
|
4116
|
+
in a fixed order — a **stop-cord** file that halts even a perfect post before any cheaper check, **dedup**
|
|
4117
|
+
keyed on the sha256 of the post's VISIBLE text rather than its bytes, and a **daily limit** (10 by default,
|
|
4118
|
+
`--max-per-day <n>`) counted over the trailing 24h. The send journal is two-phase — `pending` written before
|
|
4119
|
+
the network call, `sent` after Telegram accepts — so a crash in that window is caught by dedup instead of
|
|
4120
|
+
double-publishing, and only accepted sends eat the ceiling. An unreadable journal refuses: an unreadable
|
|
4121
|
+
counter does not prove the ceiling is unreached. The provenance gate additionally clears `kind: url` — a
|
|
4122
|
+
well-formed http(s) URL is public by construction, while a `file://`, a bare path or a non-URL is refused
|
|
4123
|
+
and never inferred from its shape. Also: `dz challenge` is now discoverable from the CLI's own help surface
|
|
4124
|
+
(it existed and was reachable only if you already knew the name), and the adversary it assembles is fed all
|
|
4125
|
+
five calibration documents rather than a subset.
|
|
4126
|
+
|
|
4127
|
+
`v0.7.6` — **a signature-only republish.** `0.7.0` shipped through `pnpm publish` rather than
|
|
4100
4128
|
`dz publish`, so the re-signing step was skipped and 17 of 497 files in the published core did not
|
|
4101
4129
|
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.
|
|
4130
|
+
the shipped behaviour changes between `0.7.0` and `0.7.6`; the integrity check stops reporting these
|
|
4103
4131
|
packages as tampered. The one code change is a TEST: the compat case that asserted the workspace
|
|
4104
4132
|
core sits exactly on `MIN_CORE` is split into an integration half and a boundary half, so a patch
|
|
4105
4133
|
bump of core no longer reddens it and `MIN_CORE` need not claim a version the CLI does not require.
|
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,EA8UzB,KAAK,YAAY,
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.js
CHANGED
|
@@ -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 }));
|