@nklisch/pi-enhanced 0.4.3 → 0.5.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 (47) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/README.md +1 -1
  3. package/node_modules/@nklisch/pi-astral-pocket/README.md +127 -93
  4. package/node_modules/@nklisch/pi-astral-pocket/package.json +2 -2
  5. package/node_modules/@nklisch/pi-astral-pocket/src/distiller.ts +196 -183
  6. package/node_modules/@nklisch/pi-astral-pocket/src/guidance.ts +26 -62
  7. package/node_modules/@nklisch/pi-astral-pocket/src/index.ts +8 -5
  8. package/node_modules/@nklisch/pi-astral-pocket/src/sessions.ts +10 -3
  9. package/node_modules/@nklisch/pi-astral-pocket/src/store.ts +439 -321
  10. package/node_modules/@nklisch/pi-astral-pocket/src/tools.ts +172 -66
  11. package/node_modules/@nklisch/pi-clearance/docs/CONFIGURATION.md +3 -3
  12. package/node_modules/@nklisch/pi-clearance/docs/DEVELOPER_GUIDE.md +11 -12
  13. package/node_modules/@nklisch/pi-clearance/docs/PACK_AUTHORING.md +5 -5
  14. package/node_modules/@nklisch/pi-clearance/docs/PRINCIPLES.md +1 -2
  15. package/node_modules/@nklisch/pi-clearance/docs/REFERENCE_PATTERNS.md +13 -19
  16. package/node_modules/@nklisch/pi-clearance/docs/SPEC.md +4 -4
  17. package/node_modules/@nklisch/pi-clearance/docs/USER_GUIDE.md +2 -3
  18. package/node_modules/@nklisch/pi-clearance/docs/VISION.md +1 -1
  19. package/node_modules/@nklisch/pi-clearance/native/clearance-core.win32-x64-msvc.node +0 -0
  20. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/README.md +2 -2
  21. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/docs/VISION.md +2 -3
  22. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/docs/architecture/architecture.md +105 -886
  23. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/docs/decisions/0002-extensions-on-a-minimal-core.md +44 -78
  24. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/docs/decisions/0003-publish-bundled-type-declarations.md +28 -57
  25. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/docs/decisions/0004-reconsider-ui-direction.md +49 -261
  26. package/node_modules/@nklisch/pi-plugins/package.json +2 -2
  27. package/package.json +2 -2
  28. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/docs/architecture/client-server-opportunities.md +0 -127
  29. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/docs/architecture/history/phase-1-api-boundary.md +0 -8
  30. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/docs/architecture/history/phase-10-structural-decomposition.md +0 -141
  31. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/docs/architecture/history/phase-11-closure-to-class.md +0 -100
  32. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/docs/architecture/history/phase-12-complexity-test-fixtures.md +0 -55
  33. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/docs/architecture/history/phase-13-remaining-smells.md +0 -88
  34. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/docs/architecture/history/phase-14-strip-policy.md +0 -49
  35. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/docs/architecture/history/phase-15-domain-model-evolution.md +0 -73
  36. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/docs/architecture/history/phase-16-invert-dependencies.md +0 -144
  37. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/docs/architecture/history/phase-17-core-consolidation.md +0 -214
  38. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/docs/architecture/history/phase-18-reconsider-ui.md +0 -166
  39. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/docs/architecture/history/phase-19-implement-ui-decisions.md +0 -282
  40. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/docs/architecture/history/phase-2-remove-scheduling.md +0 -9
  41. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/docs/architecture/history/phase-3-remove-rpc-groupjoin.md +0 -11
  42. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/docs/architecture/history/phase-4-implement-service.md +0 -8
  43. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/docs/architecture/history/phase-5-decompose-index.md +0 -42
  44. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/docs/architecture/history/phase-7-encapsulation.md +0 -173
  45. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/docs/architecture/history/phase-8-testability.md +0 -103
  46. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/docs/architecture/history/phase-9-observation-ctx.md +0 -122
  47. package/node_modules/@nklisch/pi-plugins/node_modules/@nklisch/pi-subagents/docs/decisions/0001-deferred-patches.md +0 -80
@@ -2,140 +2,246 @@ import { Type } from "typebox";
2
2
  import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
3
3
  import { withFileMutationQueue } from "@earendil-works/pi-coding-agent";
4
4
  import { join } from "node:path";
5
-
6
5
  import type { ActivationState } from "./activation.js";
7
6
  import { resolveProjectIdentity } from "./scope.js";
8
7
  import { searchAstraSessions } from "./sessions.js";
9
- import { readSummaryCapped, searchPocket, writeNote } from "./store.js";
8
+ import {
9
+ MAX_BODY_CHARS,
10
+ MAX_EVIDENCE_CHARS,
11
+ MAX_TITLE_CHARS,
12
+ retireNote,
13
+ searchPocket,
14
+ writeNote,
15
+ } from "./store.js";
10
16
 
11
17
  const INACTIVE_MESSAGE =
12
18
  "Pocket tools are only active in gpt-6-astra sessions with the pocket enabled (/pocket on).";
