pi-crew 0.9.46 → 0.9.48

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 (46) hide show
  1. package/CHANGELOG.md +83 -0
  2. package/README.md +16 -2
  3. package/dist/build-meta.json +289 -164
  4. package/dist/index.mjs +1744 -2732
  5. package/dist/index.mjs.map +4 -4
  6. package/docs/decisions/2026-07-21-broker-phase4-default-on.md +77 -0
  7. package/docs/decisions/2026-07-21-broker-windows-perms.md +91 -0
  8. package/docs/decisions/2026-07-22-broker-phase4-gated-on.md +99 -0
  9. package/docs/decisions/README.md +3 -0
  10. package/docs/publishing.md +29 -0
  11. package/package.json +3 -1
  12. package/scripts/build-bundle.mjs +7 -0
  13. package/scripts/postinstall.mjs +60 -1
  14. package/scripts/pty_probe.py +174 -0
  15. package/skills/real-test-pi-crew/SKILL.md +659 -0
  16. package/src/config/config.ts +42 -1
  17. package/src/config/defaults.ts +45 -1
  18. package/src/config/types.ts +19 -0
  19. package/src/extension/register.ts +6 -1
  20. package/src/extension/registration/context-builder.ts +4 -0
  21. package/src/extension/registration/lifecycle-handlers.ts +166 -3
  22. package/src/extension/registration/registration-types.ts +9 -0
  23. package/src/prompt/prompt-runtime.ts +108 -0
  24. package/src/runtime/broker-issuer.ts +37 -0
  25. package/src/runtime/child-pi-spawn.ts +53 -0
  26. package/src/runtime/child-pi.ts +42 -11
  27. package/src/runtime/crew-broker-child.ts +88 -0
  28. package/src/runtime/crew-broker-client.ts +673 -0
  29. package/src/runtime/crew-broker-tokens.ts +84 -0
  30. package/src/runtime/crew-broker.ts +1276 -0
  31. package/src/runtime/dynamic-workflow-context.ts +7 -3
  32. package/src/runtime/dynamic-workflow-runner.ts +1 -1
  33. package/src/runtime/plan-templates.ts +8 -6
  34. package/src/schema/config-schema.ts +14 -0
  35. package/src/state/mailbox.ts +43 -0
  36. package/src/ui/key-utils.ts +42 -0
  37. package/src/ui/keybinding-map.ts +29 -3
  38. package/src/ui/run-dashboard.ts +28 -0
  39. package/src/ui/settings-overlay.ts +42 -22
  40. package/src/utils/ndjson.ts +115 -0
  41. package/src/utils/session-utils.ts +30 -0
  42. package/src/utils/socket-path.ts +127 -0
  43. package/workflows/default.workflow.md +1 -1
  44. package/workflows/fast-fix.workflow.md +1 -1
  45. package/workflows/plan-execute.workflow.md +1 -1
  46. package/workflows/review.workflow.md +1 -1
@@ -0,0 +1,84 @@
1
+ /**
2
+ * crew-broker-tokens.ts — Per-run token registry for the broker.
3
+ *
4
+ * The token map is HEAP ONLY. It lives on the CrewBroker instance and is
5
+ * cleared on `stop()`. It is never serialized to disk, never written to
6
+ * the run directory, never logged, and never exposed via a broker method.
7
+ *
8
+ * Extracted from crew-broker.ts to keep the orchestrator file focused on
9
+ * connection / dispatch logic and to make the registry's invariants
10
+ * independently testable.
11
+ */
12
+
13
+ import { randomUUID, timingSafeEqual } from "node:crypto";
14
+
15
+ /** Length guard: tokens are 128-bit-class (UUID v4). */
16
+ export type BrokerToken = string;
17
+
18
+ /** Generate a fresh per-run token. */
19
+ export function newBrokerToken(): BrokerToken {
20
+ return randomUUID();
21
+ }
22
+
23
+ /**
24
+ * A small registry mapping runId → token. Operations are O(1) Map.
25
+ * Constant-time compare (`timingSafeEqual`) prevents side-channel
26
+ * comparison leakage of the secret. The compare normalizes both sides
27
+ * to the same byte length — differing-length inputs return false
28
+ * immediately without entering the timing-safe path (length itself is
29
+ * not a secret, only the bytes are).
30
+ */
31
+ export class BrokerTokenRegistry {
32
+ private readonly map = new Map<string, BrokerToken>();
33
+
34
+ /** Issue a token for `runId`. Idempotent per run: if a token already
35
+ * exists for this runId, the existing token is returned unchanged so that
36
+ * concurrent sibling tasks sharing a runId all authenticate with the same
37
+ * per-run token (the spec's per-run token model). Pass an explicit
38
+ * `token` only in tests that need a deterministic value. */
39
+ issue(runId: string, token?: BrokerToken): BrokerToken {
40
+ if (typeof runId !== "string" || runId.length === 0) {
41
+ throw new Error("BrokerTokenRegistry.issue: runId must be a non-empty string");
42
+ }
43
+ if (token === undefined) {
44
+ const existing = this.map.get(runId);
45
+ if (existing !== undefined) return existing;
46
+ const fresh = newBrokerToken();
47
+ this.map.set(runId, fresh);
48
+ return fresh;
49
+ }
50
+ this.map.set(runId, token);
51
+ return token;
52
+ }
53
+
54
+ /** Look up the token for `runId`. Returns undefined if absent. */
55
+ get(runId: string): BrokerToken | undefined {
56
+ return this.map.get(runId);
57
+ }
58
+
59
+ /** Constant-time equality check. Returns false on length mismatch. */
60
+ matches(runId: string, candidate: unknown): boolean {
61
+ const expected = this.map.get(runId);
62
+ if (expected === undefined) return false;
63
+ if (typeof candidate !== "string" || candidate.length === 0) return false;
64
+ const a = Buffer.from(expected, "utf8");
65
+ const b = Buffer.from(candidate, "utf8");
66
+ if (a.length !== b.length) return false;
67
+ return timingSafeEqual(a, b);
68
+ }
69
+
70
+ /** Remove the token for `runId`. */
71
+ revoke(runId: string): void {
72
+ this.map.delete(runId);
73
+ }
74
+
75
+ /** Wipe every token. Called from CrewBroker.stop(). */
76
+ clear(): void {
77
+ this.map.clear();
78
+ }
79
+
80
+ /** Diagnostic — count of registered tokens. Never returns the tokens. */
81
+ get size(): number {
82
+ return this.map.size;
83
+ }
84
+ }