@crewbie/cli 0.1.0-alpha.49

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 (165) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +253 -0
  3. package/dist/cli.d.ts +2 -0
  4. package/dist/cli.js +506 -0
  5. package/dist/cli.js.map +1 -0
  6. package/dist/config.d.ts +84 -0
  7. package/dist/config.js +178 -0
  8. package/dist/config.js.map +1 -0
  9. package/dist/core.d.ts +31 -0
  10. package/dist/core.js +186 -0
  11. package/dist/core.js.map +1 -0
  12. package/dist/execution/attribution.d.ts +10 -0
  13. package/dist/execution/attribution.js +102 -0
  14. package/dist/execution/attribution.js.map +1 -0
  15. package/dist/execution/cancel.d.ts +3 -0
  16. package/dist/execution/cancel.js +59 -0
  17. package/dist/execution/cancel.js.map +1 -0
  18. package/dist/execution/capabilities.d.ts +22 -0
  19. package/dist/execution/capabilities.js +101 -0
  20. package/dist/execution/capabilities.js.map +1 -0
  21. package/dist/execution/controls.d.ts +51 -0
  22. package/dist/execution/controls.js +257 -0
  23. package/dist/execution/controls.js.map +1 -0
  24. package/dist/execution/dispatch.d.ts +69 -0
  25. package/dist/execution/dispatch.js +831 -0
  26. package/dist/execution/dispatch.js.map +1 -0
  27. package/dist/execution/fix.d.ts +3 -0
  28. package/dist/execution/fix.js +267 -0
  29. package/dist/execution/fix.js.map +1 -0
  30. package/dist/execution/github.d.ts +15 -0
  31. package/dist/execution/github.js +43 -0
  32. package/dist/execution/github.js.map +1 -0
  33. package/dist/execution/merge.d.ts +15 -0
  34. package/dist/execution/merge.js +133 -0
  35. package/dist/execution/merge.js.map +1 -0
  36. package/dist/execution/planning-approval.d.ts +33 -0
  37. package/dist/execution/planning-approval.js +227 -0
  38. package/dist/execution/planning-approval.js.map +1 -0
  39. package/dist/execution/pr-review.d.ts +86 -0
  40. package/dist/execution/pr-review.js +339 -0
  41. package/dist/execution/pr-review.js.map +1 -0
  42. package/dist/execution/review-loop.d.ts +63 -0
  43. package/dist/execution/review-loop.js +463 -0
  44. package/dist/execution/review-loop.js.map +1 -0
  45. package/dist/execution/test-feature.d.ts +29 -0
  46. package/dist/execution/test-feature.js +240 -0
  47. package/dist/execution/test-feature.js.map +1 -0
  48. package/dist/execution/watch.d.ts +12 -0
  49. package/dist/execution/watch.js +34 -0
  50. package/dist/execution/watch.js.map +1 -0
  51. package/dist/memory/context.d.ts +14 -0
  52. package/dist/memory/context.js +82 -0
  53. package/dist/memory/context.js.map +1 -0
  54. package/dist/memory/improvement.d.ts +25 -0
  55. package/dist/memory/improvement.js +168 -0
  56. package/dist/memory/improvement.js.map +1 -0
  57. package/dist/memory/launch.d.ts +9 -0
  58. package/dist/memory/launch.js +65 -0
  59. package/dist/memory/launch.js.map +1 -0
  60. package/dist/memory/runner.d.ts +4 -0
  61. package/dist/memory/runner.js +74 -0
  62. package/dist/memory/runner.js.map +1 -0
  63. package/dist/memory/state.d.ts +10 -0
  64. package/dist/memory/state.js +42 -0
  65. package/dist/memory/state.js.map +1 -0
  66. package/dist/presentation.d.ts +19 -0
  67. package/dist/presentation.js +128 -0
  68. package/dist/presentation.js.map +1 -0
  69. package/dist/reporting/dashboard.d.ts +2 -0
  70. package/dist/reporting/dashboard.js +106 -0
  71. package/dist/reporting/dashboard.js.map +1 -0
  72. package/dist/reporting/pr-usage.d.ts +24 -0
  73. package/dist/reporting/pr-usage.js +179 -0
  74. package/dist/reporting/pr-usage.js.map +1 -0
  75. package/dist/reporting/records.d.ts +28 -0
  76. package/dist/reporting/records.js +152 -0
  77. package/dist/reporting/records.js.map +1 -0
  78. package/dist/setup/agents.d.ts +8 -0
  79. package/dist/setup/agents.js +83 -0
  80. package/dist/setup/agents.js.map +1 -0
  81. package/dist/setup/assessment.d.ts +31 -0
  82. package/dist/setup/assessment.js +75 -0
  83. package/dist/setup/assessment.js.map +1 -0
  84. package/dist/setup/auto-loaded.d.ts +17 -0
  85. package/dist/setup/auto-loaded.js +49 -0
  86. package/dist/setup/auto-loaded.js.map +1 -0
  87. package/dist/setup/copilot-version.d.ts +7 -0
  88. package/dist/setup/copilot-version.js +39 -0
  89. package/dist/setup/copilot-version.js.map +1 -0
  90. package/dist/setup/copilot.d.ts +22 -0
  91. package/dist/setup/copilot.js +164 -0
  92. package/dist/setup/copilot.js.map +1 -0
  93. package/dist/setup/init.d.ts +41 -0
  94. package/dist/setup/init.js +315 -0
  95. package/dist/setup/init.js.map +1 -0
  96. package/dist/setup/install.d.ts +12 -0
  97. package/dist/setup/install.js +211 -0
  98. package/dist/setup/install.js.map +1 -0
  99. package/dist/setup/instruction-quality.d.ts +25 -0
  100. package/dist/setup/instruction-quality.js +258 -0
  101. package/dist/setup/instruction-quality.js.map +1 -0
  102. package/dist/setup/inventory.d.ts +26 -0
  103. package/dist/setup/inventory.js +78 -0
  104. package/dist/setup/inventory.js.map +1 -0
  105. package/dist/setup/onboarding.d.ts +40 -0
  106. package/dist/setup/onboarding.js +472 -0
  107. package/dist/setup/onboarding.js.map +1 -0
  108. package/dist/setup/package.d.ts +2 -0
  109. package/dist/setup/package.js +8 -0
  110. package/dist/setup/package.js.map +1 -0
  111. package/dist/setup/planning-workflow.d.ts +3 -0
  112. package/dist/setup/planning-workflow.js +250 -0
  113. package/dist/setup/planning-workflow.js.map +1 -0
  114. package/dist/setup/repository-map.d.ts +34 -0
  115. package/dist/setup/repository-map.js +89 -0
  116. package/dist/setup/repository-map.js.map +1 -0
  117. package/dist/setup/review.d.ts +8 -0
  118. package/dist/setup/review.js +137 -0
  119. package/dist/setup/review.js.map +1 -0
  120. package/dist/setup/team.d.ts +18 -0
  121. package/dist/setup/team.js +172 -0
  122. package/dist/setup/team.js.map +1 -0
  123. package/dist/setup/templates.d.ts +11 -0
  124. package/dist/setup/templates.js +494 -0
  125. package/dist/setup/templates.js.map +1 -0
  126. package/dist/setup/terminal.d.ts +12 -0
  127. package/dist/setup/terminal.js +11 -0
  128. package/dist/setup/terminal.js.map +1 -0
  129. package/dist/setup/update.d.ts +6 -0
  130. package/dist/setup/update.js +71 -0
  131. package/dist/setup/update.js.map +1 -0
  132. package/dist/specification/batch.d.ts +50 -0
  133. package/dist/specification/batch.js +127 -0
  134. package/dist/specification/batch.js.map +1 -0
  135. package/dist/specification/plan-checks.d.ts +6 -0
  136. package/dist/specification/plan-checks.js +73 -0
  137. package/dist/specification/plan-checks.js.map +1 -0
  138. package/dist/specification/planning.d.ts +26 -0
  139. package/dist/specification/planning.js +507 -0
  140. package/dist/specification/planning.js.map +1 -0
  141. package/dist/specification/prose.d.ts +1 -0
  142. package/dist/specification/prose.js +15 -0
  143. package/dist/specification/prose.js.map +1 -0
  144. package/dist/tracking/ado.d.ts +19 -0
  145. package/dist/tracking/ado.js +128 -0
  146. package/dist/tracking/ado.js.map +1 -0
  147. package/dist/tracking/github.d.ts +8 -0
  148. package/dist/tracking/github.js +112 -0
  149. package/dist/tracking/github.js.map +1 -0
  150. package/dist/tracking/issues.d.ts +28 -0
  151. package/dist/tracking/issues.js +180 -0
  152. package/dist/tracking/issues.js.map +1 -0
  153. package/dist/tracking/native.d.ts +5 -0
  154. package/dist/tracking/native.js +30 -0
  155. package/dist/tracking/native.js.map +1 -0
  156. package/dist/tracking/refs.d.ts +14 -0
  157. package/dist/tracking/refs.js +56 -0
  158. package/dist/tracking/refs.js.map +1 -0
  159. package/dist/tracking/sources.d.ts +5 -0
  160. package/dist/tracking/sources.js +29 -0
  161. package/dist/tracking/sources.js.map +1 -0
  162. package/docs/operations.md +1114 -0
  163. package/examples/batch.json +27 -0
  164. package/examples/runs.json +22 -0
  165. package/package.json +50 -0