13
- const DEFAULT_RECALL_LIMIT = 10;
14
19
  export const MAX_RECALL_LIMIT_PER_SOURCE = 20;
15
-
16
20
  function normalizeRecallLimit(value: unknown): number {
17
- if (typeof value !== "number" || !Number.isFinite(value)) return DEFAULT_RECALL_LIMIT;
21
+ if (typeof value !== "number" || !Number.isFinite(value)) return 10;
18
22
  return Math.min(MAX_RECALL_LIMIT_PER_SOURCE, Math.max(1, Math.trunc(value)));
19
23
  }
20
-
21
24
  export interface ToolDeps {
22
25
  state: ActivationState;
23
- /** Pocket root directory (~/.pi/agent/astral-pocket). */
24
26
  root: string;
25
- /** Sessions directory (~/.pi/agent/sessions). */
26
27
  sessionsDir: string;
27
28
  maxSessionAgeDays: () => number;
28
29
  }
29
-
30
30
  function textResult(text: string) {
31
31
  return { content: [{ type: "text" as const, text }], details: {} };
32
32
  }
33
-
34
33
  export function registerPocketTools(pi: ExtensionAPI, deps: ToolDeps): void {
35
34
  pi.registerTool({
36
35
  name: "pocket_note",
37
36
  label: "Pocket Note",
38
37
  description:
39
- "Write a durable note to your persistent pocket. Notes default to the current repository. Use global scope only for explicitly portable preferences or observations never for secrets or ephemeral task state.",
40
- promptSnippet: "Save a durable cross-session note to the astral pocket",
38
+ "Save, replace or retire a current-repository navigation clue or hard-to-rediscover technical pitfall. Never save preferences, user policy, delivery history or facts already covered by current docs. New notes are project-only.",
39
+ promptSnippet:
40
+ "Save or retire a repository navigation clue or technical pitfall",
41
41
  promptGuidelines: [
42
- "Use pocket_note when you learn something durable (a decision and why, a project convention, a pitfall, a user preference) not for ephemeral task state.",
43
- "Never put secrets, credentials, tokens, or personal data in pocket notes.",
44
- "Keep pocket_note project-scoped by default; use global scope only for a clearly general preference or conditional portable observation.",
42
+ "Use pocket_note only for actionable repository navigation or verified technical pitfalls worth avoiding rediscovery; never preferences, policy, architecture/status summaries, ordinary docs facts or personal data.",
43
+ "Retire obsolete notes; replace updates agent-authored notes in place, supersedes retires source notes when saving a new learning.",
45
44
  ],
46
45
  parameters: Type.Object({
47
- title: Type.String({ description: "Short note title" }),
48
- body: Type.String({ description: "Note content — a few sentences is enough" }),
49
- keywords: Type.Optional(Type.Array(Type.String(), { description: "2-5 recall keywords" })),
50
- scope: Type.Optional(Type.Union([Type.Literal("project"), Type.Literal("global")], {
51
- description: "Project by default. Use global only for explicitly portable preferences or observations.",
52
- })),
46
+ action: Type.Optional(
47
+ Type.Union([Type.Literal("save"), Type.Literal("retire")], {
48
+ description: "Default save. Retire needs noteFile only.",
49
+ }),
50
+ ),
51
+ noteFile: Type.Optional(
52
+ Type.String({
53
+ description: "Canonical filename to retire (not a path)",
54
+ }),
55
+ ),
56
+ kind: Type.Optional(
57
+ Type.Union([Type.Literal("navigation"), Type.Literal("pitfall")], {
58
+ description: "Required for save",
59
+ }),
60
+ ),
61
+ title: Type.Optional(
62
+ Type.String({
63
+ minLength: 1,
64
+ maxLength: MAX_TITLE_CHARS,
65
+ description: "Required for save: descriptive technical title",
66
+ }),
67
+ ),
68
+ body: Type.Optional(
69
+ Type.String({
70
+ minLength: 1,
71
+ maxLength: MAX_BODY_CHARS,
72
+ description:
73
+ "Required for save: one complete actionable learning, not a status summary",
74
+ }),
75
+ ),
76
+ evidence: Type.Optional(
77
+ Type.String({
78
+ maxLength: MAX_EVIDENCE_CHARS,
79
+ description:
80
+ "Optional source path, symbol, command or other evidence pointer",
81
+ }),
82
+ ),
83
+ keywords: Type.Optional(
84
+ Type.Array(Type.String({ maxLength: 64 }), { maxItems: 5 }),
85
+ ),
86
+ replace: Type.Optional(
87
+ Type.String({
88
+ description: "Existing agent-authored note filename to update",
89
+ }),
90
+ ),
91
+ supersedes: Type.Optional(
92
+ Type.Array(Type.String(), {
93
+ maxItems: 10,
94
+ description:
95
+ "Current-repository note filenames to retire when saving this learning",
96
+ }),
97
+ ),
53
98
  }),
54
- async execute(_toolCallId, params, signal, _onUpdate, ctx) {
99
+ async execute(_id, params, signal, _onUpdate, ctx) {
55
100
  if (!deps.state.active) throw new Error(INACTIVE_MESSAGE);
56
- if (signal?.aborted) throw new Error("Pocket note cancelled");
57
- const project = ctx.cwd;
58
- const scope = params.scope ?? "project";
59
- const projectId = resolveProjectIdentity(project);
60
- const fileName = await withFileMutationQueue(join(deps.root, "POCKET.md"), async () => {
61
- if (signal?.aborted || !deps.state.active) throw new Error("Pocket note cancelled");
62
- return writeNote(deps.root, {
63
- title: params.title,
64
- body: params.body,
65
- keywords: params.keywords,
66
- project,
67
- projectId: scope === "project" ? projectId : undefined,
68
- scope,
69
- source: "agent",
70
- });
101
+ const projectId = resolveProjectIdentity(ctx.cwd);
102
+ return withFileMutationQueue(join(deps.root, "POCKET.md"), async () => {
103
+ if (signal?.aborted || !deps.state.active)
104
+ throw new Error("Pocket note cancelled");
105
+ if (params.action === "retire") {
106
+ if (!params.noteFile) throw new Error("Retire requires noteFile");
107
+ retireNote(deps.root, params.noteFile, projectId);
108
+ return textResult(
109
+ `Retired notes/${params.noteFile}; excluded from startup and default recall. Retiring generated learning also prevents further automatic extraction of its source session.`,
110
+ );
111
+ }
112
+ if (params.action !== undefined && params.action !== "save")
113
+ throw new Error("Unknown note action");
114
+ if (!params.kind || !params.title || !params.body)
115
+ throw new Error("Save requires kind, title and body");
116
+ if (params.noteFile)
117
+ throw new Error(
118
+ "Use replace to update a note, or action: retire with noteFile",
119
+ );
120
+ const fileName = writeNote(
121
+ deps.root,
122
+ {
123
+ kind: params.kind,
124
+ title: params.title,
125
+ body: params.body,
126
+ evidence: params.evidence,
127
+ keywords: params.keywords,
128
+ project: ctx.cwd,
129
+ projectId,
130
+ },
131
+ new Date(),
132
+ { replace: params.replace, supersedes: params.supersedes },
133
+ );
134
+ return textResult(`Learning saved: notes/${fileName}`);
71
135
  });
72
- return textResult(`Note saved to the pocket: notes/${fileName}`);
73
136
  },
74
137
  });
75
-
76
138
  pi.registerTool({
77
139
  name: "pocket_recall",
78
140
  label: "Pocket Recall",
79
141
  description:
80
- "Search current-repository and explicit global pocket notes plus current-repository Astra sessions. Summarized by default; pass full: true for larger excerpts or scope: all for intentional cross-repository precedent.",
81
- promptSnippet: "Search pocket notes and past astra sessions",
142
+ "Search active current-repository learning notes by default. source: sessions or both explicitly includes historical transcripts. includeHistory: true includes legacy/retired notes; scope: all searches other repositories but does not enable history. full: true returns larger excerpts, not full files.",
143
+ promptSnippet:
144
+ "Search repository learning or explicitly requested historical excerpts",
82
145
  promptGuidelines: [
83
- "Use pocket_recall for the quick pocket pass: search with keywords from the pocket summary before deep repo exploration.",
84
- "Keep recall cheap: at most 4-6 lookup steps, summarized results first, full: true only when you need exact commands or error text.",
146
+ "Start with one focused recall when a concrete navigation or rediscovery problem makes it useful; expand only if results help. Recall is not mandatory for every repository task.",
85
147
  ],
86
148
  parameters: Type.Object({
87
- query: Type.String({ description: "Keywords to search for (all must match)" }),
149
+ query: Type.String({
150
+ description: "Keywords to search for (all must match)",
151
+ }),
88
152
  source: Type.Optional(
89
- Type.Union([Type.Literal("pocket"), Type.Literal("sessions"), Type.Literal("both")], {
90
- description: "Where to search (default: both)",
153
+ Type.Union(
154
+ [
155
+ Type.Literal("pocket"),
156
+ Type.Literal("sessions"),
157
+ Type.Literal("both"),
158
+ ],
159
+ {
160
+ description:
161
+ "Default pocket. Sessions are historical precedent, not active learning.",
162
+ },
163
+ ),
164
+ ),
165
+ includeHistory: Type.Optional(
166
+ Type.Boolean({
167
+ description:
168
+ "Include labeled legacy, unclassified, retired and global notes (default false)",
169
+ }),
170
+ ),
171
+ full: Type.Optional(
172
+ Type.Boolean({
173
+ description: "Larger excerpts, not complete files (default false)",
174
+ }),
175
+ ),
176
+ limit: Type.Optional(
177
+ Type.Integer({
178
+ minimum: 1,
179
+ maximum: MAX_RECALL_LIMIT_PER_SOURCE,
180
+ description: "Max hits per source; default 10",
181
+ }),
182
+ ),
183
+ scope: Type.Optional(
184
+ Type.Union([Type.Literal("current"), Type.Literal("all")], {
185
+ description:
186
+ "Current repository by default; all adds foreign precedent, independently of includeHistory.",
91
187
  }),
92
188
  ),
93
- full: Type.Optional(Type.Boolean({ description: "Return larger excerpts (default: false)" })),
94
- limit: Type.Optional(Type.Integer({
95
- minimum: 1,
96
- maximum: MAX_RECALL_LIMIT_PER_SOURCE,
97
- description: "Max hits from each source (default: 10, maximum: 20)",
98
- })),
99
- scope: Type.Optional(Type.Union([Type.Literal("current"), Type.Literal("all")], {
100
- description: "Current repository plus global notes by default; all includes foreign repositories as precedent.",
101
- })),
102
189
  }),
103
- async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
190
+ async execute(_id, params, signal, _onUpdate, ctx) {
104
191
  if (!deps.state.active) throw new Error(INACTIVE_MESSAGE);
105
- const source = params.source ?? "both";
192
+ if (signal?.aborted) throw new Error("Pocket recall cancelled");
193
+ const source = params.source ?? "pocket";
106
194
  const limit = normalizeRecallLimit(params.limit);
107
- const recallScope = params.scope ?? "current";
195
+ const scope = params.scope ?? "current";
108
196
  const projectId = resolveProjectIdentity(ctx.cwd);
197
+ const excludeSession = {
198
+ id: ctx.sessionManager.getSessionId(),
199
+ path: ctx.sessionManager.getSessionFile(),
200
+ };
109
201
  const sections: string[] = [];
110
-
111
202
  if (source === "pocket" || source === "both") {
112
- const hits = searchPocket(deps.root, params.query, projectId, limit, params.full, recallScope);
203
+ const hits = searchPocket(
204
+ deps.root,
205
+ params.query,
206
+ projectId,
207
+ limit,
208
+ params.full,
209
+ scope,
210
+ params.includeHistory,
211
+ excludeSession,
212
+ );
113
213
  sections.push(
114
214
  hits.length === 0
115
215
  ? "Pocket notes: no matches."
116
216
  : `Pocket notes (${hits.length}):\n${hits
117
- .map((h) => `- ${h.title} [notes/${h.noteFile}]${h.project ? ` (${h.project})` : ""} · scope: ${h.scope}${recallScope === "all" && h.scope === "project" && resolveProjectIdentity(h.project) !== projectId ? " · cross-repository precedent" : ""}${h.source ? ` · ${h.source}` : ""}${h.date ? ` · ${h.date}` : ""}\n ${h.excerpt}`)
217
+ .map(
218
+ (hit) =>
219
+ `- ${hit.title} [notes/${hit.noteFile}] (${hit.project || "unknown"}) · ${hit.scope} · ${hit.date}${hit.historical ? " · historical precedent (not current authority)" : ""}${hit.retired ? " · retired" : ""}\n ${hit.excerpt}`,
220
+ )
118
221
  .join("\n")}`,
119
222
  );
120
223
  }
121
-
122
224
  if (source === "sessions" || source === "both") {
123
225
  const hits = await searchAstraSessions(deps.sessionsDir, params.query, {
124
226
  full: params.full,
125
227
  limit,
126
228
  maxAgeDays: deps.maxSessionAgeDays(),
127
229
  projectId,
128
- recallScope,
230
+ recallScope: scope,
231
+ excludeSession,
129
232
  });
233
+ if (signal?.aborted) throw new Error("Pocket recall cancelled");
130
234
  sections.push(
131
235
  hits.length === 0
132
236
  ? "Past astra sessions: no matches."
133
- : `Past astra sessions (${hits.length}):\n${hits
134
- .map((h) => `- [${h.kind}] ${h.timestamp} (${h.project})${recallScope === "all" && resolveProjectIdentity(h.project) !== projectId ? " · cross-repository precedent" : ""}\n ${h.excerpt}`)
237
+ : `Past astra sessions (${hits.length}) — historical precedent, not current authority:\n${hits
238
+ .map(
239
+ (hit) =>
240
+ `- [${hit.kind}] ${hit.timestamp} (${hit.project}) · session ${hit.sessionId}\n ${hit.excerpt}`,
241
+ )
135
242
  .join("\n")}`,
136
243
  );
137
244
  }
138
-
139
245
  return textResult(sections.join("\n\n"));
140
246
  },
141
247
  });
@@ -34,7 +34,7 @@ display, pack, and posture fields are supplied by runtime normalization.
34
34
  | `ask` | human prompt; unattended calls block-and-log | deny |
35
35
  | `auto` | model first, then human/block fallback | deny |
36
36
 
37
- `gatedTools` is a global exact-name list and defaults to empty. Non-Bash tools absent from the list bypass Clearance analysis and policy entirely, execute, and receive an audit entry marked as an allow/bypass. There are no wildcards or future-tool opt-ins, and `bash` cannot be listed. Bash remains fully gated. This intentionally makes typed edit/read protections opt-in and is a published behavioral break for the next minor release.
37
+ `gatedTools` is a global exact-name list and defaults to empty. Non-Bash tools absent from the list bypass Clearance analysis and policy entirely, execute, and receive an audit entry marked as an allow/bypass. There are no wildcards or future-tool opt-ins, and `bash` cannot be listed. Bash remains fully gated. Typed edit/read protections are opt-in.
38
38
 
39
39
  `unknownToolPosture` remains a config-file-only knob and applies only to an opted-in non-Bash tool that has no registered analyzer. It defaults to `"allow"`; it does not re-gate tools absent from `gatedTools`. Setting it to `"review"` or `"deny"` tightens opted-in unknown tools. The sealed floor and all active user/shipped deny rules run in every mode.
40
40
 
@@ -71,7 +71,7 @@ The reviewer settings selector exposes `promptPosture` and `model` interactively
71
71
 
72
72
  ## Packs
73
73
 
74
- The baseline is always the old default pack set plus `bash.network.read`, `pi.extension.network-research`, and `pi.home.safe`. Mode never changes baseline activation. Package packs remain available until explicitly enabled through `packEnablement.enabledPackagePacks`; user-owned config packs can be disabled with `disabledConfigPacks`.
74
+ The built-in baseline is described in [RULE_PACKS.md](RULE_PACKS.md#baseline), including `bash.network.read`, `pi.extension.network-research`, and `pi.home.safe`. Mode never changes baseline activation. Package packs remain available until explicitly enabled through `packEnablement.enabledPackagePacks`; user-owned config packs can be disabled with `disabledConfigPacks`.
75
75
 
76
76
  ## Commands
77
77
 
@@ -81,4 +81,4 @@ The baseline is always the old default pack set plus `bash.network.read`, `pi.ex
81
81
  - `/clearance status`, `/clearance packs`, `/clearance scope`, `/clearance tune`, `/clearance why` — unchanged surfaces with mode/baseline vocabulary. Scope management also supports `scope agent-support add|remove <path>` and `scope agent-support-defaults <on|off>`.
82
82
  - `/clearance allow <plain language>` or `/clearance allow` — hand an agent-authored structural allow request to the shared proposal card. Accepted rules land in the user-global pack; this command adds no separate config surface.
83
83
 
84
- `/clearance profile` and `/clearance auto` are removed with no aliases. The next minor release must call out the non-Bash default bypass and the typed-tool protection break.
84
+ `/clearance profile` and `/clearance auto` are unsupported and have no aliases.
@@ -2,7 +2,7 @@
2
2
 
3
3
  This guide is for people changing Pi Clearance itself.
4
4
 
5
- > The pre-public command surface is `/clearance`; removed commands and aliases are not preserved.
5
+ > The command surface is `/clearance`; unsupported commands have no compatibility aliases.
6
6
 
7
7
  For product behavior, start with [README.md](../README.md) and [USER_GUIDE.md](USER_GUIDE.md). For design intent, read the foundation docs linked at the end of this file.
8
8
 
@@ -127,7 +127,7 @@ package README snippets.
127
127
  | `src/skill/clearance-tune/` | internal tune helper harness plus display-only structured proposal presentation seam |
128
128
  | `src/skill/clearance-*/` | thin agent guidance that points to canonical docs |
129
129
  | `test/` | unit, fixture, replay, runtime, and skill tests |
130
- | `.work/` | Workbench state (active items, backlog, conventions) |
130
+ | [Repository `.work/`](../../../.work/) | Workbench state (active items, backlog, conventions) |
131
131
 
132
132
  ## Settings command surface and dispatcher seam
133
133
 
@@ -262,23 +262,22 @@ Public docs should stay practical and low-hype:
262
262
 
263
263
  The root README and these reference docs are user/developer docs. The foundation docs remain the design source of truth.
264
264
 
265
- ## Agile-workflow substrate
265
+ ## Contributor workflow
266
266
 
267
- Work is tracked in `.work/` as plain markdown items: `active/` for in-flight
268
- epics/features/stories, `backlog/` for parked ideas, and `CONVENTIONS.md` for
269
- project behavior (tags, verification commands, body discipline). Read item
270
- files directly; there is no separate query binary.
271
-
272
- Before design, implementation, or review work, read `.work/CONVENTIONS.md` and
273
- the relevant `docs/` foundation docs.
267
+ Follow the repository's [AGENTS.md](../../../AGENTS.md) and
268
+ [Workbench conventions](../../../.work/CONVENTIONS.md) for work tracking,
269
+ verification, and review.
274
270
 
275
271
  ## Foundation docs
276
272
 
277
- - [VISION.md](VISION.md) — product direction and open questions.
273
+ - [VISION.md](VISION.md) — product direction.
278
274
  - [SPEC.md](SPEC.md) — behavior contract.
279
275
  - [ARCHITECTURE.md](ARCHITECTURE.md) — module boundaries.
280
276
  - [PRINCIPLES.md](PRINCIPLES.md) — safety and execution rules.
277
+
278
+ ## Focused references
279
+
281
280
  - [RULE_PACKS.md](RULE_PACKS.md) — shipped pack intent.
282
281
  - [PACK_AUTHORING.md](PACK_AUTHORING.md) — data-pack, TypeScript-pack, and package distribution guidance.
283
282
  - [REVIEWER_PROMPTS.md](REVIEWER_PROMPTS.md) — prompt and reviewer contract.
284
- - [REFERENCE_PATTERNS.md](REFERENCE_PATTERNS.md) — reference patterns from earlier captures.
283
+ - [REFERENCE_PATTERNS.md](REFERENCE_PATTERNS.md) — policy-corpus vocabulary, command-family lessons, and capture provenance; not an implementation-pattern catalog or foundation.
@@ -305,11 +305,11 @@ is not covered makes a project-local allow return `false`. For `none-in` without
305
305
  `deny > review > allow` — so a `review` rule for `mkdir -m` and a sealed-floor `deny` for
306
306
  `sudo` still win over a matching path-scoped allow.
307
307
 
308
- The runtime enrichment seam supplies cwd and project scope only; `homeDirectory` plumbing is
309
- tracked separately. As a result a runtime `~/...` operand stays `scope: "unknown"` and fails
310
- closed rather than resolving to `home` this is safe current behavior, not a historical aside,
311
- and it causes extra review, never an unsafe allow. Supplying `homeDirectory` at the runtime
312
- seam is the follow-up that lets `~/...` classify as `home`.
308
+ Runtime enrichment receives cwd, project scope, and the resolved `homeDirectory` when
309
+ available. Supported unquoted `~/...` operands resolve lexically against that home before
310
+ scope classification; the winning scope still follows configured precedence, so it is not
311
+ necessarily `home`. Without a usable home directory, these operands remain `unknown` and
312
+ cannot satisfy a constructive allow.
313
313
 
314
314
  ## Compound shell matchers
315
315
 
@@ -56,8 +56,7 @@ the host approval boundary. Global `gatedTools` is an exact-name opt-in list wit
56
56
  wildcards or future-tool consent; Bash is always fully gated and cannot be listed. An
57
57
  opted-in tool without a registered analyzer uses `unknownToolPosture`, which defaults to
58
58
  `"allow"` and may be tightened to `"review"` or `"deny"`. The posture does not apply to
59
- absent names, and the next minor release must communicate this intentional typed-tool
60
- protection break.
59
+ absent names.
61
60
 
62
61
  **Implication:** the interpreter must be pure and total for gated calls: every analyzed
63
62
  or opted-in unknown input returns `allow`, `deny`, or `review` with a reason; bypasses are
@@ -2,11 +2,11 @@
2
2
 
3
3
  ## Purpose statement
4
4
 
5
- This document is the durable bridge from two reference sources into the clean
6
- pi-clearance product:
5
+ This policy-corpus reference preserves vocabulary, command-family lessons, and
6
+ provenance from two sources:
7
7
 
8
8
  - the local `pi-config` clearance proof of concept; and
9
- - the old fork-shaped permission-system scaffold currently being retired.
9
+ - a fork-shaped permission-system scaffold.
10
10
 
11
11
  These sources are **command-pattern, fixture-vocabulary, package-shape, and
12
12
  tune-report inspiration only**. They are not runtime architecture for
@@ -252,10 +252,9 @@ Additional shape notes:
252
252
 
253
253
  ## Package-metadata reference note
254
254
 
255
- The old fork `package.json` is mined for package-shape facts only. The durable product
256
- target identity is Pi Clearance / `pi-clearance` as a clean pre-1.0 Pi extension; `package-spine` resets the
257
- fork-shaped `name`, `version`, and `description` instead of preserving them as product
258
- identity.
255
+ The old fork `package.json` supplies package-shape reference facts only. Its name,
256
+ version, and description do not define Pi Clearance's product identity; the current
257
+ package manifest owns that metadata.
259
258
 
260
259
  Package-shape facts to carry forward:
261
260
 
@@ -268,14 +267,10 @@ Package-shape facts to carry forward:
268
267
  dependency shape.
269
268
  - Node engine: `node >=22.18`, matching the Pi host runtime expectation. Pi loads the package's TypeScript extension entrypoint directly.
270
269
 
271
- Cleanup inputs only:
272
-
273
- - The fork-shaped package `name`, `version`, and `description` are not durable identity.
274
- `package-spine` owns the reset to clean pre-1.0 metadata for this product.
275
- - The old fork exports, files list, schemas, config examples, permission-system keywords,
276
- and extra permission-manager package surface are not behavior contracts. Future package
277
- metadata should be derived from `docs/VISION.md`, `docs/SPEC.md`, and the clean module
278
- spine.
270
+ The old fork exports, files list, schemas, config examples, permission-system keywords,
271
+ and extra permission-manager package surface are not behavior contracts. Package metadata
272
+ must follow the current product boundaries in [VISION.md](VISION.md),
273
+ [SPEC.md](SPEC.md), and [ARCHITECTURE.md](ARCHITECTURE.md), not the reference scaffold.
279
274
 
280
275
  ## Do-not-port architecture bullets
281
276
 
@@ -329,7 +324,6 @@ categories the downstream fixture harness must preserve:
329
324
  `mkfs -t ext4 /dev/sda`, including when hidden inside `&&`, semicolon, or newline
330
325
  chains.
331
326
 
332
- This coverage assertion is a reference-capture check, not the final product contract.
333
- `capture-verification` enforces that the two corpus files keep these categories
334
- represented, while downstream pack/core design remains responsible for deciding which
335
- categories become allow, review, or deny under the clean interpreter.
327
+ These categories describe reference-corpus coverage, not the product's policy outcomes.
328
+ Corpus maintenance should preserve their representation; the current packs and core
329
+ interpreter determine which cases become allow, review, or deny.
@@ -14,14 +14,14 @@ Pi Clearance is a Pi extension that structurally analyzes tool calls, evaluates
14
14
  - User-owned global/project config may add policy; repository policy is tighten-only unless Pi reports the project as trusted.
15
15
  - Package installation makes packs available, not active. Explicit user-owned enablement is required. Clearance defines no npm install lifecycle hooks and package installation never reads or writes user config.
16
16
  - Global and project config written through Clearance is sparse: `version` plus recursively retained non-default user choices. Defaults remain runtime-only. Invalid or obsolete files fail strict validation and runtime falls back to floor-only policy; package installation does not migrate them.
17
- - Pre-public migrations are clean cutovers. Removed keys fail strict schema validation; there are no translators or aliases. Trusted TypeScript rule modules are deliberately cut and are never loaded.
17
+ - Unsupported config keys fail strict schema validation; there are no translators or aliases for removed keys. Executable TypeScript rule modules are never loaded.
18
18
  - The native engine is distributed as prebuilt Node-API artifacts for Linux x64 glibc, Linux arm64 glibc, macOS x64, macOS arm64, and Windows x64 MSVC. Windows ARM is not a release target. Installation never runs Cargo; a missing or unsupported artifact fails closed.
19
19
 
20
20
  ## Config
21
21
 
22
22
  `GlobalConfigSchema` contains `version`, `mode` (default `ask`), exact `gatedTools` (default empty; Bash and wildcards rejected), `unknownToolPosture`, packs, package/config enablement, reviewer advanced fields, and display preferences. Project overlays contain packs, enablement, project scope, and trusted prompt appends. Repository policy has no mode or posture. The complete schemas normalize runtime views; `src/config/persistence.ts` owns the sparse persisted representation.
23
23
 
24
- The former policy posture system and reviewer `enabled`/`mode` fields are removed. Reviewer model pinning and the compact selector/toggle settings controls remain confirm-backed. The separate reviewer consent schema/file is removed; explicit `mode: "auto"` is the acknowledgment. The next minor release must communicate the intentional typed-tool bypass behavior break.
24
+ Reviewer model pinning and the compact selector/toggle settings controls are confirm-backed. Explicit `mode: "auto"` is the acknowledgment for model review; no separate reviewer consent file is read or written. [CONFIGURATION.md](CONFIGURATION.md) lists unsupported legacy keys and their strict-validation behavior.
25
25
 
26
26
  ## Native boundary
27
27
 
@@ -39,8 +39,8 @@ corpus acquisition, proposal heuristics, presentation, and Pi I/O.
39
39
  4. user-project packs and scope;
40
40
  5. trusted repository/package inputs.
41
41
 
42
- The baseline is the former default pack set plus `bash.network.read`, `pi.extension.network-research`, and `pi.home.safe`. Individual pack ids flow into provenance; no posture pseudo-pack exists.
42
+ The baseline comprises the built-in packs described in [RULE_PACKS.md](RULE_PACKS.md#baseline), including `bash.network.read`, `pi.extension.network-research`, and `pi.home.safe`. Individual pack ids flow into provenance; no posture pseudo-pack exists.
43
43
 
44
44
  ## Commands
45
45
 
46
- `/clearance`, `/clearance setup`, `/clearance mode [off|ask|auto]`, `/clearance settings`, `/clearance status`, `/clearance packs`, `/clearance scope`, `/clearance tune`, `/clearance why`, `/clearance allow <plain language>`, and `/clearance allow`. The allow handler only hands a deterministic brief to the agent; it does not construct policy or call the reviewer. `/clearance profile` and `/clearance auto` are removed.
46
+ `/clearance`, `/clearance setup`, `/clearance mode [off|ask|auto]`, `/clearance settings`, `/clearance status`, `/clearance packs`, `/clearance scope`, `/clearance tune`, `/clearance why`, `/clearance allow <plain language>`, and `/clearance allow`. The allow handler only hands a deterministic brief to the agent; it does not construct policy or call the reviewer. `/clearance profile` and `/clearance auto` are unsupported and have no aliases.
@@ -34,7 +34,7 @@ Global and project config written through Clearance is persisted sparsely. Packa
34
34
  /clearance allow
35
35
  ```
36
36
 
37
- Bare `/clearance` opens guided setup. `/clearance mode` without an argument still opens settings. `/clearance profile` and `/clearance auto` were removed before release. There are no aliases. Settings mutations require interactive confirmation and write only user-owned config.
37
+ Bare `/clearance` opens guided setup. `/clearance mode` without an argument still opens settings. `/clearance profile` and `/clearance auto` are unsupported and have no aliases. Settings mutations require interactive confirmation and write only user-owned config.
38
38
 
39
39
  ## Allow a command family
40
40
 
@@ -59,14 +59,13 @@ Review surfaces speak plain language. The human approval card shows what the com
59
59
 
60
60
  The settings control center uses compact selector/toggle rows. It exposes mode, reviewer model and evidence posture, scope preset and unknown-path behavior, a pack explorer, exact gated non-Bash tools, and Stream briefing preferences (note mode, model label, accent). Every mutation uses confirmation, the config planner, atomic write, reload, and policy invalidation. Advanced context, budget, escalation, prompt appends, and overrides remain config-file settings; status names their customization categories without dumping values.
61
61
 
62
- The baseline is broad by default: it includes the former default pack set plus expanded inspection, shell-builtin and system/service reads, bounded development verification, network reads, typed network research, non-secret home and agent-support typed Pi reads, and safe-home typed Pi mutations. Literal project/temp output redirects and `/dev/null` are eligible, while dynamic, `.git`, unknown-fd, and network output redirects remain review-gated. Installed package packs are merely available until explicitly enabled by user-owned config.
62
+ The baseline is broad by default: the [built-in packs](RULE_PACKS.md#baseline) cover inspection, shell-builtin and system/service reads, bounded development verification, network reads, typed network research, non-secret home and agent-support typed Pi reads, and safe-home typed Pi mutations. Literal project/temp output redirects and `/dev/null` are eligible, while dynamic, `.git`, unknown-fd, and network output redirects remain review-gated. Installed package packs are merely available until explicitly enabled by user-owned config.
63
63
 
64
64
  ## Safety model
65
65
 
66
66
  - Parsed structure, not raw shell text, drives policy.
67
67
  - Non-Bash tools bypass Clearance unless their exact name appears in global `gatedTools` (default `[]`); Bash is always gated and cannot be listed.
68
68
  - Opted-in unknown tools follow `unknownToolPosture` (default `allow`). Wildcards and future-tool opt-in are not supported.
69
- - This default typed-tool bypass is an intentional published behavior break and must be called out in the next minor release.
70
69
  - Parser uncertainty and unsupported forms fail closed to review.
71
70
  - Model decisions resolve one call and never create permanent policy.
72
71
  - Tune mode proposes user-approved inspectable data-pack changes after replay and adversarial evidence; executable TypeScript rule modules are not supported.
@@ -20,4 +20,4 @@ The sealed floor always wins. Invalid config fails closed to floor-only policy.
20
20
 
21
21
  ## Trust and growth
22
22
 
23
- User-owned global/project config may widen policy. Repository policy and installed packs cannot silently widen it. Persisted settings written through Clearance contain only non-default choices, while runtime normalization supplies the rest. Package installation neither changes config nor enables packs. Tune replay, adversarial checks, explicit confirmation, and post-write validation make policy growth auditable. The default non-Bash bypass is an intentional published behavioral break requiring next-minor release communication.
23
+ User-owned global/project config may widen policy. Repository policy and installed packs cannot silently widen it. Persisted settings written through Clearance contain only non-default choices, while runtime normalization supplies the rest. Package installation neither changes config nor enables packs. Tune replay, adversarial checks, explicit confirmation, and post-write validation make policy growth auditable.
@@ -33,7 +33,7 @@ Run them in joined or detached mode, steer them while active, resume retained se
33
33
  ## Install
34
34
 
35
35
  This branch is locally qualified but unpublished, so it cannot be installed from npm yet.
36
- After an explicitly authorized publication, the package name will be `@nklisch/pi-subagents` and its immutable registry receipt will be recorded in [Fork maintenance](./docs/FORK-MAINTENANCE.md).
36
+ The published package is `@nklisch/pi-subagents`. [Fork maintenance](./docs/FORK-MAINTENANCE.md) records its provenance, release policy, and compatibility commitments.
37
37
 
38
38
  Load it directly for development:
39
39
 
@@ -458,7 +458,7 @@ It never throws — all error conditions produce a `console.warn` and return `{}
458
458
 
459
459
  This extension is a minimal, composable core: it owns agent spawning, execution, and result retrieval, and exposes a typed `SubagentsService` plus lifecycle events that other extensions build on.
460
460
 
461
- See [`docs/architecture/architecture.md`](./docs/architecture/architecture.md) for the full architecture document — design principles, domain decomposition, module dependency flow, Mermaid diagrams, and the improvement roadmap.
461
+ See [`docs/architecture/architecture.md`](./docs/architecture/architecture.md) for design principles, domain ownership, lifecycle and service contracts, and module dependency diagrams.
462
462
 
463
463
  ## Relationship to upstream
464
464
 
@@ -28,9 +28,8 @@ model, exact effective thinking level, active or final runtime, run id, delivery
28
28
  mode, and terminal reason when one exists. Parent-only lifecycle tools are
29
29
  centrally registered and removed from child tool definitions, preventing
30
30
  recursive orchestration while preserving ordinary inherited extension tools.
31
- The package excludes the retired experimental editors, wizards, and bespoke
32
- conversation viewer from the import branch (see ADR 0004 for the UI direction
33
- history).
31
+ The package excludes agent-definition editors, wizards, and a bespoke
32
+ conversation viewer; ADR 0004 defines the narrow operator UI contract.
34
33
 
35
34
  ## Fork posture
36
35