@hraness/message-like-me 0.8.2 → 0.8.3

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/CHANGELOG.md CHANGED
@@ -1,5 +1,22 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.8.3 (2026-09-06)
4
+
5
+ - Let Beeper users bring a finished private Wrench bundle into the same local
6
+ evidence corpus as Apple Messages and the other supported sources. The exact
7
+ public producer is `@hraness/wrench@0.16.7` with adapter
8
+ `beeper-local@2.4.0`.
9
+ - Pin the reviewed Beeper surface at 32 operations: 26 run through one Beeper
10
+ CLI 0.6.2 executable, including supported actions and writes, plus six fixed
11
+ Desktop loopback reads. The upstream tagged source package's 0.6.1
12
+ declaration is provenance only; executable 0.6.2 is runtime authority.
13
+ - State the process boundary consistently: Message Like Me receives no provider
14
+ credentials, never calls Wrench or Beeper operations, never sends, and keeps
15
+ every ingest path read-only with respect to its source.
16
+ - Make the exact public `@hraness/message-like-me@0.8.3` npm package the
17
+ supported default install, with the same reviewed bytes mirrored in the
18
+ immutable GitHub Release.
19
+
3
20
  ## 0.8.2
4
21
 
5
22
  - Fix the automated release admission so the npm provenance signer policy
package/README.md CHANGED
@@ -11,6 +11,12 @@ The CLI owns ingestion, storage, measurement, and export. Its copied Message
11
11
  Like Me and Ensoul Agent Skills teach Codex, Claude, and other coding agents how
12
12
  to interpret those artifacts through the agent environment you already use.
13
13
 
14
+ Beeper users can bring a bounded observation from supported connected accounts
15
+ into the same private evidence layer as Apple Messages. Wrench writes a finished
16
+ local bundle; Message Like Me verifies and ingests that directory. It receives
17
+ no provider credentials, never calls Wrench or a Beeper operation, and never
18
+ sends. Every ingest path is read-only with respect to its source.
19
+
14
20
  The result is an inspectable evidence layer for relationship-aware drafting,
15
21
  not a model of your identity. Your current meaning, facts, and intent outrank
16
22
  historical style.
@@ -37,7 +43,7 @@ Message Like Me requires Bun 1.3.14 or newer. Install the exact public npm
37
43
  package, then install both bundled Agent Skills:
38
44
 
39
45
  ```sh
40
- bun add --global @hraness/message-like-me@0.8.2
46
+ bun add --global @hraness/message-like-me@0.8.3
41
47
  messagelikeme skill install
42
48
  ```
43
49
 
@@ -101,8 +107,8 @@ visibly instead of being treated as current.
101
107
  | --- | --- | --- |
102
108
  | Apple Messages | The current macOS user's native `chat.db` history | Read-only ingestion from an ownership-checked stable local copy; Messages is never operated or changed. |
103
109
  | X data archive | Direct-message history in a caller-owned archive ZIP | X Chat is not included; the importer does not contact X, extract the archive, or download media. |
104
- | Beeper via Wrench | A bounded local bundle produced by verified Wrench v0.16.5 with Beeper adapter 2.3.0 and executable runtime 0.6.2 | Message Like Me owns zero Beeper operations, credentials, or live sessions; it reads the finished bundle, never sends, and does not claim complete history. |
105
- | WhatsApp via Wrench | A one-account native bundle produced by Wrench v0.16.5 with official Wacli 0.15.0 | Reaction-shaped rows are omitted with `reaction-state-unproven` when current state cannot be proved. Message Like Me verifies the finished bundle and never operates WhatsApp. |
110
+ | Beeper via Wrench | A finished local bundle from Wrench v0.16.7 and adapter 2.4.0; its reviewed surface has 32 operations: 26 through one pinned Beeper CLI 0.6.2 executable, including supported actions and writes, plus six fixed Desktop loopback reads | Message Like Me receives no provider credentials, never calls Wrench or a Beeper operation, and never sends; it reads only the finished bundle and does not claim complete history. |
111
+ | WhatsApp via Wrench | A one-account native bundle produced by Wrench v0.16.7 with official Wacli 0.15.0 | Reaction-shaped rows are omitted with `reaction-state-unproven` when current state cannot be proved. Message Like Me verifies the finished bundle and never operates WhatsApp. |
106
112
  | macOS Contacts | Optional names and exact email or phone handles from AddressBook | Label enrichment only; Contacts is not a messaging-history source and is never changed. |
107
113
 
108
114
  ## Add private local history
@@ -181,12 +187,12 @@ same or a later archive preserves proven deduplication; archive absence does not
181
187
  delete retained history.
182
188
 
183
189
  To study accounts connected through Beeper, install the currently verified
