unfairly 0.8.2 → 0.8.4

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 (218) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/LICENSE +15 -0
  3. package/README.md +3 -1
  4. package/dist/auth/browser-flow.d.ts +0 -1
  5. package/dist/auth/browser-flow.js +5 -81
  6. package/dist/cmd/connect.d.ts +0 -1
  7. package/dist/cmd/connect.js +1 -164
  8. package/dist/cmd/init.d.ts +0 -1
  9. package/dist/cmd/init.js +2 -138
  10. package/dist/cmd/invite.d.ts +0 -1
  11. package/dist/cmd/invite.js +4 -73
  12. package/dist/cmd/join.d.ts +0 -1
  13. package/dist/cmd/join.js +1 -91
  14. package/dist/cmd/login.d.ts +0 -1
  15. package/dist/cmd/login.js +3 -41
  16. package/dist/cmd/mcp.d.ts +0 -1
  17. package/dist/cmd/mcp.js +2 -86
  18. package/dist/cmd/pace.d.ts +23 -2
  19. package/dist/cmd/pace.js +4 -393
  20. package/dist/cmd/parse-share-input.d.ts +0 -1
  21. package/dist/cmd/parse-share-input.js +1 -56
  22. package/dist/cmd/pull.d.ts +0 -1
  23. package/dist/cmd/pull.js +7 -143
  24. package/dist/cmd/push.d.ts +0 -1
  25. package/dist/cmd/push.js +1 -85
  26. package/dist/cmd/resolve.d.ts +0 -1
  27. package/dist/cmd/resolve.js +1 -35
  28. package/dist/cmd/setup.d.ts +0 -1
  29. package/dist/cmd/setup.js +2 -345
  30. package/dist/cmd/status-card.d.ts +0 -1
  31. package/dist/cmd/status-card.js +2 -156
  32. package/dist/cmd/status.d.ts +0 -1
  33. package/dist/cmd/status.js +3 -29
  34. package/dist/cmd/watch.d.ts +0 -1
  35. package/dist/cmd/watch.js +1 -26
  36. package/dist/hosts/claude-code.d.ts +0 -1
  37. package/dist/hosts/claude-code.js +3 -180
  38. package/dist/hosts/claude-desktop.d.ts +0 -1
  39. package/dist/hosts/claude-desktop.js +3 -222
  40. package/dist/hosts/codex.d.ts +0 -1
  41. package/dist/hosts/codex.js +20 -234
  42. package/dist/hosts/shell-env.d.ts +0 -1
  43. package/dist/hosts/shell-env.js +9 -81
  44. package/dist/index.d.ts +0 -1
  45. package/dist/index.js +14 -206
  46. package/dist/lib/client.d.ts +0 -1
  47. package/dist/lib/client.js +1 -58
  48. package/dist/lib/events/emit.d.ts +0 -1
  49. package/dist/lib/events/emit.js +1 -28
  50. package/dist/lib/index.d.ts +0 -1
  51. package/dist/lib/index.js +1 -11
  52. package/dist/lib/transport.d.ts +0 -1
  53. package/dist/lib/transport.js +1 -85
  54. package/dist/lib/types/index.d.ts +0 -1
  55. package/dist/lib/types/index.js +1 -50
  56. package/dist/lib/vault/checkpoint.d.ts +0 -1
  57. package/dist/lib/vault/checkpoint.js +1 -18
  58. package/dist/lib/vault/read.d.ts +0 -1
  59. package/dist/lib/vault/read.js +1 -9
  60. package/dist/lib/vault/search.d.ts +0 -1
  61. package/dist/lib/vault/search.js +1 -10
  62. package/dist/pace/device.d.ts +3 -1
  63. package/dist/pace/device.js +2 -148
  64. package/dist/pace/enroll.d.ts +79 -0
  65. package/dist/pace/enroll.js +2 -0
  66. package/dist/pace/identity.d.ts +0 -1
  67. package/dist/pace/identity.js +1 -17
  68. package/dist/pace/install.d.ts +0 -1
  69. package/dist/pace/install.js +4 -127
  70. package/dist/pace/local-evidence.d.ts +0 -1
  71. package/dist/pace/local-evidence.js +2 -228
  72. package/dist/pace/local-sessions.d.ts +0 -1
  73. package/dist/pace/local-sessions.js +1 -254
  74. package/dist/pace/managed-config.d.ts +0 -1
  75. package/dist/pace/managed-config.js +8 -102
  76. package/dist/pace/normalize.d.ts +0 -1
  77. package/dist/pace/normalize.js +1 -293
  78. package/dist/pace/repository.d.ts +0 -1
  79. package/dist/pace/repository.js +2 -120
  80. package/dist/pace/schema.d.ts +0 -1
  81. package/dist/pace/schema.js +1 -134
  82. package/dist/pace/session-summary.d.ts +0 -1
  83. package/dist/pace/session-summary.js +2 -140
  84. package/dist/pace/spool.d.ts +0 -1
  85. package/dist/pace/spool.js +8 -87
  86. package/dist/pace-runtime.d.ts +1 -0
  87. package/dist/pace-runtime.js +2 -0
  88. package/dist/sync/api.d.ts +0 -1
  89. package/dist/sync/api.js +1 -55
  90. package/dist/sync/autoloader.d.ts +0 -1
  91. package/dist/sync/autoloader.js +5 -127
  92. package/dist/sync/conflict.d.ts +0 -1
  93. package/dist/sync/conflict.js +5 -15
  94. package/dist/sync/credentials.d.ts +0 -1
  95. package/dist/sync/credentials.js +1 -51
  96. package/dist/sync/files.d.ts +0 -1
  97. package/dist/sync/files.js +1 -71
  98. package/dist/sync/manifest.d.ts +0 -1
  99. package/dist/sync/manifest.js +1 -37
  100. package/dist/sync/repo-root.d.ts +0 -1
  101. package/dist/sync/repo-root.js +1 -24
  102. package/dist/sync/stitch-claude-md.d.ts +0 -1
  103. package/dist/sync/stitch-claude-md.js +8 -48
  104. package/dist/ui/colors.d.ts +0 -1
  105. package/dist/ui/colors.js +1 -28
  106. package/dist/ui/screens.d.ts +0 -1
  107. package/dist/ui/screens.js +5 -135
  108. package/package.json +8 -14
  109. package/plugin/.cursor-plugin/plugin.json +0 -2
  110. package/plugin/.mcp.json +1 -1
  111. package/plugin/LICENSE +15 -0
  112. package/plugin/README.md +3 -7
  113. package/plugin/gemini/gemini-extension.json +1 -1
  114. package/plugin/mcp.json +1 -1
  115. package/plugin/plugin.json +0 -2
  116. package/plugin/runtime/unfairly-intelligence.mjs +15 -0
  117. package/plugin/scripts/capture.cjs +30 -8
  118. package/plugin/skills/find-company-playbook/SKILL.md +1 -1
  119. package/dist/auth/browser-flow.d.ts.map +0 -1
  120. package/dist/auth/browser-flow.js.map +0 -1
  121. package/dist/cmd/connect.d.ts.map +0 -1
  122. package/dist/cmd/connect.js.map +0 -1
  123. package/dist/cmd/init.d.ts.map +0 -1
  124. package/dist/cmd/init.js.map +0 -1
  125. package/dist/cmd/invite.d.ts.map +0 -1
  126. package/dist/cmd/invite.js.map +0 -1
  127. package/dist/cmd/join.d.ts.map +0 -1
  128. package/dist/cmd/join.js.map +0 -1
  129. package/dist/cmd/login.d.ts.map +0 -1
  130. package/dist/cmd/login.js.map +0 -1
  131. package/dist/cmd/mcp.d.ts.map +0 -1
  132. package/dist/cmd/mcp.js.map +0 -1
  133. package/dist/cmd/pace.d.ts.map +0 -1
  134. package/dist/cmd/pace.js.map +0 -1
  135. package/dist/cmd/parse-share-input.d.ts.map +0 -1
  136. package/dist/cmd/parse-share-input.js.map +0 -1
  137. package/dist/cmd/pull.d.ts.map +0 -1
  138. package/dist/cmd/pull.js.map +0 -1
  139. package/dist/cmd/push.d.ts.map +0 -1
  140. package/dist/cmd/push.js.map +0 -1
  141. package/dist/cmd/resolve.d.ts.map +0 -1
  142. package/dist/cmd/resolve.js.map +0 -1
  143. package/dist/cmd/setup.d.ts.map +0 -1
  144. package/dist/cmd/setup.js.map +0 -1
  145. package/dist/cmd/status-card.d.ts.map +0 -1
  146. package/dist/cmd/status-card.js.map +0 -1
  147. package/dist/cmd/status.d.ts.map +0 -1
  148. package/dist/cmd/status.js.map +0 -1
  149. package/dist/cmd/watch.d.ts.map +0 -1
  150. package/dist/cmd/watch.js.map +0 -1
  151. package/dist/hosts/claude-code.d.ts.map +0 -1
  152. package/dist/hosts/claude-code.js.map +0 -1
  153. package/dist/hosts/claude-desktop.d.ts.map +0 -1
  154. package/dist/hosts/claude-desktop.js.map +0 -1
  155. package/dist/hosts/codex.d.ts.map +0 -1
  156. package/dist/hosts/codex.js.map +0 -1
  157. package/dist/hosts/shell-env.d.ts.map +0 -1
  158. package/dist/hosts/shell-env.js.map +0 -1
  159. package/dist/index.d.ts.map +0 -1
  160. package/dist/index.js.map +0 -1
  161. package/dist/lib/client.d.ts.map +0 -1
  162. package/dist/lib/client.js.map +0 -1
  163. package/dist/lib/events/emit.d.ts.map +0 -1
  164. package/dist/lib/events/emit.js.map +0 -1
  165. package/dist/lib/index.d.ts.map +0 -1
  166. package/dist/lib/index.js.map +0 -1
  167. package/dist/lib/transport.d.ts.map +0 -1
  168. package/dist/lib/transport.js.map +0 -1
  169. package/dist/lib/types/index.d.ts.map +0 -1
  170. package/dist/lib/types/index.js.map +0 -1
  171. package/dist/lib/vault/checkpoint.d.ts.map +0 -1
  172. package/dist/lib/vault/checkpoint.js.map +0 -1
  173. package/dist/lib/vault/read.d.ts.map +0 -1
  174. package/dist/lib/vault/read.js.map +0 -1
  175. package/dist/lib/vault/search.d.ts.map +0 -1
  176. package/dist/lib/vault/search.js.map +0 -1
  177. package/dist/pace/device.d.ts.map +0 -1
  178. package/dist/pace/device.js.map +0 -1
  179. package/dist/pace/identity.d.ts.map +0 -1
  180. package/dist/pace/identity.js.map +0 -1
  181. package/dist/pace/install.d.ts.map +0 -1
  182. package/dist/pace/install.js.map +0 -1
  183. package/dist/pace/local-evidence.d.ts.map +0 -1
  184. package/dist/pace/local-evidence.js.map +0 -1
  185. package/dist/pace/local-sessions.d.ts.map +0 -1
  186. package/dist/pace/local-sessions.js.map +0 -1
  187. package/dist/pace/managed-config.d.ts.map +0 -1
  188. package/dist/pace/managed-config.js.map +0 -1
  189. package/dist/pace/normalize.d.ts.map +0 -1
  190. package/dist/pace/normalize.js.map +0 -1
  191. package/dist/pace/repository.d.ts.map +0 -1
  192. package/dist/pace/repository.js.map +0 -1
  193. package/dist/pace/schema.d.ts.map +0 -1
  194. package/dist/pace/schema.js.map +0 -1
  195. package/dist/pace/session-summary.d.ts.map +0 -1
  196. package/dist/pace/session-summary.js.map +0 -1
  197. package/dist/pace/spool.d.ts.map +0 -1
  198. package/dist/pace/spool.js.map +0 -1
  199. package/dist/sync/api.d.ts.map +0 -1
  200. package/dist/sync/api.js.map +0 -1
  201. package/dist/sync/autoloader.d.ts.map +0 -1
  202. package/dist/sync/autoloader.js.map +0 -1
  203. package/dist/sync/conflict.d.ts.map +0 -1
  204. package/dist/sync/conflict.js.map +0 -1
  205. package/dist/sync/credentials.d.ts.map +0 -1
  206. package/dist/sync/credentials.js.map +0 -1
  207. package/dist/sync/files.d.ts.map +0 -1
  208. package/dist/sync/files.js.map +0 -1
  209. package/dist/sync/manifest.d.ts.map +0 -1
  210. package/dist/sync/manifest.js.map +0 -1
  211. package/dist/sync/repo-root.d.ts.map +0 -1
  212. package/dist/sync/repo-root.js.map +0 -1
  213. package/dist/sync/stitch-claude-md.d.ts.map +0 -1
  214. package/dist/sync/stitch-claude-md.js.map +0 -1
  215. package/dist/ui/colors.d.ts.map +0 -1
  216. package/dist/ui/colors.js.map +0 -1
  217. package/dist/ui/screens.d.ts.map +0 -1
  218. package/dist/ui/screens.js.map +0 -1
