pi-daddy 0.18.0 → 0.19.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 (130) hide show
  1. package/CHANGELOG.md +154 -0
  2. package/README.md +46 -2
  3. package/contracts/ledger/v2/README.md +59 -0
  4. package/contracts/ledger/v2/fixtures/capability-decision.json +95 -0
  5. package/contracts/ledger/v2/fixtures/check-receipt.json +40 -0
  6. package/contracts/ledger/v2/fixtures/child-lifecycle.json +42 -0
  7. package/contracts/ledger/v2/fixtures/workspace-lease.json +41 -0
  8. package/contracts/ledger/v2/ledger-event.schema.json +633 -0
  9. package/dist/approval-prompt.d.ts +2 -1
  10. package/dist/approval-prompt.d.ts.map +1 -1
  11. package/dist/approval-prompt.js +9 -0
  12. package/dist/approval-prompt.js.map +1 -1
  13. package/dist/approval.d.ts +4 -2
  14. package/dist/approval.d.ts.map +1 -1
  15. package/dist/approval.js +4 -0
  16. package/dist/approval.js.map +1 -1
  17. package/dist/capabilities.d.ts +105 -0
  18. package/dist/capabilities.d.ts.map +1 -1
  19. package/dist/capabilities.js +161 -3
  20. package/dist/capabilities.js.map +1 -1
  21. package/dist/catalog.d.ts +15 -1
  22. package/dist/catalog.d.ts.map +1 -1
  23. package/dist/catalog.js +54 -3
  24. package/dist/catalog.js.map +1 -1
  25. package/dist/check-runner.d.ts.map +1 -1
  26. package/dist/check-runner.js +5 -7
  27. package/dist/check-runner.js.map +1 -1
  28. package/dist/cli.d.ts.map +1 -1
  29. package/dist/cli.js +21 -1
  30. package/dist/cli.js.map +1 -1
  31. package/dist/definitions.d.ts.map +1 -1
  32. package/dist/definitions.js +7 -1
  33. package/dist/definitions.js.map +1 -1
  34. package/dist/delegate.d.ts.map +1 -1
  35. package/dist/delegate.js +32 -4
  36. package/dist/delegate.js.map +1 -1
  37. package/dist/delegation-approval.d.ts.map +1 -1
  38. package/dist/delegation-approval.js +37 -12
  39. package/dist/delegation-approval.js.map +1 -1
  40. package/dist/executor.d.ts +2 -1
  41. package/dist/executor.d.ts.map +1 -1
  42. package/dist/executor.js +1 -0
  43. package/dist/executor.js.map +1 -1
  44. package/dist/grant-env.d.ts +2 -0
  45. package/dist/grant-env.d.ts.map +1 -1
  46. package/dist/grant-env.js +26 -3
  47. package/dist/grant-env.js.map +1 -1
  48. package/dist/index.d.ts +1 -1
  49. package/dist/index.d.ts.map +1 -1
  50. package/dist/index.js +1 -1
  51. package/dist/index.js.map +1 -1
  52. package/dist/init.d.ts +13 -1
  53. package/dist/init.d.ts.map +1 -1
  54. package/dist/init.js +35 -2
  55. package/dist/init.js.map +1 -1
  56. package/dist/lease-helper.d.ts +58 -0
  57. package/dist/lease-helper.d.ts.map +1 -0
  58. package/dist/lease-helper.js +94 -0
  59. package/dist/lease-helper.js.map +1 -0
  60. package/dist/lease-record.d.ts +15 -3
  61. package/dist/lease-record.d.ts.map +1 -1
  62. package/dist/lease-record.js.map +1 -1
  63. package/dist/ledger-events.d.ts +35 -14
  64. package/dist/ledger-events.d.ts.map +1 -1
  65. package/dist/ledger-events.js +41 -0
  66. package/dist/ledger-events.js.map +1 -1
  67. package/dist/ledger.d.ts +10 -5
  68. package/dist/ledger.d.ts.map +1 -1
  69. package/dist/ledger.js +13 -3
  70. package/dist/ledger.js.map +1 -1
  71. package/dist/propagation.d.ts +16 -0
  72. package/dist/propagation.d.ts.map +1 -1
  73. package/dist/propagation.js +22 -2
  74. package/dist/propagation.js.map +1 -1
  75. package/dist/refusals.d.ts +1 -1
  76. package/dist/refusals.d.ts.map +1 -1
  77. package/dist/refusals.js +2 -0
  78. package/dist/refusals.js.map +1 -1
  79. package/dist/resolve.d.ts +10 -0
  80. package/dist/resolve.d.ts.map +1 -1
  81. package/dist/resolve.js +33 -3
  82. package/dist/resolve.js.map +1 -1
  83. package/dist/routing-authority.d.ts +71 -0
  84. package/dist/routing-authority.d.ts.map +1 -0
  85. package/dist/routing-authority.js +100 -0
  86. package/dist/routing-authority.js.map +1 -0
  87. package/dist/skill-packages.d.ts +11 -5
  88. package/dist/skill-packages.d.ts.map +1 -1
  89. package/dist/skill-packages.js +20 -11
  90. package/dist/skill-packages.js.map +1 -1
  91. package/dist/workspace-lease.d.ts +15 -3
  92. package/dist/workspace-lease.d.ts.map +1 -1
  93. package/dist/workspace-lease.js +81 -24
  94. package/dist/workspace-lease.js.map +1 -1
  95. package/dist/workspace.d.ts +25 -0
  96. package/dist/workspace.d.ts.map +1 -1
  97. package/dist/workspace.js +142 -5
  98. package/dist/workspace.js.map +1 -1
  99. package/extensions/delegation.ts +7 -1
  100. package/extensions/grants-command.ts +11 -1
  101. package/extensions/grants.ts +6 -1
  102. package/extensions/init-command.ts +33 -2
  103. package/extensions/session-report.ts +13 -20
  104. package/extensions/session.ts +9 -1
  105. package/extensions/workspace-runtime.ts +34 -4
  106. package/package.json +8 -3
  107. package/src/approval-prompt.ts +2 -1
  108. package/src/approval.ts +4 -2
  109. package/src/capabilities.ts +173 -4
  110. package/src/catalog.ts +62 -4
  111. package/src/check-runner.ts +8 -8
  112. package/src/cli.ts +24 -1
  113. package/src/definitions.ts +7 -1
  114. package/src/delegate.ts +42 -4
  115. package/src/delegation-approval.ts +37 -12
  116. package/src/executor.ts +2 -1
  117. package/src/grant-env.ts +39 -7
  118. package/src/index.ts +1 -0
  119. package/src/init.ts +40 -2
  120. package/src/lease-helper.ts +97 -0
  121. package/src/lease-record.ts +15 -3
  122. package/src/ledger-events.ts +66 -22
  123. package/src/ledger.ts +30 -6
  124. package/src/propagation.ts +23 -2
  125. package/src/refusals.ts +2 -0
  126. package/src/resolve.ts +35 -3
  127. package/src/routing-authority.ts +121 -0
  128. package/src/skill-packages.ts +20 -13
  129. package/src/workspace-lease.ts +84 -24
  130. package/src/workspace.ts +179 -6
