@gotgenes/pi-permission-system 1.2.1 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,50 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [3.0.0](https://github.com/gotgenes/pi-permission-system/compare/v2.0.0...v3.0.0) (2026-05-03)
9
+
10
+
11
+ ### ⚠ BREAKING CHANGES
12
+
13
+ * Config is now loaded from ~/.pi/agent/extensions/pi-permission-system/config.json (global) and <cwd>/.pi/extensions/pi-permission-system/config.json (project). Legacy paths are detected and merged with migration warnings.
14
+ * Config and log file paths move from the extension install directory and ~/.pi/agent/ to the extensions/<id>/ convention.
15
+
16
+ ### Features
17
+
18
+ * add config-paths module with new layout paths ([#10](https://github.com/gotgenes/pi-permission-system/issues/10)) ([532d2a1](https://github.com/gotgenes/pi-permission-system/commit/532d2a1f1d816c1cfba5419f7d0041382c848b31))
19
+ * add unified config loader ([#10](https://github.com/gotgenes/pi-permission-system/issues/10)) ([20143e0](https://github.com/gotgenes/pi-permission-system/commit/20143e0f7b608965d889433a6b9bbd6f9ab8b4cc))
20
+ * detect and merge legacy config paths ([#10](https://github.com/gotgenes/pi-permission-system/issues/10)) ([95046de](https://github.com/gotgenes/pi-permission-system/commit/95046de6a57d604c5f0d9fa8c13a64478ba15c89))
21
+ * implement config merge in unified loader ([#10](https://github.com/gotgenes/pi-permission-system/issues/10)) ([30b9afe](https://github.com/gotgenes/pi-permission-system/commit/30b9afe3d83940aa3ad708c9d6783bb2d4337743))
22
+ * update config-reporter for consolidated layout ([#10](https://github.com/gotgenes/pi-permission-system/issues/10)) ([96c9ef4](https://github.com/gotgenes/pi-permission-system/commit/96c9ef4964f9551b0fa89bbbc506f7660c055d74))
23
+ * wire index.ts to consolidated config layout ([#10](https://github.com/gotgenes/pi-permission-system/issues/10)) ([e7f8e5f](https://github.com/gotgenes/pi-permission-system/commit/e7f8e5f2fb094f0d291561258190d1892a1e6856))
24
+
25
+
26
+ ### Documentation
27
+
28
+ * plan config layout consolidation ([#10](https://github.com/gotgenes/pi-permission-system/issues/10)) ([eb2924d](https://github.com/gotgenes/pi-permission-system/commit/eb2924d57655d06f67891574839aebfa0586a43d))
29
+ * **retro:** add retro notes for issue [#20](https://github.com/gotgenes/pi-permission-system/issues/20) ([4735f0c](https://github.com/gotgenes/pi-permission-system/commit/4735f0c646a0ede11c9a76083822969eb6ca4a8f))
30
+ * update schema, example, and docs for consolidated config ([#10](https://github.com/gotgenes/pi-permission-system/issues/10)) ([39b5c01](https://github.com/gotgenes/pi-permission-system/commit/39b5c01de1c8c721e998b244e9c825a6eb05f858))
31
+
32
+ ## [2.0.0](https://github.com/gotgenes/pi-permission-system/compare/v1.2.1...v2.0.0) (2026-05-03)
33
+
34
+
35
+ ### ⚠ BREAKING CHANGES
36
+
37
+ * the pi-permission-system:permission-request event channel is no longer emitted. No known consumers exist; the type was never exported. Re-adding with a proper public contract is tracked
38
+
39
+ ### Features
40
+
41
+ * add /build-plan prompt template for non-TDD plans ([e98f13c](https://github.com/gotgenes/pi-permission-system/commit/e98f13c2ef32f51edda58ea065635bef31365baa))
42
+ * delete permission-request event channel ([#20](https://github.com/gotgenes/pi-permission-system/issues/20)) ([6a41cfa](https://github.com/gotgenes/pi-permission-system/commit/6a41cfadc56e709d255538f63ff63d587e1b64f3))
43
+
44
+
45
+ ### Documentation
46
+
47
+ * plan delete permission-request event channel ([#20](https://github.com/gotgenes/pi-permission-system/issues/20)) ([e202350](https://github.com/gotgenes/pi-permission-system/commit/e2023509f9ab849f5a1d8bc28a5705b2898b912b))
48
+ * remove event channel from preserved-identity list ([#20](https://github.com/gotgenes/pi-permission-system/issues/20)) ([52299a2](https://github.com/gotgenes/pi-permission-system/commit/52299a27aeaed6e35849878fa224d8a78dcf0f6d))
49
+ * **retro:** add retro notes for issue [#22](https://github.com/gotgenes/pi-permission-system/issues/22) ([55629fe](https://github.com/gotgenes/pi-permission-system/commit/55629fed16b6d73b6d7b02698227e2adab7acd3e))
50
+ * update copyright in license ([b27994e](https://github.com/gotgenes/pi-permission-system/commit/b27994e7d67863ce8b28aa6bd680b60bc700d66d))
51
+
8
52
  ## [1.2.1](https://github.com/gotgenes/pi-permission-system/compare/v1.2.0...v1.2.1) (2026-05-03)
9
53
 
10
54
 
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2026 MasuRii
3
+ Copyright (c) 2026 MasuRii and Christopher D. Lasher
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -6,7 +6,7 @@ Permission enforcement extension for the Pi coding agent that provides centraliz
6
6
 
7
7
  > **Fork notice:** This package is a friendly fork of [MasuRii/pi-permission-system](https://github.com/MasuRii/pi-permission-system), published to npm as `@gotgenes/pi-permission-system`.
8
8
  > This fork diverges from upstream in config layout (#10).
9
- > The `/permission-system` slash command and `pi-permission-system:permission-request` event channel names are preserved; the config and log paths are not.
9
+ > The `/permission-system` slash command name is preserved; the config and log paths are not.
10
10
 
11
11
  ## Features
12
12
 
@@ -48,7 +48,7 @@ Pi auto-discovers extensions in these paths.
48
48
 
49
49
  ### Quick Start
50
50
 
51
- 1. Create the global policy file at the Pi agent runtime root (default: `~/.pi/agent/pi-permissions.jsonc`, respects `PI_CODING_AGENT_DIR`):
51
+ 1. Create the global config file (default: `~/.pi/agent/extensions/pi-permission-system/config.json`, respects `PI_CODING_AGENT_DIR`):
52
52
 
53
53
  ```jsonc
54
54
  {
@@ -57,12 +57,12 @@ Pi auto-discovers extensions in these paths.
57
57
  "bash": "ask",
58
58
  "mcp": "ask",
59
59
  "skills": "ask",
60
- "special": "ask",
60
+ "special": "ask"
61
61
  },
62
62
  "tools": {
63
63
  "read": "allow",
64
- "write": "deny",
65
- },
64
+ "write": "deny"
65
+ }
66
66
  }
67
67
  ```
68
68
 
@@ -100,36 +100,60 @@ The extension integrates via Pi's lifecycle hooks:
100
100
 
101
101
  ## Configuration
102
102
 
103
- ### Extension Config File
103
+ ### Config File
104
+
105
+ **Location:** one unified config file per scope, following the `pi-autoformat` convention:
104
106
 
105
- **Location:** global Pi extension config (default: `~/.pi/agent/extensions/pi-permission-system/config.json`, respects `PI_CODING_AGENT_DIR`)
107
+ | Scope | Path |
108
+ | ------- | ------------------------------------------------------------------------------------------------- |
109
+ | Global | `~/.pi/agent/extensions/pi-permission-system/config.json` (respects `PI_CODING_AGENT_DIR`) |
110
+ | Project | `<cwd>/.pi/extensions/pi-permission-system/config.json` |
106
111
 
107
- The extension creates this file automatically when it is missing. It controls only extension-local logging behavior:
112
+ Project config overrides global config; per-agent frontmatter overrides both.
113
+ Object-shaped fields (`defaultPolicy`, `tools`, `bash`, `mcp`, `skills`, `special`) use shallow-merge (later source wins per-key).
114
+ Scalar fields (`debugLog`, `permissionReviewLog`, `yoloMode`) use simple replacement.
108
115
 
109
- ```json
116
+ The config file combines runtime knobs and permission policy in one object:
117
+
118
+ ```jsonc
110
119
  {
120
+ "$schema": "https://raw.githubusercontent.com/gotgenes/pi-permission-system/main/schemas/permissions.schema.json",
121
+
122
+ // Runtime knobs
111
123
  "debugLog": false,
112
124
  "permissionReviewLog": true,
113
- "yoloMode": false
125
+ "yoloMode": false,
126
+
127
+ // Policy
128
+ "defaultPolicy": {
129
+ "tools": "ask",
130
+ "bash": "ask",
131
+ "mcp": "ask",
132
+ "skills": "ask",
133
+ "special": "ask"
134
+ },
135
+ "tools": { "read": "allow", "write": "deny" },
136
+ "bash": { "git status": "allow", "git *": "ask" },
137
+ "mcp": { "mcp_status": "allow" },
138
+ "skills": { "*": "ask" },
139
+ "special": { "doom_loop": "deny", "external_directory": "ask" }
114
140
  }
115
141
  ```
116
142
 
143
+ #### Runtime knobs
144
+
117
145
  | Key | Default | Description |
118
146
  | --------------------- | ------- | ------------------------------------------------------------------------------------------------------- |
119
147
  | `debugLog` | `false` | Enables verbose diagnostic logging to `logs/pi-permission-system-debug.jsonl` |
120
148
  | `permissionReviewLog` | `true` | Enables the permission request/denial review log at `logs/pi-permission-system-permission-review.jsonl` |
121
149
  | `yoloMode` | `false` | Auto-approves `ask` results instead of prompting when yolo mode is enabled |
122
150
 
123
- Both logs write to files only under the extension directory. No debug output is printed to the terminal.
151
+ Both logs write to `~/.pi/agent/extensions/pi-permission-system/logs/`.
152
+ No debug output is printed to the terminal.
124
153
 
125
- > **Note:** Permission-rule keys (`defaultPolicy`, `tools`, `bash`, `mcp`, `skills`, `special`, `external_directory`, `doom_loop`) placed in `config.json` are silently ignored — they belong in the policy file below.
126
- > The extension warns at startup when it detects misplaced keys.
154
+ #### Policy sections
127
155
 
128
- ### Global Policy File
129
-
130
- **Location:** global Pi policy file (default: `~/.pi/agent/pi-permissions.jsonc`, respects `PI_CODING_AGENT_DIR`)
131
-
132
- The policy file is a JSON object with these sections:
156
+ The config file is a JSON object with these policy sections:
133
157
 
134
158
  | Section | Description |
135
159
  | --------------- | ---------------------------------------------------------------------------- |
@@ -169,21 +193,22 @@ permission:
169
193
 
170
194
  **Limitations:** The frontmatter parser is intentionally minimal. Use only `key: value` scalars and nested maps. Avoid arrays, multi-line scalars, and YAML anchors.
171
195
 
172
- ### Project-Level Policy Files
196
+ ### Project-Level Config and Overrides
173
197
 
174
- The extension can also layer project-local permission files relative to the active session working directory:
198
+ Project-local config uses the same format as the global config file.
199
+ Per-agent overrides use YAML frontmatter in the project agents directory:
175
200
 
176
- | Scope | Path |
177
- | ---------------------- | -------------------------------------- |
178
- | Project policy | `<cwd>/.pi/agent/pi-permissions.jsonc` |
179
- | Project agent override | `<cwd>/.pi/agent/agents/<agent>.md` |
201
+ | Scope | Path |
202
+ | ---------------------- | ------------------------------------------------------------- |
203
+ | Project config | `<cwd>/.pi/extensions/pi-permission-system/config.json` |
204
+ | Project agent override | `<cwd>/.pi/agent/agents/<agent>.md` |
180
205
 
181
- Project-local files use the same formats as the global policy file and global agent frontmatter. These project files are resolved from Pi's current session `cwd`, so they are workspace-specific and do **not** move under `PI_CODING_AGENT_DIR`.
206
+ These project files are resolved from Pi's current session `cwd`, so they are workspace-specific and do **not** move under `PI_CODING_AGENT_DIR`.
182
207
 
183
208
  **Precedence order:**
184
209
 
185
- 1. Global policy file
186
- 2. Project policy file
210
+ 1. Global config file
211
+ 2. Project config file
187
212
  3. Global agent frontmatter
188
213
  4. Project agent frontmatter
189
214
 
@@ -454,7 +479,7 @@ When the extension prompts, denies, or forwards permission requests, it can appe
454
479
 
455
480
  ```text
456
481
  Default global logs directory: ~/.pi/agent/extensions/pi-permission-system/logs/
457
- Actual global logs directory: $PI_CODING_AGENT_DIR/extensions/pi-permission-system/logs when PI_CODING_AGENT_DIR is set
482
+ Actual global logs directory: $PI_CODING_AGENT_DIR/extensions/pi-permission-system/logs/ when PI_CODING_AGENT_DIR is set
458
483
  ```
459
484
 
460
485
  - `pi-permission-system-permission-review.jsonl` — enabled by default for permission review/audit history, including bounded `toolInputPreview` values for non-bash/non-MCP tool calls
@@ -466,16 +491,17 @@ This makes it easy to verify which files the extension actually loaded:
466
491
  ```jsonc
467
492
  {
468
493
  "event": "config.resolved",
469
- "extensionConfigPath": "/…/pi-permission-system/config.json",
470
- "extensionConfigExists": true,
471
- "globalConfigPath": "/…/.pi/agent/pi-permissions.jsonc",
472
- "globalConfigExists": false,
473
- "projectConfigPath": "/…/my-project/.pi/agent/pi-permissions.jsonc",
474
- "projectConfigExists": true,
494
+ "globalConfigPath": "/…/.pi/agent/extensions/pi-permission-system/config.json",
495
+ "globalConfigExists": true,
496
+ "projectConfigPath": "/…/my-project/.pi/extensions/pi-permission-system/config.json",
497
+ "projectConfigExists": false,
475
498
  "agentsDir": "/…/.pi/agent/agents",
476
499
  "agentsDirExists": true,
477
500
  "projectAgentsDir": "/…/my-project/.pi/agent/agents",
478
501
  "projectAgentsDirExists": false,
502
+ "legacyGlobalPolicyDetected": false,
503
+ "legacyProjectPolicyDetected": false,
504
+ "legacyExtensionConfigDetected": false
479
505
  }
480
506
  ```
481
507
 
@@ -485,8 +511,10 @@ This makes it easy to verify which files the extension actually loaded:
485
511
  index.ts → Root Pi entrypoint shim
486
512
  src/
487
513
  ├── index.ts → Extension bootstrap, permission checks, readable prompts, review logging, reload handling, and subagent forwarding
514
+ ├── config-loader.ts → Unified config loader, merger, and legacy-path detection
515
+ ├── config-paths.ts → Path derivation for global, project, and legacy config locations
488
516
  ├── config-reporter.ts → Resolved config path reporting for diagnostic logs
489
- ├── extension-config.ts → Extension-local config loading and default creation
517
+ ├── extension-config.ts → Runtime config normalization and defaults
490
518
  ├── logging.ts → File-only debug/review logging helpers
491
519
  ├── permission-manager.ts → Global/project policy loading, merging, and resolution with caching
492
520
  ├── skill-prompt-sanitizer.ts → Skill prompt parsing, multi-block sanitization, and skill-read path matching
@@ -553,11 +581,40 @@ npx --yes ajv-cli@5 validate \
553
581
 
554
582
  ---
555
583
 
584
+ ## Migration from pre-v2 layout
585
+
586
+ Before v2, config was split across two files:
587
+
588
+ - Policy: `~/.pi/agent/pi-permissions.jsonc`
589
+ - Runtime knobs: `<extension-install-dir>/config.json`
590
+
591
+ These are now consolidated into one file.
592
+ The extension detects legacy files and merges them with a warning for one release.
593
+ To migrate manually:
594
+
595
+ ```bash
596
+ # Move the global policy file
597
+ mkdir -p ~/.pi/agent/extensions/pi-permission-system
598
+ mv ~/.pi/agent/pi-permissions.jsonc ~/.pi/agent/extensions/pi-permission-system/config.json
599
+
600
+ # If you had project-level policy:
601
+ mkdir -p .pi/extensions/pi-permission-system
602
+ mv .pi/agent/pi-permissions.jsonc .pi/extensions/pi-permission-system/config.json
603
+ ```
604
+
605
+ Then add any runtime knobs (`debugLog`, `permissionReviewLog`, `yoloMode`) to the same file.
606
+ The old extension-root `config.json` is no longer read from the install directory.
607
+
608
+ > **Note:** Logs also moved from `<extension-install-dir>/logs/` to `~/.pi/agent/extensions/pi-permission-system/logs/`.
609
+ > Old log files are not deleted or migrated — they remain readable but no new entries are appended.
610
+
611
+ ---
612
+
556
613
  ## Troubleshooting
557
614
 
558
615
  | Problem | Cause | Solution |
559
616
  | ------------------------------------ | ---------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
560
- | Config not applied (everything asks) | File not found or parse error | Verify the global Pi policy file (default: `~/.pi/agent/pi-permissions.jsonc`, respects `PI_CODING_AGENT_DIR`); check for trailing commas |
617
+ | Config not applied (everything asks) | File not found or parse error | Verify the global config at `~/.pi/agent/extensions/pi-permission-system/config.json` (respects `PI_CODING_AGENT_DIR`); check for trailing commas |
561
618
  | Per-agent override not applied | Frontmatter parsing issue | Ensure `---` delimiters at file top; keep YAML simple; restart session |
562
619
  | Tool blocked as unregistered | Unknown tool name | Use a registered `mcp` tool for server tools: `{ "tool": "server:tool" }` |
563
620
  | `/skill:<name>` blocked | Deny policy or confirmation unavailable | Check merged `skills` policy (global/project/agent layers). Active agent context is optional in the main session; `ask` still requires UI or forwarded confirmation. |
@@ -1,4 +1,10 @@
1
1
  {
2
+ "$schema": "https://raw.githubusercontent.com/gotgenes/pi-permission-system/main/schemas/permissions.schema.json",
3
+
4
+ "debugLog": false,
5
+ "permissionReviewLog": true,
6
+ "yoloMode": false,
7
+
2
8
  "defaultPolicy": {
3
9
  "tools": "ask",
4
10
  "bash": "ask",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gotgenes/pi-permission-system",
3
- "version": "1.2.1",
3
+ "version": "3.0.0",
4
4
  "description": "Permission enforcement extension for the Pi coding agent.",
5
5
  "type": "module",
6
6
  "main": "./index.ts",
@@ -1,17 +1,32 @@
1
1
  {
2
2
  "$schema": "https://json-schema.org/draft/2020-12/schema",
3
- "$id": "https://pi-coding-agent.local/schemas/permissions.schema.json",
4
- "title": "PI Permission Configuration",
3
+ "$id": "https://raw.githubusercontent.com/gotgenes/pi-permission-system/main/schemas/permissions.schema.json",
4
+ "title": "PI Permission System Configuration",
5
+ "description": "Unified config file combining runtime knobs and permission policy for pi-permission-system.",
5
6
  "type": "object",
6
7
  "additionalProperties": false,
7
8
  "properties": {
8
9
  "$schema": {
9
10
  "type": "string"
10
11
  },
12
+ "debugLog": {
13
+ "description": "Write verbose permission-system diagnostics to the extension logs directory.",
14
+ "type": "boolean",
15
+ "default": false
16
+ },
17
+ "permissionReviewLog": {
18
+ "description": "Write permission request and decision audit events to the extension logs directory.",
19
+ "type": "boolean",
20
+ "default": true
21
+ },
22
+ "yoloMode": {
23
+ "description": "Auto-approve ask-state permission checks, including subagent approval forwarding.",
24
+ "type": "boolean",
25
+ "default": false
26
+ },
11
27
  "defaultPolicy": {
12
28
  "type": "object",
13
29
  "additionalProperties": false,
14
- "required": ["tools", "bash", "mcp", "skills"],
15
30
  "properties": {
16
31
  "tools": {
17
32
  "$ref": "#/$defs/permissionState"
@@ -57,7 +72,6 @@
57
72
  }
58
73
  }
59
74
  },
60
- "required": ["defaultPolicy"],
61
75
  "$defs": {
62
76
  "permissionState": {
63
77
  "type": "string",