@@ -18,4 +18,3 @@ export declare function writeManagedConfigs(input: {
18
18
  includeFileNames?: boolean;
19
19
  }): Promise<string[]>;
20
20
  export {};
21
- //# sourceMappingURL=managed-config.d.ts.map
@@ -1,102 +1,8 @@
1
- import fs from "node:fs/promises";
2
- import path from "node:path";
3
- export function renderEvidencePolicy(input) {
4
- return {
5
- version: 1,
6
- include_file_names: input.includeFileNames ?? false,
7
- scan_interval_seconds: 60,
8
- max_files_per_root: 5000,
9
- roots: (input.evidenceRoots ?? []).map((root, index) => ({
10
- path: root,
11
- label: `approved-output-${index + 1}`,
12
- kind: "output",
13
- })),
14
- };
15
- }
16
- const EVENTS = {
17
- sessionStart: { codex: "SessionStart", claude: "SessionStart", gemini: "SessionStart" },
18
- toolCompleted: { codex: "PostToolUse", claude: "PostToolUse", gemini: "AfterTool" },
19
- toolFailed: { codex: "PostToolUseFailure", claude: "PostToolUseFailure", gemini: "Notification" },
20
- sessionEnd: { codex: "SessionEnd", claude: "SessionEnd", gemini: "SessionEnd" },
21
- };
22
- function hookCommand(command, source, event) {
23
- return `${command} pace capture --source ${source} --event ${event}`;
24
- }
25
- function jsonHook(command, source, event, name) {
26
- return [{
27
- matcher: "*",
28
- hooks: [{
29
- name: `ai-pace-${name}`,
30
- type: "command",
31
- command: hookCommand(command, source, event),
32
- }],
33
- }];
34
- }
35
- export function renderCodexRequirements(options) {
36
- const lines = [
37
- "# Generated by `unfairly pace config`. Deploy with MDM; do not add secrets.",
38
- "allow_managed_hooks_only = true",
39
- "",
40
- "[features]",
41
- "hooks = true",
42
- "",
43
- "[hooks]",
44
- `managed_dir = ${JSON.stringify(options.managedDir)}`,
45
- `windows_managed_dir = ${JSON.stringify(options.managedDir)}`,
46
- "",
47
- ];
48
- for (const [name, event] of Object.entries(EVENTS)) {
49
- lines.push(`[[hooks.${event.codex}]]`, 'matcher = ".*"', "", `[[hooks.${event.codex}.hooks]]`, 'type = "command"', `command = ${JSON.stringify(hookCommand(options.command, "codex", event.codex))}`, "timeout = 10", `statusMessage = ${JSON.stringify(`Recording ${name} evidence`)}`, "");
50
- }
51
- return `${lines.join("\n").trim()}\n`;
52
- }
53
- export function renderClaudeSettings(command) {
54
- return {
55
- hooks: Object.fromEntries(Object.entries(EVENTS).map(([name, event]) => [
56
- event.claude,
57
- jsonHook(command, "claude_code", event.claude, name),
58
- ])),
59
- };
60
- }
61
- export function renderGeminiSettings(command) {
62
- return {
63
- hooksConfig: { enabled: true, notifications: false },
64
- hooks: Object.fromEntries(Object.entries(EVENTS).map(([name, event]) => [
65
- event.gemini,
66
- jsonHook(command, "gemini_cli", event.gemini, name),
67
- ])),
68
- };
69
- }
70
- export function renderCursorSettings(command) {
71
- const events = {
72
- sessionStart: "sessionStart",
73
- postToolUse: "postToolUse",
74
- postToolUseFailure: "postToolUseFailure",
75
- sessionEnd: "sessionEnd",
76
- };
77
- return {
78
- version: 1,
79
- hooks: Object.fromEntries(Object.entries(events).map(([name, event]) => [
80
- event,
81
- [{
82
- command: hookCommand(command, "cursor", event),
83
- timeout: 10,
84
- ...(name.includes("Tool") ? { matcher: ".*" } : {}),
85
- }],
86
- ])),
87
- };
88
- }
89
- export async function writeManagedConfigs(input) {
90
- await fs.mkdir(input.outputDir, { recursive: true });
91
- const files = {
92
- "codex-requirements.toml": renderCodexRequirements(input),
93
- "claude-settings.json": `${JSON.stringify(renderClaudeSettings(input.command), null, 2)}\n`,
94
- "cursor-hooks.json": `${JSON.stringify(renderCursorSettings(input.command), null, 2)}\n`,
95
- "gemini-settings.json": `${JSON.stringify(renderGeminiSettings(input.command), null, 2)}\n`,
96
- "evidence-policy.json": `${JSON.stringify(renderEvidencePolicy(input), null, 2)}\n`,
97
- "repository-policy.json": `${JSON.stringify({ version: 1, mappings: [] }, null, 2)}\n`,
98
- };
99
- await Promise.all(Object.entries(files).map(([name, contents]) => fs.writeFile(path.join(input.outputDir, name), contents, { encoding: "utf8", mode: 0o644 })));
100
- return Object.keys(files).map((name) => path.join(input.outputDir, name));
101
- }
102
- //# sourceMappingURL=managed-config.js.map
1
+ import r from"node:fs/promises";import a from"node:path";function d(e){return{version:1,include_file_names:e.includeFileNames??!1,scan_interval_seconds:60,max_files_per_root:5e3,roots:(e.evidenceRoots??[]).map((n,o)=>({path:n,label:`approved-output-${o+1}`,kind:"output"}))}}const t={sessionStart:{codex:"SessionStart",claude:"SessionStart",gemini:"SessionStart"},toolCompleted:{codex:"PostToolUse",claude:"PostToolUse",gemini:"AfterTool"},toolFailed:{codex:"PostToolUseFailure",claude:"PostToolUseFailure",gemini:"Notification"},sessionEnd:{codex:"SessionEnd",claude:"SessionEnd",gemini:"SessionEnd"}};function i(e,n,o){return`${e} pace capture --source ${n} --event ${o}`}function c(e,n,o,s){return[{matcher:"*",hooks:[{name:`ai-pace-${s}`,type:"command",command:i(e,n,o)}]}]}function m(e){const n=["# Generated by `unfairly pace config`. Deploy with MDM; do not add secrets.","allow_managed_hooks_only = true","","[features]","hooks = true","","[hooks]",`managed_dir = ${JSON.stringify(e.managedDir)}`,`windows_managed_dir = ${JSON.stringify(e.managedDir)}`,""];for(const[o,s]of Object.entries(t))n.push(`[[hooks.${s.codex}]]`,'matcher = ".*"',"",`[[hooks.${s.codex}.hooks]]`,'type = "command"',`command = ${JSON.stringify(i(e.command,"codex",s.codex))}`,"timeout = 10",`statusMessage = ${JSON.stringify(`Recording ${o} evidence`)}`,"");return`${n.join(`
2
+ `).trim()}
3
+ `}function l(e){return{hooks:Object.fromEntries(Object.entries(t).map(([n,o])=>[o.claude,c(e,"claude_code",o.claude,n)]))}}function u(e){return{hooksConfig:{enabled:!0,notifications:!1},hooks:Object.fromEntries(Object.entries(t).map(([n,o])=>[o.gemini,c(e,"gemini_cli",o.gemini,n)]))}}function f(e){return{version:1,hooks:Object.fromEntries(Object.entries({sessionStart:"sessionStart",postToolUse:"postToolUse",postToolUseFailure:"postToolUseFailure",sessionEnd:"sessionEnd"}).map(([o,s])=>[s,[{command:i(e,"cursor",s),timeout:10,...o.includes("Tool")?{matcher:".*"}:{}}]]))}}async function S(e){await r.mkdir(e.outputDir,{recursive:!0});const n={"codex-requirements.toml":m(e),"claude-settings.json":`${JSON.stringify(l(e.command),null,2)}
4
+ `,"cursor-hooks.json":`${JSON.stringify(f(e.command),null,2)}
5
+ `,"gemini-settings.json":`${JSON.stringify(u(e.command),null,2)}
6
+ `,"evidence-policy.json":`${JSON.stringify(d(e),null,2)}
7
+ `,"repository-policy.json":`${JSON.stringify({version:1,mappings:[]},null,2)}
8
+ `};return await Promise.all(Object.entries(n).map(([o,s])=>r.writeFile(a.join(e.outputDir,o),s,{encoding:"utf8",mode:420}))),Object.keys(n).map(o=>a.join(e.outputDir,o))}export{l as renderClaudeSettings,m as renderCodexRequirements,f as renderCursorSettings,d as renderEvidencePolicy,u as renderGeminiSettings,S as writeManagedConfigs};
@@ -7,4 +7,3 @@ export declare function normalizeHookEvent(input: {
7
7
  now?: Date;
8
8
  }): PaceEvent;
