@akagilnc/pi-workflow-roles 0.1.5241 → 0.1.5252
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.
- package/README.md +2 -3
- package/README.zh-CN.md +2 -3
- package/dist/acp-host/production-host.js +482 -3141
- package/dist/collector-config.js +0 -1
- package/dist/headless-host/production-host.js +590 -3249
- package/dist/migrate-book-topology.js +40 -107
- package/dist/navigator-invocation-identity.js +0 -57
- package/dist/package-contracts/collector-output.js +1 -90
- package/dist/package-contracts/terminating-tools.js +2 -2
- package/dist/packaged-role-registry.js +8 -11
- package/dist/public-cli/invocation.js +2 -22
- package/dist/public-cli/main.js +256 -749
- package/dist/public-cli/option-definitions.js +4 -19
- package/dist/public-cli/settlement.js +12 -138
- package/package.json +1 -1
- package/resources/collector-bot-handbook.md +4 -2
- package/src/collector-config.ts +0 -1
- package/src/collector-role.ts +40 -535
- package/src/collector-tool-schemas.ts +7 -117
- package/src/gh-api-runner.ts +102 -0
- package/src/navigator-invocation-identity.ts +4 -121
- package/src/package-contracts/collector-output.ts +15 -174
- package/src/package-contracts/terminating-tools.ts +0 -2
- package/src/packaged-role-registry.ts +7 -10
- package/src/public-cli/invocation.ts +3 -27
- package/src/public-cli/option-definitions.ts +4 -19
- package/src/public-cli/settlement.ts +11 -177
- package/src/role-runtime-dependencies.ts +0 -4
- package/src/role-runtime.ts +39 -103
- package/src/ticket-snapshot.ts +1 -1
- package/dist/collector-evidence.js +0 -319
- package/dist/collector-github.js +0 -725
- package/dist/collector-identity.js +0 -92
- package/dist/collector-ledger.js +0 -888
- package/dist/collector-target.js +0 -169
- package/src/collector-evidence.ts +0 -466
- package/src/collector-github.ts +0 -1032
- package/src/collector-handbook.ts +0 -194
- package/src/collector-identity.ts +0 -151
- package/src/collector-ledger.ts +0 -1186
- package/src/collector-target.ts +0 -207
package/src/collector-target.ts
DELETED
|
@@ -1,207 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* #676 D1: Collector admission target recognition on structured git context.
|
|
3
|
-
* Explicit PR wins (no association queries). Otherwise gather online candidates
|
|
4
|
-
* from structured upstream head and HEAD commit association only. Deduped unique
|
|
5
|
-
* → bind; many → require explicit --pr; zero → unbound so the role can decide
|
|
6
|
-
* from task materials via the bind-target business tool. No task-text scrape,
|
|
7
|
-
* no second state machine. Git/config/transport failures keep true cause.
|
|
8
|
-
*/
|
|
9
|
-
import { execFileSync } from "node:child_process";
|
|
10
|
-
|
|
11
|
-
import type { CollectorRepository } from "./collector-config.ts";
|
|
12
|
-
import {
|
|
13
|
-
createGhApiRunner,
|
|
14
|
-
listPullRequestNumbersByCommit,
|
|
15
|
-
listPullRequestNumbersByHead,
|
|
16
|
-
} from "./collector-github.ts";
|
|
17
|
-
import { CliUsageError } from "./public-cli/cli-errors.ts";
|
|
18
|
-
import {
|
|
19
|
-
ownerFromGitHubRemoteUrl,
|
|
20
|
-
ownerRepoFromGitHubRemoteUrl,
|
|
21
|
-
} from "./public-cli/github-remote.ts";
|
|
22
|
-
|
|
23
|
-
export type ResolveCollectorTargetInput = {
|
|
24
|
-
readonly projectRoot: string;
|
|
25
|
-
readonly repository: CollectorRepository;
|
|
26
|
-
/** Caller-provided PR number when already explicit. */
|
|
27
|
-
readonly explicitPrNumber?: number;
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
export type CollectorTargetResolution =
|
|
31
|
-
| { readonly kind: "bound"; readonly prNumber: number }
|
|
32
|
-
| { readonly kind: "unbound" };
|
|
33
|
-
|
|
34
|
-
function ambiguousTarget(detail: string, cause?: unknown): never {
|
|
35
|
-
throw new CliUsageError(
|
|
36
|
-
`collector target is ambiguous: ${detail}; pass an explicit --pr`,
|
|
37
|
-
cause === undefined ? undefined : { cause },
|
|
38
|
-
);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/** Real git failure — not target ambiguity. Propagates with true cause on exit 1. */
|
|
42
|
-
function gitFailure(detail: string, cause: unknown): never {
|
|
43
|
-
throw new Error(`collector git failed: ${detail}`, {
|
|
44
|
-
cause: cause instanceof Error ? cause : new Error(String(cause)),
|
|
45
|
-
});
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
function gitText(projectRoot: string, args: readonly string[]): string {
|
|
49
|
-
return execFileSync("git", [...args], {
|
|
50
|
-
cwd: projectRoot,
|
|
51
|
-
encoding: "utf8",
|
|
52
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
53
|
-
}).trim();
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/** git config --get exit 1 = key absent; other failures keep true cause. */
|
|
57
|
-
function isGitConfigMissing(error: unknown): boolean {
|
|
58
|
-
if (typeof error !== "object" || error === null) return false;
|
|
59
|
-
const status = (error as { status?: unknown }).status;
|
|
60
|
-
return status === 1;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
function readCurrentBranch(projectRoot: string): string {
|
|
64
|
-
try {
|
|
65
|
-
return gitText(projectRoot, ["rev-parse", "--abbrev-ref", "HEAD"]);
|
|
66
|
-
} catch (error) {
|
|
67
|
-
gitFailure("cannot read current git branch", error);
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
function readHeadSha(projectRoot: string): string {
|
|
72
|
-
try {
|
|
73
|
-
return gitText(projectRoot, ["rev-parse", "HEAD"]);
|
|
74
|
-
} catch (error) {
|
|
75
|
-
gitFailure("cannot read current HEAD", error);
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
/**
|
|
80
|
-
* Head ref short name from branch.<name>.merge (refs/heads/<ref> or bare ref).
|
|
81
|
-
* Non-heads merge forms are not a structured head binding.
|
|
82
|
-
*/
|
|
83
|
-
function headRefFromMerge(merge: string): string | undefined {
|
|
84
|
-
const trimmed = merge.trim();
|
|
85
|
-
if (trimmed.length === 0) return undefined;
|
|
86
|
-
if (trimmed.startsWith("refs/heads/")) {
|
|
87
|
-
const ref = trimmed.slice("refs/heads/".length);
|
|
88
|
-
return ref.length > 0 ? ref : undefined;
|
|
89
|
-
}
|
|
90
|
-
// Reject other refs/* (e.g. refs/remotes/…) — not a PR head ref binding.
|
|
91
|
-
if (trimmed.startsWith("refs/")) return undefined;
|
|
92
|
-
return trimmed;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* Real upstream head owner + head ref from branch.<name>.remote/merge when configured.
|
|
97
|
-
* Missing config keys = not configured (undefined). Config/remote execution failures
|
|
98
|
-
* throw with true cause — never swallowed as "no upstream, keep fallback".
|
|
99
|
-
*/
|
|
100
|
-
function readUpstreamHeadBinding(
|
|
101
|
-
projectRoot: string,
|
|
102
|
-
branch: string,
|
|
103
|
-
): { readonly headOwner: string; readonly headRef: string } | undefined {
|
|
104
|
-
let remote: string | undefined;
|
|
105
|
-
try {
|
|
106
|
-
remote = gitText(projectRoot, ["config", "--get", `branch.${branch}.remote`]);
|
|
107
|
-
} catch (error) {
|
|
108
|
-
if (isGitConfigMissing(error)) remote = undefined;
|
|
109
|
-
else gitFailure(`cannot read branch.${branch}.remote`, error);
|
|
110
|
-
}
|
|
111
|
-
if (remote === undefined || remote.length === 0) return undefined;
|
|
112
|
-
|
|
113
|
-
let merge: string | undefined;
|
|
114
|
-
try {
|
|
115
|
-
merge = gitText(projectRoot, ["config", "--get", `branch.${branch}.merge`]);
|
|
116
|
-
} catch (error) {
|
|
117
|
-
if (isGitConfigMissing(error)) merge = undefined;
|
|
118
|
-
else gitFailure(`cannot read branch.${branch}.merge`, error);
|
|
119
|
-
}
|
|
120
|
-
if (merge === undefined || merge.length === 0) return undefined;
|
|
121
|
-
|
|
122
|
-
const headRef = headRefFromMerge(merge);
|
|
123
|
-
if (headRef === undefined) return undefined;
|
|
124
|
-
|
|
125
|
-
let remoteUrl: string;
|
|
126
|
-
try {
|
|
127
|
-
remoteUrl = gitText(projectRoot, ["remote", "get-url", remote]);
|
|
128
|
-
} catch (error) {
|
|
129
|
-
gitFailure(`cannot read remote URL for ${remote}`, error);
|
|
130
|
-
}
|
|
131
|
-
const headOwner = ownerFromGitHubRemoteUrl(remoteUrl);
|
|
132
|
-
if (headOwner === undefined) return undefined;
|
|
133
|
-
return { headOwner, headRef };
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
/**
|
|
137
|
-
* Resolve the Collector PR target without guessing from task text.
|
|
138
|
-
* - Explicit `--pr` → that number (no association queries).
|
|
139
|
-
* - Otherwise: full online candidates (upstream head + HEAD commit), deduped.
|
|
140
|
-
* - Exactly 1 → bound. >1 → require explicit `--pr`. 0 → unbound (role bind tool).
|
|
141
|
-
* - Git/config/transport/HTTP/JSON failures propagate with true cause.
|
|
142
|
-
*/
|
|
143
|
-
export async function resolveCollectorTarget(
|
|
144
|
-
input: ResolveCollectorTargetInput,
|
|
145
|
-
): Promise<CollectorTargetResolution> {
|
|
146
|
-
if (input.explicitPrNumber !== undefined) {
|
|
147
|
-
return { kind: "bound", prNumber: input.explicitPrNumber };
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
const branch = readCurrentBranch(input.projectRoot);
|
|
151
|
-
const detached = branch.length === 0 || branch === "HEAD";
|
|
152
|
-
|
|
153
|
-
// Detached HEAD cannot associate via branch head; commit association still runs.
|
|
154
|
-
const runner = createGhApiRunner();
|
|
155
|
-
const { owner, repo } = input.repository;
|
|
156
|
-
const numbers: number[] = [];
|
|
157
|
-
|
|
158
|
-
if (!detached) {
|
|
159
|
-
const headSha = readHeadSha(input.projectRoot);
|
|
160
|
-
const upstream = readUpstreamHeadBinding(input.projectRoot, branch);
|
|
161
|
-
|
|
162
|
-
// Prefer structured head owner:ref from real upstream merge binding (fork-safe).
|
|
163
|
-
if (upstream !== undefined) {
|
|
164
|
-
numbers.push(
|
|
165
|
-
...(await listPullRequestNumbersByHead(runner, {
|
|
166
|
-
owner,
|
|
167
|
-
repo,
|
|
168
|
-
headOwner: upstream.headOwner,
|
|
169
|
-
headRef: upstream.headRef,
|
|
170
|
-
})),
|
|
171
|
-
);
|
|
172
|
-
}
|
|
173
|
-
// Always also take commit association — never let a sole upstream hit hide a conflict.
|
|
174
|
-
numbers.push(
|
|
175
|
-
...(await listPullRequestNumbersByCommit(runner, {
|
|
176
|
-
owner,
|
|
177
|
-
repo,
|
|
178
|
-
commitSha: headSha,
|
|
179
|
-
})),
|
|
180
|
-
);
|
|
181
|
-
} else {
|
|
182
|
-
// Detached: commit association only (no branch head).
|
|
183
|
-
const headSha = readHeadSha(input.projectRoot);
|
|
184
|
-
numbers.push(
|
|
185
|
-
...(await listPullRequestNumbersByCommit(runner, {
|
|
186
|
-
owner,
|
|
187
|
-
repo,
|
|
188
|
-
commitSha: headSha,
|
|
189
|
-
})),
|
|
190
|
-
);
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
const unique = [...new Set(numbers)];
|
|
194
|
-
|
|
195
|
-
if (unique.length === 1) {
|
|
196
|
-
return { kind: "bound", prNumber: unique[0]! };
|
|
197
|
-
}
|
|
198
|
-
if (unique.length > 1) {
|
|
199
|
-
ambiguousTarget(
|
|
200
|
-
`multiple PRs associated with context: ${unique.join(", ")}`,
|
|
201
|
-
);
|
|
202
|
-
}
|
|
203
|
-
// Zero structured git hits — leave unbound so the role can decide from materials.
|
|
204
|
-
return { kind: "unbound" };
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
export { ownerRepoFromGitHubRemoteUrl, ownerFromGitHubRemoteUrl };
|