@@ -25,7 +25,7 @@
25
25
  * `source`s; the only strings that may reach it are ones that survived a whitelist here.
26
26
  */
27
27
  import { type SkillDefinition } from "./definitions.ts";
28
- import { type Capability } from "./resolve.ts";
28
+ import { isSafeCapability } from "./capabilities.ts";
29
29
  export interface DiscoveredSkill {
30
30
  definition: SkillDefinition;
31
31
  /** The file verbatim. `init` copies it rather than regenerating it, so nothing is lost in a round trip. */
@@ -94,11 +94,17 @@ export declare function isSafeName(name: string): boolean;
94
94
  * grants), which is right for the enforcement path — the catalog refuses what it does not know — and is
95
95
  * exactly why the check has to be here, at the boundary that *generates* rather than the one that enforces.
96
96
  *
97
- * The grammar is the one `docs/SPEC.md` documents: `tool:<name>`, `skill:<name>`, `agent:<name>`, and
98
- * `ext:<pkg>/<tool>` where `<pkg>` may be npm-scoped. No wildcards — those are refused separately and
99
- * loudly, because "you tried to grant yourself everything" is a different fact from "that is not a name".
97
+ * The grammar is the one `docs/SPEC.md` documents: `tool:<name>`, `skill:<name>`, `agent:<name>`,
98
+ * `workspace:<id>`, and `ext:<pkg>/<tool>` where `<pkg>` may be npm-scoped. No wildcards — those are refused
99
+ * separately and loudly, because "you tried to grant yourself everything" is a different fact from "that is
100
+ * not a name".
101
+ *
102
+ * `workspace:` was absent until 2026-08-21, so the boundary that GENERATES grants could not emit the one
103
+ * capability ADR-0035's breaking change made mandatory: a package needing to route was reported as declaring
104
+ * something that "is not a name". A namespace has to be added here as well as to the enforcing path, and
105
+ * that is the whole lesson of the review this came out of.
100
106
  */
101
- export declare function isSafeCapability(id: Capability): boolean;
107
+ export { isSafeCapability };
102
108
  /** Read one installed package, if it declares skills. `null` means "not a skill package", not an error. */
103
109
  export declare function readSkillPackage(packageDir: string): Promise<SkillPackage | null>;
