pi-notes 0.1.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.
Files changed (5) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +90 -0
  3. package/entry.ts +20 -0
  4. package/index.ts +1231 -0
  5. package/package.json +48 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Evan Huang
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,90 @@
1
+ # pi-notes
2
+
3
+ `pi-notes` keeps one compact durable continuation/task-state handoff for the current top-level Pi session. `NOTES.md` is not general notes, a diary, or proof.
4
+
5
+ ## Install
6
+
7
+ Install from the Pi package gallery (npm):
8
+
9
+ ```sh
10
+ pi install npm:pi-notes
11
+ ```
12
+
13
+ Or install the GitHub package directly:
14
+
15
+ ```sh
16
+ pi install git:github.com/evanqhuang/pi-notes
17
+ ```
18
+
19
+ The package requires Pi 0.84.4 or newer and a Node.js version supported by Pi.
20
+ After installing or updating, use `/reload` or start a new Pi session.
21
+
22
+ ## Storage
23
+
24
+ Notes are never written into the project tree. Each top-level session owns:
25
+
26
+ ```text
27
+ <getAgentDir()>/notes/<notes-id>/NOTES.md
28
+ ```
29
+
30
+ `/new` and `/fork` create fresh identities. `/tree` keeps the same identity and rematerializes the checkpoint belonging to the selected branch.
31
+
32
+ ## Commands
33
+
34
+ - `/notes` or `/notes status` — show activation, dirty state, generation, path, and tool-policy status.
35
+ - `/notes on` — activate immediately.
36
+ - `/notes off` — disable tracking/reminders without deleting the file.
37
+ - `/notes auto` — use conservative automatic activation.
38
+ - `/notes checkpoint` — request a model-authored checkpoint immediately when the agent is idle.
39
+ - `/notes resume` — explicitly seed a fresh fork/session identity from a compatible inherited checkpoint, baseline the materialized copy for integrity checks, and require a new checkpoint before relying on it.
40
+ - `/notes restore` — rematerialize the latest committed checkpoint for the active branch while preserving its clean/dirty state.
41
+
42
+ ## Tool
43
+
44
+ `checkpoint_notes` is sequential, accepts bounded structured semantic state, and has no path/session/hash/generation arguments. It writes a compact durable continuation/task-state handoff—not general notes—to the fixed session-local `NOTES.md`. Each payload field has a mutually exclusive role: `current` is the present objective/status; `completed` is finished work; `findings` are observed facts and constraints; `decisions` are chosen approaches and rationale; `failed_approaches` are failed attempts; `blockers` are unresolved impediments; `verification` contains verification commands/outcomes only; and `next_action` is the one next concrete action. Do not put verification in `completed`, repeat `current` in `next_action`, or copy deterministic working-set facts into authored sections. The extension adds deterministic harness facts internally and atomically rewrites the fixed session-local `NOTES.md`.
45
+
46
+ `current` and `next_action` accept 1–2,048 characters. Every list item accepts 1–1,024 characters; `completed`, `findings`, `decisions`, and `verification` accept at most 40 items, while `failed_approaches` and `blockers` accept at most 30. The extension validates these limits before Pi's generic tool validator and reports the offending field/path and measured size without echoing rejected state. It never silently truncates, drops, or relocates oversized authored content; summarize it and retry. The tool guidance recommends a smaller budget: `current` ≤400 characters, `next_action` ≤250 characters, at most 3 items per list, and ≤180 characters per item; do not paste plans, logs, raw test output, or file lists.
47
+
48
+ While Notes is active, built-in `edit`/`write` calls targeting the canonical Notes file are blocked. Unexpected external changes are detected before checkpointing and, when goal integration is present, before allowing goal completion; `/notes restore` rematerializes the trusted committed snapshot.
49
+
50
+ ## Lifecycle
51
+
52
+ Automatic activation is intentionally conservative: 8 turns or 32 tool calls after high-signal activity, or 10 consecutive read-only turns. Activation signal and checkpoint freshness are independent. Once the handoff is active, high-signal mutations, verification/build/test outcomes, errors, and completed subagent handoffs mark a clean checkpoint dirty immediately. Ordinary successful source reads, searches, and research remain low-signal continuity activity: they do not individually dirty a clean checkpoint or increment the 32-result pressure counter. After 16 successful read/search/research results, a separate read-only pressure threshold marks the handoff dirty and due even when the results occur in one turn. Sustained read-only investigation also marks the handoff dirty once the existing 10-consecutive-turn threshold is reached; normal dirty-turn pressure then applies. Checkpoint commit resets both read-only counters. Checkpoint pressure otherwise begins after 10 additional dirty turns or 32 continuity-relevant high-signal results; each due episode emits at most one ambient checkpoint reminder until a fresh checkpoint or a newly armed due episode. After successful compaction, re-entry requests a reread only when a committed session-local checkpoint has been materialized, and the reminder includes that checkpoint's canonical path. Dirty checkpoint pressure remains preserved independently, so compaction and completion still enforce freshness immediately even when there is no file to reread.
53
+
54
+ The extension uses Pi core APIs only:
55
+
56
+ - `tool_result` for independent high-signal activation, hybrid freshness tracking, and verification tracking.
57
+ - `before_agent_start` for the static Notes policy.
58
+ - `context` for transient de-duplicated checkpoint/re-entry reminders.
59
+ - `pi.appendEntry()` for branch-local dirty/checkpoint state.
60
+ - `session_start`, `session_tree`, `session_compact`, and `session_compact_failed` for recovery.
61
+
62
+ It does not call `pi.setActiveTools()`. If another mode hides `checkpoint_notes`, reminder pressure pauses until the tool becomes available again.
63
+
64
+ Lifecycle tests cover fresh identities, branch restoration, resume rematerialization, deferred read/research freshness, read-only threshold and streak reset, delayed checkpoint pressure, compaction pressure, inherited-resume integrity, and external-mutation gating.
65
+
66
+ ## Optional integrations
67
+
68
+ The core has no dependency on goal, plan mode, orchestrator, subagents, memory, or compaction extensions.
69
+
70
+ When present:
71
+
72
+ - `goal_progress({ status: "done" })` is blocked while active Notes are dirty or the materialized checkpoint no longer matches the last committed hash.
73
+ - `Symbol.for("pi-subagents:child-context:v1")` prevents the extension from registering in child subagent sessions.
74
+ - `pi-plan-mode` may explicitly allowlist `checkpoint_notes`; child sessions do not load `pi-notes`.
75
+
76
+ A task-state checkpoint records continuity state. It is not verification evidence and does not replace a plan, goal, todo system, or completion verifier.
77
+
78
+ ## Development
79
+
80
+ ```sh
81
+ npm ci
82
+ npm run check
83
+ npm pack --dry-run
84
+ npm audit --omit=dev
85
+ ```
86
+
87
+ The package has no runtime dependencies outside the Pi core packages and
88
+ `typebox`, which Pi provides. The extension runs with the same local access as
89
+ other Pi extensions; review the source before installing it in a sensitive
90
+ environment.
package/entry.ts ADDED
@@ -0,0 +1,20 @@
1
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
2
+ import notesExtension from "./index.js";
3
+
4
+ const CHILD_SESSION_CONTEXT_PROBE = Symbol.for("pi-subagents:child-context:v1");
5
+
6
+ /**
7
+ * pi-subagents-local exposes its child marker only while loading/building a
8
+ * child session. Capture that fact at extension factory invocation time; later
9
+ * tool/event callbacks run outside the AsyncLocalStorage scope.
10
+ */
11
+ export function isSubagentChildLoad(): boolean {
12
+ const registry = globalThis as unknown as Record<PropertyKey, unknown>;
13
+ const probe = registry[CHILD_SESSION_CONTEXT_PROBE];
14
+ return typeof probe === "function" && (probe as () => boolean)() === true;
15
+ }
16
+
17
+ export default function notesExtensionEntry(pi: ExtensionAPI): void {
18
+ if (isSubagentChildLoad()) return;
19
+ notesExtension(pi);
20
+ }