@@ -0,0 +1,179 @@
1
+ import { execFileSync } from "node:child_process";
2
+ import { GitHubError, integer, record, string } from "../core.js";
3
+ import { cloudTasks } from "../tracking/native.js";
4
+ export class UsageUnavailable extends Error {
5
+ }
6
+ export function parseUsageLog(log) {
7
+ const sessions = new Set([...log.matchAll(/\bCOPILOT_AGENT_SESSION_ID:\s*([a-f0-9-]{36})\b/g)].map((match) => match[1]));
8
+ if (sessions.size !== 1)
9
+ return null;
10
+ const turns = new Map();
11
+ for (const match of log.matchAll(/\[cca-engine\] turn=(\d+) assistant\.usage: model=\S+ input=(\d+) output=(\d+)(?=\s|$)/g)) {
12
+ const value = { input: integer(Number(match[2]), "input tokens", 0, Number.MAX_SAFE_INTEGER), output: integer(Number(match[3]), "output tokens", 0, Number.MAX_SAFE_INTEGER) };
13
+ const prior = turns.get(match[1]);
14
+ if (prior && (prior.input !== value.input || prior.output !== value.output))
15
+ return null;
16
+ turns.set(match[1], value);
17
+ }
18
+ if (!turns.size)
19
+ return null;
20
+ if ([...turns.keys()].some((turn) => Number(turn) < 1 || Number(turn) > turns.size))
21
+ return null;
22
+ const total = [...turns.values()].reduce((sum, turn) => ({ input: sum.input + turn.input, output: sum.output + turn.output }), { input: 0, output: 0 });
23
+ if (!Number.isSafeInteger(total.input) || !Number.isSafeInteger(total.output))
24
+ throw new Error("Token totals exceed safe integer limits.");
25
+ return { sessionId: [...sessions][0], inputTokens: total.input, outputTokens: total.output };
26
+ }
27
+ function actionsLog(repository, runId) {
28
+ try {
29
+ return execFileSync("gh", ["run", "view", String(runId), "--repo", repository, "--log"], {
30
+ encoding: "utf8", stdio: ["ignore", "pipe", "pipe"], timeout: 60_000, maxBuffer: 8_000_000, windowsHide: true,
31
+ });
32
+ }
33
+ catch {
34
+ throw new UsageUnavailable("Actions logs could not be read within the time/size limit; check gh access and log retention.");
35
+ }
36
+ }
37
+ export async function collectPrUsage(client, repository, pr, readLog = actionsLog) {
38
+ const result = { sessions: 0, measuredSessions: 0, inputTokens: null, outputTokens: null, credits: null, sources: [], warnings: [], actionsMinutes: null, actionsRuns: 0 };
39
+ const head = string(record(pr.head, "PR head").ref, "PR branch");
40
+ try {
41
+ await actionsTime(client, repository, head, result);
42
+ }
43
+ catch (error) {
44
+ if (!(error instanceof GitHubError && [403, 404, 410].includes(error.status)))
45
+ throw error;
46
+ result.warnings.push(`Actions run time is unavailable (HTTP ${error.status}).`);
47
+ }
48
+ try {
49
+ const native = await cloudTasks(client, repository);
50
+ if (native.warning) {
51
+ result.warnings.push(native.warning);
52
+ return result;
53
+ }
54
+ const sessions = new Set();
55
+ for (const task of native.tasks) {
56
+ if (!Array.isArray(task.artifacts) || !task.artifacts.some((raw) => {
57
+ const artifact = record(raw, "task artifact");
58
+ return artifact.provider === "github" && artifact.type === "pull" && record(artifact.data, "pull artifact").id === pr.id;
59
+ }))
60
+ continue;
61
+ const id = string(task.id, "task ID");
62
+ if (!/^[a-zA-Z0-9-]+$/.test(id))
63
+ throw new Error("Invalid native task ID.");
64
+ const detail = record(await client.request("GET", `/agents/repos/${repository}/tasks/${id}`), "native task");
65
+ if (!Array.isArray(detail.sessions)) {
66
+ result.warnings.push("Native session detail is unavailable.");
67
+ continue;
68
+ }
69
+ if (detail.session_count !== detail.sessions.length)
70
+ result.warnings.push("Native session coverage is incomplete.");
71
+ for (const raw of detail.sessions) {
72
+ const session = record(raw, "native session");
73
+ const sessionId = string(session.id, "session ID");
74
+ if (sessions.has(sessionId))
75
+ throw new Error("Duplicate native session would double-count usage.");
76
+ sessions.add(sessionId);
77
+ }
78
+ }
79
+ result.sessions = sessions.size;
80
+ if (!sessions.size) {
81
+ result.warnings.push("No attributable native sessions found.");
82
+ return result;
83
+ }
84
+ const measured = new Set(), runs = new Set();
85
+ for (let page = 1; page <= 100; page++) {
86
+ const response = record(await client.request("GET", `/repos/${repository}/actions/runs?event=dynamic&branch=${encodeURIComponent(head)}&per_page=100&page=${page}`), "Actions runs");
87
+ if (!Array.isArray(response.workflow_runs))
88
+ throw new Error("Actions returned invalid run coverage.");
89
+ for (const raw of response.workflow_runs) {
90
+ const run = record(raw, "Actions run");
91
+ // Copilot session runs carry no pull_requests link; the branch query attributes them and the log's session ID verifies it.
92
+ const pulls = Array.isArray(run.pull_requests) ? run.pull_requests : [];
93
+ if (pulls.length ? !pulls.some((pull) => record(pull, "run pull request").id === pr.id) : run.head_branch !== head)
94
+ continue;
95
+ const id = integer(run.id, "Actions run");
96
+ if (runs.has(id))
97
+ throw new Error("Actions pagination repeated a run.");
98
+ runs.add(id);
99
+ if (run.status !== "completed")
100
+ continue;
101
+ let usage;
102
+ try {
103
+ usage = parseUsageLog(readLog(repository, id));
104
+ }
105
+ catch (error) {
106
+ if (!(error instanceof UsageUnavailable))
107
+ throw error;
108
+ result.warnings.push(error.message);
109
+ continue;
110
+ }
111
+ if (!usage || !sessions.has(usage.sessionId)) {
112
+ result.warnings.push(`Run ${id} has no verifiable session-token record.`);
113
+ continue;
114
+ }
115
+ if (measured.has(usage.sessionId)) {
116
+ result.warnings.push("Multiple runs reference one session; repeated session usage was excluded.");
117
+ continue;
118
+ }
119
+ measured.add(usage.sessionId);
120
+ result.measuredSessions = measured.size;
121
+ result.inputTokens = (result.inputTokens ?? 0) + usage.inputTokens;
122
+ result.outputTokens = (result.outputTokens ?? 0) + usage.outputTokens;
123
+ if (!Number.isSafeInteger(result.inputTokens + result.outputTokens))
124
+ throw new Error("PR token totals exceed safe integer limits.");
125
+ result.sources.push(`https://github.com/${repository}/actions/runs/${id}`);
126
+ }
127
+ if (response.workflow_runs.length < 100)
128
+ break;
129
+ if (page === 100)
130
+ result.warnings.push("Actions run coverage exceeded the pagination bound.");
131
+ }
132
+ if (measured.size !== sessions.size)
133
+ result.warnings.push("Some native sessions have missing, unsupported or pending logs.");
134
+ result.warnings.push("AI-credit amount scaling is undocumented in the task API; credits are not inferred from tokens or legacy multipliers.");
135
+ return result;
136
+ }
137
+ catch (error) {
138
+ if (error instanceof GitHubError && [403, 404, 410].includes(error.status)) {
139
+ result.warnings.push(`Usage coverage is unavailable (HTTP ${error.status}).`);
140
+ return result;
141
+ }
142
+ throw error;
143
+ }
144
+ }
145
+ const RUN_PAGES = 10;
146
+ async function actionsTime(client, repository, head, result) {
147
+ let milliseconds = 0;
148
+ const seen = new Set();
149
+ for (let page = 1; page <= RUN_PAGES; page++) {
150
+ const response = record(await client.request("GET", `/repos/${repository}/actions/runs?branch=${encodeURIComponent(head)}&status=completed&per_page=100&page=${page}`), "Actions runs");
151
+ if (!Array.isArray(response.workflow_runs))
152
+ throw new Error("Actions returned invalid run coverage.");
153
+ for (const raw of response.workflow_runs) {
154
+ const run = record(raw, "Actions run");
155
+ const id = integer(run.id, "Actions run");
156
+ if (seen.has(id) || run.head_branch !== head || run.status !== "completed")
157
+ continue;
158
+ const started = Date.parse(String(run.run_started_at ?? run.created_at)), ended = Date.parse(String(run.updated_at));
159
+ if (!Number.isFinite(started) || !Number.isFinite(ended) || ended < started) {
160
+ result.warnings.push(`Run ${id} has no usable timing.`);
161
+ continue;
162
+ }
163
+ seen.add(id);
164
+ milliseconds += ended - started;
165
+ }
166
+ if (response.workflow_runs.length < 100)
167
+ break;
168
+ if (page === RUN_PAGES)
169
+ result.warnings.push("Actions run time exceeded the pagination bound; minutes are a lower bound.");
170
+ }
171
+ result.actionsRuns = seen.size;
172
+ result.actionsMinutes = Math.round(milliseconds / 6_000) / 10;
173
+ }
174
+ export function renderPrUsage(usage) {
175
+ const tokens = usage.inputTokens === null || usage.outputTokens === null ? "unavailable"
176
+ : `${usage.inputTokens + usage.outputTokens} (${usage.inputTokens} input + ${usage.outputTokens} output)`;
177
+ return `**Observed tokens:** ${tokens}; ${usage.sessions ? `${usage.measuredSessions}/${usage.sessions} known sessions` : "session coverage unavailable"}. **AI credits:** unavailable (API scaling unverified). **Actions time:** ${usage.actionsMinutes === null ? "unavailable" : `${usage.actionsMinutes} min wall-clock across ${usage.actionsRuns} runs (not billed minutes)`}. Main-session log counts, not an invoice or unique-context count; unreported subagent/tool usage is excluded.${usage.sources.length ? ` [Evidence](${usage.sources[0]})` : ""}${usage.warnings.some((warning) => !warning.startsWith("AI-credit")) ? " Coverage incomplete; inspect session logs." : ""}`;
178
+ }
179
+ //# sourceMappingURL=pr-usage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pr-usage.js","sourceRoot":"","sources":["../../src/reporting/pr-usage.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ import type { Config } from "../config.js";
2
+ import { type GitHubApi } from "../tracking/github.js";
3
+ export interface RunRecord {
4
+ schemaVersion: 1;
5
+ kind: "work-item" | "session" | "improvement-review";
6
+ sessionId: string | null;
7
+ contextStatus: "unreported" | "attested";
8
+ id: string;
9
+ specialist: string;
10
+ requestedModel: string;
11
+ observedModel: string | null;
12
+ observedModelSource: string | null;
13
+ date: string;
14
+ status: string;
15
+ issue: string;
16
+ pullRequest: string | null;
17
+ inputTokens: number | null;
18
+ outputTokens: number | null;
19
+ credits: number | null;
20
+ currencyAmount: number | null;
21
+ currency: string | null;
22
+ usageSource: string | null;
23
+ summary: string;
24
+ }
25
+ export declare function runRecord(value: unknown): RunRecord;
26
+ export declare function collectRecords(client: GitHubApi, config: Config): Promise<RunRecord[]>;
27
+ export declare function evidenceId(run: RunRecord): string;
28
+ export declare function parseRecords(value: unknown): RunRecord[];
@@ -0,0 +1,152 @@
1
+ import { hash, integer, record, string } from "../core.js";
2
+ import { isWriter } from "../tracking/github.js";
3
+ import { managedIssues } from "../tracking/issues.js";
4
+ import { taskMetadata } from "../specification/batch.js";
5
+ import { linkedPull } from "../execution/dispatch.js";
6
+ function metric(value, name) {
7
+ if (value === null || value === undefined)
8
+ return null;
9
+ if (typeof value !== "number" || !Number.isFinite(value) || value < 0)
10
+ throw new Error(`${name} must be non-negative or null.`);
11
+ return value;
12
+ }
13
+ function nullable(value, name) {
14
+ return value === null || value === undefined ? null : string(value, name);
15
+ }
16
+ export function runRecord(value) {
17
+ const data = record(value, "run");
18
+ if (data.schemaVersion !== undefined && data.schemaVersion !== 1)
19
+ throw new Error("Unsupported run-record version.");
20
+ if (data.kind !== undefined && !["session", "work-item", "improvement-review"].includes(String(data.kind)))
21
+ throw new Error("Invalid record kind.");
22
+ if (data.contextStatus !== undefined && !["unreported", "attested"].includes(String(data.contextStatus)))
23
+ throw new Error("Memory-read evidence must be unreported or explicitly attested.");
24
+ const result = {
25
+ schemaVersion: 1,
26
+ kind: data.kind === "session" ? "session" : data.kind === "improvement-review" ? "improvement-review" : "work-item",
27
+ sessionId: nullable(data.sessionId, "session ID"),
28
+ contextStatus: data.contextStatus === "attested" ? "attested" : "unreported",
29
+ id: string(data.id, "run ID"), specialist: string(data.specialist, "specialist"),
30
+ requestedModel: string(data.requestedModel, "requested model"),
31
+ observedModel: nullable(data.observedModel, "observed model"),
32
+ observedModelSource: nullable(data.observedModelSource, "observed-model evidence"),
33
+ date: string(data.date, "date"), status: string(data.status, "status"),
34
+ issue: string(data.issue, "issue"), pullRequest: nullable(data.pullRequest, "PR"),
35
+ inputTokens: metric(data.inputTokens, "input tokens"), outputTokens: metric(data.outputTokens, "output tokens"),
36
+ credits: metric(data.credits, "credits"), currencyAmount: metric(data.currencyAmount, "currency amount"),
37
+ currency: nullable(data.currency, "currency"), usageSource: nullable(data.usageSource, "usage evidence"),
38
+ summary: string(data.summary, "summary", true),
39
+ };
40
+ if (!Number.isFinite(Date.parse(result.date)))
41
+ throw new Error("Invalid run date.");
42
+ result.date = new Date(result.date).toISOString();
43
+ if (result.kind === "session" && !result.sessionId)
44
+ throw new Error("A session record needs a real session identifier.");
45
+ for (const count of [result.inputTokens, result.outputTokens])
46
+ if (count !== null && !Number.isSafeInteger(count))
47
+ throw new Error("Token counts must be whole safe integers.");
48
+ if (result.observedModel !== null && !result.observedModelSource)
49
+ throw new Error("Observed model requires runtime evidence, not an agent's assertion.");
50
+ if ([result.inputTokens, result.outputTokens, result.credits, result.currencyAmount].some((value) => value !== null) && !result.usageSource)
51
+ throw new Error("Reported usage needs an evidence source.");
52
+ if (result.currencyAmount !== null && !result.currency)
53
+ throw new Error("Currency amount requires its currency.");
54
+ if (result.summary.length > 4000)
55
+ throw new Error("Run summaries must remain compact.");
56
+ return result;
57
+ }
58
+ export async function collectRecords(client, config) {
59
+ const records = [];
60
+ for (const issue of await managedIssues(client, config.repository)) {
61
+ const metadata = taskMetadata(String(issue.body ?? ""));
62
+ if (!metadata)
63
+ continue;
64
+ const number = integer(issue.number, "issue number");
65
+ const pr = await linkedPull(client, config.repository, number, metadata.branch);
66
+ let date = string(pr?.updated_at ?? issue.updated_at, "updated timestamp");
67
+ const evidence = [];
68
+ if (pr) {
69
+ const comments = await client.list(`/repos/${config.repository}/issues/${integer(pr.number, "PR number")}/comments`);
70
+ for (const comment of comments) {
71
+ const user = comment.user === null || comment.user === undefined ? null : record(comment.user, "comment author");
72
+ const trusted = await isWriter(client, config.repository, user) || (user?.type === "Bot" && ["Copilot", "copilot-swe-agent[bot]"].includes(String(user.login)));
73
+ const body = typeof comment.body === "string" ? comment.body : "";
74
+ if (!trusted || !body.trimStart().startsWith("<!-- crewbie-memory-proposal -->"))
75
+ continue;
76
+ if (typeof comment.updated_at === "string" && comment.updated_at > date)
77
+ date = comment.updated_at;
78
+ const link = `https://github.com/${config.repository}/pull/${pr.number}#issuecomment-${comment.id}`;
79
+ evidence.push(`Deferred memory proposal (${link}): ${body.length <= 1000 ? body : "Body omitted because it exceeds the summary budget; consult the comment."}`);
80
+ }
81
+ const reviews = await client.list(`/repos/${config.repository}/pulls/${integer(pr.number, "PR number")}/reviews`);
82
+ for (const review of reviews) {
83
+ if (review.state === "DISMISSED")
84
+ continue;
85
+ if (typeof review.submitted_at === "string" && review.submitted_at > date)
86
+ date = review.submitted_at;
87
+ const body = typeof review.body === "string" ? review.body : "";
88
+ evidence.push(`Review ${review.id}: ${review.state}. ${body.length <= 1000 ? body : "Body omitted because it exceeds the summary budget; consult the review."}`);
89
+ }
90
+ const head = record(pr.head, "PR head");
91
+ const checks = record(await client.request("GET", `/repos/${config.repository}/commits/${encodeURIComponent(string(head.sha, "head revision"))}/check-runs?per_page=100`), "check runs");
92
+ if (!Array.isArray(checks.check_runs))
93
+ throw new Error("GitHub returned invalid CI results.");
94
+ for (const raw of checks.check_runs) {
95
+ const check = record(raw, "check run");
96
+ if (typeof check.completed_at === "string" && check.completed_at > date)
97
+ date = check.completed_at;
98
+ evidence.push(`CI ${String(check.name)}: ${String(check.conclusion ?? check.status)}.`);
99
+ }
100
+ if (typeof checks.total_count === "number" && checks.total_count > checks.check_runs.length)
101
+ evidence.push("Additional CI results are not included; consult the PR.");
102
+ }
103
+ const primary = String(pr?.body ?? issue.title ?? "");
104
+ let summary = [primary.length <= 2500 ? primary : "PR body omitted because it exceeds the summary budget; consult the PR.", ...evidence].join("\n");
105
+ if (summary.length > 4000)
106
+ summary = "Detailed feedback exceeds the compact record budget. Review the linked issue/PR, reviews and CI before proposing changes.";
107
+ records.push(runRecord({
108
+ id: `${config.repository}#${number}`, specialist: metadata.task.owner, requestedModel: metadata.task.model,
109
+ date,
110
+ status: pr?.merged_at ? "merged" : pr?.state === "closed" ? "failed" : pr ? "review" : issue.state === "closed" ? "closed-unmerged" : "pending",
111
+ issue: `https://github.com/${config.repository}/issues/${number}`,
112
+ pullRequest: pr ? `https://github.com/${config.repository}/pull/${integer(pr.number, "PR number")}` : null,
113
+ observedModel: null, observedModelSource: null, inputTokens: null, outputTokens: null,
114
+ credits: null, currencyAmount: null, currency: null, usageSource: null,
115
+ summary,
116
+ }));
117
+ }
118
+ const improvements = await client.list(`/repos/${config.repository}/pulls?state=closed&head=${config.repository.split("/")[0]}:crewbie/improvements`);
119
+ for (const pull of improvements) {
120
+ const number = integer(pull.number, "improvement PR");
121
+ const comments = await client.list(`/repos/${config.repository}/issues/${number}/comments`);
122
+ const trusted = [];
123
+ for (const comment of comments)
124
+ if (await isWriter(client, config.repository, comment.user))
125
+ trusted.push(comment);
126
+ const feedback = trusted.map((comment) => typeof comment.body === "string" ? comment.body : "").filter(Boolean).join("\n");
127
+ records.push(runRecord({
128
+ id: `${config.repository}:improvement#${number}`, kind: "improvement-review", specialist: "improver",
129
+ requestedModel: "Unrecorded", date: string(pull.closed_at, "closed timestamp"),
130
+ status: pull.merged_at ? "proposal-accepted" : "closed-unmerged",
131
+ issue: `https://github.com/${config.repository}/pull/${number}`,
132
+ pullRequest: `https://github.com/${config.repository}/pull/${number}`,
133
+ summary: feedback.length <= 3000 ? `Human review outcome: ${pull.merged_at ? "merged" : "closed without merge; the reason is not inferred"}.\n${feedback}` : "Human feedback exceeds the compact record budget. Consult the linked improvement PR.",
134
+ }));
135
+ }
136
+ return records;
137
+ }
138
+ export function evidenceId(run) {
139
+ return hash(JSON.stringify({ id: run.id, date: run.date, status: run.status, summary: run.summary }));
140
+ }
141
+ export function parseRecords(value) {
142
+ if (!Array.isArray(value))
143
+ throw new Error("Run records must be a list.");
144
+ const records = value.map(runRecord);
145
+ if (new Set(records.map((run) => run.id)).size !== records.length)
146
+ throw new Error("Duplicate run IDs would double-count usage.");
147
+ const sessions = records.flatMap((run) => run.sessionId ? [run.sessionId] : []);
148
+ if (new Set(sessions).size !== sessions.length)
149
+ throw new Error("Duplicate session IDs would double-count usage.");
150
+ return records;
151
+ }
152
+ //# sourceMappingURL=records.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"records.js","sourceRoot":"","sources":["../../src/reporting/records.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import { type Config, type Role } from "../config.js";
2
+ export declare function roleProfile(root: string, role: Role, config: Config): Promise<string>;
3
+ export declare function adoptedProfile(role: Role, config: Config, original: string): string;
4
+ /**
5
+ * Refreshes Crewbie's block inside a charter a human edited and keeps every other line as they wrote it,
6
+ * with the frontmatter name (and model, when both declare one) kept in step. Null when the markers are gone.
7
+ */
8
+ export declare function mergeManagedBlock(current: string, generated: string): string | null;
@@ -0,0 +1,83 @@
1
+ import { parseDocument, isMap, isSeq } from "yaml";
2
+ import { agentArchivePath } from "../config.js";
3
+ import { agentPrompt, optionalText, safePath } from "../core.js";
4
+ import { charterTools, MANAGED_END, profile } from "./templates.js";
5
+ import { removeAutoLoadedPointers } from "./auto-loaded.js";
6
+ export async function roleProfile(root, role, config) {
7
+ const generated = profile(role, config);
8
+ if (!role.sourceAgent)
9
+ return generated;
10
+ const original = await optionalText(await safePath(root, agentArchivePath(role.sourceAgent)))
11
+ ?? await optionalText(await safePath(root, role.sourceAgent));
12
+ if (original === null)
13
+ throw new Error(`Restore the original or archived agent before updating ${role.id}: ${role.sourceAgent}`);
14
+ return adoptedProfile(role, config, original);
15
+ }
16
+ export function adoptedProfile(role, config, original) {
17
+ const generated = profile(role, config);
18
+ const text = original.replace(/^\uFEFF/, "");
19
+ const header = /^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/.exec(text);
20
+ if (!header && text.startsWith("---"))
21
+ throw new Error(`Agent frontmatter is incomplete: ${role.sourceAgent}`);
22
+ const document = parseDocument(header ? header[1] : `name: crewbie-${role.id}\n`, { uniqueKeys: true });
23
+ if (document.errors.length || !isMap(document.contents))
24
+ throw new Error(`Agent frontmatter must be a valid YAML mapping: ${role.sourceAgent}`);
25
+ if (document.has("tools") && !isSeq(document.get("tools")))
26
+ throw new Error(`Preserve tool restrictions by converting ${role.sourceAgent}'s tools to a reviewed YAML list before adoption.`);
27
+ if (!document.has("tools"))
28
+ document.set("tools", charterTools(role));
29
+ document.set("name", `crewbie-${role.id}`);
30
+ if (!document.has("description"))
31
+ document.set("description", role.purpose);
32
+ // Assignment and an inherited frontmatter model must not disagree.
33
+ if (document.has("model"))
34
+ document.set("model", role.model);
35
+ const handoffs = document.get("handoffs");
36
+ if (isSeq(handoffs))
37
+ for (const handoff of handoffs.items) {
38
+ if (!isMap(handoff))
39
+ continue;
40
+ const target = handoff.get("agent");
41
+ const adopted = config.roles.find((candidate) => candidate.sourceAgent
42
+ && candidate.sourceAgent.split("/").at(-1)?.replace(/(?:\.agent)?\.md$/, "") === target);
43
+ if (adopted)
44
+ handoff.set("agent", `crewbie-${adopted.id}`);
45
+ }
46
+ // Pointers to guidance Copilot already attaches only repeat context; the archive keeps the original.
47
+ const body = removeAutoLoadedPointers(header ? text.slice(header[0].length) : text).text;
48
+ const result = `---\n${document.toString()}---\n${body}\n\n${generated.replace(/^---\n[\s\S]*?\n---\n# [^\n]*\n/, "## Crewbie integration\n")}`;
49
+ agentPrompt(result, `Adopted ${role.id} charter`, `Shorten the original ${role.sourceAgent} and rerun init, leaving room for Crewbie integration. No original instructions were truncated or archived.`);
50
+ return result;
51
+ }
52
+ const START = /<!-- crewbie:managed:start[^>]*-->/g;
53
+ function managedBlock(text) {
54
+ const starts = [...text.matchAll(START)];
55
+ const end = text.indexOf(MANAGED_END);
56
+ if (starts.length !== 1 || end < 0 || text.indexOf(MANAGED_END, end + 1) >= 0 || end < starts[0].index)
57
+ return null;
58
+ return [starts[0].index, end + MANAGED_END.length];
59
+ }
60
+ /**
61
+ * Refreshes Crewbie's block inside a charter a human edited and keeps every other line as they wrote it,
62
+ * with the frontmatter name (and model, when both declare one) kept in step. Null when the markers are gone.
63
+ */
64
+ export function mergeManagedBlock(current, generated) {
65
+ const eol = current.includes("\r\n") ? "\r\n" : "\n";
66
+ const text = current.replace(/\r\n/g, "\n");
67
+ const mine = managedBlock(text), fresh = managedBlock(generated);
68
+ if (!mine || !fresh)
69
+ return null;
70
+ let merged = text.slice(0, mine[0]) + generated.slice(fresh[0], fresh[1]) + text.slice(mine[1]);
71
+ const header = /^---\n([\s\S]*?)\n---\n/.exec(merged), source = /^---\n([\s\S]*?)\n---\n/.exec(generated);
72
+ if (header && source) {
73
+ const document = parseDocument(header[1]), wanted = parseDocument(source[1]);
74
+ if (!document.errors.length && isMap(document.contents) && !wanted.errors.length) {
75
+ document.set("name", wanted.get("name"));
76
+ if (document.has("model") && wanted.has("model"))
77
+ document.set("model", wanted.get("model"));
78
+ merged = `---\n${document.toString()}---\n${merged.slice(header[0].length)}`;
79
+ }
80
+ }
81
+ return merged.replace(/\n/g, eol);
82
+ }
83
+ //# sourceMappingURL=agents.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agents.js","sourceRoot":"","sources":["../../src/setup/agents.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ import { type Config, type Role } from "../config.js";
2
+ import { type InstructionQuality } from "./instruction-quality.js";
3
+ import { type TeamAssessment } from "./team.js";
4
+ import { type Inventory } from "./inventory.js";
5
+ import { type RepositoryMap } from "./repository-map.js";
6
+ export interface Assessment {
7
+ schemaVersion: 1;
8
+ findings: {
9
+ area: string;
10
+ status: "ready" | "gap" | "unknown";
11
+ evidence: string[];
12
+ detail: string;
13
+ }[];
14
+ questions: string[];
15
+ config: Config;
16
+ constitutionText: string | null;
17
+ instructions: {
18
+ path: string;
19
+ content: string;
20
+ beforeHash: string | null;
21
+ reason?: string;
22
+ }[];
23
+ instructionQuality: InstructionQuality;
24
+ configBeforeHash: string | null;
25
+ team: TeamAssessment;
26
+ inventory: Inventory;
27
+ installedRoles: Role[];
28
+ /** Names-only working-tree map; absent in proposals saved before it existed. */
29
+ repository?: RepositoryMap;
30
+ }
31
+ export declare function assess(root: string): Promise<Assessment>;
@@ -0,0 +1,75 @@
1
+ import { execFileSync } from "node:child_process";
2
+ import { realpath } from "node:fs/promises";
3
+ import { relative, resolve } from "node:path";
4
+ import { DEFAULT_EXECUTION_LIMITS, parseConfig } from "../config.js";
5
+ import { optionalText, safePath, textHash } from "../core.js";
6
+ import { assessInstructions, instructionFile } from "./instruction-quality.js";
7
+ import { assessTeam } from "./team.js";
8
+ import { inventory } from "./inventory.js";
9
+ import { repositoryMap } from "./repository-map.js";
10
+ const SETUP_STEPS = ".github/workflows/copilot-setup-steps.yml";
11
+ export async function assess(root) {
12
+ const absolute = await realpath(resolve(root));
13
+ const gitRoot = await realpath(execFileSync("git", ["-C", absolute, "rev-parse", "--show-toplevel"], { encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] }).trim());
14
+ if (relative(absolute, gitRoot) !== "")
15
+ throw new Error("Initialize Crewbie at the repository root, not a nested directory.");
16
+ const output = execFileSync("git", ["-C", absolute, "ls-files", "--cached", "--others", "--exclude-standard", "-z"], {
17
+ encoding: "utf8", maxBuffer: 8 * 1024 * 1024, stdio: ["ignore", "pipe", "pipe"],
18
+ });
19
+ const paths = [...new Set(output.split("\0").filter(Boolean))].sort();
20
+ const guidance = paths.filter(instructionFile);
21
+ const ci = paths.filter((path) => path.startsWith(".github/workflows/") && /\.ya?ml$/.test(path));
22
+ const existingConstitution = paths.find((path) => /(^|\/)constitution\.md$/i.test(path)) ?? null;
23
+ const installedText = await optionalText(await safePath(root, ".crewbie/config.json"));
24
+ const installed = installedText === null ? null : parseConfig(JSON.parse(installedText));
25
+ const team = await assessTeam(root, paths, installed?.roles ?? []);
26
+ const roles = [
27
+ ...(installed?.roles ?? []),
28
+ ...team.suggestions.filter(({ role }) => !installed?.roles.some((existing) => existing.id === role.id)).map(({ role }) => role),
29
+ ];
30
+ const findings = [
31
+ { area: "Instructions", status: guidance.length ? "unknown" : "gap", evidence: guidance.slice(0, 12), detail: guidance.length ? "Guidance exists; presence does not establish quality. Review the evidence-linked instruction signals and resolve policy conflicts." : "Propose agent-specific guidance only for useful missing context." },
32
+ { area: "Decisions", status: existingConstitution ? "ready" : "gap", evidence: existingConstitution ? [existingConstitution] : [], detail: "Reuse the existing constitution." },
33
+ { area: "Cloud execution", status: "unknown", evidence: ci.slice(0, 5), detail: "Run doctor with a selected repository and specialist. Account permissions and model support require separate verification." },
34
+ ci.includes(SETUP_STEPS)
35
+ ? { area: "Agent environment", status: "ready", evidence: [SETUP_STEPS], detail: "Cloud agents start with the setup steps in this workflow." }
36
+ : { area: "Agent environment", status: "gap", evidence: [], detail: `Add ${SETUP_STEPS} that installs dependencies (and checks out with fetch-depth: 0 for reviewers). Without it every agent session spends model turns installing them.` },
37
+ ];
38
+ const instructionQuality = await assessInstructions(root, paths);
39
+ const context = await inventory(root, paths);
40
+ findings.push({ area: "MCP servers", status: "unknown", evidence: context.mcp.map((file) => file.path), detail: "Inspect configured capabilities, overlap and missing integrations. Server connectivity and personal/global settings are not verified; credential values are withheld." }, { area: "Custom agents", status: "unknown", evidence: context.files.filter((file) => file.kind === "agents").map((file) => file.path), detail: "Review existing responsibilities and reuse their guidance before proposing new specialists." });
41
+ findings.push({
42
+ area: "Instruction quality", status: instructionQuality.signals.length ? "gap" : "unknown",
43
+ evidence: instructionQuality.signals.length ? [...new Set(instructionQuality.signals.map((signal) => `${signal.path}:${signal.line}`))].slice(0, 12) : instructionQuality.inspected.slice(0, 12),
44
+ detail: instructionQuality.signals.length
45
+ ? `${instructionQuality.signals.length + instructionQuality.signalsOmitted} advisory signals detected; showing ${instructionQuality.signals.length}. See instructionQuality for evidence, recommendations and study limitations. They do not block adoption or authorize rewrites.`
46
+ : "No selected static warning was found. This is not a quality certification; review repository-specific value and the disclosed inspection coverage.",
47
+ });
48
+ return {
49
+ schemaVersion: 1, findings, instructionQuality, team, inventory: context, installedRoles: installed?.roles ?? [], repository: repositoryMap(paths),
50
+ configBeforeHash: installedText === null ? null : textHash(installedText),
51
+ questions: [
52
+ "Which existing constraints are intentional, and which are legacy debt?",
53
+ "Which checks and human approvals are required before merge?",
54
+ "Which areas must agents leave unchanged?",
55
+ "Which instruction-quality warnings reflect stale or redundant guidance, and which are justified policies to preserve?",
56
+ "Which expertise does the project and upcoming feature need? Review the team evidence; add custom specialists or split, specialize and retire existing roles only after reviewing their open work.",
57
+ "Approve explicit models and domain checks for added roles. Existing models, policy and memory are preserved; discovery hints are not a fixed roster.",
58
+ "Enable hosted planning from crewbie:ready-for-planning labels? Approve planning.model first; users with repository write access can request planning, but this authorizes planning, not implementation.",
59
+ "Enable planning.executeOnMerge? Then a human approval of the exact planning head plus a human merge authorizes automatic paid execution; configure the supported assignment credential once.",
60
+ ],
61
+ config: installed ? { ...installed, roles } : {
62
+ schemaVersion: 1, repository: "", roles, constitution: existingConstitution,
63
+ maxActive: 2, modelProfile: "balanced", execution: { ...DEFAULT_EXECUTION_LIMITS }, nightly: {
64
+ enabled: false, maxRecords: 20,
65
+ allowedPaths: [
66
+ ".crewbie/team/", ".crewbie/decisions/", ".crewbie/decisions.md", ".crewbie/instructions.md",
67
+ ...[...roles.map((role) => role.id), "coordinator", "improver"].map((role) => `.github/agents/crewbie-${role}.agent.md`),
68
+ ],
69
+ }, ado: null, planning: { enabled: false, model: "" },
70
+ },
71
+ constitutionText: null,
72
+ instructions: [],
73
+ };
74
+ }
75
+ //# sourceMappingURL=assessment.js.map