9
9
  export declare function migrateLegacyEvent(event: PaceLegacyEvent): PaceEvent;
10
- //# sourceMappingURL=normalize.d.ts.map
@@ -1,293 +1 @@
1
- import { randomUUID } from "node:crypto";
2
- import { PaceEventSchema, PaceSourceSchema, } from "./schema.js";
3
- import { deterministicWorkflowId } from "./identity.js";
4
- import { resolveApprovedRepository } from "./repository.js";
5
- const EVENT_TYPES = {
6
- SessionStart: "session.started",
7
- SessionEnd: "session.ended",
8
- BeforeAgent: "session.started",
9
- AfterAgent: "session.ended",
10
- Stop: "workflow.stopped",
11
- PostToolUse: "tool.completed",
12
- AfterTool: "tool.completed",
13
- PostToolUseFailure: "tool.failed",
14
- AfterModel: "model.completed",
15
- sessionStart: "session.started",
16
- sessionEnd: "session.ended",
17
- postToolUse: "tool.completed",
18
- postToolUseFailure: "tool.failed",
19
- stop: "workflow.stopped",
20
- };
21
- const CLIENT_EVENTS = {
22
- SessionStart: "session_start",
23
- SessionEnd: "session_end",
24
- BeforeAgent: "before_agent",
25
- AfterAgent: "after_agent",
26
- Stop: "stop",
27
- PostToolUse: "tool_success",
28
- AfterTool: "tool_success",
29
- PostToolUseFailure: "tool_failure",
30
- AfterModel: "model_complete",
31
- sessionStart: "session_start",
32
- sessionEnd: "session_end",
33
- postToolUse: "tool_success",
34
- postToolUseFailure: "tool_failure",
35
- stop: "stop",
36
- };
37
- function shortString(value) {
38
- if (typeof value !== "string")
39
- return undefined;
40
- const trimmed = value.trim();
41
- return trimmed ? trimmed.slice(0, 512) : undefined;
42
- }
43
- function firstString(payload, keys) {
44
- for (const key of keys) {
45
- const value = shortString(payload[key]);
46
- if (value)
47
- return value;
48
- }
49
- return undefined;
50
- }
51
- function opaqueId(value) {
52
- const candidate = shortString(value);
53
- return candidate && /^[A-Za-z0-9_-]{1,128}$/.test(candidate) ? candidate : undefined;
54
- }
55
- function number(payload, keys) {
56
- for (const key of keys) {
57
- const value = payload[key];
58
- if (typeof value === "number" && Number.isFinite(value) && value >= 0)
59
- return value;
60
- }
61
- return undefined;
62
- }
63
- function boolean(payload, keys) {
64
- for (const key of keys)
65
- if (typeof payload[key] === "boolean")
66
- return payload[key];
67
- return undefined;
68
- }
69
- function modelFamily(value) {
70
- const model = value?.toLowerCase();
71
- if (!model)
72
- return undefined;
73
- if (/gpt|o[1-9]|codex/.test(model))
74
- return "openai_gpt";
75
- if (/claude/.test(model))
76
- return "anthropic_claude";
77
- if (/gemini|gemma/.test(model))
78
- return "google_gemini";
79
- if (/llama/.test(model))
80
- return "meta_llama";
81
- if (/mistral|mixtral|codestral/.test(model))
82
- return "mistral";
83
- return "other";
84
- }
85
- function toolCategory(value) {
86
- const tool = value?.toLowerCase();
87
- if (!tool)
88
- return undefined;
89
- if (/skill/.test(tool))
90
- return "skill";
91
- if (/read|view|open_file/.test(tool))
92
- return "file_read";
93
- if (/write|edit|patch|notebook/.test(tool))
94
- return "file_write";
95
- if (/grep|glob|search|find/.test(tool))
96
- return "code_search";
97
- if (/git|github|pull_request|commit/.test(tool))
98
- return "version_control";
99
- if (/bash|shell|terminal|exec|command/.test(tool))
100
- return "shell";
101
- if (/web|browser|fetch|http/.test(tool))
102
- return "web";
103
- if (/mcp|connector|slack|notion|drive|linear/.test(tool))
104
- return "connector";
105
- if (/agent|task|delegate/.test(tool))
106
- return "agent";
107
- return "other";
108
- }
109
- function blockerCategory(input) {
110
- const failed = ["PostToolUseFailure", "postToolUseFailure", "Stop", "stop"].includes(input.hookEvent) || input.payload.success === false;
111
- if (!failed)
112
- return undefined;
113
- const signal = [
114
- firstString(input.payload, ["error_type", "errorType"]),
115
- firstString(input.payload, ["stop_reason", "stopReason"]),
116
- firstString(input.payload, ["status"]),
117
- ].filter(Boolean).join(" ").toLowerCase();
118
- if (/authenticat|login|credential|token expired/.test(signal))
119
- return "authentication";
120
- if (/authoriz|permission|forbidden|denied|access/.test(signal))
121
- return "authorization_permission";
122
- if (/approval|confirm|consent/.test(signal))
123
- return "approval_required";
124
- if (/missing|not found|dependency|executable|command not found/.test(signal))
125
- return "missing_dependency_tool";
126
- if (/config|setting|environment|invalid option/.test(signal))
127
- return "configuration";
128
- if (/rate.?limit|quota|too many requests/.test(signal))
129
- return "rate_limit_quota";
130
- if (/provider|model unavailable|overloaded|capacity/.test(signal))
131
- return "model_provider_unavailable";
132
- if (input.hookEvent === "Stop" || input.hookEvent === "stop")
133
- return "workflow_stopped";
134
- if (input.hookEvent === "PostToolUseFailure" || input.hookEvent === "postToolUseFailure")
135
- return signal ? "tool_failure" : "unknown";
136
- return "unknown";
137
- }
138
- function approvalMode(value) {
139
- const mode = value?.toLowerCase();
140
- if (!mode)
141
- return undefined;
142
- if (/none|never|disabled/.test(mode))
143
- return "none";
144
- if (/manual|ask|confirm|prompt/.test(mode))
145
- return "manual";
146
- if (/auto|always|pre.?approved/.test(mode))
147
- return "automatic";
148
- return "unknown";
149
- }
150
- function permissionMode(value) {
151
- const mode = value?.toLowerCase();
152
- if (!mode)
153
- return undefined;
154
- if (/read.?only|readonly/.test(mode))
155
- return "read_only";
156
- if (/workspace|project.?write|write/.test(mode))
157
- return "workspace_write";
158
- if (/elevated|escalat|admin|sudo/.test(mode))
159
- return "elevated";
160
- if (/unrestricted|danger|full.?access/.test(mode))
161
- return "unrestricted";
162
- return "unknown";
163
- }
164
- function durationBucket(durationMs) {
165
- if (durationMs === undefined)
166
- return undefined;
167
- if (durationMs < 1_000)
168
- return "under_1s";
169
- if (durationMs < 10_000)
170
- return "1s_to_10s";
171
- if (durationMs < 60_000)
172
- return "10s_to_60s";
173
- if (durationMs < 300_000)
174
- return "1m_to_5m";
175
- return "over_5m";
176
- }
177
- function exitCodeBucket(exitCode) {
178
- if (exitCode === undefined)
179
- return undefined;
180
- if (exitCode === 0)
181
- return "success";
182
- if (exitCode >= 128)
183
- return "signal";
184
- return "failure";
185
- }
186
- export function normalizeHookEvent(input) {
187
- const source = PaceSourceSchema.catch("unknown").parse(input.source);
188
- const payload = input.payload && typeof input.payload === "object" && !Array.isArray(input.payload)
189
- ? input.payload
190
- : {};
191
- const sessionId = opaqueId(firstString(payload, ["session_id", "sessionId", "conversation_id"]));
192
- const suppliedWorkflowId = firstString(payload, ["workflow_id", "workflowId"]);
193
- const workflowId = suppliedWorkflowId && /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(suppliedWorkflowId)
194
- ? suppliedWorkflowId
195
- : input.installationId && sessionId
196
- ? deterministicWorkflowId({ installationId: input.installationId, source, sessionId })
197
- : undefined;
198
- const exitCode = number(payload, ["exit_code", "exitCode"]);
199
- const durationMs = number(payload, ["duration_ms", "durationMs"]);
200
- const repository = resolveApprovedRepository(firstString(payload, ["cwd", "workspace_path", "workspacePath"]));
201
- return PaceEventSchema.parse({
202
- schema_version: 3,
203
- collection_policy_version: "metadata-v3",
204
- event_id: randomUUID(),
205
- installation_id: input.installationId,
206
- workflow_id: workflowId,
207
- initiative_id: opaqueId(firstString(payload, ["initiative_id", "initiativeId"])),
208
- playbook_id: opaqueId(firstString(payload, ["playbook_id", "playbookId"])),
209
- playbook_version: opaqueId(firstString(payload, ["playbook_version", "playbookVersion"])),
210
- occurred_at: (input.now ?? new Date()).toISOString(),
211
- source,
212
- event_type: EVENT_TYPES[input.hookEvent] ?? "unknown.observed",
213
- evidence_level: "exact",
214
- session_id: sessionId,
215
- repository_id: repository?.repository_id,
216
- commit_sha: repository?.commit_sha,
217
- model_family: modelFamily(firstString(payload, ["model", "model_name", "modelName"])),
218
- tool_category: toolCategory(firstString(payload, ["tool_name", "toolName", "tool"])),
219
- blocker_category: blockerCategory({ hookEvent: input.hookEvent, payload }),
220
- attributes: {
221
- client_event: CLIENT_EVENTS[input.hookEvent] ?? "unknown",
222
- approval_mode: approvalMode(firstString(payload, ["approval_mode", "approvalMode"])),
223
- permission_mode: permissionMode(firstString(payload, ["permission_mode", "permissionMode"])),
224
- success: boolean(payload, ["success"]),
225
- exit_code_bucket: exitCodeBucket(exitCode),
226
- duration_bucket: durationBucket(durationMs),
227
- input_tokens: number(payload, ["input_tokens", "inputTokens"]),
228
- output_tokens: number(payload, ["output_tokens", "outputTokens"]),
229
- cached_tokens: number(payload, ["cached_tokens", "cachedTokens"]),
230
- },
231
- });
232
- }
233
- export function migrateLegacyEvent(event) {
234
- const attributes = event.attributes;
235
- const hookEvent = attributes.hook_event;
236
- const migrated = PaceEventSchema.parse({
237
- schema_version: 3,
238
- collection_policy_version: "metadata-v3",
239
- event_id: event.event_id,
240
- installation_id: event.installation_id,
241
- occurred_at: event.occurred_at,
242
- source: event.source,
243
- event_type: event.event_type,
244
- evidence_level: event.evidence_level,
245
- session_id: opaqueId(event.session_id),
246
- workflow_id: event.schema_version === 2 ? event.workflow_id : undefined,
247
- initiative_id: event.schema_version === 2 ? opaqueId(event.initiative_id) : undefined,
248
- playbook_id: event.schema_version === 2 ? opaqueId(event.playbook_id) : undefined,
249
- playbook_version: event.schema_version === 2 ? opaqueId(event.playbook_version) : undefined,
250
- model_family: modelFamily(event.model),
251
- tool_category: toolCategory(event.tool ?? event.skill),
252
- blocker_category: blockerCategory({
253
- hookEvent,
254
- payload: {
255
- success: attributes.success,
256
- error_type: attributes.error_type,
257
- stop_reason: attributes.stop_reason,
258
- status: attributes.status,
259
- },
260
- }),
261
- artifact_type: event.artifact_type,
262
- attributes: {
263
- client_event: event.source === "local_filesystem"
264
- ? "local_output"
265
- : event.event_type === "desktop.activity"
266
- ? "local_activity"
267
- : CLIENT_EVENTS[hookEvent] ?? "unknown",
268
- approval_mode: approvalMode(attributes.approval_mode),
269
- permission_mode: permissionMode(attributes.permission_mode),
270
- success: attributes.success,
271
- exit_code_bucket: exitCodeBucket(attributes.exit_code),
272
- duration_bucket: durationBucket(attributes.duration_ms),
273
- input_tokens: attributes.input_tokens,
274
- output_tokens: attributes.output_tokens,
275
- cached_tokens: attributes.cached_tokens,
276
- files_changed_bucket: filesChangedBucket(attributes.files_changed),
277
- local_signal: attributes.local_signal,
278
- },
279
- });
280
- return migrated;
281
- }
282
- function filesChangedBucket(value) {
283
- if (value === undefined)
284
- return undefined;
285
- if (value <= 1)
286
- return "one";
287
- if (value <= 5)
288
- return "two_to_five";
289
- if (value <= 20)
290
- return "six_to_twenty";
291
- return "over_twenty";
292
- }
293
- //# sourceMappingURL=normalize.js.map
1
+ import{randomUUID as b}from"node:crypto";import{PaceEventSchema as l,PaceSourceSchema as E}from"./schema.js";import{deterministicWorkflowId as T}from"./identity.js";import{resolveApprovedRepository as S}from"./repository.js";const I={SessionStart:"session.started",SessionEnd:"session.ended",BeforeAgent:"session.started",AfterAgent:"session.ended",Stop:"workflow.stopped",PostToolUse:"tool.completed",AfterTool:"tool.completed",PostToolUseFailure:"tool.failed",AfterModel:"model.completed",sessionStart:"session.started",sessionEnd:"session.ended",postToolUse:"tool.completed",postToolUseFailure:"tool.failed",stop:"workflow.stopped"},c={SessionStart:"session_start",SessionEnd:"session_end",BeforeAgent:"before_agent",AfterAgent:"after_agent",Stop:"stop",PostToolUse:"tool_success",AfterTool:"tool_success",PostToolUseFailure:"tool_failure",AfterModel:"model_complete",sessionStart:"session_start",sessionEnd:"session_end",postToolUse:"tool_success",postToolUseFailure:"tool_failure",stop:"stop"};function u(e){if(typeof e!="string")return;const o=e.trim();return o?o.slice(0,512):void 0}function n(e,o){for(const t of o){const r=u(e[t]);if(r)return r}}function s(e){const o=u(e);return o&&/^[A-Za-z0-9_-]{1,128}$/.test(o)?o:void 0}function i(e,o){for(const t of o){const r=e[t];if(typeof r=="number"&&Number.isFinite(r)&&r>=0)return r}}function x(e,o){for(const t of o)if(typeof e[t]=="boolean")return e[t]}function _(e){const o=e?.toLowerCase();if(o)return/gpt|o[1-9]|codex/.test(o)?"openai_gpt":/claude/.test(o)?"anthropic_claude":/gemini|gemma/.test(o)?"google_gemini":/llama/.test(o)?"meta_llama":/mistral|mixtral|codestral/.test(o)?"mistral":"other"}function f(e){const o=e?.toLowerCase();if(o)return/skill/.test(o)?"skill":/read|view|open_file/.test(o)?"file_read":/write|edit|patch|notebook/.test(o)?"file_write":/grep|glob|search|find/.test(o)?"code_search":/git|github|pull_request|commit/.test(o)?"version_control":/bash|shell|terminal|exec|command/.test(o)?"shell":/web|browser|fetch|http/.test(o)?"web":/mcp|connector|slack|notion|drive|linear/.test(o)?"connector":/agent|task|delegate/.test(o)?"agent":"other"}function p(e){if(!(["PostToolUseFailure","postToolUseFailure","Stop","stop"].includes(e.hookEvent)||e.payload.success===!1))return;const t=[n(e.payload,["error_type","errorType"]),n(e.payload,["stop_reason","stopReason"]),n(e.payload,["status"])].filter(Boolean).join(" ").toLowerCase();return/authenticat|login|credential|token expired/.test(t)?"authentication":/authoriz|permission|forbidden|denied|access/.test(t)?"authorization_permission":/approval|confirm|consent/.test(t)?"approval_required":/missing|not found|dependency|executable|command not found/.test(t)?"missing_dependency_tool":/config|setting|environment|invalid option/.test(t)?"configuration":/rate.?limit|quota|too many requests/.test(t)?"rate_limit_quota":/provider|model unavailable|overloaded|capacity/.test(t)?"model_provider_unavailable":e.hookEvent==="Stop"||e.hookEvent==="stop"?"workflow_stopped":(e.hookEvent==="PostToolUseFailure"||e.hookEvent==="postToolUseFailure")&&t?"tool_failure":"unknown"}function m(e){const o=e?.toLowerCase();if(o)return/none|never|disabled/.test(o)?"none":/manual|ask|confirm|prompt/.test(o)?"manual":/auto|always|pre.?approved/.test(o)?"automatic":"unknown"}function k(e){const o=e?.toLowerCase();if(o)return/read.?only|readonly/.test(o)?"read_only":/workspace|project.?write|write/.test(o)?"workspace_write":/elevated|escalat|admin|sudo/.test(o)?"elevated":/unrestricted|danger|full.?access/.test(o)?"unrestricted":"unknown"}function y(e){if(e!==void 0)return e<1e3?"under_1s":e<1e4?"1s_to_10s":e<6e4?"10s_to_60s":e<3e5?"1m_to_5m":"over_5m"}function v(e){if(e!==void 0)return e===0?"success":e>=128?"signal":"failure"}function L(e){const o=E.catch("unknown").parse(e.source),t=e.payload&&typeof e.payload=="object"&&!Array.isArray(e.payload)?e.payload:{},r=s(n(t,["session_id","sessionId","conversation_id"])),a=n(t,["workflow_id","workflowId"]),w=a&&/^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(a)?a:e.installationId&&r?T({installationId:e.installationId,source:o,sessionId:r}):void 0,h=i(t,["exit_code","exitCode"]),g=i(t,["duration_ms","durationMs"]),d=S(n(t,["cwd","workspace_path","workspacePath"]));return l.parse({schema_version:3,collection_policy_version:"metadata-v3",event_id:b(),installation_id:e.installationId,workflow_id:w,initiative_id:s(n(t,["initiative_id","initiativeId"])),playbook_id:s(n(t,["playbook_id","playbookId"])),playbook_version:s(n(t,["playbook_version","playbookVersion"])),occurred_at:(e.now??new Date).toISOString(),source:o,event_type:I[e.hookEvent]??"unknown.observed",evidence_level:"exact",session_id:r,repository_id:d?.repository_id,commit_sha:d?.commit_sha,model_family:_(n(t,["model","model_name","modelName"])),tool_category:f(n(t,["tool_name","toolName","tool"])),blocker_category:p({hookEvent:e.hookEvent,payload:t}),attributes:{client_event:c[e.hookEvent]??"unknown",approval_mode:m(n(t,["approval_mode","approvalMode"])),permission_mode:k(n(t,["permission_mode","permissionMode"])),success:x(t,["success"]),exit_code_bucket:v(h),duration_bucket:y(g),input_tokens:i(t,["input_tokens","inputTokens"]),output_tokens:i(t,["output_tokens","outputTokens"]),cached_tokens:i(t,["cached_tokens","cachedTokens"])}})}function q(e){const o=e.attributes,t=o.hook_event;return l.parse({schema_version:3,collection_policy_version:"metadata-v3",event_id:e.event_id,installation_id:e.installation_id,occurred_at:e.occurred_at,source:e.source,event_type:e.event_type,evidence_level:e.evidence_level,session_id:s(e.session_id),workflow_id:e.schema_version===2?e.workflow_id:void 0,initiative_id:e.schema_version===2?s(e.initiative_id):void 0,playbook_id:e.schema_version===2?s(e.playbook_id):void 0,playbook_version:e.schema_version===2?s(e.playbook_version):void 0,model_family:_(e.model),tool_category:f(e.tool??e.skill),blocker_category:p({hookEvent:t,payload:{success:o.success,error_type:o.error_type,stop_reason:o.stop_reason,status:o.status}}),artifact_type:e.artifact_type,attributes:{client_event:e.source==="local_filesystem"?"local_output":e.event_type==="desktop.activity"?"local_activity":c[t]??"unknown",approval_mode:m(o.approval_mode),permission_mode:k(o.permission_mode),success:o.success,exit_code_bucket:v(o.exit_code),duration_bucket:y(o.duration_ms),input_tokens:o.input_tokens,output_tokens:o.output_tokens,cached_tokens:o.cached_tokens,files_changed_bucket:A(o.files_changed),local_signal:o.local_signal}})}function A(e){if(e!==void 0)return e<=1?"one":e<=5?"two_to_five":e<=20?"six_to_twenty":"over_twenty"}export{q as migrateLegacyEvent,L as normalizeHookEvent};
@@ -69,4 +69,3 @@ export declare function resolveApprovedRepository(cwd: string | undefined): {
69
69
  commit_sha: string;
70
70
  } | undefined;
