@kingcrab/pi-imessage 0.0.42 → 1.0.0
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/README.md +101 -108
- package/dist/agent/behavior.js +79 -0
- package/dist/agent/chats.js +67 -0
- package/dist/agent/commands.js +163 -0
- package/dist/agent/compaction.js +51 -0
- package/dist/agent/deliver.js +139 -0
- package/dist/agent/direct-send.js +68 -0
- package/dist/agent/harness.js +79 -0
- package/dist/agent/health.js +32 -0
- package/dist/agent/models.js +69 -0
- package/dist/agent/progress-format.js +87 -0
- package/dist/agent/progress.js +135 -0
- package/dist/agent/prompt.js +79 -0
- package/dist/agent/replies.js +9 -0
- package/dist/agent/run.js +159 -0
- package/dist/agent/scheduling.js +290 -0
- package/dist/agent/time.js +18 -0
- package/dist/cli.js +88 -191
- package/dist/config/settings.js +60 -0
- package/dist/extensions/browser.js +326 -0
- package/dist/extensions/final-text.js +23 -0
- package/dist/extensions/memory.js +109 -0
- package/dist/extensions/message.js +33 -0
- package/dist/extensions/read-image.js +72 -0
- package/dist/extensions/schedules.js +41 -0
- package/dist/extensions/subagent.js +54 -0
- package/dist/extensions/web.js +99 -0
- package/dist/extensions/workspace.js +98 -0
- package/dist/main.js +571 -74
- package/dist/transport/attachments.js +37 -0
- package/dist/transport/http.js +110 -0
- package/dist/{rich-text.js → transport/rich-text.js} +25 -13
- package/dist/{send.js → transport/send.js} +13 -13
- package/dist/transport/watch.js +124 -0
- package/dist/web/app.js +748 -0
- package/dist/web/history.js +87 -0
- package/dist/web/memory.js +81 -0
- package/dist/web/page.js +28 -0
- package/dist/web/schedules.js +74 -0
- package/dist/web/server.js +348 -0
- package/dist/web/style.css +543 -0
- package/dist/web/tasks.js +63 -0
- package/docs/adr/0001-durable-owns-state.md +11 -0
- package/docs/adr/0002-module-layering.md +11 -0
- package/docs/adr/0003-replies-at-most-once.md +11 -0
- package/docs/adr/0004-native-extensions.md +11 -0
- package/docs/adr/0005-history-migration.md +11 -0
- package/docs/adr/0006-jsonl-storage.md +11 -0
- package/docs/adr/0007-images-by-path.md +11 -0
- package/docs/adr/0008-compaction-and-run.md +11 -0
- package/docs/adr/0009-one-shot-cutover.md +11 -0
- package/docs/adr/0010-test-budget.md +11 -0
- package/docs/adr/0011-reconcile-unsent-answers.md +24 -0
- package/docs/adr/0012-run-in-owned-conversation.md +22 -0
- package/docs/adr/0013-thin-adapters-around-durable.md +18 -0
- package/docs/adr/0014-ephemeral-private-storage.md +13 -0
- package/docs/adr/0015-ordinary-stop-keeps-native-inbox.md +21 -0
- package/docs/adr/0016-process-http-transport.md +21 -0
- package/docs/adr/0017-browser-cli-owned-scope.md +22 -0
- package/docs/adr/0018-tasks-without-prompt-api.md +19 -0
- package/docs/adr/0019-remove-scheduled-services.md +41 -0
- package/docs/adr/0020-chat-task-progress.md +41 -0
- package/docs/adr/0021-readable-progress-without-link-previews.md +33 -0
- package/docs/adr/0022-progress-admission-and-settlement.md +35 -0
- package/docs/adr/0023-retain-progress-type-prefixes.md +18 -0
- package/docs/adr/0024-status-marker-before-type-prefix.md +13 -0
- package/docs/adr/0025-reusable-progress-and-command-preview.md +49 -0
- package/docs/adr/0026-inline-command-only-requests.md +16 -0
- package/docs/adr/0027-command-preview-width.md +10 -0
- package/docs/adr/0028-command-preview-120.md +8 -0
- package/docs/adr/0030-shared-web-read-cache.md +33 -0
- package/docs/adr/0031-quiet-compaction-progress.md +32 -0
- package/docs/adr/0032-native-background-schedules.md +58 -0
- package/docs/adr/0033-operator-scheduled-run.md +23 -0
- package/docs/adr/0034-machine-local-schedule-time.md +36 -0
- package/docs/adr/0035-external-business-task-extensions.md +56 -0
- package/docs/adr/0036-workspace-policy-and-neutral-service-id.md +37 -0
- package/docs/adr/0037-restart-during-in-flight-work.md +30 -0
- package/docs/adr/0038-restart-any-time.md +25 -0
- package/docs/adr/0039-rerun-interrupted-tools.md +24 -0
- package/docs/adr/0040-chat-progress-notices.md +44 -0
- package/docs/adr/0041-restart-and-recovery.md +28 -0
- package/docs/adr/0042-background-schedules-and-workspace-extensions.md +44 -0
- package/docs/adr/0043-remove-legacy-migration.md +23 -0
- package/docs/adr/0044-message-channels.md +32 -0
- package/docs/adr/0045-chat-scheduling-tools.md +51 -0
- package/docs/adr/0046-selective-command-redaction.md +31 -0
- package/docs/adr/0047-one-scheduling-path.md +158 -0
- package/docs/adr/README.md +50 -0
- package/docs/api.md +92 -0
- package/docs/architecture.md +164 -0
- package/docs/browser.md +93 -0
- package/docs/memory.md +27 -0
- package/docs/screenshot.png +0 -0
- package/docs/workspace-extensions.md +133 -0
- package/examples/workspace-extensions/system-context/index.ts +69 -0
- package/examples/workspace-extensions/system-context/package.json +3 -0
- package/ops/README.md +267 -0
- package/ops/preflight.mjs +28 -0
- package/package.json +33 -45
- package/dist/agent.d.ts +0 -60
- package/dist/agent.d.ts.map +0 -1
- package/dist/agent.js +0 -715
- package/dist/agent.js.map +0 -1
- package/dist/cli.d.ts +0 -15
- package/dist/cli.d.ts.map +0 -1
- package/dist/cli.js.map +0 -1
- package/dist/imessage.d.ts +0 -33
- package/dist/imessage.d.ts.map +0 -1
- package/dist/imessage.js +0 -76
- package/dist/imessage.js.map +0 -1
- package/dist/logger.d.ts +0 -33
- package/dist/logger.d.ts.map +0 -1
- package/dist/logger.js +0 -104
- package/dist/logger.js.map +0 -1
- package/dist/main.d.ts +0 -5
- package/dist/main.d.ts.map +0 -1
- package/dist/main.js.map +0 -1
- package/dist/memory.d.ts +0 -53
- package/dist/memory.d.ts.map +0 -1
- package/dist/memory.js +0 -196
- package/dist/memory.js.map +0 -1
- package/dist/model-health.d.ts +0 -11
- package/dist/model-health.d.ts.map +0 -1
- package/dist/model-health.js +0 -67
- package/dist/model-health.js.map +0 -1
- package/dist/pipeline.d.ts +0 -27
- package/dist/pipeline.d.ts.map +0 -1
- package/dist/pipeline.js +0 -59
- package/dist/pipeline.js.map +0 -1
- package/dist/queue.d.ts +0 -23
- package/dist/queue.d.ts.map +0 -1
- package/dist/queue.js +0 -89
- package/dist/queue.js.map +0 -1
- package/dist/rich-text.d.ts +0 -26
- package/dist/rich-text.d.ts.map +0 -1
- package/dist/rich-text.js.map +0 -1
- package/dist/self-echo.d.ts +0 -19
- package/dist/self-echo.d.ts.map +0 -1
- package/dist/self-echo.js +0 -54
- package/dist/self-echo.js.map +0 -1
- package/dist/send.d.ts +0 -24
- package/dist/send.d.ts.map +0 -1
- package/dist/send.js.map +0 -1
- package/dist/settings.d.ts +0 -44
- package/dist/settings.d.ts.map +0 -1
- package/dist/settings.js +0 -80
- package/dist/settings.js.map +0 -1
- package/dist/store.d.ts +0 -57
- package/dist/store.d.ts.map +0 -1
- package/dist/store.js +0 -124
- package/dist/store.js.map +0 -1
- package/dist/tasks.d.ts +0 -95
- package/dist/tasks.d.ts.map +0 -1
- package/dist/tasks.js +0 -384
- package/dist/tasks.js.map +0 -1
- package/dist/types.d.ts +0 -93
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -38
- package/dist/types.js.map +0 -1
- package/dist/watch.d.ts +0 -21
- package/dist/watch.d.ts.map +0 -1
- package/dist/watch.js +0 -219
- package/dist/watch.js.map +0 -1
- package/dist/web/data.d.ts +0 -11
- package/dist/web/data.d.ts.map +0 -1
- package/dist/web/data.js +0 -56
- package/dist/web/data.js.map +0 -1
- package/dist/web/html.d.ts +0 -5
- package/dist/web/html.d.ts.map +0 -1
- package/dist/web/html.js +0 -16
- package/dist/web/html.js.map +0 -1
- package/dist/web/index.d.ts +0 -23
- package/dist/web/index.d.ts.map +0 -1
- package/dist/web/index.js +0 -279
- package/dist/web/index.js.map +0 -1
- package/dist/web/render.d.ts +0 -11
- package/dist/web/render.d.ts.map +0 -1
- package/dist/web/render.js +0 -56
- package/dist/web/render.js.map +0 -1
- package/dist/web/templates/logs.eta +0 -75
- package/dist/web/templates/memory.eta +0 -91
- package/dist/web/templates/page.eta +0 -98
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# 0033. Explicit operator run at startup
|
|
2
|
+
|
|
3
|
+
Status: proposed (owner requested one real Workplace English trial)
|
|
4
|
+
|
|
5
|
+
**Problem.** A configured job cannot be exercised on demand through the read-only
|
|
6
|
+
Web UI. Opening another Harness on the live workspace is unsafe.
|
|
7
|
+
|
|
8
|
+
**Decision.** An authorized owning-service restart may pass
|
|
9
|
+
`serve --run-scheduled JOB --request-id ID`. The existing owner admits one native
|
|
10
|
+
background occurrence in the configured job's conversation, after installing its
|
|
11
|
+
extension. It saves the request ID and task ID atomically; repeating that startup
|
|
12
|
+
request returns the same task. Refuse missing/disabled jobs or another live
|
|
13
|
+
occurrence. Do not alter the recurring task or its saved deadline.
|
|
14
|
+
|
|
15
|
+
Normal startup without the flags remains unchanged. The local startup request
|
|
16
|
+
is not stored in settings or installed into launchd. There is no new HTTP route,
|
|
17
|
+
Web action button, alternate writer, polling worker or operating-system job.
|
|
18
|
+
English still enforces the existing per-date card dedupe and learning policy;
|
|
19
|
+
this is not permission to bypass a quota or replay an uncertain send.
|
|
20
|
+
|
|
21
|
+
**Consequences.** This small operator entry requires a safe restart to trigger.
|
|
22
|
+
It is deliberately not a general interactive scheduler-management API. A live
|
|
23
|
+
trial can invoke the configured model and send its card, requiring owner consent.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# 0034. Use the service machine's local time for schedules
|
|
2
|
+
|
|
3
|
+
Status: proposed (owner requested the complete local-time change)
|
|
4
|
+
|
|
5
|
+
**Problem.** Daily deadlines, learning dates and schedule history are hard-coded
|
|
6
|
+
for Asia/Shanghai, even when the service runs on a machine in another timezone.
|
|
7
|
+
|
|
8
|
+
**Example.** A daily 07:45 job on a New York machine should run at 07:45 there,
|
|
9
|
+
including after a daylight-saving change, not at 07:45 Shanghai time.
|
|
10
|
+
|
|
11
|
+
**Decision.**
|
|
12
|
+
|
|
13
|
+
- Use the service process's local calendar for daily deadlines and learning dates.
|
|
14
|
+
By default this is the machine timezone; an explicit `TZ` environment override
|
|
15
|
+
is respected and retained by installation and routine restart.
|
|
16
|
+
- Calculate the next daily slot by calendar date, not by adding 24 hours. Use
|
|
17
|
+
JavaScript Date's local-time rules: nonexistent spring-forward times move
|
|
18
|
+
forward through the gap; repeated fall-back times select the first occurrence.
|
|
19
|
+
- Include the service timezone in each configured job's read-only projection.
|
|
20
|
+
The Web UI formats deadlines and history in that timezone, not the browser's.
|
|
21
|
+
- Retain saved absolute deadlines, occurrence dates, task IDs, learning history
|
|
22
|
+
and send receipts. The next computed slot uses local time. A timezone change
|
|
23
|
+
does not authorize regenerating cards, backfilling dates or replaying sends.
|
|
24
|
+
- Six-hour compaction remains an elapsed-time interval, independent of timezone
|
|
25
|
+
and daylight-saving changes.
|
|
26
|
+
|
|
27
|
+
This proposal supersedes only ADR 0032's fixed Asia/Shanghai calendar policy.
|
|
28
|
+
All other scheduling, recovery and at-most-once delivery decisions remain intact.
|
|
29
|
+
|
|
30
|
+
**Consequences.** Moving a deployment or changing `TZ` changes future calendar
|
|
31
|
+
slots. An already saved deadline remains an absolute instant until processed;
|
|
32
|
+
restart does not silently replace its checkpoint.
|
|
33
|
+
|
|
34
|
+
**Rejected.** Changing only README text, hard-coded UTC offsets, adding 24 hours
|
|
35
|
+
for calendar recurrence, using the browser timezone for server schedules, and
|
|
36
|
+
rewriting production learning or receipt data.
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# 0035. Workspace-owned business extensions
|
|
2
|
+
|
|
3
|
+
Status: accepted
|
|
4
|
+
|
|
5
|
+
**Problem.** Personal business logic, such as English learning, does not belong
|
|
6
|
+
in the reusable messaging framework.
|
|
7
|
+
|
|
8
|
+
**Example.** Changing a personal task should change a workspace extension, not
|
|
9
|
+
framework scheduling, settings, prompts or Web code.
|
|
10
|
+
|
|
11
|
+
**Decision.**
|
|
12
|
+
|
|
13
|
+
- Put personal code and configuration in
|
|
14
|
+
`WORKING_DIR/extensions/<name>/index.ts` and `config.json`. Each native Durable
|
|
15
|
+
extension may provide tools, define multiple tasks and optionally schedule them.
|
|
16
|
+
Both the owner and chat assistant may create extensions; add no permission list
|
|
17
|
+
or extra confirmation gate.
|
|
18
|
+
- Scan direct child directories at startup and on `/reload`. Reject duplicate
|
|
19
|
+
extension/task names. Validate before replacing definitions; failed reloads keep
|
|
20
|
+
the old definitions. Do not execute skills or attachments as extensions.
|
|
21
|
+
- Keep generic daily/interval scheduling, non-overlapping execution, recovery,
|
|
22
|
+
outgoing queues, send receipts and read-only Web history in the framework.
|
|
23
|
+
Six-hour compaction remains built-in maintenance using the same components.
|
|
24
|
+
Durable owns persisted tasks and business state; there is no second pipeline.
|
|
25
|
+
- Reload does not interrupt current calls. The next tool/task invocation uses
|
|
26
|
+
new code and configuration; do not proactively reset saved deadlines. Extensions
|
|
27
|
+
provide native migrations when saved task structures change.
|
|
28
|
+
- Removing an extension stops future scheduling, not current calls, and retains
|
|
29
|
+
history, business data and receipts. Keep definitions needed by unfinished work
|
|
30
|
+
in memory; missing required task code on restart must fail explicitly.
|
|
31
|
+
- Move English code and configuration into its workspace extension. Remove all
|
|
32
|
+
English-specific framework branches and personal job IDs. Preserve existing
|
|
33
|
+
settings, task IDs, checkpoints, deadlines, learning records and send IDs during
|
|
34
|
+
migration; never regenerate saved cards or replay uncertain sends. Verify with
|
|
35
|
+
faux models and temporary storage, then migrate under the single service owner
|
|
36
|
+
with source/configuration rollback copies.
|
|
37
|
+
|
|
38
|
+
```mermaid
|
|
39
|
+
sequenceDiagram
|
|
40
|
+
participant W as Workspace Extensions
|
|
41
|
+
participant S as Service
|
|
42
|
+
participant D as Durable
|
|
43
|
+
|
|
44
|
+
S->>W: Scan code and configuration
|
|
45
|
+
W-->>S: Tools, tasks and schedules
|
|
46
|
+
S->>D: Register or replace definitions
|
|
47
|
+
D->>D: Wait for the deadline
|
|
48
|
+
D->>W: Invoke task
|
|
49
|
+
W->>D: Persist state and results
|
|
50
|
+
D->>D: Save next deadline
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
**Consequences.** Workspace extensions are trusted code and need backup with their
|
|
54
|
+
configuration. This is the target design, not an implementation claim. It replaces
|
|
55
|
+
ADR 0032's embedded English logic; Durable ownership, at-most-once delivery and
|
|
56
|
+
ADR 0034's machine-local time rules remain unchanged.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# 0036. Workspace policy and a neutral service identity
|
|
2
|
+
|
|
3
|
+
Status: accepted (owner accepted on 2026-10-06)
|
|
4
|
+
|
|
5
|
+
**Problem.** A reusable message service should not hard-code an operator's system
|
|
6
|
+
record layout, fallback model, billing tier or personal launchd identifier.
|
|
7
|
+
|
|
8
|
+
**Example.** One workspace can explicitly retain its current fallback and priority
|
|
9
|
+
tier, while another fails on an unavailable default rather than choosing a model
|
|
10
|
+
or spending preference on the user's behalf.
|
|
11
|
+
|
|
12
|
+
**Decision.**
|
|
13
|
+
|
|
14
|
+
- Keep memory and the other shared native tools built in. ADR 0035 owns personal
|
|
15
|
+
business code and its scheduling configuration.
|
|
16
|
+
- Move `SYSTEM.md` summary loading into an optional workspace extension; its
|
|
17
|
+
path, boundary and byte budget are configuration. Move system-record update
|
|
18
|
+
instructions into workspace `AGENTS.md`, not the framework prompt.
|
|
19
|
+
- `settings.json.modelPolicy.fallback` optionally selects a provider/model pair.
|
|
20
|
+
An absent fallback fails explicitly when the selected default is unavailable.
|
|
21
|
+
Use only an available model with configured authentication.
|
|
22
|
+
- `modelPolicy.codexServiceTier` optionally chooses `default` or `priority`.
|
|
23
|
+
Absence leaves the provider payload unchanged. Reload applies policy to future
|
|
24
|
+
requests; it does not interrupt existing calls.
|
|
25
|
+
- Generate launchd jobs with neutral identity `org.pi-imessage.service`. Do not
|
|
26
|
+
silently rename a loaded controller or start another pipeline. Migrate an
|
|
27
|
+
installed personal-label job only under the operations handover procedure.
|
|
28
|
+
- Existing configuration remains compatible. The offline migration preserves
|
|
29
|
+
unknown settings and explicitly records the prior fallback/tier, rather than
|
|
30
|
+
silently changing live model or cost behavior. It retains source/configuration
|
|
31
|
+
rollback copies and never rewrites Durable state.
|
|
32
|
+
|
|
33
|
+
**Consequences.** The workspace owns and backs up its personal code and policy.
|
|
34
|
+
New installations have no implicit fallback or priority preference. A foreground
|
|
35
|
+
Terminal deployment needs no controller migration when no old-label job exists.
|
|
36
|
+
This supersedes ADR 0004's hard-coded Codex fast wrapper choice only, not its
|
|
37
|
+
native-extension or no-SDK-adapter decisions.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# 0037. Restart during in-flight work
|
|
2
|
+
|
|
3
|
+
Status: accepted
|
|
4
|
+
|
|
5
|
+
**Problem.** Routine deployment waits for an idle service. An active chat can keep
|
|
6
|
+
the service busy for a long time, so a finished change stays undeployed.
|
|
7
|
+
|
|
8
|
+
**Example.** A deployment waited while a chat ran a long model request. The owner
|
|
9
|
+
restarted anyway: the old process exited in about one second and the new one
|
|
10
|
+
resumed the same conversation, which continued its tool calls.
|
|
11
|
+
|
|
12
|
+
**Decision.**
|
|
13
|
+
|
|
14
|
+
- Do not wait for idle. Model generations, queued submissions, admitted scheduled
|
|
15
|
+
occurrences and imminent scheduler wakes do not defer a routine restart.
|
|
16
|
+
Durable owns their recovery, and saved deadlines are absolute.
|
|
17
|
+
- Stop only at a moment when no tool is running and no message send is in
|
|
18
|
+
progress. Recheck immediately before stopping.
|
|
19
|
+
- Stop with SIGTERM only. A shutdown timeout stops the deployment; never force-kill,
|
|
20
|
+
steal the lock or start a second pipeline.
|
|
21
|
+
- Accept the recovery costs: an interrupted model request is sent again. A tool
|
|
22
|
+
that started anyway is not replayed; the model sees the interruption. A send
|
|
23
|
+
that started anyway becomes `unknown` and is never resent.
|
|
24
|
+
- After startup, verify that interrupted work continues, and that send receipt
|
|
25
|
+
counts are unchanged apart from new sends.
|
|
26
|
+
|
|
27
|
+
**Consequences.** Deployment no longer depends on chat activity. A restart may
|
|
28
|
+
cost one repeated model request and delay a reply by a few seconds. This changes
|
|
29
|
+
only the idle requirement in the routine restart procedure (`ops/README.md`);
|
|
30
|
+
at-most-once delivery (ADR 0003) and the one-owner rule are unchanged.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# 0038. Restart at any time
|
|
2
|
+
|
|
3
|
+
Status: accepted (owner decided on 2026-10-06)
|
|
4
|
+
|
|
5
|
+
**Problem.** ADR 0037 still waits for a moment with no running tool and no send
|
|
6
|
+
in progress. That check adds a step and can still delay a deployment.
|
|
7
|
+
|
|
8
|
+
**Example.** A chat runs a long bash command. Under ADR 0037 the deployment
|
|
9
|
+
waits for it; under this decision the restart proceeds, and the model sees the
|
|
10
|
+
interrupted command after recovery.
|
|
11
|
+
|
|
12
|
+
**Decision.**
|
|
13
|
+
|
|
14
|
+
- A routine restart may stop the service at any time. No task, tool, send or
|
|
15
|
+
scheduler state defers it.
|
|
16
|
+
- Stop with SIGTERM only. A shutdown timeout stops the deployment; never
|
|
17
|
+
force-kill, steal the lock or start a second pipeline.
|
|
18
|
+
- Recovery is Durable's: an interrupted model request is sent again, an
|
|
19
|
+
interrupted tool is not replayed, and an interrupted send becomes `unknown`
|
|
20
|
+
and is never resent.
|
|
21
|
+
|
|
22
|
+
**Consequences.** A restart can lose one reply (left `unknown`) or leave a tool
|
|
23
|
+
half-done for the model to check. This supersedes ADR 0037's stop-moment rule;
|
|
24
|
+
its verification steps, at-most-once delivery (ADR 0003) and the one-owner rule
|
|
25
|
+
remain.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# 0039. Rerun interrupted tools by default
|
|
2
|
+
|
|
3
|
+
Status: accepted (owner decided on 2026-10-06)
|
|
4
|
+
|
|
5
|
+
**Problem.** Durable reruns an interrupted tool only when the tool declares
|
|
6
|
+
`replay: "safe"`; its default is `unsafe`. Bash, file edits, image reads and
|
|
7
|
+
workspace tools therefore fail after a restart, although almost all of them can
|
|
8
|
+
simply run again.
|
|
9
|
+
|
|
10
|
+
**Example.** A restart interrupts `bash` listing a directory. Before, the model
|
|
11
|
+
received "interrupted and may have partially run" and had to decide what to do;
|
|
12
|
+
now the command runs again and the turn continues.
|
|
13
|
+
|
|
14
|
+
**Decision.**
|
|
15
|
+
|
|
16
|
+
- The host treats every tool without an explicit `replay` as `safe`, including
|
|
17
|
+
built-in, Durable and workspace extension tools.
|
|
18
|
+
- A tool whose effect must not repeat declares `replay: "unsafe"`.
|
|
19
|
+
- Replies and `send_message` keep at-most-once delivery through their own send
|
|
20
|
+
receipts (ADR 0003): a rerun never resends a `sending` or `unknown` message.
|
|
21
|
+
|
|
22
|
+
**Consequences.** Restarts rarely surface interrupted tools to the model. A
|
|
23
|
+
rerun tool may repeat a partial effect, such as appending to a file twice. This
|
|
24
|
+
supersedes the interrupted-tool clause of ADR 0038.
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# 0040. Chat progress notices
|
|
2
|
+
|
|
3
|
+
Status: accepted (owner accepted on 2026-10-06; consolidates ADRs 0020–0028 and 0031 without changing behavior)
|
|
4
|
+
|
|
5
|
+
**Problem.** The current progress format is spread over ten ADRs that each
|
|
6
|
+
replace a detail of the previous one.
|
|
7
|
+
|
|
8
|
+
**Example.**
|
|
9
|
+
|
|
10
|
+
```text
|
|
11
|
+
→ [tool] bash: node search.mjs "Shanghai weather" --count 5
|
|
12
|
+
✓ [tool] bash (0.8s)
|
|
13
|
+
→ [subagent/tool] read: path=/tmp/a.jpg
|
|
14
|
+
× [subagent/tool] read (0.1s)
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
**Decision.**
|
|
18
|
+
|
|
19
|
+
- With `settings.json` `progressMessages: true`, observe native task admission
|
|
20
|
+
and settlement through Durable's commit subscription. No wrapper, polling or
|
|
21
|
+
second execution loop. `pi.generation` tasks are not reported.
|
|
22
|
+
- Send one request notice at admission and one response notice at settlement,
|
|
23
|
+
to the owning reply-enabled chat. Child tasks follow Durable ownership and are
|
|
24
|
+
labelled with their parents, such as `[subagent/tool]`. Health and unrelated
|
|
25
|
+
ownerless conversations stay quiet.
|
|
26
|
+
- Format: status marker first (`→` request, `✓` success, `×` anything else),
|
|
27
|
+
then `[parents/type]`, then the native name. Success requires a completed task
|
|
28
|
+
and a tool result without an error flag. Responses show elapsed time from
|
|
29
|
+
admission, including queueing.
|
|
30
|
+
- Bash requests show the command inline, at most 120 Unicode code points. Screen
|
|
31
|
+
the whole command first: a credential indicator hides it, and URLs and common
|
|
32
|
+
domains are defanged so iMessage shows no link preview. Other tools show
|
|
33
|
+
bounded argument summaries; URLs show only a defanged hostname; timeouts are
|
|
34
|
+
omitted. Never show outputs, thinking, prompts or document contents.
|
|
35
|
+
- Six-hour maintenance compaction is quiet. Manual `/compact` and Durable's
|
|
36
|
+
automatic threshold/overflow compactions are reported.
|
|
37
|
+
- `src/agent/progress-format.ts` holds a transport-independent `ProgressEvent`
|
|
38
|
+
and pure formatting and screening functions; iMessage is one adapter.
|
|
39
|
+
- Each notice uses a direct-send receipt keyed by task ID. Unknown sends are not
|
|
40
|
+
retried, and work admitted before startup is not replayed. Final replies wait
|
|
41
|
+
for queued notices first.
|
|
42
|
+
|
|
43
|
+
**Consequences.** A busy turn sends many notices. Screening is best effort and
|
|
44
|
+
cannot detect every secret. This supersedes ADRs 0020–0028 and 0031.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# 0041. Restart and recovery
|
|
2
|
+
|
|
3
|
+
Status: accepted (owner accepted on 2026-10-06; consolidates ADRs 0037–0039 without changing behavior)
|
|
4
|
+
|
|
5
|
+
**Problem.** Restart rules are spread over three ADRs, each replacing part of
|
|
6
|
+
the previous one.
|
|
7
|
+
|
|
8
|
+
**Example.** A chat is running `bash` when a deployment restarts the service.
|
|
9
|
+
The old process exits within seconds, the new one starts, the command runs
|
|
10
|
+
again and the turn continues.
|
|
11
|
+
|
|
12
|
+
**Decision.**
|
|
13
|
+
|
|
14
|
+
- A routine restart may happen at any time; no task, tool, send or scheduler
|
|
15
|
+
state defers it.
|
|
16
|
+
- Stop with SIGTERM only. A shutdown timeout stops the deployment; never
|
|
17
|
+
force-kill, steal the lock or start a second pipeline.
|
|
18
|
+
- Durable recovers everything else. An interrupted model request is sent again.
|
|
19
|
+
A tool without an explicit `replay` reruns; a tool whose effect must not
|
|
20
|
+
repeat declares `replay: "unsafe"`.
|
|
21
|
+
- Replies and `send_message` stay at most once (ADR 0003): an interrupted send
|
|
22
|
+
becomes `unknown` and is never resent.
|
|
23
|
+
- After startup, verify that interrupted work continues and that receipt counts
|
|
24
|
+
change only by new and interrupted sends.
|
|
25
|
+
|
|
26
|
+
**Consequences.** Deployment never waits for chat activity. A restart can cost
|
|
27
|
+
one repeated model request, lose one reply or repeat a partial tool effect;
|
|
28
|
+
the owner accepts these as rare. This supersedes ADRs 0037–0039.
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# 0042. Background schedules and workspace extensions
|
|
2
|
+
|
|
3
|
+
Status: accepted (owner accepted on 2026-10-06; consolidates ADRs 0019 and 0032–0035 without changing behavior)
|
|
4
|
+
|
|
5
|
+
**Problem.** Scheduling was removed (0019), rebuilt natively (0032–0034) and
|
|
6
|
+
then separated from personal business code (0035). The current rules are
|
|
7
|
+
spread over five ADRs that partly contradict each other.
|
|
8
|
+
|
|
9
|
+
**Example.** A daily 07:45 workspace task and six-hour compaction both keep
|
|
10
|
+
their deadlines across a restart. Changing the task's code changes only
|
|
11
|
+
`WORKING_DIR/extensions/<name>/`, not the framework.
|
|
12
|
+
|
|
13
|
+
**Decision.**
|
|
14
|
+
|
|
15
|
+
- **Retired services stay removed:** cron, reminders, delayed prompts,
|
|
16
|
+
completion watchers, PT Automation and HTTP `/prompt` / `/send`. Their
|
|
17
|
+
endpoints return 404; stored old data is kept but unused.
|
|
18
|
+
- **Workspace extensions** hold personal code: `WORKING_DIR/extensions/<name>/`
|
|
19
|
+
with `index.ts` and `config.json`. Each is a trusted native Durable extension
|
|
20
|
+
with tools, tasks and optional schedules. The owner and the chat assistant
|
|
21
|
+
may both create them. Startup, `/reload` and `reload_extensions` scan direct
|
|
22
|
+
child directories. Duplicate names are rejected; a failed reload keeps the
|
|
23
|
+
old definitions; running calls keep their code.
|
|
24
|
+
- **Framework scheduling** gives each schedule a dedicated conversation with a
|
|
25
|
+
background task whose checkpoint saves the absolute next deadline. Each
|
|
26
|
+
occurrence is a child task; occurrences never overlap. Daily slots run only
|
|
27
|
+
today's slot, without backfill; interval slots skip missed ticks. Six-hour
|
|
28
|
+
compaction uses the same mechanism and stays built in.
|
|
29
|
+
- **Time** is the service machine's local timezone (or `TZ`). Daily slots are
|
|
30
|
+
computed by calendar date, so daylight-saving changes keep the wall-clock
|
|
31
|
+
time. Saved deadlines are never reset by reload, restart or timezone change.
|
|
32
|
+
- **Delivery** commits business state and the outgoing item together. The host
|
|
33
|
+
sends through existing receipts at most once; `unknown` is never resent.
|
|
34
|
+
- **Operator run:** `serve --run-scheduled JOB --request-id ID` admits one
|
|
35
|
+
occurrence at startup; repeating the same request ID returns the same task.
|
|
36
|
+
- **History:** `/scheduled` shows each schedule, its deadline and the latest
|
|
37
|
+
ten occurrences from native task records. Viewing never starts work.
|
|
38
|
+
- **Removal:** removing an extension stops future scheduling only. Unfinished
|
|
39
|
+
work keeps its code in memory; restart fails explicitly if required code is
|
|
40
|
+
missing.
|
|
41
|
+
|
|
42
|
+
**Consequences.** The service must be running to act at a deadline. Workspace
|
|
43
|
+
extensions are trusted code and need backup. This supersedes ADRs 0019 and
|
|
44
|
+
0032–0035, and the scheduler clause of ADR 0013.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# 0043. Remove the legacy migration code
|
|
2
|
+
|
|
3
|
+
Status: accepted (owner decided on 2026-10-06)
|
|
4
|
+
|
|
5
|
+
**Problem.** The one-time cutover from the legacy service is done, but its code
|
|
6
|
+
and runbook remain: `src/migrate/`, the `pi-imessage import` command, a test and
|
|
7
|
+
`ops/CUTOVER.md`. Readers must learn a whole layer that will never run again.
|
|
8
|
+
|
|
9
|
+
**Example.** A new contributor reads the package table, finds `migrate/` next to
|
|
10
|
+
`main.ts`, and spends time on history import rules unrelated to any change.
|
|
11
|
+
|
|
12
|
+
**Decision.**
|
|
13
|
+
|
|
14
|
+
- Delete `src/migrate/`, the `import` CLI command, `test/migrate.test.ts` and
|
|
15
|
+
`ops/CUTOVER.md`.
|
|
16
|
+
- Keep them reachable at the annotated tag `archive/legacy-migration`, the last
|
|
17
|
+
revision that contains them. A tag is fixed and runnable; a wiki copy is not.
|
|
18
|
+
- The rule "never run old and new message pipelines concurrently" stays in
|
|
19
|
+
`AGENTS.md` and `ops/README.md`.
|
|
20
|
+
|
|
21
|
+
**Consequences.** Imported history already lives in Durable storage and is
|
|
22
|
+
unaffected. Rerunning a migration means checking out the tag in a separate
|
|
23
|
+
worktree. This replaces ADRs 0005 and 0009, whose work is complete.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# 0044. Organize message sources as channels
|
|
2
|
+
|
|
3
|
+
Status: proposed
|
|
4
|
+
|
|
5
|
+
**Problem.** `transport/` is iMessage-only: it polls `chat.db` and sends through
|
|
6
|
+
Messages.app. A second message source, such as Telegram, has no place to go, and
|
|
7
|
+
the name "transport" suggests a network layer. `transport/http.ts` is the shared
|
|
8
|
+
outgoing HTTP client, not a message source.
|
|
9
|
+
|
|
10
|
+
**Example.** Adding Telegram today would mean putting `telegram-watch.ts` beside
|
|
11
|
+
`watch.ts`, while `agent/` imports `MessageSender` from the iMessage `send.ts`.
|
|
12
|
+
|
|
13
|
+
**Decision.** Apply this when the second channel is implemented, not before
|
|
14
|
+
(no abstraction until needed):
|
|
15
|
+
|
|
16
|
+
- Rename `transport/` to `channels/`, with one directory per channel:
|
|
17
|
+
`channels/imessage/` (`watch.ts`, `send.ts`, `rich-text.ts`,
|
|
18
|
+
`attachments.ts`), `channels/telegram/`, and so on.
|
|
19
|
+
- Put the shared contract in `channels/types.ts`: the incoming message shape and
|
|
20
|
+
`MessageSender`. `agent/` depends on this contract, never on one channel.
|
|
21
|
+
- Move the process HTTP client (ADR 0016) out of the channel package, for example
|
|
22
|
+
to `config/` or a small `net/` package at the bottom layer.
|
|
23
|
+
- Identify chats as `<channel>:<id>` for new channels. Existing iMessage chat
|
|
24
|
+
GUIDs stay unchanged, so `settings.json` allowlists and Durable `Chats`
|
|
25
|
+
records remain valid.
|
|
26
|
+
|
|
27
|
+
**Consequences.** One rename and an import update when the second channel
|
|
28
|
+
arrives; until then the code stays as it is. The layer rule (ADR 0002) is
|
|
29
|
+
unchanged: channels stay below `agent/` and contain no agent logic.
|
|
30
|
+
|
|
31
|
+
**Rejected.** A generic plugin loader for channels: there is one real channel
|
|
32
|
+
today, and workspace extensions (ADR 0042) already cover tool plugins.
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# 0045. Native chat scheduling tools
|
|
2
|
+
|
|
3
|
+
Status: proposed
|
|
4
|
+
|
|
5
|
+
**Problem.** A simple deferred chat request currently requires the assistant to
|
|
6
|
+
write a trusted workspace extension and reload it. That is useful for reusable
|
|
7
|
+
business code, but unnecessarily complex for an ordinary reminder or agent task.
|
|
8
|
+
|
|
9
|
+
**Example.** In iMessage, "remind me in ten minutes" should create a task through
|
|
10
|
+
`schedule_task`, just as it does in the coding agent. "Every day at 09:00,
|
|
11
|
+
summarize new items" should not require generated TypeScript either.
|
|
12
|
+
|
|
13
|
+
**Decision.**
|
|
14
|
+
|
|
15
|
+
- Add built-in `schedule_task`, `list_scheduled_tasks` and
|
|
16
|
+
`cancel_scheduled_task` tools for chat conversations. The scheduling tool takes
|
|
17
|
+
a time and a prompt, with optional explicit daily or interval repetition.
|
|
18
|
+
Support durations, clock times and absolute datetimes; do not add a cron parser.
|
|
19
|
+
- Bind each task to its originating chat in host code. List and cancellation
|
|
20
|
+
operate only on that chat's interactive schedules, never framework maintenance
|
|
21
|
+
or workspace extension schedules. Return a stable ID and the actual deadline.
|
|
22
|
+
- Use native Durable background tasks and documents in the existing owning
|
|
23
|
+
service. Creation must be atomic and deduplicated by the scheduling tool call;
|
|
24
|
+
interruption must not create a second schedule. Persist absolute deadlines,
|
|
25
|
+
configuration and cancellation. No detached timer, operating-system scheduler,
|
|
26
|
+
legacy job files, HTTP prompt/send endpoint or second pipeline.
|
|
27
|
+
- Execute each occurrence in a fresh isolated agent conversation with the
|
|
28
|
+
normal authorized tools. Send its final result back to the originating chat
|
|
29
|
+
through the existing at-most-once receipts and passive chat records, without
|
|
30
|
+
steering an unrelated active chat turn. A scheduled prompt is a saved user
|
|
31
|
+
request, not a system instruction.
|
|
32
|
+
- Recurring occurrences never overlap and skip missed slots. One-shot tasks
|
|
33
|
+
execute once when overdue, including after restart. Cancellation prevents
|
|
34
|
+
future admission; it does not undo an already admitted occurrence or resend
|
|
35
|
+
uncertain effects. Keep existing restart recovery and unknown-send safeguards.
|
|
36
|
+
- Use the service machine's timezone, including explicit `TZ`, and expose native
|
|
37
|
+
deadlines and occurrence records on the existing read-only Scheduled page.
|
|
38
|
+
The service must be running to execute work; persistence does not wake a
|
|
39
|
+
stopped service or machine.
|
|
40
|
+
- Keep workspace extensions for reusable business tools and tasks. Existing
|
|
41
|
+
extension schedules and six-hour compaction retain their IDs, deadlines and
|
|
42
|
+
behavior. Reload must not disable or reset interactive schedules.
|
|
43
|
+
- Replace the chat prompt's extension-writing requirement for ordinary scheduled
|
|
44
|
+
work with brief instructions to use these tools. Do not remove unrelated chat
|
|
45
|
+
steering or delivery safeguards.
|
|
46
|
+
|
|
47
|
+
**Consequences.** This deliberately replaces ADR 0042's retirement of ordinary
|
|
48
|
+
reminders and delayed agent prompts, but not its retired external services or
|
|
49
|
+
workspace extension contract. It also replaces that clause of ADR 0018. It is a
|
|
50
|
+
small native management interface over Durable, not a return to the old cron
|
|
51
|
+
service. Implementation follows owner acceptance; accepted ADRs stay unchanged.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# 0046. Selective command-preview redaction
|
|
2
|
+
|
|
3
|
+
Status: proposed (owner requested `***` value masking on 2026-10-06; implementation tracked in #36)
|
|
4
|
+
|
|
5
|
+
Supersedes only ADR 0040's whole-command credential suppression rule.
|
|
6
|
+
|
|
7
|
+
**Problem.** A mention of `token`, `password`, `.env` or `auth.json` hides the
|
|
8
|
+
entire command, even when it is just a source search or filename.
|
|
9
|
+
|
|
10
|
+
**Example.** `TOKEN=demo123 curl --retry 3` becomes
|
|
11
|
+
`→ [tool] bash: TOKEN=*** curl --retry 3`. `rg 'token' src` remains readable.
|
|
12
|
+
|
|
13
|
+
**Decision.** Replace recognized credential values with `***`, retaining the
|
|
14
|
+
surrounding command instead of a hidden-command placeholder. Cover sensitive
|
|
15
|
+
assignments, options, authorization headers, URL userinfo, structured values,
|
|
16
|
+
known credential prefixes and PEM private-key blocks. Read complete shell words,
|
|
17
|
+
including quoted fragments, escaped spaces and command substitutions. Opaque
|
|
18
|
+
escaped JSON and ambiguous substitutions may lose additional argument text to
|
|
19
|
+
avoid showing a partial credential. Filenames and keyword mentions alone do not
|
|
20
|
+
trigger hiding. Screening remains best effort, not an arbitrary-secret guarantee.
|
|
21
|
+
|
|
22
|
+
Apply masking to the full command before whitespace normalization, URL/domain
|
|
23
|
+
defanging and the existing 120-Unicode-code-point bound. Native execution,
|
|
24
|
+
non-bash summaries, progress ownership, settlement and durable receipts remain
|
|
25
|
+
unchanged. No new scheduler, pipeline, tool execution or delivery replay.
|
|
26
|
+
|
|
27
|
+
**Verification.** Extend the existing isolated messaging regression with exact
|
|
28
|
+
preview examples, quote/escape cases, structured credentials, line continuations,
|
|
29
|
+
substitutions, known prefixes, private keys, keyword-only searches and masking
|
|
30
|
+
before truncation. Existing native execution, ownership and uncertain-send
|
|
31
|
+
regressions remain in force.
|