184
- [`@hraness/wrench@0.16.5`](https://www.npmjs.com/package/@hraness/wrench/v/0.16.5)
190
+ [`@hraness/wrench@0.16.7`](https://www.npmjs.com/package/@hraness/wrench/v/0.16.7)
185
191
  package from npm, then use Wrench to create a new private Message Like Me
186
192
  bundle:
187
193
 
188
194
  ```sh
189
- bun add --global @hraness/wrench@0.16.5
195
+ bun add --global @hraness/wrench@0.16.7
190
196
  wrench beeper export-message-like-me \
191
197
  --auth <beeper-auth-id> \
192
198
  --output /absolute/private/path/beeper-bundle \
@@ -195,19 +201,21 @@ wrench beeper export-message-like-me \
195
201
 
196
202
  The optional `--limit-chats`, `--limit-messages`, and `--max-participants`
197
203
  flags lower the export bounds. The output path must be a normalized absolute
198
- path to a directory that does not already exist. Wrench v0.16.5 adapter
199
- `beeper-local@2.3.0` exposes 32 reviewed Beeper operations: 27 use the pinned
200
- CLI and 5 use fixed Desktop loopback reads. Message Like Me owns none of
201
- those operations. The bundle command enters Wrench's separate internal bounded
202
- export, which fixes the raw export arguments, excludes attachments, and
204
+ path to a directory that does not already exist. Wrench v0.16.7 adapter
205
+ `beeper-local@2.4.0` exposes 32 reviewed Beeper operations: 26 through one
206
+ pinned Beeper CLI 0.6.2 executable, including supported actions and writes, plus
207
+ six fixed Desktop loopback reads. Message Like Me never calls Wrench or any of
208
+ those Beeper operations. The bundle command enters Wrench's separate internal
209
+ bounded export, which fixes the raw export arguments, excludes attachments, and
203
210
  preserves explicit incomplete-coverage evidence instead of claiming full
204
211
  history.
205
212
 
206
213
  Wrench calls the pinned
207
214
  [official Beeper CLI 0.6.2 release](https://github.com/beeper/cli/releases/tag/v0%2E6%2E2)
208
- directly. The exact executable reports version `0.6.2`; the tagged source file
209
- `packages/cli/package.json` declares `0.6.1`. That source value is provenance
210
- only and never overrides the executable runtime identity. Wrench enumerates
215
+ directly. The executable reports version `0.6.2`, which is the runtime
216
+ authority. At the upstream tag, `packages/cli/package.json` declares `0.6.1`;
217
+ that source-package value is provenance only and never overrides the executable
218
+ runtime identity. Wrench enumerates
211
219
  the connected account realm, invokes `export --no-attachments` once per
212
220
  account in deterministic order, and reports the account ordinal, elapsed-time
213
221
  heartbeats, and cumulative validated chat and message counts on stderr. It
@@ -239,7 +247,7 @@ iMessage and prior bundle sources remain alongside it.
239
247
  The interchange, integrity, identity, and reimport laws are in the
240
248
  [version-one local message bundle contract](docs/local-message-bundle-v1.md).
241
249
  Message Like Me accepts bundle schema `1` with source ID `beeper-local` and
242
- source-transform version `1.1.0`. Wrench v0.16.5 is the currently verified
250
+ source-transform version `1.1.0`. Wrench v0.16.7 is the currently verified
243
251
  producer. Compatibility is determined by those exact manifest coordinates,
244
252
  not by an open-ended Wrench package range.
245
253
 
@@ -250,11 +258,11 @@ reappearance restores it. Older snapshots cannot overwrite newer state. Use
250
258
  `sources show <source-id> --private --json` only when you deliberately need the
251
259
  private provider account and source metadata.
252
260
 
253
- For native WhatsApp evidence, install Wrench v0.16.5 and let its official
261
+ For native WhatsApp evidence, install Wrench v0.16.7 and let its official
254
262
  Wacli 0.15.0 adapter create the one-account v2 bundle:
255
263
 
256
264
  ```sh
257
- bun add --global @hraness/wrench@0.16.5
265
+ bun add --global @hraness/wrench@0.16.7
258
266
  wrench whatsapp export-message-like-me \
259
267
  --auth <whatsapp-auth-id> \
260
268
  --output /absolute/private/path/whatsapp-bundle \
@@ -274,7 +282,7 @@ surfaces are excluded. The complete contract is in
274
282
  [local message bundle v2](docs/local-message-bundle-v2.md).
275
283
 
276
284
  Wacli v0.15.0 may retain an earlier emoji after a reaction is removed, so its
277
- local rows cannot prove current active reaction state. Wrench v0.16.5 omits
285
+ local rows cannot prove current active reaction state. Wrench v0.16.7 omits
278
286
  every reaction-shaped row and adds `reaction-state-unproven` when it observes
279
287
  one. An empty `reactions.ndjson` from this producer means reaction behavior was
280
288
  unobservable, not that the account had no reactions. The v2 wire contract keeps
package/dist/cli.js CHANGED
@@ -6214,7 +6214,7 @@ class LocalStore {
6214
6214
  }
6215
6215
 
6216
6216
  // src/version.ts
6217
- var MESSAGE_LIKE_ME_VERSION = "0.8.2";
6217
+ var MESSAGE_LIKE_ME_VERSION = "0.8.3";
6218
6218
 
6219
6219
  // src/x-archive.ts
6220
6220
  import { createHash as createHash4 } from "crypto";
@@ -1,18 +1,19 @@
1
1
  # Local message bundle version 1
2
2
 
3
- `message-like-me.local-message-bundle` is a private directory interchange for
4
- moving a bounded local provider observation into Message Like Me. It separates
5
- provider capture from analysis: a producer handles provider access and writes
6
- the bundle, while `messagelikeme ingest bundle` verifies and normalizes it. The
7
- importer never receives provider credentials, starts Wrench, invokes a Beeper
8
- operation, or sends a message.
3
+ Beeper users can bring a bounded provider observation into Message Like Me's
4
+ private local evidence layer without giving Message Like Me a provider
5
+ credential or send access. Wrench writes a finished
6
+ `message-like-me.local-message-bundle`; `messagelikeme ingest bundle` verifies
7
+ and normalizes that directory. The importer never starts or calls Wrench, never
8
+ invokes a Beeper operation, and never sends. Like every Message Like Me ingest
9
+ path, it is read-only with respect to its source.
9
10
 
10
11
  The currently verified producer is the local Beeper export in the
11
- [`@hraness/wrench@0.16.5`](https://www.npmjs.com/package/@hraness/wrench/v/0.16.5)
12
+ [`@hraness/wrench@0.16.7`](https://www.npmjs.com/package/@hraness/wrench/v/0.16.7)
12
13
  npm package:
13
14
 
14
15
  ```sh
15
- bun add --global @hraness/wrench@0.16.5
16
+ bun add --global @hraness/wrench@0.16.7
16
17
  wrench beeper export-message-like-me \
17
18
  --auth <beeper-auth-id> \
18
19
  --output <normalized-absolute-new-directory> \
@@ -31,16 +32,18 @@ express.
31
32
  ## Compatibility coordinates
32
33
 
33
34
  Message Like Me accepts schema version `1` with source ID `beeper-local` and
34
- source-transform version `1.1.0`. Wrench v0.16.5 emits those coordinates through
35
- adapter `beeper-local@2.3.0`. That adapter has 32 reviewed Beeper operations:
36
- 27 use the pinned CLI and 5 use fixed Desktop loopback reads. The Message
37
- Like Me bundle is made by Wrench's separate internal bounded export, not by a
38
- Message Like Me provider operation. It fixes the raw export arguments, excludes
39
- attachments, and preserves incomplete-coverage evidence. It does not claim a
40
- complete Beeper history.
41
-
42
- The pinned Beeper CLI executable reports version `0.6.2`. At the corresponding
43
- source tag, `packages/cli/package.json` declares `0.6.1`; that source value is
35
+ source-transform version `1.1.0`. Wrench v0.16.7 emits those coordinates through
36
+ adapter `beeper-local@2.4.0`. That adapter has 32 reviewed Beeper operations:
37
+ 26 through one pinned Beeper CLI 0.6.2 executable, including supported actions
38
+ and writes, plus six fixed Desktop loopback reads. The Message Like Me bundle is
39
+ made by Wrench's separate internal bounded export, not by a Message Like Me
40
+ provider operation. It fixes the raw export arguments, excludes attachments,
41
+ and preserves incomplete-coverage evidence. It does not claim a complete
42
+ Beeper history.
43
+
44
+ The pinned Beeper CLI executable reports version `0.6.2`; that executable is
45
+ the runtime authority. At the upstream source tag,
46
+ `packages/cli/package.json` declares `0.6.1`; that source-package value is
44
47
  provenance only and never overrides executable runtime identity. A later Wrench
45
48
  package release remains compatible only while its manifest still declares the
46
49
  same bundle schema, source ID, and `source.version: "1.1.0"`. Package age,
@@ -49,8 +52,9 @@ coordinates. The provider version records the pinned Beeper CLI used for
49
52
  capture and may change without changing the bundle contract.
50
53
 
51
54
  Message Like Me owns zero Beeper operations, credentials, or live sessions. It
52
- does not start Wrench, call the provider, or support sending. Its authority
53
- begins at strict verification of the already finished private directory.
55
+ does not start or call Wrench, call the provider, or support sending. Its
56
+ authority begins at strict verification of the already finished private
57
+ directory.
54
58
 
55
59
  The dependency-free package subpath is the executable contract authority for
56
60
  producers and consumers:
@@ -10,7 +10,7 @@ network, or sends a message.
10
10
  The intended producer flow is:
11
11
 
12
12
  ```sh
13
- bun add --global @hraness/wrench@0.16.5
13
+ bun add --global @hraness/wrench@0.16.7
14
14
  wrench whatsapp export-message-like-me \
15
15
  --auth <whatsapp-auth-id> \
16
16
  --output /absolute/private/path/whatsapp-bundle
@@ -20,7 +20,7 @@ messagelikeme ingest bundle \
20
20
  --json
21
21
  ```
22
22
 
23
- The checked compatibility coordinates are Wrench v0.16.5 and official Wacli
23
+ The checked compatibility coordinates are Wrench v0.16.7 and official Wacli
24
24
  v0.15.0. Wrench owns that executable dependency and its authentication state;
25
25
  neither enters Message Like Me.
26
26
 
@@ -89,7 +89,7 @@ byte disagreement, and SHA-256 disagreement. The same public bounds as v1
89
89
  apply, except v2 admits exactly one account.
90
90
 
91
91
  The v2 wire contract retains the fixed `reactions.ndjson` artifact and strict
92
- reaction parser for proven records. The checked Wrench v0.16.5/Wacli v0.15.0
92
+ reaction parser for proven records. The checked Wrench v0.16.7/Wacli v0.15.0
93
93
  producer leaves that artifact empty because it cannot prove current reaction
94
94
  state.
95
95
 
@@ -162,7 +162,7 @@ duplicates cannot prove equivalence.
162
162
 
163
163
  Both source provenances and all source-unique history remain stored. Proven
164
164
  message duplicates contribute once. A reaction can deduplicate only when a
165
- conforming producer supplies a proven reaction record; Wrench v0.16.5 supplies
165
+ conforming producer supplies a proven reaction record; Wrench v0.16.7 supplies
166
166
  none, so this overlap path does not reconcile reaction state. The native Wacli
167
167
  conversation is the preferred action route and carries the exact private
168
168
  `whatsappJid` coordinate. Its proven Beeper duplicate remains evidence with
@@ -164,51 +164,145 @@ App-pinned status context, integration ID, enforcement state, and empty bypass
164
164
  sets before admitting a release. Any drift blocks promotion until it is reviewed
165
165
  and repaired out of band.
166
166
 
167
- ### Bootstrap one workflow-control epoch
167
+ ### Review one workflow-control epoch
168
168
 
169
- The routine promotion is intentionally incapable of crossing a change to
169
+ Routine promotion remains incapable of silently crossing a change to
170
170
  `.github/workflows/**`. Its complete-history gate rejects that range before the
171
- key environment even though GitHub may allow a contents-capable token to move a
172
- ref to an existing workflow-changing commit. The permanent App has only
173
- `statuses:write` plus `metadata:read`; it cannot move any ref. The checked
174
- workflow must never mint persistent App `contents` or `workflows` authority or
175
- treat permission omission alone as the workflow-control boundary.
176
-
177
- When an already-established `website-production` ref predates reviewed workflow
178
- control changes, perform one separately approved control-epoch bootstrap after
179
- the target's immutable Release and public npm bytes have passed admission:
180
-
181
- 1. Record the exact current production SHA, exact release SHA, annotated tag,
182
- immutable Latest Release, ruleset readbacks, and the complete reviewed commit
183
- range. Let the routine promotion fail at its workflow-range gate; do not
184
- approve the key environment for that rejected run.
185
- 2. In an owner-operated, out-of-band procedure, explicitly authorize a single
186
- control-epoch credential selected to numeric repository ID `1342143606` with
187
- only the temporary permissions needed to post the pinned status and move the
188
- workflow-changing ref. Keep that credential out of Actions and preserve the
189
- required-status-check and ref-lifecycle rulesets.
190
- 3. Post the exact App-sourced success status for the release SHA, then use the
191
- same fixed repository, exact annotated-tag target, and nonempty
192
- `--force-with-lease=refs/heads/website-production:<expected-old-sha>` contract
193
- to make exactly one fast-forward. Immediately replace the success with the
194
- terminal non-success status, revoke the credential, and prove the ref is the
195
- exact release SHA. Never leave a reusable success context behind.
196
- 4. Restore and read back the permanent App's exact `statuses:write` plus
197
- `metadata:read` closure, absence of `contents` and `workflows` authority, and
198
- singleton repository set. Generate a fresh App private key, replace
199
- `MLM_RELEASE_APP_PRIVATE_KEY`, and delete the control-epoch key. Routine
200
- automation must remain paused until both the App downgrade and key rotation
201
- are proven.
202
- 5. Dispatch `Promote website production` for the same immutable tag. Because
203
- the external bootstrap made the ref already exact, recovery stays outside
204
- `production-ref-writer-key`, mints no token, and accepts only the bounded
205
- exact-SHA Vercel Production outcome that postdates the Release.
206
-
207
- That bootstrap closes one workflow-control epoch; it is not precedent for a
208
- routine broad token, a persistent ref bypass, or an unleased manual ref move.
209
- Any later release whose newly reachable history contains a workflow-tree change
210
- starts a new control epoch and requires its own explicit review and
211
- authorization.
171
+ key environment. A reviewed workflow change uses the v2 control-epoch digest;
172
+ it does not use an out-of-band ref write or broaden either credential. The
173
+ permanent App remains exactly `statuses:write` plus `metadata:read`, and only the
174
+ job-scoped `GITHUB_TOKEN` may perform the existing explicit-lease ref move after
175
+ the pinned App status exists.
176
+
177
+ When an established protected ref predates reviewed workflow-control changes:
178
+
179
+ 1. Keep the workflow disabled except during each separately bound dispatch. Record the
180
+ exact protected-ref SHA, target SHA, current workflow-source SHA, repository
181
+ ID, tag coordinate, ruleset readbacks, and public release admission. Dispatch
182
+ the production or canary workflow once with an empty
183
+ `control_epoch_digest`. That run must fail at the complete-history gate before
184
+ the contents-writer environment is admitted and before any status-only App
185
+ token is minted.
186
+ 2. Preserve the failed step summary. It must contain the exact v2
187
+ domain, protected ref, old SHA, target SHA, current workflow-source SHA, tag
188
+ (or canary `no-tag` sentinel), ordered old-through-workflow-source commit inventory,
189
+ every corresponding `.github/workflows` tree OID, the derived ordered change
190
+ list, and the canonical lowercase SHA-256 digest. Independently reconstruct
191
+ that inventory from only the governed refs and review every workflow-tree
192
+ transition. Failed-step command-file outputs are not retrievable review
193
+ evidence. Do not trust the digest without reviewing its complete preimage.
194
+ In a disposable, complete, non-shallow clone populated only with the exact
195
+ advertised `main`, protected branch, and (for production) stable annotated-tag
196
+ refs, substitute the recorded values and reconstruct the ordered inventory:
197
+
198
+ ```sh
199
+ protected_ref=refs/heads/website-production # use the canary ref for a canary run
200
+ old_sha=<40-hex-protected-ref-sha>
201
+ target_sha=<40-hex-target-sha>
202
+ workflow_sha=<40-hex-current-main-sha>
203
+ tag=<stable-tag-or-no-tag>
204
+
205
+ test "$(git rev-parse --is-shallow-repository)" = false
206
+ test "$(git rev-parse --verify "${protected_ref}^{commit}")" = "$old_sha"
207
+ test "$(git rev-parse --verify 'refs/heads/main^{commit}')" = "$workflow_sha"
208
+ git merge-base --is-ancestor "$old_sha" "$target_sha"
209
+ git merge-base --is-ancestor "$target_sha" "$workflow_sha"
210
+ if [ "$tag" = no-tag ]; then
211
+ test "$target_sha" = "$workflow_sha"
212
+ else
213
+ test "$(git rev-parse --verify "refs/tags/${tag}^{commit}")" = "$target_sha"
214
+ fi
215
+ test "$(git rev-list --count "$old_sha..$workflow_sha")" -le 250
216
+ {
217
+ printf '%s\n' "$old_sha"
218
+ git rev-list --topo-order --reverse "$old_sha..$workflow_sha"
219
+ } | while IFS= read -r commit_sha; do
220
+ printf '%s %s\n' "$commit_sha" \
221
+ "$(git rev-parse --verify "${commit_sha}:.github/workflows")"
222
+ done
223
+ ```
224
+
225
+ Compare every printed commit/tree pair, in order, with the failed-run summary;
226
+ adjacent rows with different tree OIDs must exactly match its changed-row
227
+ markers. The target must appear in that inventory. Then use the reviewed
228
+ helper from that same audited workflow-source checkout to reconstruct the
229
+ canonical receipt and digest:
230
+
231
+ ```sh
232
+ MODE=production \
233
+ PREVIOUS_SHA="$old_sha" \
234
+ TARGET_SHA="$target_sha" \
235
+ WORKFLOW_SHA="$workflow_sha" \
236
+ PROTECTED_REF="$protected_ref" \
237
+ VERIFIED_TAG="$tag" \
238
+ node --input-type=module -e '
239
+ import { describeControlEpoch } from "./scripts/release-workflow-range.mjs";
240
+ const receipt = describeControlEpoch({
241
+ currentMainSha: process.env.WORKFLOW_SHA,
242
+ mode: process.env.MODE,
243
+ previousSha: process.env.PREVIOUS_SHA,
244
+ protectedRef: process.env.PROTECTED_REF,
245
+ repository: "hraness/message-like-me",
246
+ repositoryId: 1342143606,
247
+ tag: process.env.VERIFIED_TAG,
248
+ targetSha: process.env.TARGET_SHA,
249
+ workflowSha: process.env.WORKFLOW_SHA,
250
+ });
251
+ process.stdout.write(JSON.stringify(receipt) + "\n");
252
+ '
253
+ ```
254
+
255
+ The resulting JSON's domain, ref, coordinates, ordered `inventory`, derived
256
+ `changes`, and `digest` must exactly match the human-readable failed-step
257
+ summary. Use `MODE=canary`, the canary ref, `tag=no-tag`, and a target equal to
258
+ the workflow source for a canary review. Do not fetch an unbounded ref
259
+ namespace, hand-assemble a digest, use a different checkout, or reorder the
260
+ inventory.
261
+ 3. Dispatch one fresh manual attempt 1 from exact current `main` with that exact
262
+ digest. Automatic `workflow_run` events, rerun attempts, already-exact refs,
263
+ and unchanged-workflow ranges must reject any digest. The gate recomputes the
264
+ complete inventory and digest before environment admission; any source, tag,
265
+ ref, target, ancestry, inventory, or digest drift fails closed.
266
+ 4. Before approving `production-ref-writer-key`, compare the fresh run title,
267
+ tag, v2 domain, protected ref, old SHA, target SHA, workflow-source SHA,
268
+ ordered inventory, change list, and digest with both the independently
269
+ reviewed failed-run summary and the locally reconstructed receipt. Reject the
270
+ environment admission if any field or ordered
271
+ inventory row differs. After approval, the hash-pinned helper
272
+ recomputes and revalidates the same transition before reading the key. The
273
+ normal split-authority sequence then applies unchanged: terminalize the status
274
+ to the exact App-authored `error`, then prove the writer is denied with one exact
275
+ `GH013: Repository rule violations found for refs/heads/website-production.`
276
+ payload and one exact `remote: - Required status check "message-like-me/website-production-authority" is errored.`
277
+ reason. Before exact comparison, normalize only one consistent known Git
278
+ non-TTY display suffix: zero, one, or eight ASCII spaces on both semantic
279
+ remote lines. Any other trailing byte, suffix length, or mixed framing is a
280
+ rejection. Mutable
281
+ Git progress, transport ordering, and helper-label framing are diagnostic
282
+ only; the hash-pinned helper's fixed executable, remote, arguments, and
283
+ refspec bind the operation.
284
+ Post and read back one App-authored success,
285
+ revoke that App token, make one exact non-force fast-forward with a nonempty
286
+ expected-old lease, replace success with the terminal non-success status
287
+ using a separately minted status-only token, revoke it, and complete the
288
+ read-only provider outcome gate.
289
+ 5. After provider success, read back the protected ref at the exact target and
290
+ treat that target's `.github/workflows` tree OID as the baseline for the next
291
+ routine range. Re-read the permanent App's exact `statuses:write` plus
292
+ `metadata:read` permissions, absence of `contents` and `workflows` authority,
293
+ singleton `{hraness/message-like-me}` repository selection, and the terminal
294
+ non-success status. A completed epoch requires no key rotation because it
295
+ created or replaced no credential and every short-lived App token was revoked;
296
+ an interrupted run still follows the separate quarantine and cleanup
297
+ procedure.
298
+
299
+ The digest is scoped to one exact transition and is never permission to reuse a
300
+ stale run, skip fresh ref and source readbacks, expand the App, add a personal
301
+ token or deploy key, recreate a protected ref, force a move, or mutate a
302
+ ruleset. If a run is interrupted, follow the quarantine and cleanup procedure;
303
+ never treat the digest as retry authority. A later range with any different
304
+ coordinate or inventory requires a new no-digest rejection and independent
305
+ review.
212
306
 
213
307
  ### Prove the split status-and-writer boundary before product release
214
308
 
@@ -217,16 +311,34 @@ release, precreate persistent ref
217
311
  `refs/heads/website-production-writer-canary` at the reviewed control commit.
218
312
  Apply separate active rulesets with the same no-bypass protections and the same
219
313
  App-pinned required status check to that exact canary ref. Prove every side of
220
- the split credential contract after the App downgrade and key rotation:
221
-
222
- 1. The negative workflow-delta canary targets a reviewed descendant that
223
- changes `.github/workflows/**`. The complete-history gate must reject it
224
- before environment admission and before token minting. Permission omission
225
- is not the gate: record the complete-history rejection itself.
226
- 2. The positive non-workflow canary targets a reviewed descendant for which
314
+ the split credential contract:
315
+
316
+ 1. The workflow-delta canary targets exact current `main`, which changes
317
+ `.github/workflows/**`. First prove the empty-digest rejection before
318
+ environment admission, independently review the complete v2 receipt, then
319
+ prove that one fresh manual attempt 1 with its exact digest recomputes the
320
+ transition before and after environment admission and advances only that
321
+ target. Permission omission is not the gate: retain both runs and their exact
322
+ receipts as evidence.
323
+ 2. A later positive non-workflow canary targets a reviewed descendant for which
227
324
  every newly reachable commit preserves the baseline workflow-tree OID. Prove
228
- the status-only App token cannot update the ref and the job-scoped writer
229
- token cannot update it before the exact App-sourced success exists.
325
+ it accepts no digest and uses the unchanged v1 routine receipt. Prove
326
+ the status-only App token cannot update the ref. After posting and reading
327
+ back the App-authored terminal `error`, prove the job-scoped writer token is
328
+ rejected with exactly one `GH013: Repository rule violations found for
329
+ refs/heads/website-production-writer-canary.` payload and exactly one
330
+ `remote: - Required status check "message-like-me/website-production-writer-canary-authority" is errored.`
331
+ reason. Before exact comparison, normalize only one consistent known Git
332
+ non-TTY display suffix: zero, one, or eight ASCII spaces on both semantic
333
+ remote lines. Any other trailing byte, suffix length, or mixed framing is a
334
+ rejection.
335
+ Mutable Git progress, transport ordering, and helper-label framing are
336
+ diagnostic only; the hash-pinned helper's fixed executable, remote,
337
+ arguments, and refspec bind the operation.
338
+ An `is expected` reason, a missing-status interpretation, another state,
339
+ branch, context, duplicate GH013 payload, or multiple rule reasons is not
340
+ this proof. The writer must remain unable to update until the exact
341
+ App-sourced success exists.
230
342
  3. Post one success status on the exact positive target under context
231
343
  `message-like-me/website-production-writer-canary-authority`, prove its exact
232
344
  readback, and revoke that short-lived status-only token. With the success
@@ -394,17 +506,23 @@ recovery. Both paths use the same checks. That workflow:
394
506
  3. enters `production-ref-writer-key` with `deployment:false` only when the
395
507
  baseline and a separate read-only preflight prove that the ref must advance.
396
508
  That preflight first imports complete exact governed history and enumerates
397
- every commit newly reachable in `<expected-old>..<verified-release>`, capped
398
- at 250 commits. It rejects shallow or incomplete history, non-fast-forwards,
399
- malformed or oversized inventories, and any commit whose
400
- `.github/workflows` tree OID differs from the expected-old baseline. Checking
401
- every newly reachable commit catches merge-side changes and an edit followed
402
- by a revert even when the two endpoint trees match. The fresh secret-bearing
403
- job installs no dependencies; in a step that does not receive the private
404
- key, it verifies hard-coded SHA-256 pins for the seven reviewed helpers,
405
- repeats the exact complete-history proof, and emits a bounded receipt binding
406
- the expected-old SHA, release SHA, commit count and digest, and baseline
407
- workflow-tree OID. The promotion helper validates that receipt before it may
509
+ every commit from the expected-old protected-ref SHA through the exact
510
+ current workflow-source SHA, capped at 250 newly reachable commits. It proves
511
+ the tagged release target is an advancing ancestor inside that range and
512
+ rejects shallow or incomplete history, non-fast-forwards, and malformed or
513
+ oversized inventories. Checking every ordered `.github/workflows` tree OID
514
+ catches merge-side changes and an edit followed by a revert even when two
515
+ endpoint trees match. If every tree preserves the baseline, any supplied
516
+ digest is forbidden and the frozen v1 receipt binds the expected-old and
517
+ release SHAs, transition commit count and digest, and baseline workflow-tree
518
+ OID. If any tree changes, the empty-digest attempt publishes the full v2
519
+ inventory, derived tree transitions, current workflow source, tagged target,
520
+ and canonical digest, then rejects before the writer environment. Only a
521
+ fresh manual attempt 1 carrying that independently reviewed exact digest may
522
+ continue. The secret-bearing job installs no dependencies; in a step that
523
+ does not receive the private key, it verifies hard-coded SHA-256 pins for the
524
+ seven reviewed helpers and recomputes the selected v1 or v2 receipt before
525
+ reading the key. The promotion helper validates that receipt before it may
408
526
  enter the App-token lifecycle. A checked local helper then signs a
409
527
  bounded RS256 App JWT, authenticates the exact App ID, client ID, slug, and
410
528
  organization owner, then reads the checked installation ID and requires its
@@ -605,9 +723,10 @@ exact existing npm version and immutable artifact-complete Latest Release. It
605
723
  never creates, replaces, or edits an npm version or GitHub Release.
606
724
 
607
725
  If `website-production` still precedes the release commit, recovery performs
608
- the same checked explicit-lease fast-forward only when every newly reachable
609
- commit preserves the baseline workflow-tree OID, and requires one new provider
610
- outcome.
726
+ the same checked explicit-lease fast-forward and requires one new provider
727
+ outcome. A baseline-preserving range uses the frozen v1 no-digest receipt; a
728
+ workflow-changing range requires the exact independently reviewed v2 digest and
729
+ recomputes its old-through-current-workflow-source inventory before authority.
611
730
  If the ref is already exact, the baseline marks advancement false, skips the
612
731
  entire `production-ref-writer-key` job, and mints no App token. A separate
613
732
  read-only job accepts only the unique latest exact-SHA Production deployment in
@@ -616,9 +735,10 @@ itself must be provider-accepted. A newer terminal failure, error, or inactive
616
735
  attempt blocks recovery instead of allowing an older success to be reused.
617
736
  Recovery then repeats the terminal authority readbacks. A missing ref is a hard
618
737
  failure and must not be recreated by the workflow. If the desired transition
619
- crosses any workflow change, use the separately approved control-epoch
620
- bootstrap above; after that exact external advancement, the already-exact
621
- recovery path supplies the provider proof without reading the App key.
738
+ crosses any workflow change, use the reviewed v2 control-epoch digest above.
739
+ The exact-digest attempt performs the normal checked lease advancement; it does
740
+ not externally advance the ref. A later already-exact recovery, if needed,
741
+ supplies only the provider proof and remains outside the key environment.
622
742
 
623
743
  When a tag run fails after its exact draft or immutable Release exists, preserve
624
744
  its evidence and rerun that same workflow. Re-running only failed jobs is
@@ -629,5 +749,5 @@ the same tag, commit, deterministic draft, and tarball; npm provenance must bind
629
749
  the same run ID and an allowed actual positive attempt. Correct only the failed
630
750
  control and use the website recovery path after public admission succeeds. Do
631
751
  not retag, delete the immutable Release or exact residual draft, manually move
632
- `website-production` outside the one separately approved control-epoch
633
- bootstrap, redeploy from Vercel, or weaken a ruleset to make the run pass.
752
+ `website-production`, reuse a stale control-epoch digest as retry authority,
753
+ redeploy from Vercel, or weaken a ruleset to make the run pass.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hraness/message-like-me",
3
- "version": "0.8.2",
3
+ "version": "0.8.3",
4
4
  "description": "A local-first CLI and Agent Skill for studying private messaging history and drafting messages that sound like you.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -116,7 +116,7 @@ messagelikeme ingest bundle --input <absolute-private-whatsapp-bundle> --json
116
116
  Do not request or handle Wacli session state or WhatsApp linked-device
117
117
  authentication, call Wacli, inspect its database, synchronize the account, or
118
118
  open bundle records in agent context. Wrench owns those provider operations.
119
- The Wrench v0.16.5/Wacli v0.15.0 producer omits every reaction-shaped row and
119
+ The Wrench v0.16.7/Wacli v0.15.0 producer omits every reaction-shaped row and
120
120
  reports `reaction-state-unproven` when it encounters one because current active
121
121
  or removed state is not durable. Treat that warning, and an empty reaction
122
122
  artifact from this producer, as unobservable reaction behavior. Do not infer
@@ -21,7 +21,7 @@ sensitive local data.
21
21
  synchronize a linked device, inspect its database, or expose exact JIDs.
22
22
  Wrench owns that provider boundary. `--overlap-source` requires explicit
23
23
  intent and exact CLI proof; it never authorizes fuzzy account or contact
24
- matching. The Wrench v0.16.5 producer omits reaction-shaped Wacli rows with
24
+ matching. The Wrench v0.16.7 producer omits reaction-shaped Wacli rows with
25
25
  `reaction-state-unproven`; never turn that missing evidence into a claim that
26
26
  no reactions occurred.
27
27
  - Treat a caller-owned X data archive ZIP as private source evidence. Pass only