@kingcrab/pi-imessage 1.1.1 → 1.2.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 +4 -6
- package/dist/agent/behavior.js +7 -13
- package/dist/agent/chats.js +7 -8
- package/dist/agent/commands.js +16 -11
- package/dist/agent/harness.js +6 -0
- package/dist/agent/progress.js +30 -4
- package/dist/agent/prompt.js +41 -24
- package/dist/agent/run.js +5 -4
- package/dist/agent/scheduling.js +11 -34
- package/dist/cli.js +42 -5
- package/dist/config/settings.js +4 -0
- package/dist/extensions/browser.js +7 -3
- package/dist/extensions/codemode.js +16 -0
- package/dist/extensions/final-text.js +12 -0
- package/dist/extensions/schedules.js +1 -1
- package/dist/extensions/subagent.js +3 -12
- package/dist/extensions/workspace.js +6 -2
- package/dist/main.js +42 -49
- package/dist/transport/watch.js +7 -1
- package/dist/web/app.js +63 -121
- package/dist/web/server.js +7 -14
- package/dist/web/style.css +0 -6
- package/dist/web/tasks.js +12 -120
- package/docs/adr/{0004-native-extensions.md → 0003-native-extensions.md} +1 -1
- package/docs/adr/{0006-jsonl-storage.md → 0004-jsonl-storage.md} +1 -1
- package/docs/adr/{0007-images-by-path.md → 0005-images-by-path.md} +1 -1
- package/docs/adr/{0010-test-budget.md → 0006-test-budget.md} +1 -1
- package/docs/adr/{0011-reconcile-unsent-answers.md → 0007-reconcile-unsent-answers.md} +2 -2
- package/docs/adr/{0012-run-in-owned-conversation.md → 0008-run-in-owned-conversation.md} +5 -5
- package/docs/adr/{0032-native-background-schedules.md → 0009-native-background-schedules.md} +1 -1
- package/docs/adr/0010-framework-and-workspace.md +27 -0
- package/docs/adr/README.md +24 -48
- package/docs/api.md +16 -8
- package/docs/architecture.md +19 -8
- package/docs/browser.md +7 -7
- package/docs/install.md +109 -0
- package/docs/workspace-extensions.md +8 -4
- package/package.json +4 -5
- package/dist/agent/compaction.js +0 -51
- package/dist/agent/error-log.js +0 -37
- package/dist/extensions/restart.js +0 -100
- package/docs/adr/0003-replies-at-most-once.md +0 -11
- package/docs/adr/0005-history-migration.md +0 -11
- package/docs/adr/0008-compaction-and-run.md +0 -11
- package/docs/adr/0009-one-shot-cutover.md +0 -11
- package/docs/adr/0013-thin-adapters-around-durable.md +0 -18
- package/docs/adr/0014-ephemeral-private-storage.md +0 -13
- package/docs/adr/0015-ordinary-stop-keeps-native-inbox.md +0 -21
- package/docs/adr/0016-process-http-transport.md +0 -21
- package/docs/adr/0017-browser-cli-owned-scope.md +0 -22
- package/docs/adr/0018-tasks-without-prompt-api.md +0 -19
- package/docs/adr/0019-remove-scheduled-services.md +0 -41
- package/docs/adr/0020-chat-task-progress.md +0 -41
- package/docs/adr/0021-readable-progress-without-link-previews.md +0 -33
- package/docs/adr/0022-progress-admission-and-settlement.md +0 -35
- package/docs/adr/0023-retain-progress-type-prefixes.md +0 -18
- package/docs/adr/0024-status-marker-before-type-prefix.md +0 -13
- package/docs/adr/0025-reusable-progress-and-command-preview.md +0 -49
- package/docs/adr/0026-inline-command-only-requests.md +0 -16
- package/docs/adr/0027-command-preview-width.md +0 -10
- package/docs/adr/0028-command-preview-120.md +0 -8
- package/docs/adr/0030-shared-web-read-cache.md +0 -33
- package/docs/adr/0031-quiet-compaction-progress.md +0 -32
- package/docs/adr/0033-operator-scheduled-run.md +0 -23
- package/docs/adr/0034-machine-local-schedule-time.md +0 -36
- package/docs/adr/0035-external-business-task-extensions.md +0 -56
- package/docs/adr/0036-workspace-policy-and-neutral-service-id.md +0 -37
- package/docs/adr/0037-restart-during-in-flight-work.md +0 -30
- package/docs/adr/0038-restart-any-time.md +0 -25
- package/docs/adr/0039-rerun-interrupted-tools.md +0 -24
- package/docs/adr/0040-chat-progress-notices.md +0 -44
- package/docs/adr/0041-restart-and-recovery.md +0 -28
- package/docs/adr/0042-background-schedules-and-workspace-extensions.md +0 -44
- package/docs/adr/0043-remove-legacy-migration.md +0 -23
- package/docs/adr/0044-message-channels.md +0 -32
- package/docs/adr/0045-chat-scheduling-tools.md +0 -51
- package/docs/adr/0046-selective-command-redaction.md +0 -31
- package/docs/adr/0047-one-scheduling-path.md +0 -158
- package/docs/adr/0048-quiet-attachment-reads.md +0 -11
- package/docs/adr/0049-per-chat-progress-notices.md +0 -21
- package/docs/adr/0052-host-owned-self-restart.md +0 -53
- package/docs/adr/0053-service-log-errors.md +0 -44
- package/ops/README.md +0 -250
- package/ops/preflight.mjs +0 -28
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
# 0024. Status marker before the type prefix
|
|
2
|
-
|
|
3
|
-
Status: accepted (owner explicitly corrected marker placement on 2026-10-05)
|
|
4
|
-
|
|
5
|
-
Supersedes the prefix-first display order in ADR 0023 only. Preserve all
|
|
6
|
-
native routing, safe descriptions, settlement verification and receipt rules.
|
|
7
|
-
|
|
8
|
-
**Example.** `→ [tool] bash: Check the weather`, then `✓ [tool] bash (0.8s)`.
|
|
9
|
-
Child tools use `→ [subagent/tool] read: path=…`. Failure uses `×` first.
|
|
10
|
-
|
|
11
|
-
**Decision.** Put the status marker at the very beginning, immediately followed
|
|
12
|
-
by the retained bracketed type/parent label. Ask for short everyday action
|
|
13
|
-
wording instead of implementation jargon. Omit timeout and raw commands.
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
# 0025. Reusable progress data and short command previews
|
|
2
|
-
|
|
3
|
-
Status: accepted (owner approved option 5, then clarified request/response names and app reuse on 2026-10-05)
|
|
4
|
-
|
|
5
|
-
Supersedes the command-opaque/request-name display rules of ADR 0021 and the
|
|
6
|
-
request display examples of ADR 0024. Native lifecycle, routing, receipt IDs,
|
|
7
|
-
uncertain-effect handling and response formatting are unchanged.
|
|
8
|
-
|
|
9
|
-
**Problem.** The owner wants readable request purposes, a useful short bash
|
|
10
|
-
preview, no tool names in any request, and reusable rules for a future app.
|
|
11
|
-
|
|
12
|
-
**Example.**
|
|
13
|
-
|
|
14
|
-
```text
|
|
15
|
-
→ [tool] Check the weather
|
|
16
|
-
node search.mjs "Shanghai weather" --count 5
|
|
17
|
-
✓ [tool] bash (0.8s)
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
**Decision.**
|
|
21
|
-
|
|
22
|
-
- Requests keep the leading arrow and bracketed type/parent label. Tool names
|
|
23
|
-
do not appear as separate request labels or parenthetical suffixes. Responses
|
|
24
|
-
keep the deployed format: marker, type/parent label, native name and elapsed
|
|
25
|
-
time. This latest clarification replaces the earlier proposed hidden-bash
|
|
26
|
-
response and option-5 parenthetical response examples.
|
|
27
|
-
- Bash requests add a second line with at most 100 Unicode code points,
|
|
28
|
-
including a trailing ellipsis when truncated. Screen the whole command
|
|
29
|
-
before truncation. Recognized credential indicators suppress the entire
|
|
30
|
-
preview; explicit URLs and common bare domains are defanged. Native
|
|
31
|
-
execution and timeout enforcement remain unchanged.
|
|
32
|
-
- Screening is conservative and best effort, not a guarantee against arbitrary
|
|
33
|
-
unknown secrets. Do not restore raw tool outputs or document-content notices.
|
|
34
|
-
- `src/agent/progress-format.ts` defines a transport-independent structured
|
|
35
|
-
ProgressEvent and pure summarization, screening and text formatting functions.
|
|
36
|
-
The native observer creates safe request/response events; iMessage is the
|
|
37
|
-
current plain-text adapter. Future apps can render event fields and reuse
|
|
38
|
-
the safety functions without parsing iMessage text or copying its lifecycle.
|
|
39
|
-
- The event retains the native name internally, allowing app rendering and
|
|
40
|
-
response formatting, even though request text omits it. Raw command strings
|
|
41
|
-
do not belong in exported progress events; only screened previews do.
|
|
42
|
-
- No app transport, new scheduler, listener, database or delivery replay is
|
|
43
|
-
introduced in this change. A future app connection must wire its own
|
|
44
|
-
delivery/receipt policy explicitly.
|
|
45
|
-
|
|
46
|
-
**Verification.** Isolated regressions cover the request/response event format,
|
|
47
|
-
all-request name omission, native command execution/failure, preview length and
|
|
48
|
-
Unicode, screening before truncation, credential suppression, URL defanging,
|
|
49
|
-
child attribution, unknown receipts and no restart replay.
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
# 0026. Inline command-only requests
|
|
2
|
-
|
|
3
|
-
Status: accepted (owner specified `bash: <command>` and a 50-character limit on 2026-10-05)
|
|
4
|
-
|
|
5
|
-
Supersedes the request-name omission, second-line preview and 100-character
|
|
6
|
-
limit in ADR 0025. Preserve shared ProgressEvent data, screening, native
|
|
7
|
-
execution, ownership, response formatting and receipt/recovery rules.
|
|
8
|
-
|
|
9
|
-
**Example.** `→ [tool] bash: printf hi`, then `✓ [tool] bash (0.8s)`.
|
|
10
|
-
Other tools retain the screenshot format, e.g. `→ [tool] read: path=/tmp/a.jpg`.
|
|
11
|
-
|
|
12
|
-
**Decision.** Requests show native name and safe arguments inline. Bash uses
|
|
13
|
-
only its screened command preview, not purpose/description text. The preview
|
|
14
|
-
is at most 50 Unicode code points including an ellipsis when truncated.
|
|
15
|
-
Screen the entire original command before truncation. No actual execution
|
|
16
|
-
limit or output handling changes. Response notices remain unchanged.
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
# 0027. Modest command preview width
|
|
2
|
-
|
|
3
|
-
Status: accepted (owner delegated a slightly longer preview on 2026-10-05)
|
|
4
|
-
|
|
5
|
-
Supersedes only ADR 0026's fixed 50-character width. The current default is
|
|
6
|
-
80 Unicode code points, including a trailing ellipsis when truncated. This
|
|
7
|
-
balances useful context with phone readability. Keep the same inline
|
|
8
|
-
`→ [tool] bash: <screened command>` format and unchanged response notices.
|
|
9
|
-
Whole-command screening still occurs before truncation; no purpose text,
|
|
10
|
-
raw output, tool execution or channel architecture changes.
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
# 0028. Use 120 characters for command previews
|
|
2
|
-
|
|
3
|
-
Status: accepted (owner selected120 after viewing80/120/150/180 examples on 2026-10-05)
|
|
4
|
-
|
|
5
|
-
Supersedes only ADR 0027's80-character default. Show at most120 Unicode code
|
|
6
|
-
points in the command portion, including a trailing ellipsis when truncated.
|
|
7
|
-
Retain the inline command-only request, existing response, whole-command
|
|
8
|
-
screening before truncation and transport-independent event/formatter.
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
# 0030. Share a versioned web read cache
|
|
2
|
-
|
|
3
|
-
Status: rejected (owner decided on 2026-10-06: a cold read takes about 40 ms, and every commit invalidated the cache anyway; the cache was removed)
|
|
4
|
-
|
|
5
|
-
**Context.** The chat overview requests each conversation separately and repeats
|
|
6
|
-
reads on refresh and navigation. Large native payloads include model-only data
|
|
7
|
-
that the page never renders. Time-based caching would hide recent changes.
|
|
8
|
-
|
|
9
|
-
**Decision.** Keep one bounded, process-local cache in `web/`, shared by pages
|
|
10
|
-
and read-only APIs. Read through the owning Harness, never its storage files.
|
|
11
|
-
Every non-empty Durable commit changes the native cache version. File-backed
|
|
12
|
-
views validate inode, size and nanosecond modification/change timestamps on
|
|
13
|
-
each access; enumerate memory namespaces on each request to detect additions
|
|
14
|
-
and removals. Coalesce concurrent reads and recheck the version after loading;
|
|
15
|
-
retry if it changed. Do not retain rejected reads or oversized results.
|
|
16
|
-
|
|
17
|
-
Limit the cache to 128 entries and a 16 MiB serialized-size budget using
|
|
18
|
-
least-recently-used eviction. This budget is not an exact JavaScript heap limit.
|
|
19
|
-
Do not cache model health requests or resolved registry-dependent agent choices.
|
|
20
|
-
|
|
21
|
-
Embed display-only chat data in the initial HTML and batch overview refreshes.
|
|
22
|
-
Keep existing native data response shapes. SSE readiness includes a process and
|
|
23
|
-
revision marker so the client can detect changes between HTML loading and stream
|
|
24
|
-
attachment, without always fetching the initial view twice. Refreshes already
|
|
25
|
-
in flight do not discard subsequent change notices.
|
|
26
|
-
|
|
27
|
-
**Consequences.** Restart discards the cache. There is no second durable state,
|
|
28
|
-
execution log, writer or model call. A response reflects versions checked while
|
|
29
|
-
it is read; changes during network transit still require a later refresh. File
|
|
30
|
-
freshness relies on filesystem metadata, not a fixed stale-data interval.
|
|
31
|
-
|
|
32
|
-
**Rejected.** Browser-local copies as the shared cache, fixed cache TTLs,
|
|
33
|
-
persistent materialized views, and rebuilding all page data on every commit.
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
# 0031. Hide only six-hour compaction progress
|
|
2
|
-
|
|
3
|
-
Status: proposed (owner clarified trigger-specific visibility on 2026-10-06)
|
|
4
|
-
|
|
5
|
-
Narrows ADR 0020's compaction notices only for six-hour maintenance ticks.
|
|
6
|
-
|
|
7
|
-
**Problem.** The six-hour timer emits `pi.compaction` progress into chat. The
|
|
8
|
-
owner wants that timer quiet, but wants progress for manual `/compact` and
|
|
9
|
-
automatic context-threshold/overflow compaction.
|
|
10
|
-
|
|
11
|
-
**Example.** A timer tick sends neither a start nor completion notice. Manual
|
|
12
|
-
`/compact` shows both notices and its command result. A native context-triggered
|
|
13
|
-
compaction shows both notices.
|
|
14
|
-
|
|
15
|
-
**Decision.** Track exact task IDs admitted by `compactChats` using process-local
|
|
16
|
-
Harness-scoped state. Before a compaction admission notice, wait for in-flight
|
|
17
|
-
timer admissions to resolve so the observer can classify the committed task
|
|
18
|
-
before `compact()` has returned its ID. Suppress only a matching timer task's
|
|
19
|
-
notice; without an admission notice its settlement also remains quiet. Consume
|
|
20
|
-
the classification after observation. Do not mute an entire conversation or
|
|
21
|
-
filter by native reason: both the timer and `/compact` use reason `manual`.
|
|
22
|
-
|
|
23
|
-
Native manual, threshold and overflow task progress keeps its existing routing,
|
|
24
|
-
receipts and settlement formatting. Timer execution, logs, six-hour cadence,
|
|
25
|
-
manual command results and other progress are unchanged. Classification is not
|
|
26
|
-
persisted because pre-start task progress is never replayed.
|
|
27
|
-
|
|
28
|
-
**Verification.** An existing isolated faux-provider messaging regression with
|
|
29
|
-
progress enabled checks timer admission/settlement create no notices or progress
|
|
30
|
-
receipts, manual `/compact` shows progress and its result, and native tasks with
|
|
31
|
-
threshold/overflow reasons retain both progress receipts. Existing tool and
|
|
32
|
-
child-task progress regressions remain enabled.
|
|
@@ -1,23 +0,0 @@
|
|
|
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.
|
|
@@ -1,36 +0,0 @@
|
|
|
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.
|
|
@@ -1,56 +0,0 @@
|
|
|
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.
|
|
@@ -1,37 +0,0 @@
|
|
|
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.
|
|
@@ -1,30 +0,0 @@
|
|
|
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.
|
|
@@ -1,25 +0,0 @@
|
|
|
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.
|
|
@@ -1,24 +0,0 @@
|
|
|
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.
|
|
@@ -1,44 +0,0 @@
|
|
|
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.
|
|
@@ -1,28 +0,0 @@
|
|
|
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.
|
|
@@ -1,44 +0,0 @@
|
|
|
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.
|
|
@@ -1,23 +0,0 @@
|
|
|
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.
|
|
@@ -1,32 +0,0 @@
|
|
|
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.
|
|
@@ -1,51 +0,0 @@
|
|
|
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.
|