104
110
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"skill-packages.d.ts","sourceRoot":"","sources":["../src/skill-packages.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAKH,OAAO,EAA8C,KAAK,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAEpG,OAAO,EAAkB,KAAK,UAAU,EAAE,MAAM,cAAc,CAAC;AAE/D,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,eAAe,CAAC;IAC5B,2GAA2G;IAC3G,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,6FAA6F;AAC7F,MAAM,MAAM,aAAa;AACvB,uFAAuF;AACrF,aAAa;AACf,yFAAyF;GACvF,mBAAmB;AACrB,yGAAyG;GACvG,UAAU;AACZ,iFAAiF;GAC/E,UAAU,CAAC;AAEf,MAAM,WAAW,YAAY;IAC3B,uFAAuF;IACvF,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,aAAa,CAAC;IACtB,sDAAsD;IACtD,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,yGAAyG;IACzG,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,uGAAuG;IACvG,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,MAAM,EAAE,eAAe,EAAE,CAAC;CAC3B;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEhD;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,UAAU,GAAG,OAAO,CAMxD;AA2DD,2GAA2G;AAC3G,wBAAsB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAkCvF;AAED;;;;;;GAMG;AACH;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAGvD;AAED,wBAAsB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAgBhF"}
1
+ {"version":3,"file":"skill-packages.d.ts","sourceRoot":"","sources":["../src/skill-packages.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAKH,OAAO,EAA8C,KAAK,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAGpG,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAErD,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,eAAe,CAAC;IAC5B,2GAA2G;IAC3G,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,6FAA6F;AAC7F,MAAM,MAAM,aAAa;AACvB,uFAAuF;AACrF,aAAa;AACf,yFAAyF;GACvF,mBAAmB;AACrB,yGAAyG;GACvG,UAAU;AACZ,iFAAiF;GAC/E,UAAU,CAAC;AAEf,MAAM,WAAW,YAAY;IAC3B,uFAAuF;IACvF,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,aAAa,CAAC;IACtB,sDAAsD;IACtD,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,yGAAyG;IACzG,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,uGAAuG;IACvG,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,MAAM,EAAE,eAAe,EAAE,CAAC;CAC3B;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEhD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAGH,OAAO,EAAE,gBAAgB,EAAE,CAAC;AA+D5B,2GAA2G;AAC3G,wBAAsB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAkCvF;AAED;;;;;;GAMG;AACH;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAGvD;AAED,wBAAsB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAgBhF"}
@@ -29,7 +29,8 @@ import { homedir } from "node:os";
29
29
  import { join, resolve, sep } from "node:path";
30
30
  import { ceilingForDefinition, parseSkillDefinition } from "./definitions.js";
31
31
  import { WILDCARD } from "./pi-tools.js";
32
- import { AGENT_WILDCARD } from "./resolve.js";
32
+ import { AGENT_WILDCARD, WORKSPACE_WILDCARD } from "./resolve.js";
33
+ import { isSafeCapability } from "./capabilities.js";
33
34
  /**
34
35
  * May this definition's name be written into a capability id, a shell file and a path?
35
36
  *
@@ -68,18 +69,26 @@ export function isSafeName(name) {
68
69
  * grants), which is right for the enforcement path — the catalog refuses what it does not know — and is
69
70
  * exactly why the check has to be here, at the boundary that *generates* rather than the one that enforces.
70
71
  *
71
- * The grammar is the one `docs/SPEC.md` documents: `tool:<name>`, `skill:<name>`, `agent:<name>`, and
72
- * `ext:<pkg>/<tool>` where `<pkg>` may be npm-scoped. No wildcards — those are refused separately and
73
- * loudly, because "you tried to grant yourself everything" is a different fact from "that is not a name".
72
+ * The grammar is the one `docs/SPEC.md` documents: `tool:<name>`, `skill:<name>`, `agent:<name>`,
73
+ * `workspace:<id>`, and `ext:<pkg>/<tool>` where `<pkg>` may be npm-scoped. No wildcards — those are refused
74
+ * separately and loudly, because "you tried to grant yourself everything" is a different fact from "that is
75
+ * not a name".
76
+ *
77
+ * `workspace:` was absent until 2026-08-21, so the boundary that GENERATES grants could not emit the one
78
+ * capability ADR-0035's breaking change made mandatory: a package needing to route was reported as declaring
79
+ * something that "is not a name". A namespace has to be added here as well as to the enforcing path, and
80
+ * that is the whole lesson of the review this came out of.
81
+ */
82
+ // Imported as well as re-exported: a bare `export … from` does not bind the name in this module's scope, and
83
+ // `refusalFor` below calls it. Re-exported because this has been the import site since 0.13.0.
84
+ export { isSafeCapability };
85
+ /**
86
+ * The ids that confer authority over a whole namespace. A package declaring one is claiming it, not
87
+ * describing a need — so it is reported as a *wildcard claim* rather than as a malformed name, which is a
88
+ * different sentence to show an operator. `workspace:*` belongs here for the same reason `agent:*` does.
74
89
  */
75
- export function isSafeCapability(id) {
76
- const segment = "[A-Za-z0-9][A-Za-z0-9._-]*";
77
- return (new RegExp(`^(tool|skill|agent):${segment}$`).test(id) ||
78
- new RegExp(`^ext:(@${segment}/)?${segment}/${segment}$`).test(id));
79
- }
80
- /** The two ids that confer root authority. A package declaring one is claiming it, not describing a need. */
81
90
  function wildcardsIn(capabilities) {
82
- return capabilities.filter((c) => c === WILDCARD || c === AGENT_WILDCARD);
91
+ return capabilities.filter((c) => c === WILDCARD || c === AGENT_WILDCARD || c === WORKSPACE_WILDCARD);
83
92
  }
84
93
  /**
85
94
  * Everything about one declared skill that would make it unsafe to scaffold. `null` when it is fine.
@@ -1 +1 @@
1
- {"version":3,"file":"skill-packages.js","sourceRoot":"","sources":["../src/skill-packages.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"skill-packages.js","sourceRoot":"","sources":["../src/skill-packages.ts"],"names":[],"mappings":"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"}
@@ -4,9 +4,15 @@ import type { ValidatedWorkspace, WorkspaceAccess } from "./workspace.ts";
4
4
  export declare const ENV_WORKSPACE_LEASE_DIR = "PI_GRANTS_WORKSPACE_LEASE_DIR";
5
5
  export declare function defaultWorkspaceLeaseDir(env?: NodeJS.ProcessEnv): string;
6
6
  /**
7
- * The ledger outcome for a release. ONE definition, exported, because two call sites had their own copies
8
- * and the check runner's copy asserted `released` unconditionally — reproducing in the evidence path the
9
- * exact defect this union was added to expose (R-100/R-103).
7
+ * The ledger outcome for a release. Exported because call sites had their own copies and the check runner's
8
+ * asserted `released` unconditionally — reproducing in the evidence path the exact defect this union was
9
+ * added to expose (R-100/R-103).
10
+ *
11
+ * **It is NOT the only definition, and saying so here was wrong.** `extensions/workspace-runtime.ts` keeps a
12
+ * private copy with no `not-held` arm, and it is the one the whole delegation path uses — so releasing a
13
+ * *read* lease on a delegated child is still recorded `released`, a handover the kernel never performed.
14
+ * Measured; open as R-141; the sentence claiming a single definition survived two review passes because
15
+ * `test/workspace.test.ts` pins the `not-held` arm on THIS function, which no delegation path calls.
10
16
  */
11
17
  export declare function leaseReleaseLedgerOutcome(outcome: LeaseReleaseOutcome | "retained", reason: string): "timeout" | "released" | "released-unrecorded" | "lost" | "retained" | "uncontended";
12
18
  /**
@@ -22,6 +28,12 @@ export declare function acquireWorkspaceLease(input: {
22
28
  signal?: AbortSignal;
23
29
  flockCommand?: string;
24
30
  acquisitionTimeoutMs?: number;
31
+ /**
32
+ * Bound on how long ONE `herdr tab close` attempt may take before it counts as failed (R-146). A hung
33
+ * herdr is not a failed herdr: without this the attempt never returns and the retry bound below is
34
+ * unreachable.
35
+ */
36
+ herdrCloseTimeoutMs?: number;
25
37
  /** Bound on the helper's `herdr tab close` retries before it releases the lock anyway (R-102). */
26
38
  herdrCloseAttempts?: number;
27
39
  }): Promise<WorkspaceLease>;
