@codyswann/lisa 2.278.0 → 2.279.1
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/dist/cli/doctor-readiness-credentials.d.ts +46 -0
- package/dist/cli/doctor-readiness-credentials.d.ts.map +1 -0
- package/dist/cli/doctor-readiness-credentials.js +199 -0
- package/dist/cli/doctor-readiness-credentials.js.map +1 -0
- package/dist/cli/doctor-readiness-delivery.d.ts +16 -0
- package/dist/cli/doctor-readiness-delivery.d.ts.map +1 -0
- package/dist/cli/doctor-readiness-delivery.js +243 -0
- package/dist/cli/doctor-readiness-delivery.js.map +1 -0
- package/dist/cli/doctor-readiness-journey.d.ts +4 -10
- package/dist/cli/doctor-readiness-journey.d.ts.map +1 -1
- package/dist/cli/doctor-readiness-journey.js +17 -1
- package/dist/cli/doctor-readiness-journey.js.map +1 -1
- package/dist/cli/doctor-readiness-release-path.d.ts +62 -0
- package/dist/cli/doctor-readiness-release-path.d.ts.map +1 -0
- package/dist/cli/doctor-readiness-release-path.js +275 -0
- package/dist/cli/doctor-readiness-release-path.js.map +1 -0
- package/dist/cli/doctor-readiness-types.d.ts +25 -0
- package/dist/cli/doctor-readiness-types.d.ts.map +1 -0
- package/dist/cli/doctor-readiness-types.js +13 -0
- package/dist/cli/doctor-readiness-types.js.map +1 -0
- package/dist/cli/doctor-readiness-workflows.d.ts +64 -0
- package/dist/cli/doctor-readiness-workflows.d.ts.map +1 -0
- package/dist/cli/doctor-readiness-workflows.js +198 -0
- package/dist/cli/doctor-readiness-workflows.js.map +1 -0
- package/dist/cli/doctor-readiness.d.ts +19 -3
- package/dist/cli/doctor-readiness.d.ts.map +1 -1
- package/dist/cli/doctor-readiness.js +87 -26
- package/dist/cli/doctor-readiness.js.map +1 -1
- package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
- package/dist/core/upstream-evidence-manifest.js +10 -0
- 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,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Credential over-authority detection for the delivery/authority readiness
|
|
3
|
+
* dimension — ship blocker B3 (PRD #1739, #1896).
|
|
4
|
+
*
|
|
5
|
+
* B3 asks whether the credential that ships carries only the authority it needs.
|
|
6
|
+
* The question is answered offline from what the workflows *declare*, because a
|
|
7
|
+
* credential's blast radius is a property of the declaration, not of any
|
|
8
|
+
* particular run: a token granted `write-all` is over-authorized whether or not
|
|
9
|
+
* today's run happened to use it.
|
|
10
|
+
*
|
|
11
|
+
* Four declarations are treated as material over-authority: inherited secrets
|
|
12
|
+
* (`secrets: inherit` hands a called workflow everything), `write-all`/`read-all`
|
|
13
|
+
* blanket permission grants, a job that uses `GITHUB_TOKEN` with no
|
|
14
|
+
* `permissions` block at all (so it takes the repository default rather than a
|
|
15
|
+
* stated minimum), and static long-lived AWS keys in a job that could have used
|
|
16
|
+
* OIDC instead. Each is provable from the declaration alone.
|
|
17
|
+
*
|
|
18
|
+
* A fifth signal — one secret NAME appearing under several environments — is
|
|
19
|
+
* reported as an *observation*, never a blocker: environment secrets are meant
|
|
20
|
+
* to reuse one name per environment, and repository-scope versus
|
|
21
|
+
* environment-scope is not decidable from YAML.
|
|
22
|
+
*
|
|
23
|
+
* It lives beside the delivery producer rather than inside it for file-size
|
|
24
|
+
* hygiene — the same split the blocker gate and journey wiring already use.
|
|
25
|
+
* @module cli/doctor-readiness-credentials
|
|
26
|
+
*/
|
|
27
|
+
import type { ParsedWorkflow } from "./doctor-readiness-workflows.js";
|
|
28
|
+
/** The credential half of a delivery/authority assessment. */
|
|
29
|
+
export interface CredentialFindings {
|
|
30
|
+
/** Provable over-authority: each line stands blocker B3. */
|
|
31
|
+
readonly violations: readonly string[];
|
|
32
|
+
/** Observations that are real but not decidable offline; never blocking. */
|
|
33
|
+
readonly informational: readonly string[];
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Detect credential over-authority across the repository's workflows.
|
|
37
|
+
*
|
|
38
|
+
* Violations are ordered by consequence: blanket grants and inherited secrets
|
|
39
|
+
* first (they are unbounded), then narrower over-authority. Anything the
|
|
40
|
+
* workflow files cannot settle lands in `informational`, which carries no
|
|
41
|
+
* `blocker` key and therefore can never flip a verdict.
|
|
42
|
+
* @param workflows - Parsed workflows
|
|
43
|
+
* @returns Violations and informational observations
|
|
44
|
+
*/
|
|
45
|
+
export declare function detectCredentialFindings(workflows: readonly ParsedWorkflow[]): CredentialFindings;
|
|
46
|
+
//# sourceMappingURL=doctor-readiness-credentials.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor-readiness-credentials.d.ts","sourceRoot":"","sources":["../../src/cli/doctor-readiness-credentials.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,OAAO,KAAK,EACV,cAAc,EAGf,MAAM,iCAAiC,CAAC;AA4OzC,8DAA8D;AAC9D,MAAM,WAAW,kBAAkB;IACjC,4DAA4D;IAC5D,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;IACvC,4EAA4E;IAC5E,QAAQ,CAAC,aAAa,EAAE,SAAS,MAAM,EAAE,CAAC;CAC3C;AAED;;;;;;;;;GASG;AACH,wBAAgB,wBAAwB,CACtC,SAAS,EAAE,SAAS,cAAc,EAAE,GACnC,kBAAkB,CAYpB"}
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
/** Blanket permission scalars that grant far more than any one job needs. */
|
|
2
|
+
const BLANKET_PERMISSIONS = new Set(["write-all", "read-all"]);
|
|
3
|
+
/** Matches every `secrets.NAME` reference inside a job's declared text. */
|
|
4
|
+
const SECRET_REFERENCE = /secrets\.(\w+)/g;
|
|
5
|
+
/** Static AWS credential inputs that OIDC (`id-token: write`) would replace. */
|
|
6
|
+
const STATIC_AWS_KEYS = ["aws-access-key-id", "aws-secret-access-key"];
|
|
7
|
+
/** Matches a repository-token reference in either of its spellings. */
|
|
8
|
+
const REPOSITORY_TOKEN = /GITHUB_TOKEN|github\.token/;
|
|
9
|
+
/**
|
|
10
|
+
* Flatten every string a job declares — step commands, actions, `env`, and
|
|
11
|
+
* `with` — into one searchable blob so a credential reference is found wherever
|
|
12
|
+
* it is stated.
|
|
13
|
+
* @param job - The parsed job
|
|
14
|
+
* @returns Newline-joined declared text
|
|
15
|
+
*/
|
|
16
|
+
function jobText(job) {
|
|
17
|
+
return job.steps
|
|
18
|
+
.flatMap(step => [step.run, step.uses, step.inputs])
|
|
19
|
+
.filter(part => part !== "")
|
|
20
|
+
.join("\n");
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Whether a permissions block grants OIDC token minting, which is what makes a
|
|
24
|
+
* keyless cloud login possible.
|
|
25
|
+
* @param permissions - A job- or workflow-level permissions block
|
|
26
|
+
* @returns True when `id-token` is granted write
|
|
27
|
+
*/
|
|
28
|
+
function grantsOidc(permissions) {
|
|
29
|
+
return (typeof permissions === "object" &&
|
|
30
|
+
permissions !== null &&
|
|
31
|
+
permissions["id-token"] === "write");
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Report a blanket `write-all`/`read-all` grant at either scope.
|
|
35
|
+
* @param scope - Human-readable scope label for the evidence line
|
|
36
|
+
* @param permissions - The permissions block to inspect
|
|
37
|
+
* @returns Evidence lines (empty when the grant is scoped)
|
|
38
|
+
*/
|
|
39
|
+
function blanketGrantViolations(scope, permissions) {
|
|
40
|
+
if (typeof permissions === "string" && BLANKET_PERMISSIONS.has(permissions)) {
|
|
41
|
+
return [
|
|
42
|
+
`${scope} declares \`permissions: ${permissions}\`, granting every ` +
|
|
43
|
+
"scope the repository token can carry instead of only what the job needs",
|
|
44
|
+
];
|
|
45
|
+
}
|
|
46
|
+
return [];
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Report an inherited secret block, which hands a called workflow every secret
|
|
50
|
+
* the repository holds rather than the ones it needs.
|
|
51
|
+
* @param where - Evidence location label
|
|
52
|
+
* @param job - The parsed job
|
|
53
|
+
* @returns Evidence lines (empty when secrets are mapped explicitly)
|
|
54
|
+
*/
|
|
55
|
+
function inheritedSecretViolations(where, job) {
|
|
56
|
+
return job.secrets === "inherit"
|
|
57
|
+
? [
|
|
58
|
+
`${where} declares \`secrets: inherit\`, handing the called workflow ` +
|
|
59
|
+
"every secret in the repository rather than the ones it needs",
|
|
60
|
+
]
|
|
61
|
+
: [];
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Report a job that uses the repository token with no `permissions:` block at
|
|
65
|
+
* either scope, so it runs at the repository default instead of a stated
|
|
66
|
+
* minimum.
|
|
67
|
+
* @param where - Evidence location label
|
|
68
|
+
* @param workflow - The workflow declaring the job
|
|
69
|
+
* @param job - The parsed job
|
|
70
|
+
* @param text - The job's flattened declared text
|
|
71
|
+
* @returns Evidence lines (empty when permissions are declared)
|
|
72
|
+
*/
|
|
73
|
+
function unscopedTokenViolations(where, workflow, job, text) {
|
|
74
|
+
const unscoped = REPOSITORY_TOKEN.test(text) &&
|
|
75
|
+
job.permissions === null &&
|
|
76
|
+
workflow.permissions === null;
|
|
77
|
+
return unscoped
|
|
78
|
+
? [
|
|
79
|
+
`${where} uses GITHUB_TOKEN with no \`permissions:\` block at either ` +
|
|
80
|
+
"scope, so it runs with the repository default rather than a stated minimum",
|
|
81
|
+
]
|
|
82
|
+
: [];
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Report static long-lived cloud keys in a job that could have authenticated
|
|
86
|
+
* keylessly through OIDC.
|
|
87
|
+
* @param where - Evidence location label
|
|
88
|
+
* @param workflow - The workflow declaring the job
|
|
89
|
+
* @param job - The parsed job
|
|
90
|
+
* @param text - The job's flattened declared text
|
|
91
|
+
* @returns Evidence lines (empty when the job is keyless or already OIDC-enabled)
|
|
92
|
+
*/
|
|
93
|
+
function staticKeyViolations(where, workflow, job, text) {
|
|
94
|
+
const staticKey = STATIC_AWS_KEYS.find(key => text.includes(key));
|
|
95
|
+
if (staticKey === undefined ||
|
|
96
|
+
grantsOidc(job.permissions) ||
|
|
97
|
+
grantsOidc(workflow.permissions)) {
|
|
98
|
+
return [];
|
|
99
|
+
}
|
|
100
|
+
return [
|
|
101
|
+
`${where} authenticates with the static long-lived credential ` +
|
|
102
|
+
`\`${staticKey}\` where keyless OIDC (\`id-token: write\`) would do`,
|
|
103
|
+
];
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Detect per-job credential over-authority inside one workflow.
|
|
107
|
+
* @param workflow - The parsed workflow
|
|
108
|
+
* @param job - The job to inspect
|
|
109
|
+
* @returns Evidence lines for this job (empty when scoped correctly)
|
|
110
|
+
*/
|
|
111
|
+
function jobCredentialViolations(workflow, job) {
|
|
112
|
+
const where = `${workflow.file} job \`${job.id}\``;
|
|
113
|
+
const text = jobText(job);
|
|
114
|
+
return [
|
|
115
|
+
...blanketGrantViolations(where, job.permissions),
|
|
116
|
+
...inheritedSecretViolations(where, job),
|
|
117
|
+
...unscopedTokenViolations(where, workflow, job, text),
|
|
118
|
+
...staticKeyViolations(where, workflow, job, text),
|
|
119
|
+
];
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Pair every secret reference with each deployment environment that uses it.
|
|
123
|
+
* @param workflows - Parsed workflows
|
|
124
|
+
* @returns One pair per (secret, environment) reference
|
|
125
|
+
*/
|
|
126
|
+
function secretEnvironmentPairs(workflows) {
|
|
127
|
+
const jobs = workflows.flatMap(workflow => workflow.jobs);
|
|
128
|
+
return jobs
|
|
129
|
+
.filter(job => job.environment.length > 0)
|
|
130
|
+
.flatMap(job => jobSecretEnvironmentPairs(job));
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Pair one job's secret references with the environments that job deploys to.
|
|
134
|
+
* @param job - A job declaring at least one environment
|
|
135
|
+
* @returns One pair per (secret, environment) reference in this job
|
|
136
|
+
*/
|
|
137
|
+
function jobSecretEnvironmentPairs(job) {
|
|
138
|
+
const secrets = [...jobText(job).matchAll(SECRET_REFERENCE)]
|
|
139
|
+
.map(match => match[1] ?? "")
|
|
140
|
+
// GITHUB_TOKEN is minted fresh per job per run, so it cannot be "shared"
|
|
141
|
+
// between environments — reporting it as such is impossible by construction.
|
|
142
|
+
.filter(secret => secret !== "GITHUB_TOKEN");
|
|
143
|
+
return secrets.flatMap(secret => job.environment.map(environment => ({ secret, environment })));
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Sort and de-duplicate a list of names for stable evidence text.
|
|
147
|
+
* @param names - Raw names
|
|
148
|
+
* @returns Unique names in locale order
|
|
149
|
+
*/
|
|
150
|
+
function uniqueSorted(names) {
|
|
151
|
+
return [...new Set(names)].sort((a, b) => a.localeCompare(b));
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Note each secret NAME that appears under more than one deployment environment.
|
|
155
|
+
*
|
|
156
|
+
* This is informational, never a standing blocker. GitHub environment secrets
|
|
157
|
+
* are *supposed* to reuse one name across environments — that is the recommended
|
|
158
|
+
* least-privilege pattern, with a distinct value stored per environment — and
|
|
159
|
+
* whether a given name resolves to a repository-scoped secret (genuinely shared)
|
|
160
|
+
* or an environment-scoped one (correctly isolated) is not decidable from the
|
|
161
|
+
* YAML. Blocking on it would fail correct repositories for doing the right thing.
|
|
162
|
+
* @param workflows - Parsed workflows
|
|
163
|
+
* @returns Observation lines (empty when no name is reused)
|
|
164
|
+
*/
|
|
165
|
+
function sharedSecretObservations(workflows) {
|
|
166
|
+
const pairs = secretEnvironmentPairs(workflows);
|
|
167
|
+
return uniqueSorted(pairs.map(pair => pair.secret)).flatMap(secret => {
|
|
168
|
+
const environments = uniqueSorted(pairs.filter(pair => pair.secret === secret).map(pair => pair.environment));
|
|
169
|
+
return environments.length > 1
|
|
170
|
+
? [
|
|
171
|
+
`secret name \`${secret}\` appears under ${environments.length} ` +
|
|
172
|
+
`deployment environments (${environments.join(", ")}). If it is an ` +
|
|
173
|
+
"environment-scoped secret this is the recommended pattern; if it " +
|
|
174
|
+
"is repository-scoped, one credential spans every environment. " +
|
|
175
|
+
"Which one it is cannot be determined from the workflow files.",
|
|
176
|
+
]
|
|
177
|
+
: [];
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Detect credential over-authority across the repository's workflows.
|
|
182
|
+
*
|
|
183
|
+
* Violations are ordered by consequence: blanket grants and inherited secrets
|
|
184
|
+
* first (they are unbounded), then narrower over-authority. Anything the
|
|
185
|
+
* workflow files cannot settle lands in `informational`, which carries no
|
|
186
|
+
* `blocker` key and therefore can never flip a verdict.
|
|
187
|
+
* @param workflows - Parsed workflows
|
|
188
|
+
* @returns Violations and informational observations
|
|
189
|
+
*/
|
|
190
|
+
export function detectCredentialFindings(workflows) {
|
|
191
|
+
return {
|
|
192
|
+
violations: [
|
|
193
|
+
...workflows.flatMap(workflow => blanketGrantViolations(workflow.file, workflow.permissions)),
|
|
194
|
+
...workflows.flatMap(workflow => workflow.jobs.flatMap(job => jobCredentialViolations(workflow, job))),
|
|
195
|
+
],
|
|
196
|
+
informational: sharedSecretObservations(workflows),
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
//# sourceMappingURL=doctor-readiness-credentials.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor-readiness-credentials.js","sourceRoot":"","sources":["../../src/cli/doctor-readiness-credentials.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { ReadinessDimensionRecord } from "./doctor-readiness-types.js";
|
|
2
|
+
import { type ParsedWorkflow } from "./doctor-readiness-workflows.js";
|
|
3
|
+
/** The delivery/authority readiness dimension id (readiness-rubric, RRR-1). */
|
|
4
|
+
export declare const DELIVERY_AUTHORITY_DIMENSION_ID = "delivery-authority";
|
|
5
|
+
/**
|
|
6
|
+
* Assess the delivery/authority dimension: B2 (release path bypasses the
|
|
7
|
+
* validated artifact) and B3 (credentials carry unintended authority). Offline
|
|
8
|
+
* by construction — it reads only the repository's declared workflows, and
|
|
9
|
+
* degrades to a stated-reason SKIP wherever those files cannot settle the
|
|
10
|
+
* question.
|
|
11
|
+
* @param root - Project root to assess
|
|
12
|
+
* @param parsedWorkflows - Pre-parsed workflows (default: parse `root`)
|
|
13
|
+
* @returns The delivery/authority dimension record
|
|
14
|
+
*/
|
|
15
|
+
export declare function assessDeliveryAuthorityDimension(root: string, parsedWorkflows?: readonly ParsedWorkflow[]): Promise<ReadinessDimensionRecord>;
|
|
16
|
+
//# sourceMappingURL=doctor-readiness-delivery.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor-readiness-delivery.d.ts","sourceRoot":"","sources":["../../src/cli/doctor-readiness-delivery.ts"],"names":[],"mappings":"AAmCA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAC;AAC5E,OAAO,EACL,KAAK,cAAc,EAEpB,MAAM,iCAAiC,CAAC;AAEzC,+EAA+E;AAC/E,eAAO,MAAM,+BAA+B,uBAAuB,CAAC;AAgPpE;;;;;;;;;GASG;AACH,wBAAsB,gCAAgC,CACpD,IAAI,EAAE,MAAM,EACZ,eAAe,CAAC,EAAE,SAAS,cAAc,EAAE,GAC1C,OAAO,CAAC,wBAAwB,CAAC,CAiBnC"}
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The delivery/authority readiness producer — ship blockers B2 and B3
|
|
3
|
+
* (PRD #1739, #1896).
|
|
4
|
+
*
|
|
5
|
+
* Dimension 7 of the `readiness-rubric` asks two questions no other dimension
|
|
6
|
+
* can answer: does the thing that ships equal the thing that was validated
|
|
7
|
+
* (B2), and does the shipping credential carry only the authority it needs
|
|
8
|
+
* (B3)? Both are answered offline from the repository's own
|
|
9
|
+
* `.github/workflows/*.yml` declarations — the release path is a property of
|
|
10
|
+
* what CI declares, so no network call is needed and none is made.
|
|
11
|
+
*
|
|
12
|
+
* Two disciplines are load-bearing rather than stylistic:
|
|
13
|
+
*
|
|
14
|
+
* 1. **A finding names a `blocker` id ONLY on an actual violation.** The blocker
|
|
15
|
+
* engine stands a blocker up on any finding that names an id and carries
|
|
16
|
+
* evidence, regardless of the finding's status — so a clean repository's PASS
|
|
17
|
+
* finding must carry no `blocker` key, or a healthy repository reports
|
|
18
|
+
* NOT_READY.
|
|
19
|
+
* 2. **Never manufacture RED from absence.** Reading workflow files offline
|
|
20
|
+
* cannot see a calling workflow, an upstream `workflow_run`, or a branch
|
|
21
|
+
* protection rule. When the file alone does not prove a bypass, this producer
|
|
22
|
+
* renders a stated-reason SKIP — including when the repository publishes
|
|
23
|
+
* nothing at all, because "nothing ships here" is not proof that what ships
|
|
24
|
+
* was validated.
|
|
25
|
+
* @module cli/doctor-readiness-delivery
|
|
26
|
+
*/
|
|
27
|
+
import { detectCredentialFindings, } from "./doctor-readiness-credentials.js";
|
|
28
|
+
import { assessReleasePath, PROMOTION_ACTION, } from "./doctor-readiness-release-path.js";
|
|
29
|
+
import { parseRepositoryWorkflows, } from "./doctor-readiness-workflows.js";
|
|
30
|
+
/** The delivery/authority readiness dimension id (readiness-rubric, RRR-1). */
|
|
31
|
+
export const DELIVERY_AUTHORITY_DIMENSION_ID = "delivery-authority";
|
|
32
|
+
/** The ship blocker for a release path that bypasses the validated artifact. */
|
|
33
|
+
const RELEASE_BLOCKER_ID = "B2";
|
|
34
|
+
/** The ship blocker for credentials carrying material unintended authority. */
|
|
35
|
+
const CREDENTIAL_BLOCKER_ID = "B3";
|
|
36
|
+
/**
|
|
37
|
+
* Assess every publishing job across every workflow.
|
|
38
|
+
* @param workflows - Parsed workflows
|
|
39
|
+
* @returns What the release paths established, in aggregate
|
|
40
|
+
*/
|
|
41
|
+
function summarizeReleasePaths(workflows) {
|
|
42
|
+
const outcomes = workflows.flatMap(workflow => workflow.jobs.flatMap(job => {
|
|
43
|
+
const outcome = assessReleasePath(workflow, job);
|
|
44
|
+
return outcome ? [outcome] : [];
|
|
45
|
+
}));
|
|
46
|
+
return {
|
|
47
|
+
violations: outcomes.flatMap(outcome => outcome.kind === "violation" ? [outcome.evidence] : []),
|
|
48
|
+
unresolved: outcomes.flatMap(outcome => outcome.kind === "unresolved" ? [outcome.reason] : []),
|
|
49
|
+
cleanCount: outcomes.filter(outcome => outcome.kind === "clean").length,
|
|
50
|
+
publishJobCount: outcomes.length,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Build the B2 finding from its evidence lines.
|
|
55
|
+
* @param violations - Evidence lines
|
|
56
|
+
* @returns The rubric-shaped B2 finding
|
|
57
|
+
*/
|
|
58
|
+
function releaseFinding(violations) {
|
|
59
|
+
return {
|
|
60
|
+
blocker: RELEASE_BLOCKER_ID,
|
|
61
|
+
invariant_violated: "what ships to users is the exact artifact the validating pipeline checked",
|
|
62
|
+
evidence: violations.join(" | "),
|
|
63
|
+
why_proof_missed: "the existing checks prove things about the source tree, not about the " +
|
|
64
|
+
"artifact the release path actually hands to users, so a release that " +
|
|
65
|
+
"skips or rebuilds past them still reports green",
|
|
66
|
+
root_correction: "make the release job depend on the validating jobs and publish only an " +
|
|
67
|
+
`artifact downloaded via \`${PROMOTION_ACTION}\`, so the validated bytes ` +
|
|
68
|
+
"are the only bytes that can ship",
|
|
69
|
+
machinery_to_remove: [
|
|
70
|
+
"any rebuild step inside the release job, which exists only because the " +
|
|
71
|
+
"validated artifact was not carried forward",
|
|
72
|
+
],
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Build the B3 finding from its evidence lines.
|
|
77
|
+
* @param violations - Evidence lines
|
|
78
|
+
* @returns The rubric-shaped B3 finding
|
|
79
|
+
*/
|
|
80
|
+
function credentialFinding(violations) {
|
|
81
|
+
return {
|
|
82
|
+
blocker: CREDENTIAL_BLOCKER_ID,
|
|
83
|
+
invariant_violated: "a shipping credential carries only the authority the job it runs needs",
|
|
84
|
+
evidence: violations.join(" | "),
|
|
85
|
+
why_proof_missed: "credential scope is declared, never exercised, so no test or review run " +
|
|
86
|
+
"observes the unused authority a workflow silently carries",
|
|
87
|
+
root_correction: "declare a minimal job-level `permissions:` block, map secrets explicitly " +
|
|
88
|
+
"per environment instead of inheriting them, and prefer keyless OIDC over " +
|
|
89
|
+
"long-lived static keys",
|
|
90
|
+
machinery_to_remove: [
|
|
91
|
+
"blanket permission grants and inherited secret blocks made unnecessary " +
|
|
92
|
+
"by explicit per-job scoping",
|
|
93
|
+
],
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Wrap non-blocking observations as findings. They deliberately carry no
|
|
98
|
+
* `blocker` key: naming one would stand a blocker up on an observation that was
|
|
99
|
+
* never decidable offline.
|
|
100
|
+
* @param notes - Informational lines
|
|
101
|
+
* @returns Findings, one per note
|
|
102
|
+
*/
|
|
103
|
+
function informationalFindings(notes) {
|
|
104
|
+
return notes.map(note => ({ observation: note, blocking: false }));
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Build the SKIP record for a repository whose release paths could not be
|
|
108
|
+
* settled from the workflow files alone.
|
|
109
|
+
* @param reasons - Stated reasons, one per unsettled release path
|
|
110
|
+
* @param credentials - The credential half of the assessment
|
|
111
|
+
* @returns The SKIP dimension record
|
|
112
|
+
*/
|
|
113
|
+
function unresolvedRecord(reasons, credentials) {
|
|
114
|
+
return {
|
|
115
|
+
id: DELIVERY_AUTHORITY_DIMENSION_ID,
|
|
116
|
+
status: "SKIP",
|
|
117
|
+
findings: [
|
|
118
|
+
{ reason: reasons.join(" | "), skip: true },
|
|
119
|
+
...informationalFindings(credentials.informational),
|
|
120
|
+
],
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Build the PASS record. It carries evidence of exactly what was inspected and
|
|
125
|
+
* names no `blocker` — naming one here would stand the blocker up.
|
|
126
|
+
* @param summary - What the release paths established
|
|
127
|
+
* @param workflows - Parsed workflows
|
|
128
|
+
* @param credentials - The credential half of the assessment
|
|
129
|
+
* @returns The PASS dimension record
|
|
130
|
+
*/
|
|
131
|
+
function cleanRecord(summary, workflows, credentials) {
|
|
132
|
+
return {
|
|
133
|
+
id: DELIVERY_AUTHORITY_DIMENSION_ID,
|
|
134
|
+
status: "PASS",
|
|
135
|
+
findings: [
|
|
136
|
+
{
|
|
137
|
+
evidence: `Inspected ${summary.publishJobCount} publishing job(s) across ` +
|
|
138
|
+
`${workflows.length} workflow file(s): each is preceded by a test ` +
|
|
139
|
+
`run or promotes the CI-built artifact via \`${PROMOTION_ACTION}\`. ` +
|
|
140
|
+
"No workflow declares blanket permissions, inherited secrets, or " +
|
|
141
|
+
"static cloud keys.",
|
|
142
|
+
checked: [RELEASE_BLOCKER_ID, CREDENTIAL_BLOCKER_ID],
|
|
143
|
+
},
|
|
144
|
+
...informationalFindings(credentials.informational),
|
|
145
|
+
],
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Build the FAIL record from whichever halves found violations, ordered by
|
|
150
|
+
* consequence: shipping unvalidated bytes outranks over-broad authority, because
|
|
151
|
+
* it is already user-visible rather than latent.
|
|
152
|
+
* @param summary - What the release paths established
|
|
153
|
+
* @param credentials - The credential half of the assessment
|
|
154
|
+
* @returns The FAIL dimension record
|
|
155
|
+
*/
|
|
156
|
+
function violationRecord(summary, credentials) {
|
|
157
|
+
return {
|
|
158
|
+
id: DELIVERY_AUTHORITY_DIMENSION_ID,
|
|
159
|
+
status: "FAIL",
|
|
160
|
+
findings: [
|
|
161
|
+
...(summary.violations.length > 0
|
|
162
|
+
? [releaseFinding(summary.violations)]
|
|
163
|
+
: []),
|
|
164
|
+
...(credentials.violations.length > 0
|
|
165
|
+
? [credentialFinding(credentials.violations)]
|
|
166
|
+
: []),
|
|
167
|
+
// A standing blocker must not swallow the release paths that could not be
|
|
168
|
+
// settled offline: dropping those reasons is #1898's defect one layer in.
|
|
169
|
+
// They carry no `blocker` key, so they add nothing to the verdict.
|
|
170
|
+
...informationalFindings(summary.unresolved),
|
|
171
|
+
...informationalFindings(credentials.informational),
|
|
172
|
+
],
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Build the SKIP record for a repository that declares no workflows at all.
|
|
177
|
+
* @returns The SKIP dimension record
|
|
178
|
+
*/
|
|
179
|
+
function noWorkflowsRecord() {
|
|
180
|
+
return {
|
|
181
|
+
id: DELIVERY_AUTHORITY_DIMENSION_ID,
|
|
182
|
+
status: "SKIP",
|
|
183
|
+
findings: [
|
|
184
|
+
{
|
|
185
|
+
reason: "no .github/workflows/*.yml files were found, so this repository " +
|
|
186
|
+
"declares no release path or shipping credential to assess; " +
|
|
187
|
+
"delivery authority is not established either way",
|
|
188
|
+
skip: true,
|
|
189
|
+
},
|
|
190
|
+
],
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Build the SKIP record for a repository whose workflows publish nothing.
|
|
195
|
+
* @param workflows - Parsed workflows
|
|
196
|
+
* @param credentials - The credential half of the assessment
|
|
197
|
+
* @returns The SKIP dimension record
|
|
198
|
+
*/
|
|
199
|
+
function noReleasePathRecord(workflows, credentials) {
|
|
200
|
+
return {
|
|
201
|
+
id: DELIVERY_AUTHORITY_DIMENSION_ID,
|
|
202
|
+
status: "SKIP",
|
|
203
|
+
findings: [
|
|
204
|
+
{
|
|
205
|
+
reason: `None of the ${workflows.length} workflow file(s) declares a ` +
|
|
206
|
+
"publishing or deploy step, so whether what ships equals what was " +
|
|
207
|
+
"validated is not established either way. Credential scope was " +
|
|
208
|
+
"assessed and found nothing over-authorized.",
|
|
209
|
+
skip: true,
|
|
210
|
+
},
|
|
211
|
+
...informationalFindings(credentials.informational),
|
|
212
|
+
],
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Assess the delivery/authority dimension: B2 (release path bypasses the
|
|
217
|
+
* validated artifact) and B3 (credentials carry unintended authority). Offline
|
|
218
|
+
* by construction — it reads only the repository's declared workflows, and
|
|
219
|
+
* degrades to a stated-reason SKIP wherever those files cannot settle the
|
|
220
|
+
* question.
|
|
221
|
+
* @param root - Project root to assess
|
|
222
|
+
* @param parsedWorkflows - Pre-parsed workflows (default: parse `root`)
|
|
223
|
+
* @returns The delivery/authority dimension record
|
|
224
|
+
*/
|
|
225
|
+
export async function assessDeliveryAuthorityDimension(root, parsedWorkflows) {
|
|
226
|
+
const workflows = parsedWorkflows ?? (await parseRepositoryWorkflows(root));
|
|
227
|
+
if (workflows.length === 0) {
|
|
228
|
+
return noWorkflowsRecord();
|
|
229
|
+
}
|
|
230
|
+
const summary = summarizeReleasePaths(workflows);
|
|
231
|
+
const credentials = detectCredentialFindings(workflows);
|
|
232
|
+
if (summary.violations.length > 0 || credentials.violations.length > 0) {
|
|
233
|
+
return violationRecord(summary, credentials);
|
|
234
|
+
}
|
|
235
|
+
if (summary.unresolved.length > 0) {
|
|
236
|
+
return unresolvedRecord(summary.unresolved, credentials);
|
|
237
|
+
}
|
|
238
|
+
if (summary.publishJobCount === 0) {
|
|
239
|
+
return noReleasePathRecord(workflows, credentials);
|
|
240
|
+
}
|
|
241
|
+
return cleanRecord(summary, workflows, credentials);
|
|
242
|
+
}
|
|
243
|
+
//# sourceMappingURL=doctor-readiness-delivery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor-readiness-delivery.js","sourceRoot":"","sources":["../../src/cli/doctor-readiness-delivery.ts"],"names":[],"mappings":"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"}
|
|
@@ -26,20 +26,14 @@
|
|
|
26
26
|
* @module cli/doctor-readiness-journey
|
|
27
27
|
*/
|
|
28
28
|
import { type MutationPolicy, resolveMutationPolicy } from "./doctor-readiness-journey-freshness.js";
|
|
29
|
+
import type { ReadinessDimensionRecord } from "./doctor-readiness-types.js";
|
|
29
30
|
import { type RuntimeWorkerSignature } from "./doctor-worker-journey.js";
|
|
30
31
|
export { resolveMutationPolicy, type MutationPolicy };
|
|
31
32
|
/** The execution/proof readiness dimension id (readiness-rubric, RRR-1). */
|
|
32
33
|
export declare const EXECUTION_PROOF_DIMENSION_ID = "execution-proof";
|
|
33
34
|
/** The proportionality readiness dimension id (readiness-rubric, RRR-1). */
|
|
34
35
|
export declare const PROPORTIONALITY_DIMENSION_ID = "proportionality";
|
|
35
|
-
|
|
36
|
-
type ReadinessStatus = "PASS" | "WARN" | "FAIL" | "SKIP";
|
|
37
|
-
/** A per-dimension record the readiness collector persists. */
|
|
38
|
-
export interface JourneyDimensionRecord {
|
|
39
|
-
readonly id: string;
|
|
40
|
-
readonly status: ReadinessStatus;
|
|
41
|
-
readonly findings: readonly unknown[];
|
|
42
|
-
}
|
|
36
|
+
export type { ReadinessDimensionRecord };
|
|
43
37
|
/** The outcome of running a representative journey. */
|
|
44
38
|
export type JourneyOutcome = {
|
|
45
39
|
readonly result: "passed";
|
|
@@ -97,7 +91,7 @@ export interface ProportionalityOptions {
|
|
|
97
91
|
* @param options - Injected collaborators and freshness inputs
|
|
98
92
|
* @returns The execution/proof dimension record
|
|
99
93
|
*/
|
|
100
|
-
export declare function assessExecutionProofDimension(targetPath: string, options?: ExecutionProofOptions): Promise<
|
|
94
|
+
export declare function assessExecutionProofDimension(targetPath: string, options?: ExecutionProofOptions): Promise<ReadinessDimensionRecord>;
|
|
101
95
|
/**
|
|
102
96
|
* Assess the proportionality dimension: surface #1742's scaffolding-subtraction
|
|
103
97
|
* candidate count into `machinery_to_remove`. Surfaced, never auto-deleted
|
|
@@ -106,5 +100,5 @@ export declare function assessExecutionProofDimension(targetPath: string, option
|
|
|
106
100
|
* @param options - Injected subtraction count
|
|
107
101
|
* @returns The proportionality dimension record
|
|
108
102
|
*/
|
|
109
|
-
export declare function assessProportionalityDimension(targetPath: string, options?: ProportionalityOptions): Promise<
|
|
103
|
+
export declare function assessProportionalityDimension(targetPath: string, options?: ProportionalityOptions): Promise<ReadinessDimensionRecord>;
|
|
110
104
|
//# sourceMappingURL=doctor-readiness-journey.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doctor-readiness-journey.d.ts","sourceRoot":"","sources":["../../src/cli/doctor-readiness-journey.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,OAAO,EAEL,KAAK,cAAc,EACnB,qBAAqB,EAEtB,MAAM,yCAAyC,CAAC;AACjD,OAAO,EAEL,KAAK,sBAAsB,EAE5B,MAAM,4BAA4B,CAAC;AAKpC,OAAO,EAAE,qBAAqB,EAAE,KAAK,cAAc,EAAE,CAAC;AAEtD,4EAA4E;AAC5E,eAAO,MAAM,4BAA4B,oBAAoB,CAAC;AAE9D,4EAA4E;AAC5E,eAAO,MAAM,4BAA4B,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"doctor-readiness-journey.d.ts","sourceRoot":"","sources":["../../src/cli/doctor-readiness-journey.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,OAAO,EAEL,KAAK,cAAc,EACnB,qBAAqB,EAEtB,MAAM,yCAAyC,CAAC;AACjD,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAC;AAC5E,OAAO,EAEL,KAAK,sBAAsB,EAE5B,MAAM,4BAA4B,CAAC;AAKpC,OAAO,EAAE,qBAAqB,EAAE,KAAK,cAAc,EAAE,CAAC;AAEtD,4EAA4E;AAC5E,eAAO,MAAM,4BAA4B,oBAAoB,CAAC;AAE9D,4EAA4E;AAC5E,eAAO,MAAM,4BAA4B,oBAAoB,CAAC;AAa9D,YAAY,EAAE,wBAAwB,EAAE,CAAC;AAEzC,uDAAuD;AACvD,MAAM,MAAM,cAAc,GACtB;IAAE,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GACxD;IACE,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;CACjC,CAAC;AAEN,yDAAyD;AACzD,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,sBAAsB,CAAC;IAC3C,QAAQ,CAAC,cAAc,EAAE,cAAc,CAAC;CACzC;AAED,sEAAsE;AACtE,MAAM,MAAM,aAAa,GAAG,CAC1B,OAAO,EAAE,iBAAiB,KACvB,OAAO,CAAC,cAAc,CAAC,CAAC;AAE7B,6EAA6E;AAC7E,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,SAAS,EAAE,sBAAsB,CAAC;CAC5C;AAED,4DAA4D;AAC5D,MAAM,MAAM,kBAAkB,GAAG,CAC/B,OAAO,EAAE,oBAAoB,KAC1B,OAAO,CAAC,MAAM,CAAC,CAAC;AAErB,yDAAyD;AACzD,MAAM,WAAW,qBAAqB;IACpC,oDAAoD;IACpD,QAAQ,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC;IACpB;;;;OAIG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IACpC;;;;OAIG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,aAAa,CAAC;IACpC,iFAAiF;IACjF,QAAQ,CAAC,UAAU,CAAC,EAAE,kBAAkB,CAAC;IACzC,kFAAkF;IAClF,QAAQ,CAAC,cAAc,CAAC,EAAE,cAAc,CAAC;CAC1C;AAED,0DAA0D;AAC1D,MAAM,WAAW,sBAAsB;IACrC,mFAAmF;IACnF,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;CACpC;AAED;;;;;GAKG;AACH,wBAAsB,6BAA6B,CACjD,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE,qBAA0B,GAClC,OAAO,CAAC,wBAAwB,CAAC,CAsBnC;AAED;;;;;;;GAOG;AACH,wBAAsB,8BAA8B,CAClD,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAAC,wBAAwB,CAAC,CAyCnC"}
|
|
@@ -72,13 +72,29 @@ export async function assessProportionalityDimension(targetPath, options = {}) {
|
|
|
72
72
|
const count = options.subtractionCount ??
|
|
73
73
|
(await resolveWorkerJourneyEvidence(targetPath)).subtractionCount;
|
|
74
74
|
if (count <= 0) {
|
|
75
|
-
|
|
75
|
+
// A SKIP is never blank (#1898): it states why the dimension was not
|
|
76
|
+
// assessed, so silence is reported as silence rather than as health.
|
|
77
|
+
return {
|
|
78
|
+
id: PROPORTIONALITY_DIMENSION_ID,
|
|
79
|
+
status: "SKIP",
|
|
80
|
+
findings: [
|
|
81
|
+
{
|
|
82
|
+
reason: "the worker-epoch runner (#1742) surfaced no scaffolding-subtraction " +
|
|
83
|
+
"candidates, so there is nothing to weigh against the job; " +
|
|
84
|
+
"proportionality is reported as unassessed rather than as proven",
|
|
85
|
+
skip: true,
|
|
86
|
+
},
|
|
87
|
+
],
|
|
88
|
+
};
|
|
76
89
|
}
|
|
77
90
|
return {
|
|
78
91
|
id: PROPORTIONALITY_DIMENSION_ID,
|
|
79
92
|
status: "SKIP",
|
|
80
93
|
findings: [
|
|
81
94
|
{
|
|
95
|
+
reason: "proportionality is surfaced, never scored: subtraction candidates " +
|
|
96
|
+
"are reported for operator review and no readiness judgement is made",
|
|
97
|
+
skip: true,
|
|
82
98
|
machinery_to_remove: [
|
|
83
99
|
`${count} worker-specific scaffolding-subtraction candidate` +
|
|
84
100
|
`${count === 1 ? "" : "s"} surfaced by the worker-epoch runner (#1742)`,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doctor-readiness-journey.js","sourceRoot":"","sources":["../../src/cli/doctor-readiness-journey.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,OAAO,EACL,4BAA4B,EAE5B,qBAAqB,EACrB,4BAA4B,GAC7B,MAAM,yCAAyC,CAAC;
|
|
1
|
+
{"version":3,"file":"doctor-readiness-journey.js","sourceRoot":"","sources":["../../src/cli/doctor-readiness-journey.ts"],"names":[],"mappings":"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"}
|