@@ -84,7 +84,12 @@ uniform surface.
8484| ` find ` | glob (` ** ` crosses dirs), sorted relative paths |
8585| ` ls ` | type markers + sizes, dirs first |
8686
87- All path-taking tools enforce the project boundary (` requirePathInsideProject ` ) before any I/O.
87+ All path-taking tools enforce the project boundary through ` resolveWorkspacePath `
88+ (src/tools/paths.ts) before any I/O: the lexical path is resolved, then ** canonicalized with
89+ ` fs.realpathSync ` on both sides** (existing target — or nearest existing ancestor for new
90+ files — versus canonical project root). Symlink escapes (` link -> /etc/hosts ` , writing through
91+ a symlinked directory, broken symlinks) are rejected with a model-friendly
92+ ` Path resolves outside project directory: … ` error while ordinary relative paths keep working.
8893
8994## 4. Tool execution flow
9095
@@ -116,10 +121,22 @@ Three layers (src/permissions):
116121 Unknown verbs are treated as ` write ` .
1171222 . ** rules.ts** — per-tool defaults: reads inside the project → ALLOW; writes anywhere and
118123 reads outside → ASK; bash routes through the classifier; unknown tools → ASK.
119- 3 . ** manager.ts** — the runtime gate. ASK verdicts consult session-scoped "always allow"
120- patterns (e.g. ` bash: npm install … ` family), then ` mode ` (` auto ` approves everything),
121- then the host's prompt callback. No callback ⇒ safe deny. The TUI dialog offers
122- * Allow once / Always allow this pattern / Deny* .
124+ 3 . ** manager.ts** — the runtime gate. Order of evaluation:
125+
126+ ```
127+ hard DENY rule (catastrophic shell: rm -rf /, mkfs, raw disk write, …)
128+ → refused unconditionally; auto mode and dialogs can never override it
129+ ALLOW verdict → run
130+ ASK verdict → remembered "always allow" pattern?
131+ → mode === "auto"? approved
132+ → prompt callback available? dialog decides
133+ → otherwise safe DENY
134+ ```
135+
136+ Semantics differ by surface: the TUI shows the dialog (* Allow once / Always allow this
137+ pattern / Deny* ); headless ` -p ` has no dialog, so its default is deny-on-ASK and automation
138+ requires the explicit ` --permission-mode auto ` opt-in. SIGINT and the Ctrl+C binding share
139+ the same interrupt logic so ISIG terminals behave identically.
123140
124141## 6. Context engineering
125142
@@ -138,6 +155,12 @@ Three layers (src/permissions):
138155
139156## 7. Session
140157
158+ Every interactive launch owns a session from message one: plain ` tinycode ` maps to
159+ ` {mode:"new"} ` , ` --continue ` attaches the newest session whose stored cwd matches (never
160+ another project's; falls back to a new session with a note when none matches), ` --session <id> `
161+ attaches exactly that id. ` /new ` rotates the id and clears the live transcript — Pi's
162+ ` Agent.reset() ` preserves systemPrompt/model/tools/hooks, so tool calling continues seamlessly.
163+
141164One JSONL file per session in ` <dataHome>/sessions/<id>.jsonl ` (id = UUIDv7):
142165
143166``` jsonl
@@ -147,11 +170,11 @@ One JSONL file per session in `<dataHome>/sessions/<id>.jsonl` (id = UUIDv7):
147170{"type" :" message" ,"message" :{ …toolResult… }}
148171```
149172
150- Writes are synchronous appends; a torn final line (crash mid-append) is skipped on load.
151- The header is rewritten once when the first real prompt lands so ` /sessions ` shows titles.
152- ` --continue ` attaches the newest session for the cwd; ` --session <id> ` any other; attach
153- restores the transcript verbatim into the live ` Agent ` . Tests redirect storage via
154- ` TINYCODE_HOME ` .
173+ Writes are synchronous appends — files are never truncated after creation (the first real
174+ prompt adds the title by rewriting the not-yet-valuable header line only). ` attach() ` is
175+ strictly read-only: it restores the transcript into the live ` Agent ` and keeps appending to
176+ the same file, so a crash during resume cannot destroy history. A torn final line (crash
177+ mid-append) is skipped on load. Tests redirect storage via ` TINYCODE_HOME ` .
155178
156179## 8. Skills
157180
0 commit comments