@hraness/message-like-me 0.8.16 → 0.8.18
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 +14 -0
- package/README.md +1 -1
- package/dist/cli.js +1 -1
- package/docs/textbutler/architecture.md +11 -1
- package/docs/textbutler/local-data.md +8 -0
- package/package.json +7 -6
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.8.18 (2026-09-23)
|
|
4
|
+
|
|
5
|
+
- Bind legacy installation to the exact public `@hraness/message-like-me@0.8.18` npm package, with the same reviewed bytes mirrored in the immutable GitHub Release. This does not install the Textbutler menu companion or enable automatic replies.
|
|
6
|
+
- Let the local TextButler app build against a persistent owner signing identity with `--signing-identity`, so macOS permission grants such as Full Disk Access and Apple Events bind to a stable certificate instead of each ad-hoc rebuild's changing code hash. The managed app receipt records the signing class explicitly (`ad-hoc` or `certificate`), treats a signing-class change as a new permission target that requires reinstall, and rejects unreviewed signing classes at startup. Ad-hoc signing remains the default for development builds.
|
|
7
|
+
|
|
8
|
+
## 0.8.17 (2026-09-23)
|
|
9
|
+
|
|
10
|
+
- Bind legacy installation to the exact public `@hraness/message-like-me@0.8.17` npm package, with the same reviewed bytes mirrored in the immutable GitHub Release. This does not install the Textbutler menu companion or enable automatic replies.
|
|
11
|
+
- Add isolated per-contact habitats: each enrolled contact gets a private workspace whose bounded evolution loop proposes, evaluates and promotes reply-guidance updates through the admitted subscription driver, with journaled budgets and reservations.
|
|
12
|
+
- Harden the reply steel thread: an uncertain send is quarantined until the owner resolves it with `replies reconcile CONTACT [--sent|--failed]`, which can also prove delivery from bounded conversation history. Runs are retained for 90 days, restart recovery abandons pre-dispatch work and marks dispatched work indeterminate, and grant intent is recorded before any upstream request.
|
|
13
|
+
- Make dispatch cancellation exact: a reply that has crossed the dispatch boundary is never aborted into a false failure, transport receipts stay authoritative over hook errors, and gateway driver failures report stable budget, unavailable, and output fault classes.
|
|
14
|
+
- Keep the automatic loop honest under load: inbound events drain in batches, a degraded transport keeps pending work and only reports attention after repeated failures, reactions and echoes can no longer erase or trigger pending replies, and a continuous inbound stream is answered within a bounded debounce instead of starving.
|
|
15
|
+
- Accept bare-object driver output, map silent suggestions to an explicit outcome, supervise the messaging transport child with custody-verified recovery, keep injected contact-workspace guidance out of trusted policy, and reseal the reviewed XCB composition receipt over the current sources.
|
|
16
|
+
|
|
3
17
|
## 0.8.16 (2026-09-22)
|
|
4
18
|
|
|
5
19
|
- Bind legacy installation to the exact public `@hraness/message-like-me@0.8.16` npm package, with the same reviewed bytes mirrored in the immutable GitHub Release. This does not install the Textbutler menu companion or enable automatic replies.
|
package/README.md
CHANGED
|
@@ -167,7 +167,7 @@ Message Like Me requires Bun 1.3.14 or newer. Install the exact public npm
|
|
|
167
167
|
package, then install both bundled Agent Skills:
|
|
168
168
|
|
|
169
169
|
```sh
|
|
170
|
-
bun add --global @hraness/message-like-me@0.8.
|
|
170
|
+
bun add --global @hraness/message-like-me@0.8.18
|
|
171
171
|
messagelikeme skill install
|
|
172
172
|
```
|
|
173
173
|
|
package/dist/cli.js
CHANGED
|
@@ -25088,7 +25088,7 @@ function commandPlatformLive(io, cleanupFailure) {
|
|
|
25088
25088
|
import { isAbsolute as isAbsolute7, resolve as resolve8 } from "path";
|
|
25089
25089
|
|
|
25090
25090
|
// src/version.ts
|
|
25091
|
-
var MESSAGE_LIKE_ME_VERSION = "0.8.
|
|
25091
|
+
var MESSAGE_LIKE_ME_VERSION = "0.8.18";
|
|
25092
25092
|
|
|
25093
25093
|
// src/command-input.ts
|
|
25094
25094
|
var HELP = `Message Like Me ${MESSAGE_LIKE_ME_VERSION}
|
|
@@ -26,7 +26,7 @@ flowchart LR
|
|
|
26
26
|
|
|
27
27
|
Ghostget owns native permissions, message and contact acquisition, provider actions, and receipts. Textbutler does not open chat.db or automate Messages directly. xcb owns subscription credentials, provider admission, model catalogs, confinement, cancellation and account custody. Textbutler invokes its native zero-tool generation API and interprets returned operation proposals through its own contact broker. Textbutler owns conversation policy and the durable send transaction. The menu companion changes owner settings through a small local protocol; it never gives a model arbitrary local commands.
|
|
28
28
|
|
|
29
|
-
The background lifecycle uses a user LaunchAgent: native messaging belongs to the signed-in Mac user, and login persistence is independent of the menu companion. Installation records the exact runtime, entrypoint, data directory and generation; removal verifies its private receipt and loaded service identity. Uninstall preserves contact data. New settings start paused. A private SQLite custody lock prevents duplicate daemon ownership and permits recovery only for a dead recorded process and its exact unserved socket. A minimal native TextButler.app can supervise the verified daemon so Full Disk Access belongs to the app. Its private installation receipt pins the runtime, payload, native executable and signature resources; a changed identity blocks startup. The app accepts fixed daemon, menu and iMessage setup roles, with no arbitrary command passthrough. Local builds
|
|
29
|
+
The background lifecycle uses a user LaunchAgent: native messaging belongs to the signed-in Mac user, and login persistence is independent of the menu companion. Installation records the exact runtime, entrypoint, data directory and generation; removal verifies its private receipt and loaded service identity. Uninstall preserves contact data. New settings start paused. A private SQLite custody lock prevents duplicate daemon ownership and permits recovery only for a dead recorded process and its exact unserved socket. A minimal native TextButler.app can supervise the verified daemon so Full Disk Access belongs to the app. Its private installation receipt pins the runtime, payload, native executable and signature resources; a changed identity blocks startup. The app accepts fixed daemon, menu and iMessage setup roles, with no arbitrary command passthrough. Local builds default to an ad-hoc signature, so a rebuilt app may require a fresh macOS permission grant; building with a persistent signing identity keeps grants bound to that certificate across rebuilds.
|
|
30
30
|
|
|
31
31
|
The daemon serves owner controls, enrollment jobs and a reply loop through its own supervised Ghostget process. Startup, enablement and recovery establish a silent event boundary, refresh bounded history and admit only subsequent eligible inbound messages. A failed catch-up pauses the affected conversation. No provider work starts without explicit owner account configuration.
|
|
32
32
|
|
|
@@ -106,6 +106,16 @@ An owner send reuses the contact's live standing grant when it covers the needed
|
|
|
106
106
|
|
|
107
107
|
`replies.send` returns `submitted`, `failed`, `partial`, `cancelled`, or `indeterminate`. An indeterminate owner send blocks the next reply for that contact — automatic or owner-initiated — until the journaled intent is reconciled, exactly like an automatic send.
|
|
108
108
|
|
|
109
|
+
## Contact habitats
|
|
110
|
+
|
|
111
|
+
When the owner enables `habitat` in `host.json`, each enrolled conversation gets an isolated habitat: a bounded, durable learning state stored in the private run journal, plus a fast reply driver and a slower background evolver. Habitat state is never shared between conversations — two threads to the same person keep separate habitats.
|
|
112
|
+
|
|
113
|
+
The fast driver answers ordinary replies with one bounded model call instead of the multi-turn subscription loop. The default route is a Vercel AI Gateway Qwen model with reasoning disabled; a local OpenAI-compatible endpoint is the alternative route. Prompt, context, output and wall-clock budgets are fixed in code. A classified response and its composition share the same inference, and follow-up learning starts only after the transport accepts a submitted reply — never on a draft.
|
|
114
|
+
|
|
115
|
+
Evolution runs in the background when the contact is idle: it re-reads the reply's intended purpose against a bounded window of later messages and reactions, proposes a candidate plan, replays incumbent and candidate on retained cases with blinded ordering, and asks an independent judge for per-case scores. Promotion requires follow-up evidence, cited evidence IDs, safety on every case, no regression, and a bounded improvement margin. Every step keeps replayable Algal receipts in the private journal. Plans are data, not code: they can adjust guidance, context size, reply length, humor and bounded tool flags, but never providers, accounts, recipients, permissions, disclosure, or executable programs. Explicit owner rollback restores a retained ancestor plan.
|
|
116
|
+
|
|
117
|
+
External effects stay host-brokered and off by default. Web search uses the gateway's server-side Exa tool; it is disabled in the default plan, admitted queries are checked against the private corpus for identifier shapes, verbatim spans and proper nouns, and results are untrusted excerpts. Meme search matches a bounded public Imgflip catalog locally, admits only known template images after byte and signature validation, and never uploads conversation text or captions. Billed calls reserve against a global daily budget in the journal before dispatch; provider-reported generation costs settle each reservation to its actual amount, and ambiguous outcomes retain the conservative reservation with no retry. The production gateway key itself also carries a provider-enforced daily quota.
|
|
118
|
+
|
|
109
119
|
## Hooks and plugins
|
|
110
120
|
|
|
111
121
|
The initial lifecycle is `message.received`, `reply.decide`, `reply.compose`, `reply.before-send`, `reply.sent`, `memory.updated`, and `run.failed`. Hooks have a named/versioned owner-installed extension, deterministic registration order, a deadline, and a cancellation signal. Failure before dispatch closes admission. A notification-hook failure after a receipt cannot change that receipt or trigger resend.
|
|
@@ -23,6 +23,14 @@ A pending transition also keeps `state/macos-app-upgrade.json` in the data
|
|
|
23
23
|
directory until completion or rollback is proven. Keep both locations intact
|
|
24
24
|
while an upgrade is unresolved.
|
|
25
25
|
|
|
26
|
+
When habitats are enabled, the run journal additionally keeps per-contact
|
|
27
|
+
habitat state (the promoted reply plan, bounded reply episodes, observed
|
|
28
|
+
follow-up windows, evaluation records and rollback lineage), replayable
|
|
29
|
+
inference receipts for each evaluation, and a global daily table of API
|
|
30
|
+
usage reservations with their provider-cost settlements. Gateway and other
|
|
31
|
+
provider credentials live under `state/provider-credentials` with owner-only
|
|
32
|
+
permissions; they never enter contact workspaces or journal evidence.
|
|
33
|
+
|
|
26
34
|
The explicit legacy iMessage crash reconciliation script accepts a private
|
|
27
35
|
witness for the Ghostget 0.18.16 startup failure. It checks the original crash,
|
|
28
36
|
app, connector, account and process state, then archives a bounded settlement
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hraness/message-like-me",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.18",
|
|
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",
|
|
@@ -92,18 +92,19 @@
|
|
|
92
92
|
"@hraness/oh": "https://github.com/hraness/oh/releases/download/v0.10.8/hraness-oh-0.10.8.tgz"
|
|
93
93
|
},
|
|
94
94
|
"devDependencies": {
|
|
95
|
-
"@hraness/agentmixer": "https://github.com/hraness/agentmixer/releases/download/v0.1.1/hraness-agentmixer-0.1.1.tgz",
|
|
96
95
|
"@anthropic-ai/claude-agent-sdk": "0.3.268",
|
|
97
|
-
"@hraness/desktop-foundation": "https://github.com/hraness/desktop-foundation/releases/download/v0.7.0/hraness-desktop-foundation-0.7.0.tgz",
|
|
98
96
|
"@anthropic-ai/sdk": "0.125.0",
|
|
97
|
+
"@hraness/agentmixer": "https://github.com/hraness/agentmixer/releases/download/v0.1.1/hraness-agentmixer-0.1.1.tgz",
|
|
98
|
+
"@hraness/algal": "github:hraness/algal#c5bd50452a676dc0b035ef206178c397de0cba92",
|
|
99
|
+
"@hraness/desktop-foundation": "https://github.com/hraness/desktop-foundation/releases/download/v0.7.0/hraness-desktop-foundation-0.7.0.tgz",
|
|
100
|
+
"@hraness/local-custody": "github:hraness/local-custody#v0.4.0",
|
|
101
|
+
"@hraness/support-foundation": "github:hraness/support-foundation#2d034b357680353574411217d68b02b6755b07ed",
|
|
99
102
|
"@modelcontextprotocol/sdk": "1.30.0",
|
|
100
103
|
"@types/bun": "1.3.14",
|
|
101
104
|
"effect": "3.22.1",
|
|
102
105
|
"fast-check": "4.9.0",
|
|
103
106
|
"sigstore": "4.1.1",
|
|
104
107
|
"typescript": "6.0.3",
|
|
105
|
-
"zod": "4.6.2"
|
|
106
|
-
"@hraness/support-foundation": "github:hraness/support-foundation#2d034b357680353574411217d68b02b6755b07ed",
|
|
107
|
-
"@hraness/local-custody": "github:hraness/local-custody#v0.4.0"
|
|
108
|
+
"zod": "4.6.2"
|
|
108
109
|
}
|
|
109
110
|
}
|