unfairly 0.8.1 → 0.8.2

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 (80) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/README.md +15 -2
  3. package/dist/auth/browser-flow.d.ts +9 -0
  4. package/dist/auth/browser-flow.d.ts.map +1 -1
  5. package/dist/auth/browser-flow.js +11 -4
  6. package/dist/auth/browser-flow.js.map +1 -1
  7. package/dist/cmd/invite.js +2 -2
  8. package/dist/cmd/invite.js.map +1 -1
  9. package/dist/cmd/pace.d.ts +80 -0
  10. package/dist/cmd/pace.d.ts.map +1 -0
  11. package/dist/cmd/pace.js +393 -0
  12. package/dist/cmd/pace.js.map +1 -0
  13. package/dist/cmd/setup.d.ts +2 -0
  14. package/dist/cmd/setup.d.ts.map +1 -1
  15. package/dist/cmd/setup.js +20 -6
  16. package/dist/cmd/setup.js.map +1 -1
  17. package/dist/index.js +96 -2
  18. package/dist/index.js.map +1 -1
  19. package/dist/lib/types/index.d.ts +6 -6
  20. package/dist/pace/device.d.ts +101 -0
  21. package/dist/pace/device.d.ts.map +1 -0
  22. package/dist/pace/device.js +148 -0
  23. package/dist/pace/device.js.map +1 -0
  24. package/dist/pace/identity.d.ts +10 -0
  25. package/dist/pace/identity.d.ts.map +1 -0
  26. package/dist/pace/identity.js +17 -0
  27. package/dist/pace/identity.js.map +1 -0
  28. package/dist/pace/install.d.ts +28 -0
  29. package/dist/pace/install.d.ts.map +1 -0
  30. package/dist/pace/install.js +127 -0
  31. package/dist/pace/install.js.map +1 -0
  32. package/dist/pace/local-evidence.d.ts +75 -0
  33. package/dist/pace/local-evidence.d.ts.map +1 -0
  34. package/dist/pace/local-evidence.js +228 -0
  35. package/dist/pace/local-evidence.js.map +1 -0
  36. package/dist/pace/local-sessions.d.ts +48 -0
  37. package/dist/pace/local-sessions.d.ts.map +1 -0
  38. package/dist/pace/local-sessions.js +254 -0
  39. package/dist/pace/local-sessions.js.map +1 -0
  40. package/dist/pace/managed-config.d.ts +21 -0
  41. package/dist/pace/managed-config.d.ts.map +1 -0
  42. package/dist/pace/managed-config.js +102 -0
  43. package/dist/pace/managed-config.js.map +1 -0
  44. package/dist/pace/normalize.d.ts +10 -0
  45. package/dist/pace/normalize.d.ts.map +1 -0
  46. package/dist/pace/normalize.js +293 -0
  47. package/dist/pace/normalize.js.map +1 -0
  48. package/dist/pace/repository.d.ts +72 -0
  49. package/dist/pace/repository.d.ts.map +1 -0
  50. package/dist/pace/repository.js +120 -0
  51. package/dist/pace/repository.js.map +1 -0
  52. package/dist/pace/schema.d.ts +1325 -0
  53. package/dist/pace/schema.d.ts.map +1 -0
  54. package/dist/pace/schema.js +134 -0
  55. package/dist/pace/schema.js.map +1 -0
  56. package/dist/pace/session-summary.d.ts +179 -0
  57. package/dist/pace/session-summary.d.ts.map +1 -0
  58. package/dist/pace/session-summary.js +140 -0
  59. package/dist/pace/session-summary.js.map +1 -0
  60. package/dist/pace/spool.d.ts +6 -0
  61. package/dist/pace/spool.d.ts.map +1 -0
  62. package/dist/pace/spool.js +87 -0
  63. package/dist/pace/spool.js.map +1 -0
  64. package/package.json +3 -1
  65. package/plugin/.claude-plugin/plugin.json +9 -0
  66. package/plugin/.codex-plugin/plugin.json +21 -0
  67. package/plugin/.cursor-plugin/plugin.json +16 -0
  68. package/plugin/.mcp.json +8 -0
  69. package/plugin/README.md +19 -0
  70. package/plugin/deploy/README.md +30 -0
  71. package/plugin/gemini/GEMINI.md +3 -0
  72. package/plugin/gemini/gemini-extension.json +12 -0
  73. package/plugin/gemini/hooks/hooks.json +52 -0
  74. package/plugin/hooks/cursor-hooks.json +25 -0
  75. package/plugin/hooks/hooks.json +56 -0
  76. package/plugin/mcp.json +10 -0
  77. package/plugin/plugin.json +32 -0
  78. package/plugin/scripts/capture.cjs +46 -0
  79. package/plugin/skills/find-company-playbook/SKILL.md +12 -0
  80. package/plugin/skills/publish-learning/SKILL.md +8 -0
