@akagilnc/pi-workflow-roles 0.1.2118 → 0.1.2124
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 -4
- package/README.zh-CN.md +2 -4
- package/dist/public-cli/main.js +214 -165
- package/package.json +1 -1
- package/src/public-cli/invocation.ts +18 -28
- package/src/public-cli/option-definitions.ts +35 -62
- package/src/public-cli/taishi-run.ts +41 -52
- package/src/taishi-cohort.ts +4 -0
- package/src/taishi-entry.ts +111 -49
- package/src/taishi-index.ts +39 -20
- package/src/taishi-ledger.ts +90 -45
- package/src/taishi-page.ts +64 -8
package/src/taishi-page.ts
CHANGED
|
@@ -96,15 +96,26 @@ export type TaishiOptionalTimestamp =
|
|
|
96
96
|
* through directory discovery — keep this envelope stable.
|
|
97
97
|
* C1 efficiency fields (完全耗时 / 排除后改动行数 / 耗时每千行 / 末次活动)
|
|
98
98
|
* live on the envelope so sweep can project index rows without family dig.
|
|
99
|
-
*
|
|
100
|
-
*
|
|
99
|
+
* #399: page mechanical address includes book identity (and ticket when set).
|
|
100
|
+
* projectRoot is a retained recording/display field — not the address key.
|
|
101
101
|
*/
|
|
102
102
|
export type TaishiIssueMetricsPage = {
|
|
103
103
|
readonly kind: "taishi-issue-metrics";
|
|
104
104
|
readonly mode: "issue";
|
|
105
|
+
/** Ledger book identity — part of the page mechanical address (#399). */
|
|
106
|
+
readonly bookKey: string;
|
|
107
|
+
/**
|
|
108
|
+
* Recording/display face (cwd or sweep workspace pointer).
|
|
109
|
+
* Not the page mechanical key after #399 / ADR 0068 revision.
|
|
110
|
+
*/
|
|
105
111
|
readonly projectRoot: string;
|
|
106
112
|
/** Caller typed issue number — present only when supplied on the entry. */
|
|
107
113
|
readonly issueNumber?: number;
|
|
114
|
+
/**
|
|
115
|
+
* Path-narrow address fragment for sweep/legacy fixture pages that share a
|
|
116
|
+
* book but represent distinct workspace roots. Absent on CLI book/ticket pages.
|
|
117
|
+
*/
|
|
118
|
+
readonly scopeRootIdentity?: string;
|
|
108
119
|
readonly legs: readonly TaishiLegEntry[];
|
|
109
120
|
readonly unreadable: readonly TaishiUnreadableRun[];
|
|
110
121
|
readonly unreadableCount: number;
|
|
@@ -124,13 +135,48 @@ export type TaishiIssueMetricsPage = {
|
|
|
124
135
|
readonly lastActivityAt: TaishiOptionalTimestamp;
|
|
125
136
|
};
|
|
126
137
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
138
|
+
/**
|
|
139
|
+
* Page mechanical address (#399): always carries book identity.
|
|
140
|
+
* - book scope (CLI bare): bookKey only
|
|
141
|
+
* - ticket scope (CLI --ticket N): bookKey + issueNumber
|
|
142
|
+
* - root-narrow (sweep/legacy): bookKey + scopeRootIdentity
|
|
143
|
+
*/
|
|
144
|
+
export type TaishiIssuePageAddress = {
|
|
145
|
+
readonly bookKey: string;
|
|
146
|
+
readonly issueNumber?: number;
|
|
147
|
+
readonly scopeRootIdentity?: string;
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
export function taishiIssuePageKey(address: TaishiIssuePageAddress): string {
|
|
151
|
+
const parts = ["book", address.bookKey];
|
|
152
|
+
if (address.issueNumber !== undefined) {
|
|
153
|
+
parts.push("ticket", String(address.issueNumber));
|
|
154
|
+
} else if (address.scopeRootIdentity !== undefined) {
|
|
155
|
+
parts.push("root", physicalPathIdentity(address.scopeRootIdentity));
|
|
156
|
+
}
|
|
157
|
+
return createHash("sha256").update(parts.join("\0")).digest("hex").slice(0, 32);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
export function taishiIssuePagePath(
|
|
161
|
+
ledgerHome: string,
|
|
162
|
+
address: TaishiIssuePageAddress,
|
|
163
|
+
): string {
|
|
164
|
+
return join(ledgerHome, "taishi", "issues", `${taishiIssuePageKey(address)}.json`);
|
|
130
165
|
}
|
|
131
166
|
|
|
132
|
-
export function
|
|
133
|
-
|
|
167
|
+
export function taishiIssuePageAddressFromPage(
|
|
168
|
+
page: Pick<
|
|
169
|
+
TaishiIssueMetricsPage,
|
|
170
|
+
"bookKey" | "issueNumber" | "scopeRootIdentity"
|
|
171
|
+
>,
|
|
172
|
+
): TaishiIssuePageAddress {
|
|
173
|
+
return {
|
|
174
|
+
bookKey: page.bookKey,
|
|
175
|
+
...(page.issueNumber === undefined ? {} : { issueNumber: page.issueNumber }),
|
|
176
|
+
...(page.scopeRootIdentity === undefined
|
|
177
|
+
? {}
|
|
178
|
+
: { scopeRootIdentity: page.scopeRootIdentity }),
|
|
179
|
+
};
|
|
134
180
|
}
|
|
135
181
|
|
|
136
182
|
function sortLegs(legs: readonly TaishiLegEntry[]): TaishiLegEntry[] {
|
|
@@ -250,6 +296,7 @@ export function summarizeTaishiRunEfficiency(
|
|
|
250
296
|
}
|
|
251
297
|
|
|
252
298
|
export async function buildTaishiIssueMetricsPage(input: {
|
|
299
|
+
readonly bookKey: string;
|
|
253
300
|
readonly projectRoot: string;
|
|
254
301
|
readonly runs: readonly TaishiReadableRunFacts[];
|
|
255
302
|
readonly unreadable: readonly TaishiUnreadableRun[];
|
|
@@ -259,6 +306,11 @@ export async function buildTaishiIssueMetricsPage(input: {
|
|
|
259
306
|
readonly changedLines?: number;
|
|
260
307
|
/** Caller typed issue number — retained on page for cohort index join. */
|
|
261
308
|
readonly issueNumber?: number;
|
|
309
|
+
/**
|
|
310
|
+
* When set, page address is book+root (sweep/legacy path-narrow).
|
|
311
|
+
* Must be absent for CLI whole-book / ticket pages so cross-cwd same book collides correctly.
|
|
312
|
+
*/
|
|
313
|
+
readonly scopeRootIdentity?: string;
|
|
262
314
|
}): Promise<TaishiIssueMetricsPage> {
|
|
263
315
|
// Discover before compose/write — missing family tree fails loud with native
|
|
264
316
|
// ENOENT/ENOTDIR (no empty-registry wash) and never emits a success page.
|
|
@@ -283,9 +335,13 @@ export async function buildTaishiIssueMetricsPage(input: {
|
|
|
283
335
|
const envelope = {
|
|
284
336
|
kind: "taishi-issue-metrics" as const,
|
|
285
337
|
mode: "issue" as const,
|
|
338
|
+
bookKey: input.bookKey,
|
|
286
339
|
projectRoot,
|
|
287
340
|
// exactOptionalPropertyTypes: only materialize when caller supplied it.
|
|
288
341
|
...(input.issueNumber === undefined ? {} : { issueNumber: input.issueNumber }),
|
|
342
|
+
...(input.scopeRootIdentity === undefined
|
|
343
|
+
? {}
|
|
344
|
+
: { scopeRootIdentity: physicalPathIdentity(input.scopeRootIdentity) }),
|
|
289
345
|
legs,
|
|
290
346
|
unreadable,
|
|
291
347
|
unreadableCount: unreadable.length,
|
|
@@ -312,7 +368,7 @@ export async function writeTaishiIssueMetricsPage(
|
|
|
312
368
|
ledgerHome: string,
|
|
313
369
|
page: TaishiIssueMetricsPage,
|
|
314
370
|
): Promise<string> {
|
|
315
|
-
const path = taishiIssuePagePath(ledgerHome, page
|
|
371
|
+
const path = taishiIssuePagePath(ledgerHome, taishiIssuePageAddressFromPage(page));
|
|
316
372
|
ensureRealDirectoryTree(ledgerHome, dirname(path));
|
|
317
373
|
assertLedgerFileInsideHome(path, ledgerHome);
|
|
318
374
|
await writeFileAtomically(path, `${JSON.stringify(page, null, 2)}\n`);
|