@codyswann/lisa 4.6.6 → 4.6.8
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/all/copy-contents/gitignore +13 -0
- package/dist/cli/doctor-readiness-tracking.d.ts +21 -0
- package/dist/cli/doctor-readiness-tracking.d.ts.map +1 -0
- package/dist/cli/doctor-readiness-tracking.js +115 -0
- package/dist/cli/doctor-readiness-tracking.js.map +1 -0
- package/dist/cli/doctor-skip-jobs-migration.d.ts +5 -1
- package/dist/cli/doctor-skip-jobs-migration.d.ts.map +1 -1
- package/dist/cli/doctor-skip-jobs-migration.js +120 -74
- package/dist/cli/doctor-skip-jobs-migration.js.map +1 -1
- package/dist/cli/doctor.d.ts.map +1 -1
- package/dist/cli/doctor.js +8 -0
- package/dist/cli/doctor.js.map +1 -1
- package/dist/cli/workflow-moments.d.ts +67 -0
- package/dist/cli/workflow-moments.d.ts.map +1 -0
- package/dist/cli/workflow-moments.js +225 -0
- package/dist/cli/workflow-moments.js.map +1 -0
- package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
- package/dist/core/upstream-evidence-manifest.js +6 -1
- package/dist/core/upstream-evidence-manifest.js.map +1 -1
- package/package.json +1 -1
- package/plugins/lisa/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-agy/plugin.json +1 -1
- package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk-agy/plugin.json +1 -1
- package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-expo-agy/plugin.json +1 -1
- package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs-agy/plugin.json +1 -1
- package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw-agy/plugin.json +1 -1
- package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser-agy/plugin.json +1 -1
- package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-rails-agy/plugin.json +1 -1
- package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript-agy/plugin.json +1 -1
- package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki-agy/plugin.json +1 -1
- package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/** The moment `quality.yml` resolves gates at when a caller declares none. */
|
|
2
|
+
export declare const DEFAULT_MOMENT = "pull-request";
|
|
3
|
+
/**
|
|
4
|
+
* Strip YAML quoting and a trailing comment from an inline scalar.
|
|
5
|
+
* @param raw - The text after `key:`
|
|
6
|
+
* @returns The scalar's value
|
|
7
|
+
*/
|
|
8
|
+
export declare function scalar(raw: string): string;
|
|
9
|
+
/**
|
|
10
|
+
* The `moment` declared among the keys sitting at one indentation.
|
|
11
|
+
*
|
|
12
|
+
* Scoped by indentation rather than taken from anywhere in the file: a
|
|
13
|
+
* workflow may call `quality.yml` twice with different moments, and attributing
|
|
14
|
+
* one job's moment to the other's tokens would produce a declaration that is
|
|
15
|
+
* legal for neither.
|
|
16
|
+
* @param lines - The workflow file's lines
|
|
17
|
+
* @param at - Index to scan outwards from
|
|
18
|
+
* @param indent - The indentation of the keys to scan
|
|
19
|
+
* @returns The declared moment, or the workflow's default
|
|
20
|
+
*/
|
|
21
|
+
export declare function momentFor(lines: string[], at: number, indent: string): string;
|
|
22
|
+
/**
|
|
23
|
+
* Every workflow file in a project's `.github/workflows` directory.
|
|
24
|
+
* @param targetPath - Project root
|
|
25
|
+
* @returns Absolute paths, empty when the directory is absent
|
|
26
|
+
*/
|
|
27
|
+
export declare function workflowFiles(targetPath: string): Promise<string[]>;
|
|
28
|
+
/** One job that reaches `quality.yml`, whether or not it passes `skip_jobs`. */
|
|
29
|
+
export interface QualityCall {
|
|
30
|
+
/** Workflow file, relative to the project root. */
|
|
31
|
+
readonly file: string;
|
|
32
|
+
/** The moment it resolves, or null when an expression decides it. */
|
|
33
|
+
readonly moment: string | null;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Every job in a project that reaches `quality.yml`.
|
|
37
|
+
* @param targetPath - Project root
|
|
38
|
+
* @returns One entry per job, in workflow-file order
|
|
39
|
+
*/
|
|
40
|
+
export declare function qualityCalls(targetPath: string): Promise<QualityCall[]>;
|
|
41
|
+
/** What else in the project resolves the moment a token's caller resolves. */
|
|
42
|
+
export interface MomentContext {
|
|
43
|
+
/** The moment the caller resolves. */
|
|
44
|
+
readonly moment: string;
|
|
45
|
+
/** Every job resolving it, this caller included, named by workflow file. */
|
|
46
|
+
readonly callers: readonly string[];
|
|
47
|
+
/** Jobs whose moment an expression sets, so doctor cannot pin which it is. */
|
|
48
|
+
readonly unpinned: readonly string[];
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* The clause naming the jobs whose moment could not be pinned, if any.
|
|
52
|
+
* @param context - The moment and every job resolving it
|
|
53
|
+
* @returns A parenthetical clause, or the empty string
|
|
54
|
+
*/
|
|
55
|
+
export declare function unpinnedClause(context: MomentContext): string;
|
|
56
|
+
/**
|
|
57
|
+
* Which jobs resolve one moment.
|
|
58
|
+
*
|
|
59
|
+
* A job whose moment an expression decides counts against every moment: it may
|
|
60
|
+
* be this one, and leaving it out would under-report the callers a declaration
|
|
61
|
+
* governs — the direction that produces the harmful advice.
|
|
62
|
+
* @param calls - Every job in the project reaching `quality.yml`
|
|
63
|
+
* @param moment - The moment to resolve callers for
|
|
64
|
+
* @returns The moment and the jobs resolving it
|
|
65
|
+
*/
|
|
66
|
+
export declare function momentContext(calls: readonly QualityCall[], moment: string): MomentContext;
|
|
67
|
+
//# sourceMappingURL=workflow-moments.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflow-moments.d.ts","sourceRoot":"","sources":["../../src/cli/workflow-moments.ts"],"names":[],"mappings":"AAoBA,8EAA8E;AAC9E,eAAO,MAAM,cAAc,iBAAiB,CAAC;AAuB7C;;;;GAIG;AACH,wBAAgB,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAI1C;AAmBD;;;;;;;;;;;GAWG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAS7E;AAgDD;;;;GAIG;AACH,wBAAsB,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAQzE;AAED,gFAAgF;AAChF,MAAM,WAAW,WAAW;IAC1B,mDAAmD;IACnD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,qEAAqE;IACrE,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC;AAqCD;;;;GAIG;AACH,wBAAsB,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,CAM7E;AAED,8EAA8E;AAC9E,MAAM,WAAW,aAAa;IAC5B,sCAAsC;IACtC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,4EAA4E;IAC5E,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,8EAA8E;IAC9E,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;CACtC;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,aAAa,GAAG,MAAM,CAO7D;AAED;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAC3B,KAAK,EAAE,SAAS,WAAW,EAAE,EAC7B,MAAM,EAAE,MAAM,GACb,aAAa,CAYf"}
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Which moment each job in a project's workflows resolves `quality.yml` gates
|
|
3
|
+
* at, and which jobs reach `quality.yml` at all.
|
|
4
|
+
*
|
|
5
|
+
* Split out of `doctor-skip-jobs-migration` because the two questions have
|
|
6
|
+
* different populations. That check reports the jobs passing `skip_jobs`; the
|
|
7
|
+
* jobs that decide whether its advice is SAFE are mostly the ones passing no
|
|
8
|
+
* `skip_jobs` at all, because a gate declaration is keyed by gate and moment in
|
|
9
|
+
* `.lisa.config.json` and therefore governs every job resolving that moment
|
|
10
|
+
* (CodySwannGT/lisa#3100).
|
|
11
|
+
*
|
|
12
|
+
* Matched as text rather than through a YAML parse, for the same reason
|
|
13
|
+
* `doctor-reusable-workflow-refs` does: a caller whose YAML is malformed still
|
|
14
|
+
* passes the input, and a parse failure would silently drop the file from the
|
|
15
|
+
* audit — reporting a migrated project because one file could not be read.
|
|
16
|
+
* @module cli/workflow-moments
|
|
17
|
+
*/
|
|
18
|
+
import { readdir, readFile } from "node:fs/promises";
|
|
19
|
+
import * as path from "node:path";
|
|
20
|
+
/** The moment `quality.yml` resolves gates at when a caller declares none. */
|
|
21
|
+
export const DEFAULT_MOMENT = "pull-request";
|
|
22
|
+
/** A caller's `moment` input, whatever quoting style it uses. */
|
|
23
|
+
const MOMENT_INPUT = /^([ \t]{0,64})moment:[ \t]{0,64}(.{0,4096})$/;
|
|
24
|
+
/** Any `uses:` line, with its indentation and its unparsed value. */
|
|
25
|
+
const USES_INPUT = /^([ \t]{0,64})uses:[ \t]{0,64}(.{0,4096})$/;
|
|
26
|
+
/**
|
|
27
|
+
* A `uses:` value reaching `quality.yml`, directly or through `release.yml`.
|
|
28
|
+
*
|
|
29
|
+
* `release.yml` counts because it forwards its own `moment` input straight on
|
|
30
|
+
* to `quality.yml`, so a job calling it resolves a `quality.yml` gate set just
|
|
31
|
+
* as directly as a job naming `quality.yml` itself.
|
|
32
|
+
*/
|
|
33
|
+
const QUALITY_WORKFLOW = /workflows\/(?:quality|release)\.ya?ml(?:@|$)/;
|
|
34
|
+
/** The `with:` key — the sibling of `uses:` whose children carry `moment`. */
|
|
35
|
+
const WITH_BLOCK = /^with:[ \t]{0,64}(?:#.{0,512})?$/;
|
|
36
|
+
/** A `workflow_call` trigger, in either the block or the inline-list form. */
|
|
37
|
+
const WORKFLOW_CALL = /^(?:[ \t]{1,64}workflow_call:|on:.{0,256}workflow_call)/;
|
|
38
|
+
/**
|
|
39
|
+
* Strip YAML quoting and a trailing comment from an inline scalar.
|
|
40
|
+
* @param raw - The text after `key:`
|
|
41
|
+
* @returns The scalar's value
|
|
42
|
+
*/
|
|
43
|
+
export function scalar(raw) {
|
|
44
|
+
const withoutComment = /^(['"])(.*?)\1/.exec(raw.trim());
|
|
45
|
+
if (withoutComment)
|
|
46
|
+
return withoutComment[2] ?? "";
|
|
47
|
+
return raw.split("#")[0]?.trim() ?? "";
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* A predicate for "this line is still a key of the block sitting at `indent`".
|
|
51
|
+
*
|
|
52
|
+
* Blank lines count as inside so a block separated by one is not cut in half.
|
|
53
|
+
* @param lines - The workflow file's lines
|
|
54
|
+
* @param indent - The leading whitespace of the block's keys
|
|
55
|
+
* @returns The predicate
|
|
56
|
+
*/
|
|
57
|
+
function blockAt(lines, indent) {
|
|
58
|
+
return (index) => {
|
|
59
|
+
const line = lines[index];
|
|
60
|
+
if (line === undefined)
|
|
61
|
+
return false;
|
|
62
|
+
if (line.trim() === "")
|
|
63
|
+
return true;
|
|
64
|
+
return line.startsWith(indent) && !/^[ \t]/.test(line.slice(indent.length));
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* The `moment` declared among the keys sitting at one indentation.
|
|
69
|
+
*
|
|
70
|
+
* Scoped by indentation rather than taken from anywhere in the file: a
|
|
71
|
+
* workflow may call `quality.yml` twice with different moments, and attributing
|
|
72
|
+
* one job's moment to the other's tokens would produce a declaration that is
|
|
73
|
+
* legal for neither.
|
|
74
|
+
* @param lines - The workflow file's lines
|
|
75
|
+
* @param at - Index to scan outwards from
|
|
76
|
+
* @param indent - The indentation of the keys to scan
|
|
77
|
+
* @returns The declared moment, or the workflow's default
|
|
78
|
+
*/
|
|
79
|
+
export function momentFor(lines, at, indent) {
|
|
80
|
+
const inBlock = blockAt(lines, indent);
|
|
81
|
+
const declaredAt = (index) => {
|
|
82
|
+
const match = MOMENT_INPUT.exec(lines[index] ?? "");
|
|
83
|
+
return match && match[1] === indent ? scalar(match[2] ?? "") : null;
|
|
84
|
+
};
|
|
85
|
+
const scan = (index, step) => inBlock(index) ? (declaredAt(index) ?? scan(index + step, step)) : null;
|
|
86
|
+
return scan(at - 1, -1) ?? scan(at + 1, 1) ?? DEFAULT_MOMENT;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* The indentation of a block's first child line.
|
|
90
|
+
* @param lines - The workflow file's lines
|
|
91
|
+
* @param from - Index to start looking at
|
|
92
|
+
* @param outer - The parent key's leading whitespace
|
|
93
|
+
* @returns The child indentation, or null when the block has no children
|
|
94
|
+
*/
|
|
95
|
+
function firstChildIndent(lines, from, outer) {
|
|
96
|
+
const line = lines[from];
|
|
97
|
+
if (line === undefined)
|
|
98
|
+
return null;
|
|
99
|
+
if (line.trim() === "")
|
|
100
|
+
return firstChildIndent(lines, from + 1, outer);
|
|
101
|
+
const lead = /^[ \t]{0,128}/.exec(line)?.[0] ?? "";
|
|
102
|
+
return lead.length > outer.length && lead.startsWith(outer) ? lead : null;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* The moment one `uses:` call resolves gates at.
|
|
106
|
+
*
|
|
107
|
+
* `with:` is a sibling key of `uses:` inside the same job and `moment:` is one
|
|
108
|
+
* of its children, so this locates the sibling `with:` and then reuses the
|
|
109
|
+
* indentation-scoped scan `momentFor` performs around a `skip_jobs` line.
|
|
110
|
+
* @param lines - The workflow file's lines
|
|
111
|
+
* @param at - Index of the `uses:` line
|
|
112
|
+
* @param indent - That line's leading whitespace
|
|
113
|
+
* @returns The declared moment, or the workflow's default
|
|
114
|
+
*/
|
|
115
|
+
function momentForCall(lines, at, indent) {
|
|
116
|
+
const inBlock = blockAt(lines, indent);
|
|
117
|
+
const findWith = (index, step) => {
|
|
118
|
+
if (!inBlock(index))
|
|
119
|
+
return null;
|
|
120
|
+
if (WITH_BLOCK.test((lines[index] ?? "").slice(indent.length)))
|
|
121
|
+
return index;
|
|
122
|
+
return findWith(index + step, step);
|
|
123
|
+
};
|
|
124
|
+
const withAt = findWith(at - 1, -1) ?? findWith(at + 1, 1);
|
|
125
|
+
if (withAt === null)
|
|
126
|
+
return DEFAULT_MOMENT;
|
|
127
|
+
const children = firstChildIndent(lines, withAt + 1, indent);
|
|
128
|
+
return children === null
|
|
129
|
+
? DEFAULT_MOMENT
|
|
130
|
+
: momentFor(lines, withAt, children);
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Every workflow file in a project's `.github/workflows` directory.
|
|
134
|
+
* @param targetPath - Project root
|
|
135
|
+
* @returns Absolute paths, empty when the directory is absent
|
|
136
|
+
*/
|
|
137
|
+
export async function workflowFiles(targetPath) {
|
|
138
|
+
const dir = path.join(targetPath, ".github", "workflows");
|
|
139
|
+
const entries = await readdir(dir).catch(() => undefined);
|
|
140
|
+
if (entries === undefined)
|
|
141
|
+
return [];
|
|
142
|
+
return entries
|
|
143
|
+
.filter(name => /\.ya?ml$/.test(name))
|
|
144
|
+
.sort((left, right) => left.localeCompare(right))
|
|
145
|
+
.map(name => path.join(dir, name));
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Every job in one workflow that reaches `quality.yml`.
|
|
149
|
+
*
|
|
150
|
+
* A workflow that is itself called by others (`on: workflow_call`) is skipped.
|
|
151
|
+
* `release.yml` is one, and it forwards whatever moment ITS caller passed — so
|
|
152
|
+
* counting it would invent a caller no repository ever triggers, and would name
|
|
153
|
+
* a file the operator cannot edit.
|
|
154
|
+
* @param targetPath - Project root
|
|
155
|
+
* @param file - Absolute path to the workflow
|
|
156
|
+
* @returns One entry per job reaching `quality.yml`
|
|
157
|
+
*/
|
|
158
|
+
async function qualityCallsIn(targetPath, file) {
|
|
159
|
+
const lines = (await readFile(file, "utf8").catch(() => "")).split("\n");
|
|
160
|
+
if (lines.some(line => WORKFLOW_CALL.test(line)))
|
|
161
|
+
return [];
|
|
162
|
+
return lines.flatMap((line, index) => {
|
|
163
|
+
const match = USES_INPUT.exec(line);
|
|
164
|
+
if (match === null)
|
|
165
|
+
return [];
|
|
166
|
+
if (!QUALITY_WORKFLOW.test(scalar(match[2] ?? "")))
|
|
167
|
+
return [];
|
|
168
|
+
const moment = momentForCall(lines, index, match[1] ?? "");
|
|
169
|
+
return [
|
|
170
|
+
{
|
|
171
|
+
file: path.relative(targetPath, file),
|
|
172
|
+
// An expression is not a moment. Reported as null so the advice counts
|
|
173
|
+
// this job against EVERY moment and says it could not be pinned —
|
|
174
|
+
// guessing the default instead would shrink the set of callers a
|
|
175
|
+
// declaration is known to govern, which is the direction that harms.
|
|
176
|
+
moment: moment.includes("${{") ? null : moment,
|
|
177
|
+
},
|
|
178
|
+
];
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Every job in a project that reaches `quality.yml`.
|
|
183
|
+
* @param targetPath - Project root
|
|
184
|
+
* @returns One entry per job, in workflow-file order
|
|
185
|
+
*/
|
|
186
|
+
export async function qualityCalls(targetPath) {
|
|
187
|
+
const files = await workflowFiles(targetPath);
|
|
188
|
+
const perFile = await Promise.all(files.map(file => qualityCallsIn(targetPath, file)));
|
|
189
|
+
return perFile.flat();
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* The clause naming the jobs whose moment could not be pinned, if any.
|
|
193
|
+
* @param context - The moment and every job resolving it
|
|
194
|
+
* @returns A parenthetical clause, or the empty string
|
|
195
|
+
*/
|
|
196
|
+
export function unpinnedClause(context) {
|
|
197
|
+
if (context.unpinned.length === 0)
|
|
198
|
+
return "";
|
|
199
|
+
return (` (${context.unpinned.join(", ")} builds its moment from an expression, ` +
|
|
200
|
+
"so doctor cannot tell which moment it resolves and counts it here rather " +
|
|
201
|
+
"than assuming it is a different one)");
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Which jobs resolve one moment.
|
|
205
|
+
*
|
|
206
|
+
* A job whose moment an expression decides counts against every moment: it may
|
|
207
|
+
* be this one, and leaving it out would under-report the callers a declaration
|
|
208
|
+
* governs — the direction that produces the harmful advice.
|
|
209
|
+
* @param calls - Every job in the project reaching `quality.yml`
|
|
210
|
+
* @param moment - The moment to resolve callers for
|
|
211
|
+
* @returns The moment and the jobs resolving it
|
|
212
|
+
*/
|
|
213
|
+
export function momentContext(calls, moment) {
|
|
214
|
+
const byName = (left, right) => left.localeCompare(right);
|
|
215
|
+
const unpinned = calls.filter(call => call.moment === null);
|
|
216
|
+
return {
|
|
217
|
+
moment,
|
|
218
|
+
callers: calls
|
|
219
|
+
.filter(call => call.moment === null || call.moment === moment)
|
|
220
|
+
.map(call => call.file)
|
|
221
|
+
.sort(byName),
|
|
222
|
+
unpinned: [...new Set(unpinned.map(call => call.file))].sort(byName),
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
//# sourceMappingURL=workflow-moments.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflow-moments.js","sourceRoot":"","sources":["../../src/cli/workflow-moments.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"upstream-evidence-manifest.d.ts","sourceRoot":"","sources":["../../src/core/upstream-evidence-manifest.ts"],"names":[],"mappings":"AACA,iFAAiF;AACjF,eAAO,MAAM,0BAA0B,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CA84EpE,CAAC;AAEL,4EAA4E;AAC5E,eAAO,MAAM,yBAAyB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"upstream-evidence-manifest.d.ts","sourceRoot":"","sources":["../../src/core/upstream-evidence-manifest.ts"],"names":[],"mappings":"AACA,iFAAiF;AACjF,eAAO,MAAM,0BAA0B,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CA84EpE,CAAC;AAEL,4EAA4E;AAC5E,eAAO,MAAM,yBAAyB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CA2kPjE,CAAC;AAEL,sFAAsF;AACtF,eAAO,MAAM,uBAAuB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAk6I/D,CAAC"}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
/** Generated by scripts/generate-upstream-evidence-manifest.mjs. Do not edit. */
|
|
3
3
|
export const UPSTREAM_EVIDENCE_MANIFEST = Object.freeze({
|
|
4
4
|
"all/copy-contents/.gitattributes": "9d3831007e681186a3673e1037ef3fc82980cab2fc04e27c0868e562912c9e9f",
|
|
5
|
-
"all/copy-contents/gitignore": "
|
|
5
|
+
"all/copy-contents/gitignore": "06fc4bca36fabe2abc81e60b3e3886dcb9a0eacb4ae9d670beb2125a4eb4f850",
|
|
6
6
|
"all/copy-overwrite/scripts/check-conflict-markers.mjs": "d7a689bcc122af7f38d1c536924fc2f3dcb503b09658ffc6035ccbe720d14d6b",
|
|
7
7
|
"all/copy-overwrite/scripts/check-state-classification.mjs": "a72910f9885629dd6d8a739b900f5603e4b53d68ece64100a2a5647016b58e1e",
|
|
8
8
|
"all/copy-overwrite/scripts/lib/bounded-spawn.mjs": "72e277ada531914d7bc51c3cb8dc67b8881aa817d96fa2f9f4d81668a3d3bbc1",
|
|
@@ -7192,6 +7192,7 @@ export const UPSTREAM_SURFACE_MANIFEST = Object.freeze({
|
|
|
7192
7192
|
"src/cli/doctor-readiness-supply-chain-ruby.ts": true,
|
|
7193
7193
|
"src/cli/doctor-readiness-supply-chain-scan.ts": true,
|
|
7194
7194
|
"src/cli/doctor-readiness-supply-chain.ts": true,
|
|
7195
|
+
"src/cli/doctor-readiness-tracking.ts": true,
|
|
7195
7196
|
"src/cli/doctor-readiness-types.ts": true,
|
|
7196
7197
|
"src/cli/doctor-readiness-workflows.ts": true,
|
|
7197
7198
|
"src/cli/doctor-readiness-workspaces.ts": true,
|
|
@@ -7288,6 +7289,7 @@ export const UPSTREAM_SURFACE_MANIFEST = Object.freeze({
|
|
|
7288
7289
|
"src/cli/update-cmd.ts": true,
|
|
7289
7290
|
"src/cli/version-cmd.ts": true,
|
|
7290
7291
|
"src/cli/version.ts": true,
|
|
7292
|
+
"src/cli/workflow-moments.ts": true,
|
|
7291
7293
|
"src/cli/workstation-cmd.ts": true,
|
|
7292
7294
|
"src/codex/agent-installer.ts": true,
|
|
7293
7295
|
"src/codex/agent-transformer.ts": true,
|
|
@@ -7805,12 +7807,14 @@ export const UPSTREAM_SURFACE_MANIFEST = Object.freeze({
|
|
|
7805
7807
|
"tests/unit/cli/doctor-readiness-supply-chain-ruby.test.ts": true,
|
|
7806
7808
|
"tests/unit/cli/doctor-readiness-supply-chain-workspaces.test.ts": true,
|
|
7807
7809
|
"tests/unit/cli/doctor-readiness-supply-chain.test.ts": true,
|
|
7810
|
+
"tests/unit/cli/doctor-readiness-tracking.test.ts": true,
|
|
7808
7811
|
"tests/unit/cli/doctor-readiness-workflows.test.ts": true,
|
|
7809
7812
|
"tests/unit/cli/doctor-readiness.test.ts": true,
|
|
7810
7813
|
"tests/unit/cli/doctor-render.test.ts": true,
|
|
7811
7814
|
"tests/unit/cli/doctor-reusable-workflow-refs.test.ts": true,
|
|
7812
7815
|
"tests/unit/cli/doctor-serialize-legs-contract.test.ts": true,
|
|
7813
7816
|
"tests/unit/cli/doctor-skip-jobs-migration.test.ts": true,
|
|
7817
|
+
"tests/unit/cli/doctor-skip-jobs-moment-callers.test.ts": true,
|
|
7814
7818
|
"tests/unit/cli/doctor-sonar.test.ts": true,
|
|
7815
7819
|
"tests/unit/cli/doctor-traceability-gate.test.ts": true,
|
|
7816
7820
|
"tests/unit/cli/doctor-worker-epoch.test.ts": true,
|
|
@@ -8560,6 +8564,7 @@ export const UPSTREAM_SURFACE_MANIFEST = Object.freeze({
|
|
|
8560
8564
|
"tests/unit/strategies/queue-status-fixture-smoke-and-read-only.test.ts": true,
|
|
8561
8565
|
"tests/unit/strategies/queue-status-prd-readers.test.ts": true,
|
|
8562
8566
|
"tests/unit/strategies/queue-status-scaffold.test.ts": true,
|
|
8567
|
+
"tests/unit/strategies/readiness-report-merge-exposure.test.ts": true,
|
|
8563
8568
|
"tests/unit/strategies/readiness-rubric-contract.test.ts": true,
|
|
8564
8569
|
"tests/unit/strategies/ready-role-filing-contract.test.ts": true,
|
|
8565
8570
|
"tests/unit/strategies/rejection-detection-rule.test.ts": true,
|