@@ -0,0 +1,293 @@
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
@@ -0,0 +1 @@
1
+ {"version":3,"file":"normalize.js","sourceRoot":"","sources":["../../src/pace/normalize.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,72 @@
1
+ import { z } from "zod";
2
+ declare const policySchema: z.ZodObject<{
3
+ version: z.ZodLiteral<1>;
4
+ mappings: z.ZodArray<z.ZodObject<{
5
+ remote_fingerprint: z.ZodString;
6
+ repository_id: z.ZodString;
7
+ }, "strict", z.ZodTypeAny, {
8
+ repository_id: string;
9
+ remote_fingerprint: string;
10
+ }, {
11
+ repository_id: string;
12
+ remote_fingerprint: string;
13
+ }>, "many">;
14
+ /** Skills and playbooks the organization has published. Only these, plus published plugin skills, are reported by name. */
15
+ skills: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
16
+ }, "strict", z.ZodTypeAny, {
17
+ version: 1;
18
+ mappings: {
19
+ repository_id: string;
20
+ remote_fingerprint: string;
21
+ }[];
22
+ skills?: string[] | undefined;
23
+ }, {
24
+ version: 1;
25
+ mappings: {
26
+ repository_id: string;
27
+ remote_fingerprint: string;
28
+ }[];
29
+ skills?: string[] | undefined;
30
+ }>;
31
+ export declare function repositoryPolicyPath(): string;
32
+ /**
33
+ * `git@github.com:Org/Repo.git`, `https://github.com/org/repo` and
34
+ * `ssh://git@github.com/Org/Repo.git` all canonicalize to `github.com/org/repo`.
35
+ * The server fingerprints GitHub repositories the same way (src/lib/ai-pace/github.ts).
36
+ */
37
+ export declare function canonicalRemote(remote: string): string | null;
38
+ export declare function repositoryRemoteFingerprint(remote: string): string;
39
+ export type RepositoryPolicy = z.infer<typeof policySchema>;
40
+ export declare function parseRepositoryPolicy(value: unknown): RepositoryPolicy;
41
+ export declare function readRepositoryPolicy(): RepositoryPolicy | undefined;
42
+ /**
43
+ * The checkout to inspect for a session: its working directory, or, when that
44
+ * worktree has since been removed, the nearest surviving ancestor directory.
45
+ */
46
+ export declare function surviving(cwd: string | null | undefined): string | undefined;
47
+ /** The approved repository a working directory belongs to, or undefined when it is not approved. */
48
+ export declare function approvedRepositoryId(cwd: string | null | undefined, policy?: {
49
+ version: 1;
50
+ mappings: {
51
+ repository_id: string;
52
+ remote_fingerprint: string;
53
+ }[];
54
+ skills?: string[] | undefined;
55
+ } | undefined): string | undefined;
56
+ /**
57
+ * Commits the session's author made during the session window on the session's
58
+ * line of history: its branch when that ref still exists (local or origin),
59
+ * otherwise the surviving checkout's HEAD. Only full SHAs leave the machine;
60
+ * the branch name is used locally and never uploaded.
61
+ */
62
+ export declare function sessionCommitShas(cwd: string, window: {
63
+ startedAt: string;
64
+ endedAt: string;
65
+ branch?: string | null;
66
+ }): string[];
67
+ export declare function resolveApprovedRepository(cwd: string | undefined): {
68
+ repository_id: string;
69
+ commit_sha: string;
70
+ } | undefined;
71
+ export {};
72
+ //# sourceMappingURL=repository.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repository.d.ts","sourceRoot":"","sources":["../../src/pace/repository.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,QAAA,MAAM,YAAY;;;;;;;;;;;;IAMhB,2HAA2H;;;;;;;;;;;;;;;;EAElH,CAAC;AAEZ,wBAAgB,oBAAoB,IAAI,MAAM,CAE7C;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAG7D;AAED,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAElE;AAcD,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;AAE5D,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,gBAAgB,CAEtE;AAED,wBAAgB,oBAAoB,IAAI,gBAAgB,GAAG,SAAS,CAEnE;AAUD;;;GAGG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAQ5E;AAED,oGAAoG;AACpG,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAAE,MAAM;;;;;;;aAAe,GAAG,MAAM,GAAG,SAAS,CAM9G;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GAAG,MAAM,EAAE,CAgB/H;AAED,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG;IAAE,aAAa,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAO5H"}
@@ -0,0 +1,120 @@
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
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repository.js","sourceRoot":"","sources":["../../src/pace/repository.ts"],"names":[],"mappings":"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"}