@@ -1 +1 @@
1
- {"version":3,"file":"workspace-lease.d.ts","sourceRoot":"","sources":["../src/workspace-lease.ts"],"names":[],"mappings":"AACA,OAAO,EAKL,KAAK,mBAAmB,EACxB,KAAK,cAAc,EACpB,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAM7E,OAAO,KAAK,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAE1E,eAAO,MAAM,uBAAuB,kCAAkC,CAAC;AAEvE,wBAAgB,wBAAwB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,CAGrF;AAoBD;;;;GAIG;AACH,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,mBAAmB,GAAG,UAAU,EACzC,MAAM,EAAE,MAAM,GACb,SAAS,GAAG,UAAU,GAAG,qBAAqB,GAAG,MAAM,GAAG,UAAU,GAAG,aAAa,CAQtF;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,MAAM,GAAG,OAAO,EACxB,SAAS,EAAE,OAAO,GAAG,SAAS,GAC7B,UAAU,GAAG,aAAa,GAAG,WAAW,CAG1C;AAED,wBAAsB,qBAAqB,CAAC,KAAK,EAAE;IACjD,SAAS,EAAE,kBAAkB,CAAC;IAC9B,MAAM,EAAE,eAAe,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,kGAAkG;IAClG,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B,GAAG,OAAO,CAAC,cAAc,CAAC,CA4N1B"}
1
+ {"version":3,"file":"workspace-lease.d.ts","sourceRoot":"","sources":["../src/workspace-lease.ts"],"names":[],"mappings":"AACA,OAAO,EAKL,KAAK,mBAAmB,EACxB,KAAK,cAAc,EACpB,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAM7E,OAAO,KAAK,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAG1E,eAAO,MAAM,uBAAuB,kCAAkC,CAAC;AAEvE,wBAAgB,wBAAwB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,CAGrF;AAGD;;;;;;;;;;GAUG;AACH,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,mBAAmB,GAAG,UAAU,EACzC,MAAM,EAAE,MAAM,GACb,SAAS,GAAG,UAAU,GAAG,qBAAqB,GAAG,MAAM,GAAG,UAAU,GAAG,aAAa,CAQtF;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,MAAM,GAAG,OAAO,EACxB,SAAS,EAAE,OAAO,GAAG,SAAS,GAC7B,UAAU,GAAG,aAAa,GAAG,WAAW,CAG1C;AAED,wBAAsB,qBAAqB,CAAC,KAAK,EAAE;IACjD,SAAS,EAAE,kBAAkB,CAAC;IAC9B,MAAM,EAAE,eAAe,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B;;;;OAIG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,kGAAkG;IAClG,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B,GAAG,OAAO,CAAC,cAAc,CAAC,CA4R1B"}
@@ -5,32 +5,22 @@ import { mkdir, readFile, rename, writeFile } from "node:fs/promises";
5
5
  import { homedir } from "node:os";
6
6
  import { join } from "node:path";
7
7
  import { GovernanceRefusal, refusal } from "./refusals.js";
8
+ import { assertCloseBounds, HELPER_SOURCE, LEASE_READY, unrefStream } from "./lease-helper.js";
8
9
  export const ENV_WORKSPACE_LEASE_DIR = "PI_GRANTS_WORKSPACE_LEASE_DIR";
9
10
  export function defaultWorkspaceLeaseDir(env = process.env) {
10
11
  const agentDir = env.PI_CODING_AGENT_DIR ?? join(homedir(), ".pi", "agent");
11
12
  return env[ENV_WORKSPACE_LEASE_DIR] ?? join(agentDir, "pi-daddy", "workspace-leases");
12
13
  }
13
- const LEASE_READY = "PI_DADDY_LEASE_READY";
14
- // The lock holder also owns crash cleanup for the governed child. If the parent dies, stdin closes;
15
- // the helper signals the attached process, or closes the herdr tab, before releasing flock. A raw
16
- // descendant deliberately detached by bash remains ADR-0012's OS-containment boundary, not a lease
17
- // guarantee. The process branch SIGTERMs, escalates to SIGKILL at +500ms, and releases at +750ms
18
- // WITHOUT confirming death (R-101). The herdr branch retries `tab close` a BOUNDED number of times
19
- // and then releases anyway, leaving a marker file: an unreleasable lock strands a worktree forever
20
- // with no in-product recovery, which is strictly worse than a recorded failure to close (R-102).
21
- const HELPER_SOURCE = `
22
- import { execFile } from "node:child_process";
23
- import { writeFileSync } from "node:fs";
24
- let clean=false, target=null, buffered="";
25
- process.stdout.write(${JSON.stringify(`${LEASE_READY}:`)}+process.pid+"\\n");
26
- process.stdin.setEncoding("utf8");
27
- process.stdin.on("data",chunk=>{buffered+=chunk;for(;;){const i=buffered.indexOf("\\n");if(i<0)break;const line=buffered.slice(0,i);buffered=buffered.slice(i+1);try{const value=JSON.parse(line);if(value.release)clean=true;else if(value.process_pid)target={process_pid:value.process_pid};else if(value.herdr_tab)target={herdr_tab:value.herdr_tab};}catch{}}});
28
- process.stdin.on("end",()=>{if(clean||!target)return process.exit(0);if(target.process_pid){try{process.kill(target.process_pid,"SIGTERM")}catch{return process.exit(0)}setTimeout(()=>{try{process.kill(target.process_pid,"SIGKILL")}catch{}},500);return setTimeout(()=>process.exit(0),750);}let left=Number(process.env.PI_DADDY_LEASE_CLOSE_ATTEMPTS||10);const giveUp=()=>{try{if(process.env.PI_DADDY_LEASE_MARKER)writeFileSync(process.env.PI_DADDY_LEASE_MARKER,JSON.stringify({reason:"herdr-close-failed",herdr_tab:target.herdr_tab})+"\\n")}catch{}process.exit(0)};const close=()=>execFile("herdr",["tab","close",target.herdr_tab],error=>{if(!error)return process.exit(0);if(--left<=0)return giveUp();setTimeout(close,1000)});close();});
29
- process.stdin.resume();`;
30
14
  /**
31
- * The ledger outcome for a release. ONE definition, exported, because two call sites had their own copies
32
- * and the check runner's copy asserted `released` unconditionally — reproducing in the evidence path the
33
- * exact defect this union was added to expose (R-100/R-103).
15
+ * The ledger outcome for a release. Exported because call sites had their own copies and the check runner's
16
+ * asserted `released` unconditionally — reproducing in the evidence path the exact defect this union was
17
+ * added to expose (R-100/R-103).
18
+ *
19
+ * **It is NOT the only definition, and saying so here was wrong.** `extensions/workspace-runtime.ts` keeps a
20
+ * private copy with no `not-held` arm, and it is the one the whole delegation path uses — so releasing a
21
+ * *read* lease on a delegated child is still recorded `released`, a handover the kernel never performed.
22
+ * Measured; open as R-141; the sentence claiming a single definition survived two review passes because
23
+ * `test/workspace.test.ts` pins the `not-held` arm on THIS function, which no delegation path calls.
34
24
  */