71
71
  export {};
72
- //# sourceMappingURL=repository.d.ts.map
@@ -1,120 +1,2 @@
1
- import { createHash } from "node:crypto";
2
- import { execFileSync } from "node:child_process";
3
- import fs from "node:fs";
4
- import os from "node:os";
5
- import path from "node:path";
6
- import { z } from "zod";
7
- const policySchema = z.object({
8
- version: z.literal(1),
9
- mappings: z.array(z.object({
10
- remote_fingerprint: z.string().regex(/^[a-f0-9]{64}$/),
11
- repository_id: z.string().uuid(),
12
- }).strict()).max(500),
13
- /** Skills and playbooks the organization has published. Only these, plus published plugin skills, are reported by name. */
14
- skills: z.array(z.string().regex(/^[a-z0-9][a-z0-9:_.-]{0,119}$/)).max(2000).optional(),
15
- }).strict();
16
- export function repositoryPolicyPath() {
17
- return process.env.UNFAIRLY_PACE_REPOSITORY_POLICY ?? path.join(os.homedir(), ".unfairly", "pace", "repository-policy.json");
18
- }
19
- /**
20
- * `git@github.com:Org/Repo.git`, `https://github.com/org/repo` and
21
- * `ssh://git@github.com/Org/Repo.git` all canonicalize to `github.com/org/repo`.
22
- * The server fingerprints GitHub repositories the same way (src/lib/ai-pace/github.ts).
23
- */
24
- export function canonicalRemote(remote) {
25
- const match = /^(?:[a-z+]+:\/\/)?(?:[^@/\s]+@)?([^/:\s]+)(?::\d+)?[:/](.+?)(?:\.git)?\/?$/i.exec(remote.trim());
26
- return match ? `${match[1].toLowerCase()}/${match[2].toLowerCase()}` : null;
27
- }
28
- export function repositoryRemoteFingerprint(remote) {
29
- return createHash("sha256").update(canonicalRemote(remote) ?? remote.trim().toLowerCase()).digest("hex");
30
- }
31
- function git(cwd, args) {
32
- try {
33
- return execFileSync("git", ["-C", cwd, ...args], {
34
- encoding: "utf8",
35
- stdio: ["ignore", "pipe", "ignore"],
36
- timeout: 750,
37
- }).trim() || undefined;
38
- }
39
- catch {
40
- return undefined;
41
- }
42
- }
43
- export function parseRepositoryPolicy(value) {
44
- return policySchema.parse(value);
45
- }
46
- export function readRepositoryPolicy() {
47
- return readPolicy();
48
- }
49
- function readPolicy() {
50
- try {
51
- return policySchema.parse(JSON.parse(fs.readFileSync(repositoryPolicyPath(), "utf8")));
52
- }
53
- catch {
54
- return undefined;
55
- }
56
- }
57
- /**
58
- * The checkout to inspect for a session: its working directory, or, when that
59
- * worktree has since been removed, the nearest surviving ancestor directory.
60
- */
61
- export function surviving(cwd) {
62
- let current = cwd ? path.resolve(cwd) : undefined;
63
- while (current && !fs.existsSync(current)) {
64
- const parent = path.dirname(current);
65
- if (parent === current)
66
- return undefined;
67
- current = parent;
68
- }
69
- return current && git(current, ["rev-parse", "--is-inside-work-tree"]) === "true" ? current : undefined;
70
- }
71
- /** The approved repository a working directory belongs to, or undefined when it is not approved. */
72
- export function approvedRepositoryId(cwd, policy = readPolicy()) {
73
- const checkout = surviving(cwd);
74
- if (!checkout || !policy?.mappings.length)
75
- return undefined;
76
- const remote = git(checkout, ["config", "--get", "remote.origin.url"]);
77
- if (!remote)
78
- return undefined;
79
- return policy.mappings.find((candidate) => candidate.remote_fingerprint === repositoryRemoteFingerprint(remote))?.repository_id;
80
- }
81
- /**
82
- * Commits the session's author made during the session window on the session's
83
- * line of history: its branch when that ref still exists (local or origin),
84
- * otherwise the surviving checkout's HEAD. Only full SHAs leave the machine;
85
- * the branch name is used locally and never uploaded.
86
- */
87
- export function sessionCommitShas(cwd, window) {
88
- const checkout = surviving(cwd);
89
- if (!checkout)
90
- return [];
91
- const author = git(checkout, ["config", "--get", "user.email"]);
92
- if (!author)
93
- return [];
94
- const worktreeAlive = path.resolve(cwd) === checkout;
95
- let ref = worktreeAlive ? "HEAD" : undefined;
96
- if (window.branch && /^[\w./-]{1,200}$/.test(window.branch) && !window.branch.startsWith("-")) {
97
- for (const candidate of [`refs/heads/${window.branch}`, `refs/remotes/origin/${window.branch}`]) {
98
- if (git(checkout, ["rev-parse", "--verify", "--quiet", candidate])) {
99
- ref = candidate;
100
- break;
101
- }
102
- }
103
- }
104
- if (!ref)
105
- return [];
106
- const until = new Date(Date.parse(window.endedAt) + 5 * 60_000).toISOString();
107
- const output = git(checkout, ["log", ref, "--fixed-strings", `--author=${author}`, `--since=${window.startedAt}`, `--until=${until}`, "--format=%H", "-n", "50"]);
108
- return (output ?? "").split("\n").filter((sha) => /^[a-f0-9]{40}$/i.test(sha));
109
- }
110
- export function resolveApprovedRepository(cwd) {
111
- const repositoryId = approvedRepositoryId(cwd);
112
- if (!cwd || !repositoryId)
113
- return undefined;
114
- const mapping = { repository_id: repositoryId };
115
- const commit = git(cwd, ["rev-parse", "HEAD"]);
116
- if (!commit || !/^[a-f0-9]{40}$/i.test(commit))
117
- return undefined;
118
- return { repository_id: mapping.repository_id, commit_sha: commit };
119
- }
120
- //# sourceMappingURL=repository.js.map
1
+ import{createHash as g}from"node:crypto";import{execFileSync as y}from"node:child_process";import p from"node:fs";import h from"node:os";import a from"node:path";import{z as n}from"zod";const f=n.object({version:n.literal(1),mappings:n.array(n.object({remote_fingerprint:n.string().regex(/^[a-f0-9]{64}$/),repository_id:n.string().uuid()}).strict()).max(500),skills:n.array(n.string().regex(/^[a-z0-9][a-z0-9:_.-]{0,119}$/)).max(2e3).optional()}).strict();function x(){return process.env.UNFAIRLY_PACE_REPOSITORY_POLICY??a.join(h.homedir(),".unfairly","pace","repository-policy.json")}function v(r){const e=/^(?:[a-z+]+:\/\/)?(?:[^@/\s]+@)?([^/:\s]+)(?::\d+)?[:/](.+?)(?:\.git)?\/?$/i.exec(r.trim());return e?`${e[1].toLowerCase()}/${e[2].toLowerCase()}`:null}function _(r){return g("sha256").update(v(r)??r.trim().toLowerCase()).digest("hex")}function o(r,e){try{return y("git",["-C",r,...e],{encoding:"utf8",stdio:["ignore","pipe","ignore"],timeout:750}).trim()||void 0}catch{return}}function I(r){return f.parse(r)}function L(){return d()}function d(){try{return f.parse(JSON.parse(p.readFileSync(x(),"utf8")))}catch{return}}function m(r){let e=r?a.resolve(r):void 0;for(;e&&!p.existsSync(e);){const t=a.dirname(e);if(t===e)return;e=t}return e&&o(e,["rev-parse","--is-inside-work-tree"])==="true"?e:void 0}function $(r,e=d()){const t=m(r);if(!t||!e?.mappings.length)return;const i=o(t,["config","--get","remote.origin.url"]);if(i)return e.mappings.find(c=>c.remote_fingerprint===_(i))?.repository_id}function O(r,e){const t=m(r);if(!t)return[];const i=o(t,["config","--get","user.email"]);if(!i)return[];let u=a.resolve(r)===t?"HEAD":void 0;if(e.branch&&/^[\w./-]{1,200}$/.test(e.branch)&&!e.branch.startsWith("-")){for(const s of[`refs/heads/${e.branch}`,`refs/remotes/origin/${e.branch}`])if(o(t,["rev-parse","--verify","--quiet",s])){u=s;break}}if(!u)return[];const l=new Date(Date.parse(e.endedAt)+5*6e4).toISOString();return(o(t,["log",u,"--fixed-strings",`--author=${i}`,`--since=${e.startedAt}`,`--until=${l}`,"--format=%H","-n","50"])??"").split(`
2
+ `).filter(s=>/^[a-f0-9]{40}$/i.test(s))}function j(r){const e=$(r);if(!r||!e)return;const t={repository_id:e},i=o(r,["rev-parse","HEAD"]);if(!(!i||!/^[a-f0-9]{40}$/i.test(i)))return{repository_id:t.repository_id,commit_sha:i}}export{$ as approvedRepositoryId,v as canonicalRemote,I as parseRepositoryPolicy,L as readRepositoryPolicy,x as repositoryPolicyPath,_ as repositoryRemoteFingerprint,j as resolveApprovedRepository,O as sessionCommitShas,m as surviving};
@@ -1322,4 +1322,3 @@ export declare const PaceBatchSchema: z.ZodObject<{
1322
1322
  }[];
1323
1323
  }>;
1324
1324
  export type PaceBatch = z.infer<typeof PaceBatchSchema>;
1325
- //# sourceMappingURL=schema.d.ts.map