35
25
  export function leaseReleaseLedgerOutcome(outcome, reason) {
36
26
  if (outcome === "retained")
@@ -55,6 +45,8 @@ export function leaseAcquisitionOutcome(access, recovered) {
55
45
  return recovered === true ? "recovered" : "acquired";
56
46
  }
57
47
  export async function acquireWorkspaceLease(input) {
48
+ // Before the read-lease return, so both paths are validated (R-152).
49
+ assertCloseBounds(input);
58
50
  if (input.access === "read") {
59
51
  return {
60
52
  workspace: input.workspace,
@@ -63,7 +55,9 @@ export async function acquireWorkspaceLease(input) {
63
55
  recovered: false,
64
56
  attachProcess: () => { },
65
57
  attachHerdrTab: () => { },
66
- markRetained: async () => { },
58
+ // A read lease took no kernel lock, so there is nothing to keep: `not-held` is the same answer
59
+ // `release()` gives, and it is the truth rather than a retention that never happened (R-152).
60
+ markRetained: async () => "not-held",
67
61
  readCloseFailure: async () => null,
68
62
  lost: new Promise(() => { }),
69
63
  // No kernel lock was ever taken, so there is no handover to claim (R-105, release side).
@@ -81,7 +75,12 @@ export async function acquireWorkspaceLease(input) {
81
75
  process.execPath, "--input-type=module", "-e", HELPER_SOURCE,
82
76
  ], {
83
77
  stdio: ["pipe", "pipe", "pipe"],
84
- env: { ...process.env, PI_DADDY_LEASE_MARKER: paths.marker, PI_DADDY_LEASE_CLOSE_ATTEMPTS: String(input.herdrCloseAttempts ?? 10) },
78
+ env: {
79
+ ...process.env,
80
+ PI_DADDY_LEASE_MARKER: paths.marker,
81
+ PI_DADDY_LEASE_CLOSE_ATTEMPTS: String(input.herdrCloseAttempts ?? 10),
82
+ PI_DADDY_LEASE_CLOSE_TIMEOUT_MS: String(input.herdrCloseTimeoutMs ?? 15_000),
83
+ },
85
84
  // Own process group, for two reasons. It lets teardown kill `flock` AND the helper holding the lock
86
85
  // file descriptor as one unit even before the helper has reported its pid (R-99), and it stops a
87
86
  // stray group signal — a terminal Ctrl-C, a closed window — from releasing a live writer's lock as
@@ -208,12 +207,70 @@ export async function acquireWorkspaceLease(input) {
208
207
  async markRetained(reason = "retained") {
209
208
  // Deliberately does NOT touch the kernel lock or the helper: the pane may still be live. It only
210
209
  // stops the record from looking like a crash.
210
+ //
211
+ // **Both guards below exist because the CALLER ledgers whatever this returns (R-152).**
212
+ //
213
+ // Already settled: `release()` checked `settled` and this did not, so a completed handover could be
214
+ // rewritten into `retained:…` and the memoized answer flipped with it — the mirror of the defect R-146
215
+ // fixed, reachable by the `try { … } finally { await lease.release() }` shape this API invites.
216
+ if (settled)
217
+ return settled;
218
+ // Already dead: the helper is gone and the kernel lock with it, so the fact is `lost`. Recording a
219
+ // retention here tells an operator a pane may still be live and tells the next owner nothing crashed —
220
+ // precisely the two facts R-103's outcome union was added to keep apart.
221
+ if (holder.exitCode !== null || holder.signalCode !== null)
222
+ return (settled = "lost");
211
223
  const current = await readMetadata(paths.metadata);
224
+ let recorded = false;
212
225
  if (current !== "malformed" && current?.token === token) {
213
- await atomicMetadata(paths.metadata, {
226
+ recorded = await atomicMetadata(paths.metadata, {
214
227
  ...metadata, state: "released", released_at: new Date().toISOString(), release_reason: `retained:${reason}`,
215
- }).catch(() => undefined);
228
+ }).then(() => true, () => false);
216
229
  }
230
+ /**
231
+ * **It must, however, let THIS process exit (R-146).** Leaving the helper alone is the decision;
232
+ * leaving the parent's three pipes and the child handle referenced was an accident, and it meant a
233
+ * retained lease wedged its own process forever — measured `exit=124` against `exit=0` for the same
234
+ * sequence ending in `release()`.
235
+ *
236
+ * **Which hosts it actually wedged, corrected after review.** `process.exit()` runs `exit` handlers and
237
+ * ignores pending handles, so this only bites a host that lets the loop drain: pi's **print** mode sets
238
+ * `process.exitCode` and returns (`dist/main.js`), and a library consumer — an ADR-0034 external
239
+ * controller calling this package directly — does the same. pi's interactive and rpc modes call
240
+ * `process.exit()` explicitly (`dist/modes/interactive/interactive-mode.js:3148`), so there the process
241
+ * still leaves and `pane-reaper`'s `process.once("exit")` sweep still runs. An earlier version of this
242
+ * comment claimed the sweep was lost generally and cited `src/cli.ts`, which has one subcommand
243
+ * (`init`) and can neither hold a lease nor open a pane.
244
+ *
245
+ * Unref rather than close, because the lock must outlive this call: when the parent does exit, the
246
+ * helper sees EOF and runs the path it was written for — bounded `herdr tab close` attempts, a marker
247
+ * file, then release anyway (R-102: an unreleasable lock strands a worktree with no in-product
248
+ * recovery, which is strictly worse than a recorded failure to close). Narrowed to this path on
249
+ * purpose: at spawn it would remove the accidental guarantee that a process cannot exit while a lease
250
+ * is still ACTIVE, which is a different decision and not this fix.
251
+ */
252
+ /**
253
+ * **Terminal (R-146).** `releasing` stops a late `holder.close` being reported as a lost lease, and
254
+ * `settled` stops a later `release()` running the clean handshake — which it did: measured, it returned
255
+ * `released`, overwrote `retained:herdr-close-failed` with `completed`, and sent `{release:true}` so the
256
+ * helper exited `clean` and never attempted the close. The pane retention exists to protect was
257
+ * abandoned silently, and the ledger asserted a clean handover for a lease kept *because* a pane would
258
+ * not close. No in-tree caller does this — but `WorkspaceLease` is a public export and
259
+ * `try { … } finally { await lease.release() }` is the obvious shape for the external controllers this
260
+ * whole fix is for.
261
+ */
262
+ releasing = true;
263
+ // **Settle only if the record was actually written.** An unwritable lease directory used to leave the
264
+ // record `state: "active"` while the ledger said `retained`, so the next owner reported a phantom
265
+ // `recovered: true` — and making retention terminal removed the later `release()` that would still have
266
+ // written the handover. Unsettled, that repair is available again; the residue is stated in R-152
267
+ // rather than implied, because nothing here can write a record to a directory that refuses writes.
268
+ if (recorded)
269
+ settled = "retained";
270
+ holder.unref();
271
+ unrefStream(holder.stdout);
272
+ unrefStream(holder.stderr);
273
+ return "retained";
217
274
  },
218
275
  async readCloseFailure() {
219
276
  try {
@@ -1 +1 @@
1
- {"version":3,"file":"workspace-lease.js","sourceRoot":"","sources":["../src/workspace-lease.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"workspace-lease.js","sourceRoot":"","sources":["../src/workspace-lease.ts"],"names":[],"mappings":"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"}
@@ -5,6 +5,17 @@ export interface WorkspaceRegistryFile {
5
5
  workspaces: Record<string, {
6
6
  path: string;
7
7
  }>;
8
+ /**
9
+ * Where this was loaded from, carried so a refusal can NAME it.
10
+ *
11
+ * `docs/SPEC.md` claimed an unregistered id is refused "with `WORKSPACE_NOT_REGISTERED`, which names the
12
+ * file", and `catalog.ts` justified exempting the whole namespace from the unknown check on the strength of
13
+ * that — *"a second, weaker check here can only turn that precise refusal into a misleading one"*. The
14
+ * refusal named no file: the registry object had no idea where it came from. Carried on the object rather
15
+ * than passed per call so a caller cannot forget it. Optional because a hand-built literal (tests,
16
+ * `workspaceEntries` fixtures) has no source.
17
+ */
18
+ source?: string;
8
19
  }
9
20
  export interface ValidatedWorkspace {
10
21
  workspaceId: string;
@@ -13,6 +24,20 @@ export interface ValidatedWorkspace {
13
24
  gitCommonDir: string;
14
25
  }
15
26
  export declare function loadWorkspaceRegistry(path: string): Promise<WorkspaceRegistryFile>;
27
+ /**
28
+ * The registered workspace ids, for `planInit` to scaffold and `/grants` to list. `[]` when there is no registry or it is broken.
29
+ *
30
+ * Fails SOFT, and only because nothing here is an authority: this decides which ids appear as COMMENTS in a
31
+ * generated file. `loadWorkspaceRegistry` throws a GovernanceRefusal naming the file, and that refusal is
32
+ * the operator's signal at the point of use, where routing genuinely depends on it. Swallowing it there
33
+ * would be unsafe; swallowing it here costs a suggestion. Same argument as `buildCatalog`'s.
34
+ *
35
+ * Lives here rather than in `init.ts` because it reads the filesystem, and `planInit` — the centrepiece of
36
+ * that module — documents itself as "Pure: no filesystem". It is a registry concern; this is where the
37
+ * registry lives. Moved when `init.ts` crossed the 400-line ceiling, which this project splits for rather
38
+ * than raising (`delegate.ts` at 413, `grants.ts` at 398).
39
+ */
40
+ export declare function registeredWorkspaceIds(registryPath?: string | undefined): Promise<string[]>;
16
41
  export declare function resolveWorkspace(registry: WorkspaceRegistryFile, workspaceId: string): Promise<ValidatedWorkspace>;
17
42
  /**
18
43
  * Canonicalize and validate the initial workspace against Git's registered worktree list.
@@ -1 +1 @@
1
- {"version":3,"file":"workspace.d.ts","sourceRoot":"","sources":["../src/workspace.ts"],"names":[],"mappings":"AAUA,eAAO,MAAM,sBAAsB,iCAAiC,CAAC;AAGrE,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,OAAO,CAAC;AAE/C,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,CAAC,CAAC;IACX,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC9C;AAED,MAAM,WAAW,kBAAkB;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,wFAAwF;IACxF,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,wBAAsB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,CAAC,CA6BxF;AAED,wBAAsB,gBAAgB,CAAC,QAAQ,EAAE,qBAAqB,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAUxH;AAED;;;GAGG;AACH,wBAAsB,2BAA2B,CAAC,KAAK,EAAE;IACvD,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAyC9B;AAED;;;;GAIG;AACH,OAAO,EACL,uBAAuB,EACvB,qBAAqB,EACrB,wBAAwB,EACxB,uBAAuB,EACvB,yBAAyB,EACzB,KAAK,mBAAmB,EACxB,KAAK,cAAc,GACpB,MAAM,sBAAsB,CAAC"}
1
+ {"version":3,"file":"workspace.d.ts","sourceRoot":"","sources":["../src/workspace.ts"],"names":[],"mappings":"AAaA,eAAO,MAAM,sBAAsB,iCAAiC,CAAC;AAGrE,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,OAAO,CAAC;AAE/C,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,CAAC,CAAC;IACX,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC7C;;;;;;;;;OASG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,kBAAkB;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,wFAAwF;IACxF,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;CACtB;AAsBD,wBAAsB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,CAAC,CA+IxF;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,sBAAsB,CAAC,YAAY,qBAAsC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAOlH;AAED,wBAAsB,gBAAgB,CAAC,QAAQ,EAAE,qBAAqB,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAaxH;AAED;;;GAGG;AACH,wBAAsB,2BAA2B,CAAC,KAAK,EAAE;IACvD,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAyC9B;AAED;;;;GAIG;AACH,OAAO,EACL,uBAAuB,EACvB,qBAAqB,EACrB,wBAAwB,EACxB,uBAAuB,EACvB,yBAAyB,EACzB,KAAK,mBAAmB,EACxB,KAAK,cAAc,GACpB,MAAM,sBAAsB,CAAC"}
package/dist/workspace.js CHANGED
@@ -1,20 +1,116 @@
1
1
  import { createHash, randomUUID } from "node:crypto";
2
2
  import { execFile } from "node:child_process";
3
3
  import { once } from "node:events";
4
- import { mkdir, readFile, realpath, rename, stat, writeFile } from "node:fs/promises";
4
+ import { mkdir, open, readFile, realpath, rename, stat, writeFile } from "node:fs/promises";
5
+ import { constants } from "node:fs";
5
6
  import { homedir } from "node:os";
6
7
  import { isAbsolute, join } from "node:path";
7
8
  import { promisify } from "node:util";
8
9
  import { GovernanceRefusal, refusal } from "./refusals.js";
10
+ import { isSafeWorkspaceId, workspaceCapability } from "./capabilities.js";
9
11
  const execFileAsync = promisify(execFile);
10
12
  export const ENV_WORKSPACE_REGISTRY = "PI_GRANTS_WORKSPACE_REGISTRY";
13
+ /**
14
+ * How long a registry read may take before it is a refusal rather than a wait.
15
+ *
16
+ * **R-79's defect class, and this reader reintroduced it.** That entry records a probe that hung forever on
17
+ * a FIFO with "no timeout anywhere in the path". This function used a bare `readFile`, which was survivable
18
+ * while it ran only at spawn time — and stopped being survivable when 0.19.0 began reading the registry from
19
+ * `buildCatalog` and `registeredWorkspaceIds`, both awaited inside `session_start`. Measured on `52135ca`:
20
+ * `PI_GRANTS_WORKSPACE_REGISTRY` pointing at a FIFO blocked session start indefinitely, so the session never
21
+ * reached the `holding [...]` line, the executor probe, or any control after it — and `delegate` awaits the
22
+ * same promise, so delegation hung too. A blocking special file, an unresponsive network mount or a hostile
23
+ * `mkfifo` all reach it.
24
+ *
25
+ * Two seconds because this is an operator-authored local JSON file: any legitimate one is a single-digit
26
+ * millisecond read (measured: 8ms), so the bound is three orders of magnitude of headroom and still bounded.
27
+ */
28
+ const REGISTRY_READ_TIMEOUT_MS = 2_000;
29
+ /** A registry is an operator-authored JSON file; anything approaching this is not one. */
30
+ const REGISTRY_MAX_BYTES = 1 << 20;
11
31
  export async function loadWorkspaceRegistry(path) {
32
+ // **One handle, opened non-blocking, and every check made against THAT handle.** Three defects made this
33
+ // the shape rather than `stat`-then-`readFile`:
34
+ //
35
+ // - `AbortSignal.timeout` cannot rescue a FIFO: a signal is observed between chunks, while a FIFO blocks
36
+ // inside `open(2)` before any read begins. `O_NONBLOCK` makes the open itself return instead (measured:
37
+ // 1ms), which is what actually bounds this path. R-79's defect class, and R-136's.
38
+ // - `stat` by name followed by `readFile` by name is a TOCTOU: swapping a regular file for a FIFO between
39
+ // the two hung the loader indefinitely, and the attacker is any process at the same uid — precisely the
40
+ // actor the mode check below cannot exclude. Measured, 5 of 6 iterations completing in ~1ms and the
41
+ // sixth never returning. `fstat` on a held descriptor has no name to re-resolve.
42
+ // - a second reader (the ADR-0035 registry pin, since reverted to its own PR) reimplemented the guards and
43
+ // got them wrong. One reader is why that cannot happen again.
44
+ let handle;
45
+ try {
46
+ handle = await open(path, constants.O_RDONLY | constants.O_NONBLOCK);
47
+ }
48
+ catch (error) {
49
+ throw new GovernanceRefusal(refusal("WORKSPACE_NOT_REGISTERED", `workspace registry ${path} could not be opened (${String(error)})`, { registry_path: path }));
50
+ }
51
+ let raw;
52
+ try {
53
+ const info = await handle.stat();
54
+ if (!info.isFile()) {
55
+ throw new GovernanceRefusal(refusal("WORKSPACE_NOT_REGISTERED", `workspace registry ${path} is not a regular file — refusing to read it. A FIFO, device or socket ` +
56
+ `at ${ENV_WORKSPACE_REGISTRY} would block session start rather than fail, because opening one ` +
57
+ `waits for a writer that may never come.`, { registry_path: path }));
58
+ }
59
+ if (info.size > REGISTRY_MAX_BYTES) {
60
+ throw new GovernanceRefusal(refusal("WORKSPACE_NOT_REGISTERED", `workspace registry ${path} is ${info.size} bytes, over the ${REGISTRY_MAX_BYTES} limit — refusing ` +
61
+ `rather than reading it into memory at session start.`, { registry_path: path }));
62
+ }
63
+ // **Ownership and mode are NOT checked here, and that is a scope decision (R-137, ADR-0036).** A
64
+ // previous revision refused a registry not owned by this user or writable by others. Those guards are
65
+ // about *tamper resistance*, which is a different question from the one ADR-0035 raised, and they went in
66
+ // mid-review without an ADR — where they promptly acquired a false claim ("nobody ELSE may rewrite it":
67
+ // it inspects the file and never its parent directory, and `rename(2)` needs only directory write) and a
68
+ // false-positive refusal of `0664`, which `umask 002` produces for every file an operator creates.
69
+ //
70
+ // What IS checked above is what ADR-0035 made this reader's problem: it began reading the registry at
71
+ // SESSION START, so the read must be bounded and must not block. Integrity is R-137, open and measured.
72
+ // The deadline is checked BETWEEN chunks, which is all `AbortSignal.timeout` ever did on the previous
73
+ // implementation — review measured 74 of 200 one-MiB reads completing in full with `signal.aborted`
74
+ // already true, because a signal is never observed *inside* a libuv read request. An explicit check makes
75
+ // the bound as real as it can be in-process, and its limit is the same one honestly stated below: a
76
+ // stalled `open` or a single wedged read cannot be interrupted from here.
77
+ const deadline = Date.now() + REGISTRY_READ_TIMEOUT_MS;
78
+ const buffer = Buffer.allocUnsafe(REGISTRY_MAX_BYTES + 1);
79
+ let filled = 0;
80
+ while (filled < buffer.length) {
81
+ if (Date.now() > deadline) {
82
+ throw new GovernanceRefusal(refusal("WORKSPACE_NOT_REGISTERED", `workspace registry ${path} did not finish reading within ${REGISTRY_READ_TIMEOUT_MS}ms — ` +
83
+ `refusing rather than waiting, because session start awaits this read.`, { registry_path: path }));
84
+ }
85
+ const { bytesRead } = await handle.read(buffer, filled, buffer.length - filled, filled);
86
+ if (bytesRead === 0)
87
+ break;
88
+ filled += bytesRead;
89
+ }
90
+ if (filled > REGISTRY_MAX_BYTES) {
91
+ throw new GovernanceRefusal(refusal("WORKSPACE_NOT_REGISTERED", `workspace registry ${path} exceeded the ${REGISTRY_MAX_BYTES} limit while being read — it grew ` +
92
+ `after its size was checked. Refusing rather than allocating it.`, { registry_path: path }));
93
+ }
94
+ raw = buffer.subarray(0, filled).toString("utf8");
95
+ }
96
+ catch (error) {
97
+ if (error instanceof GovernanceRefusal)
98
+ throw error;
99
+ const timedOut = error instanceof Error && (error.name === "AbortError" || error.name === "TimeoutError");
100
+ throw new GovernanceRefusal(refusal("WORKSPACE_NOT_REGISTERED", timedOut
101
+ ? `workspace registry ${path} did not return within ${REGISTRY_READ_TIMEOUT_MS}ms — refusing rather ` +
102
+ `than waiting, because session start awaits this read.`
103
+ : `workspace registry ${path} could not be read (${String(error)})`, { registry_path: path }));
104
+ }
105
+ finally {
106
+ await handle.close().catch(() => { });
107
+ }
12
108
  let parsed;
13
109
  try {
14
- parsed = JSON.parse(await readFile(path, "utf8"));
110
+ parsed = JSON.parse(raw);
15
111
  }
16
112
  catch (error) {
17
- throw new GovernanceRefusal(refusal("WORKSPACE_NOT_REGISTERED", `workspace registry ${path} could not be read (${String(error)})`, { registry_path: path }));
113
+ throw new GovernanceRefusal(refusal("WORKSPACE_NOT_REGISTERED", `workspace registry ${path} is not valid JSON (${String(error)})`, { registry_path: path }));
18
114
  }
19
115
  const file = parsed;
20
116
  if (file?.version !== 1 || !file.workspaces || typeof file.workspaces !== "object" || Array.isArray(file.workspaces)) {
@@ -24,13 +120,54 @@ export async function loadWorkspaceRegistry(path) {
24
120
  if (!id || !value || typeof value.path !== "string" || !isAbsolute(value.path)) {
25
121
  throw new GovernanceRefusal(refusal("WORKSPACE_NOT_REGISTERED", `workspace registry entry ${JSON.stringify(id)} must name an absolute path`, { registry_path: path, workspace_id: id }));
26
122
  }
123
+ // ADR-0035 made a registry id the tail of a CAPABILITY id (`workspace:<id>`), so this file is an input
124
+ // to the grant grammar and has to obey it — the STRICT one. This shipped with the loose
125
+ // `isWellFormedCapability` blocklist, and review measured what that let through: an id of `*` minted
126
+ // `WORKSPACE_WILDCARD` (an operator naming one worktree held routing over all of them), an id with a
127
+ // space became two capabilities because `ceilingForDefinition` splits on `[\s,]+`, and quote/`$()` ids
128
+ // reached a generated file whose own instructions say to paste them into `PI_GRANTS_GRANT`. See
129
+ // `isSafeCapability`, which is now the one grammar for both channels into that file.
130
+ if (!isSafeWorkspaceId(id)) {
131
+ throw new GovernanceRefusal(refusal("GRANT_ID_MALFORMED", `workspace registry id ${JSON.stringify(id)} cannot be used: since ADR-0035 an id becomes the ` +
132
+ `capability ${JSON.stringify(workspaceCapability(id))}, and an id must match ` +
133
+ `[A-Za-z0-9][A-Za-z0-9._/-]* — slashes and dots are fine (a worktree named after its branch ` +
134
+ `works), but not spaces, quotes, commas, wildcards, shell metacharacters or non-ASCII, each of ` +
135
+ `which either splits into several capabilities or reaches a file you are told to source. ` +
136
+ `Rename it in ${path}.`, { registry_path: path, workspace_id: id }));
137
+ }
138
+ }
139
+ return { version: 1, workspaces: structuredClone(file.workspaces), source: path };
140
+ }
141
+ /**
142
+ * The registered workspace ids, for `planInit` to scaffold and `/grants` to list. `[]` when there is no registry or it is broken.
143
+ *
144
+ * Fails SOFT, and only because nothing here is an authority: this decides which ids appear as COMMENTS in a
145
+ * generated file. `loadWorkspaceRegistry` throws a GovernanceRefusal naming the file, and that refusal is
146
+ * the operator's signal at the point of use, where routing genuinely depends on it. Swallowing it there
147
+ * would be unsafe; swallowing it here costs a suggestion. Same argument as `buildCatalog`'s.
148
+ *
149
+ * Lives here rather than in `init.ts` because it reads the filesystem, and `planInit` — the centrepiece of
150
+ * that module — documents itself as "Pure: no filesystem". It is a registry concern; this is where the
151
+ * registry lives. Moved when `init.ts` crossed the 400-line ceiling, which this project splits for rather
152
+ * than raising (`delegate.ts` at 413, `grants.ts` at 398).
153
+ */
154
+ export async function registeredWorkspaceIds(registryPath = process.env[ENV_WORKSPACE_REGISTRY]) {
155
+ if (!registryPath)
156
+ return [];
157
+ try {
158
+ return Object.keys((await loadWorkspaceRegistry(registryPath)).workspaces).sort();
159
+ }
160
+ catch {
161
+ return [];
27
162
  }
28
- return { version: 1, workspaces: structuredClone(file.workspaces) };
29
163
  }
30
164
  export async function resolveWorkspace(registry, workspaceId) {
31
165
  const registered = Object.hasOwn(registry.workspaces, workspaceId) ? registry.workspaces[workspaceId] : undefined;
166
+ const known = Object.keys(registry.workspaces).sort();
32
167
  if (!registered) {
33
- throw new GovernanceRefusal(refusal("WORKSPACE_NOT_REGISTERED", `workspace ${JSON.stringify(workspaceId)} is not present in the operator-owned registry`, { workspace_id: workspaceId }));
168
+ throw new GovernanceRefusal(refusal("WORKSPACE_NOT_REGISTERED", `workspace ${JSON.stringify(workspaceId)} is not present in the operator-owned registry` +
169
+ (registry.source ? ` ${registry.source}` : "") +
170
+ (known.length > 0 ? ` — it lists: ${known.join(", ")}` : " — it lists nothing"), { workspace_id: workspaceId, ...(registry.source ? { registry_path: registry.source } : {}) }));
34
171
  }
35
172
  return validateRegisteredWorkspace({ workspaceId, registeredRoot: registered.path });
36
173
  }