@codyswann/lisa 4.55.1 → 4.55.2
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/core/nightly-e2e-guard-behavior-certificate.js +2 -2
- package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
- package/dist/core/upstream-evidence-manifest.js +4 -65
- package/dist/core/upstream-evidence-manifest.js.map +1 -1
- package/package.json +4 -4
- package/plugins/lisa/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa/.codex-plugin/skills/lisa-linear-access/SKILL.md +1 -2
- package/plugins/lisa/scripts/linear-state-write-target.mjs +2 -2
- package/plugins/lisa/scripts/qa-signal-lifecycle.mjs +24 -11
- package/plugins/lisa/scripts/resolve-lifecycle-role.mjs +2 -7
- package/plugins/lisa/skills/lisa-linear-access/SKILL.md +1 -2
- package/plugins/lisa-agy/plugin.json +1 -1
- package/plugins/lisa-agy/scripts/linear-state-write-target.mjs +2 -2
- package/plugins/lisa-agy/scripts/qa-signal-lifecycle.mjs +24 -11
- package/plugins/lisa-agy/scripts/resolve-lifecycle-role.mjs +2 -7
- package/plugins/lisa-agy/skills/lisa-linear-access/SKILL.md +1 -2
- 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-copilot/scripts/linear-state-write-target.mjs +2 -2
- package/plugins/lisa-copilot/scripts/qa-signal-lifecycle.mjs +24 -11
- package/plugins/lisa-copilot/scripts/resolve-lifecycle-role.mjs +2 -7
- package/plugins/lisa-copilot/skills/lisa-linear-access/SKILL.md +1 -2
- package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cursor/scripts/linear-state-write-target.mjs +2 -2
- package/plugins/lisa-cursor/scripts/qa-signal-lifecycle.mjs +24 -11
- package/plugins/lisa-cursor/scripts/resolve-lifecycle-role.mjs +2 -7
- package/plugins/lisa-cursor/skills/lisa-linear-access/SKILL.md +1 -2
- 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
- package/plugins/src/base/scripts/linear-state-write-target.mjs +2 -2
- package/plugins/src/base/scripts/qa-signal-lifecycle.mjs +24 -11
- package/plugins/src/base/scripts/resolve-lifecycle-role.mjs +2 -7
- package/plugins/src/base/skills/lisa-linear-access/SKILL.md +1 -2
- package/plugins/lisa/.codex-plugin/skills/lisa-qa-checklist/SKILL.md +0 -70
- package/plugins/lisa/.codex-plugin/skills/lisa-qa-checklist/agents/openai.yaml +0 -4
- package/plugins/lisa/.codex-plugin/skills/lisa-qa-clear/SKILL.md +0 -86
- package/plugins/lisa/.codex-plugin/skills/lisa-qa-clear/agents/openai.yaml +0 -4
- package/plugins/lisa/.codex-plugin/skills/lisa-qa-fail/SKILL.md +0 -119
- package/plugins/lisa/.codex-plugin/skills/lisa-qa-fail/agents/openai.yaml +0 -4
- package/plugins/lisa/.codex-plugin/skills/lisa-qa-queue/SKILL.md +0 -94
- package/plugins/lisa/.codex-plugin/skills/lisa-qa-queue/agents/openai.yaml +0 -4
- package/plugins/lisa/commands/qa-checklist.md +0 -6
- package/plugins/lisa/commands/qa-clear.md +0 -6
- package/plugins/lisa/commands/qa-fail.md +0 -6
- package/plugins/lisa/commands/qa-queue.md +0 -6
- package/plugins/lisa/skills/lisa-qa-checklist/SKILL.md +0 -70
- package/plugins/lisa/skills/lisa-qa-checklist/agents/openai.yaml +0 -4
- package/plugins/lisa/skills/lisa-qa-clear/SKILL.md +0 -86
- package/plugins/lisa/skills/lisa-qa-clear/agents/openai.yaml +0 -4
- package/plugins/lisa/skills/lisa-qa-fail/SKILL.md +0 -119
- package/plugins/lisa/skills/lisa-qa-fail/agents/openai.yaml +0 -4
- package/plugins/lisa/skills/lisa-qa-queue/SKILL.md +0 -94
- package/plugins/lisa/skills/lisa-qa-queue/agents/openai.yaml +0 -4
- package/plugins/lisa-agy/commands/lisa/qa-checklist.md +0 -6
- package/plugins/lisa-agy/commands/lisa/qa-clear.md +0 -6
- package/plugins/lisa-agy/commands/lisa/qa-fail.md +0 -6
- package/plugins/lisa-agy/commands/lisa/qa-queue.md +0 -6
- package/plugins/lisa-agy/skills/lisa-qa-checklist/SKILL.md +0 -70
- package/plugins/lisa-agy/skills/lisa-qa-clear/SKILL.md +0 -86
- package/plugins/lisa-agy/skills/lisa-qa-fail/SKILL.md +0 -119
- package/plugins/lisa-agy/skills/lisa-qa-queue/SKILL.md +0 -94
- package/plugins/lisa-copilot/commands/lisa/qa-checklist.md +0 -6
- package/plugins/lisa-copilot/commands/lisa/qa-clear.md +0 -6
- package/plugins/lisa-copilot/commands/lisa/qa-fail.md +0 -6
- package/plugins/lisa-copilot/commands/lisa/qa-queue.md +0 -6
- package/plugins/lisa-copilot/skills/lisa-qa-checklist/SKILL.md +0 -70
- package/plugins/lisa-copilot/skills/lisa-qa-clear/SKILL.md +0 -86
- package/plugins/lisa-copilot/skills/lisa-qa-fail/SKILL.md +0 -119
- package/plugins/lisa-copilot/skills/lisa-qa-queue/SKILL.md +0 -94
- package/plugins/lisa-cursor/commands/lisa/qa-checklist.md +0 -6
- package/plugins/lisa-cursor/commands/lisa/qa-clear.md +0 -6
- package/plugins/lisa-cursor/commands/lisa/qa-fail.md +0 -6
- package/plugins/lisa-cursor/commands/lisa/qa-queue.md +0 -6
- package/plugins/lisa-cursor/skills/lisa-qa-checklist/SKILL.md +0 -70
- package/plugins/lisa-cursor/skills/lisa-qa-clear/SKILL.md +0 -86
- package/plugins/lisa-cursor/skills/lisa-qa-fail/SKILL.md +0 -119
- package/plugins/lisa-cursor/skills/lisa-qa-queue/SKILL.md +0 -94
- package/plugins/src/base/commands/qa-checklist.md +0 -6
- package/plugins/src/base/commands/qa-clear.md +0 -6
- package/plugins/src/base/commands/qa-fail.md +0 -6
- package/plugins/src/base/commands/qa-queue.md +0 -6
- package/plugins/src/base/skills/lisa-qa-checklist/SKILL.md +0 -70
- package/plugins/src/base/skills/lisa-qa-clear/SKILL.md +0 -86
- package/plugins/src/base/skills/lisa-qa-fail/SKILL.md +0 -119
- package/plugins/src/base/skills/lisa-qa-queue/SKILL.md +0 -94
package/package.json
CHANGED
|
@@ -187,7 +187,7 @@
|
|
|
187
187
|
"zod-validation-error": "^4.0.0"
|
|
188
188
|
},
|
|
189
189
|
"name": "@codyswann/lisa",
|
|
190
|
-
"version": "4.55.
|
|
190
|
+
"version": "4.55.2",
|
|
191
191
|
"description": "Claude Code governance framework that applies guardrails, guidance, and automated enforcement to projects",
|
|
192
192
|
"main": "dist/index.js",
|
|
193
193
|
"exports": {
|
|
@@ -336,7 +336,7 @@
|
|
|
336
336
|
"test": "tests"
|
|
337
337
|
},
|
|
338
338
|
"types": "./dist/index.d.ts",
|
|
339
|
-
"lisaReleaseCommit": "
|
|
340
|
-
"gitHead": "
|
|
341
|
-
"lisaReleaseTag": "v4.55.
|
|
339
|
+
"lisaReleaseCommit": "dfa8eee4cbdc81e60bd25f83e68afea9deb8d45a",
|
|
340
|
+
"gitHead": "dfa8eee4cbdc81e60bd25f83e68afea9deb8d45a",
|
|
341
|
+
"lisaReleaseTag": "v4.55.2"
|
|
342
342
|
}
|
|
@@ -188,8 +188,7 @@ Consumers pass business-shaped arguments only; they do not embed GraphQL.
|
|
|
188
188
|
|
|
189
189
|
**This layer does not accept a state to write. It resolves one.** A `save-issue`
|
|
190
190
|
that changes the workflow state declares `lifecycle_role:<ROLE>` — the semantic
|
|
191
|
-
role it is applying (`ready`, `claimed`, `blocked`, `review`, `done
|
|
192
|
-
`qa.queue`, `qa.certified`) — plus `env:<KEY>` when the role is the env-indexed
|
|
191
|
+
role it is applying (`ready`, `claimed`, `blocked`, `review`, `done`) — plus `env:<KEY>` when the role is the env-indexed
|
|
193
192
|
`done`. This layer then resolves that role against config and the team's own
|
|
194
193
|
catalog, and sends the ID **it** resolved.
|
|
195
194
|
|
|
@@ -174,8 +174,8 @@ export const resolveStateWriteTarget = ({
|
|
|
174
174
|
return refuse(
|
|
175
175
|
REFUSALS.MISSING_ROLE,
|
|
176
176
|
"no lifecycle role was declared. Every `stateId` write must name the role " +
|
|
177
|
-
"it is applying (ready | claimed | blocked | review | done
|
|
178
|
-
"
|
|
177
|
+
"it is applying (ready | claimed | blocked | review | done) so the " +
|
|
178
|
+
"configured target can be resolved instead of trusted."
|
|
179
179
|
);
|
|
180
180
|
|
|
181
181
|
// The environment key belongs to exactly one shape: an env-indexed `done`.
|
|
@@ -71,10 +71,13 @@ import {
|
|
|
71
71
|
parseArgs,
|
|
72
72
|
parseConfig,
|
|
73
73
|
readPath,
|
|
74
|
-
resolveRole,
|
|
75
74
|
} from "./resolve-lifecycle-role.mjs";
|
|
76
75
|
|
|
77
|
-
/**
|
|
76
|
+
/**
|
|
77
|
+
* The QA-failure signal. Historically applied by the retired `lisa-qa-fail`
|
|
78
|
+
* skill; now applied by a human or by whatever a project uses for QA, and read
|
|
79
|
+
* by rework triage.
|
|
80
|
+
*/
|
|
78
81
|
export const QA_FAILURE_SIGNAL = "qa-failure";
|
|
79
82
|
|
|
80
83
|
/** The human-gate signal: applied at filing, read by every intake sweep. */
|
|
@@ -190,8 +193,13 @@ const verdictOf = body => {
|
|
|
190
193
|
};
|
|
191
194
|
|
|
192
195
|
/**
|
|
193
|
-
* Role names whose occupancy proves the QA failure was resolved:
|
|
194
|
-
*
|
|
196
|
+
* Role names whose occupancy proves the QA failure was resolved: every
|
|
197
|
+
* environment rung of the terminal `done` map.
|
|
198
|
+
*
|
|
199
|
+
* Previously this also resolved a `qa.certified` role. That role was retired
|
|
200
|
+
* along with the QA acceptance skills that were its only writers, so reaching a
|
|
201
|
+
* `done` rung is now the whole proof. A project that wants a distinct
|
|
202
|
+
* post-QA state expresses it as a `done` rung.
|
|
195
203
|
*
|
|
196
204
|
* @param {object} options inputs
|
|
197
205
|
* @param {string} options.vendor `jira` | `linear` | `github`
|
|
@@ -199,16 +207,21 @@ const verdictOf = body => {
|
|
|
199
207
|
* @returns {string[]} configured role names, empty when none are bound
|
|
200
208
|
*/
|
|
201
209
|
export const voidingRoles = ({ vendor, config }) => {
|
|
202
|
-
const certified = resolveRole({
|
|
203
|
-
role: "qa.certified",
|
|
204
|
-
vendor,
|
|
205
|
-
global: config,
|
|
206
|
-
});
|
|
207
210
|
const root = VENDOR_ROOTS[vendor];
|
|
208
211
|
const doneMap = root ? readPath(config, `${root}.done`) : undefined;
|
|
212
|
+
// `done` has two sanctioned shapes: an env-indexed map, and a single scalar
|
|
213
|
+
// state for a project with one terminal rung. Every other reader handles
|
|
214
|
+
// both — linear-state-write-target.mjs:147, lifecycle-label-trust.mjs:213,
|
|
215
|
+
// queue-status-build-readers.mjs:315 — and this one must too. Missing the
|
|
216
|
+
// scalar here returns NO voiding roles at all, which holds a QA failure live
|
|
217
|
+
// forever on exactly the projects with the simplest config.
|
|
209
218
|
const done =
|
|
210
|
-
|
|
211
|
-
|
|
219
|
+
typeof doneMap === "string"
|
|
220
|
+
? [doneMap]
|
|
221
|
+
: doneMap && typeof doneMap === "object"
|
|
222
|
+
? Object.values(doneMap)
|
|
223
|
+
: [];
|
|
224
|
+
return done.filter(
|
|
212
225
|
name => typeof name === "string" && name.trim().length > 0
|
|
213
226
|
);
|
|
214
227
|
};
|
|
@@ -80,12 +80,7 @@ export const REQUIRED_ROLES = Object.freeze([
|
|
|
80
80
|
* Roles a project MAY bind. Omitting one means the lifecycle skips that
|
|
81
81
|
* transition. These have NO built-in default — that is the whole point of R1.
|
|
82
82
|
*/
|
|
83
|
-
export const OPTIONAL_ROLES = Object.freeze([
|
|
84
|
-
"review",
|
|
85
|
-
"qa.queue",
|
|
86
|
-
"qa.certified",
|
|
87
|
-
"human_needed",
|
|
88
|
-
]);
|
|
83
|
+
export const OPTIONAL_ROLES = Object.freeze(["review", "human_needed"]);
|
|
89
84
|
|
|
90
85
|
/** Where each vendor keeps its build lifecycle role map. */
|
|
91
86
|
export const VENDOR_ROOTS = Object.freeze({
|
|
@@ -155,7 +150,7 @@ export const parseConfig = file => {
|
|
|
155
150
|
* built-in default tier: see R1 in the module docblock.
|
|
156
151
|
*
|
|
157
152
|
* @param {object} options resolution inputs
|
|
158
|
-
* @param {string} options.role role name (`ready`, `review`, `
|
|
153
|
+
* @param {string} options.role role name (`ready`, `review`, `human_needed`, …)
|
|
159
154
|
* @param {string} options.vendor one of `jira` | `linear` | `github`
|
|
160
155
|
* @param {"read" | "write"} [options.intent] what the caller will do with it
|
|
161
156
|
* @param {string} [options.env] env key when resolving the env-keyed `done` map
|
|
@@ -188,8 +188,7 @@ Consumers pass business-shaped arguments only; they do not embed GraphQL.
|
|
|
188
188
|
|
|
189
189
|
**This layer does not accept a state to write. It resolves one.** A `save-issue`
|
|
190
190
|
that changes the workflow state declares `lifecycle_role:<ROLE>` — the semantic
|
|
191
|
-
role it is applying (`ready`, `claimed`, `blocked`, `review`, `done
|
|
192
|
-
`qa.queue`, `qa.certified`) — plus `env:<KEY>` when the role is the env-indexed
|
|
191
|
+
role it is applying (`ready`, `claimed`, `blocked`, `review`, `done`) — plus `env:<KEY>` when the role is the env-indexed
|
|
193
192
|
`done`. This layer then resolves that role against config and the team's own
|
|
194
193
|
catalog, and sends the ID **it** resolved.
|
|
195
194
|
|
|
@@ -174,8 +174,8 @@ export const resolveStateWriteTarget = ({
|
|
|
174
174
|
return refuse(
|
|
175
175
|
REFUSALS.MISSING_ROLE,
|
|
176
176
|
"no lifecycle role was declared. Every `stateId` write must name the role " +
|
|
177
|
-
"it is applying (ready | claimed | blocked | review | done
|
|
178
|
-
"
|
|
177
|
+
"it is applying (ready | claimed | blocked | review | done) so the " +
|
|
178
|
+
"configured target can be resolved instead of trusted."
|
|
179
179
|
);
|
|
180
180
|
|
|
181
181
|
// The environment key belongs to exactly one shape: an env-indexed `done`.
|
|
@@ -71,10 +71,13 @@ import {
|
|
|
71
71
|
parseArgs,
|
|
72
72
|
parseConfig,
|
|
73
73
|
readPath,
|
|
74
|
-
resolveRole,
|
|
75
74
|
} from "./resolve-lifecycle-role.mjs";
|
|
76
75
|
|
|
77
|
-
/**
|
|
76
|
+
/**
|
|
77
|
+
* The QA-failure signal. Historically applied by the retired `lisa-qa-fail`
|
|
78
|
+
* skill; now applied by a human or by whatever a project uses for QA, and read
|
|
79
|
+
* by rework triage.
|
|
80
|
+
*/
|
|
78
81
|
export const QA_FAILURE_SIGNAL = "qa-failure";
|
|
79
82
|
|
|
80
83
|
/** The human-gate signal: applied at filing, read by every intake sweep. */
|
|
@@ -190,8 +193,13 @@ const verdictOf = body => {
|
|
|
190
193
|
};
|
|
191
194
|
|
|
192
195
|
/**
|
|
193
|
-
* Role names whose occupancy proves the QA failure was resolved:
|
|
194
|
-
*
|
|
196
|
+
* Role names whose occupancy proves the QA failure was resolved: every
|
|
197
|
+
* environment rung of the terminal `done` map.
|
|
198
|
+
*
|
|
199
|
+
* Previously this also resolved a `qa.certified` role. That role was retired
|
|
200
|
+
* along with the QA acceptance skills that were its only writers, so reaching a
|
|
201
|
+
* `done` rung is now the whole proof. A project that wants a distinct
|
|
202
|
+
* post-QA state expresses it as a `done` rung.
|
|
195
203
|
*
|
|
196
204
|
* @param {object} options inputs
|
|
197
205
|
* @param {string} options.vendor `jira` | `linear` | `github`
|
|
@@ -199,16 +207,21 @@ const verdictOf = body => {
|
|
|
199
207
|
* @returns {string[]} configured role names, empty when none are bound
|
|
200
208
|
*/
|
|
201
209
|
export const voidingRoles = ({ vendor, config }) => {
|
|
202
|
-
const certified = resolveRole({
|
|
203
|
-
role: "qa.certified",
|
|
204
|
-
vendor,
|
|
205
|
-
global: config,
|
|
206
|
-
});
|
|
207
210
|
const root = VENDOR_ROOTS[vendor];
|
|
208
211
|
const doneMap = root ? readPath(config, `${root}.done`) : undefined;
|
|
212
|
+
// `done` has two sanctioned shapes: an env-indexed map, and a single scalar
|
|
213
|
+
// state for a project with one terminal rung. Every other reader handles
|
|
214
|
+
// both — linear-state-write-target.mjs:147, lifecycle-label-trust.mjs:213,
|
|
215
|
+
// queue-status-build-readers.mjs:315 — and this one must too. Missing the
|
|
216
|
+
// scalar here returns NO voiding roles at all, which holds a QA failure live
|
|
217
|
+
// forever on exactly the projects with the simplest config.
|
|
209
218
|
const done =
|
|
210
|
-
|
|
211
|
-
|
|
219
|
+
typeof doneMap === "string"
|
|
220
|
+
? [doneMap]
|
|
221
|
+
: doneMap && typeof doneMap === "object"
|
|
222
|
+
? Object.values(doneMap)
|
|
223
|
+
: [];
|
|
224
|
+
return done.filter(
|
|
212
225
|
name => typeof name === "string" && name.trim().length > 0
|
|
213
226
|
);
|
|
214
227
|
};
|
|
@@ -80,12 +80,7 @@ export const REQUIRED_ROLES = Object.freeze([
|
|
|
80
80
|
* Roles a project MAY bind. Omitting one means the lifecycle skips that
|
|
81
81
|
* transition. These have NO built-in default — that is the whole point of R1.
|
|
82
82
|
*/
|
|
83
|
-
export const OPTIONAL_ROLES = Object.freeze([
|
|
84
|
-
"review",
|
|
85
|
-
"qa.queue",
|
|
86
|
-
"qa.certified",
|
|
87
|
-
"human_needed",
|
|
88
|
-
]);
|
|
83
|
+
export const OPTIONAL_ROLES = Object.freeze(["review", "human_needed"]);
|
|
89
84
|
|
|
90
85
|
/** Where each vendor keeps its build lifecycle role map. */
|
|
91
86
|
export const VENDOR_ROOTS = Object.freeze({
|
|
@@ -155,7 +150,7 @@ export const parseConfig = file => {
|
|
|
155
150
|
* built-in default tier: see R1 in the module docblock.
|
|
156
151
|
*
|
|
157
152
|
* @param {object} options resolution inputs
|
|
158
|
-
* @param {string} options.role role name (`ready`, `review`, `
|
|
153
|
+
* @param {string} options.role role name (`ready`, `review`, `human_needed`, …)
|
|
159
154
|
* @param {string} options.vendor one of `jira` | `linear` | `github`
|
|
160
155
|
* @param {"read" | "write"} [options.intent] what the caller will do with it
|
|
161
156
|
* @param {string} [options.env] env key when resolving the env-keyed `done` map
|
|
@@ -188,8 +188,7 @@ Consumers pass business-shaped arguments only; they do not embed GraphQL.
|
|
|
188
188
|
|
|
189
189
|
**This layer does not accept a state to write. It resolves one.** A `save-issue`
|
|
190
190
|
that changes the workflow state declares `lifecycle_role:<ROLE>` — the semantic
|
|
191
|
-
role it is applying (`ready`, `claimed`, `blocked`, `review`, `done
|
|
192
|
-
`qa.queue`, `qa.certified`) — plus `env:<KEY>` when the role is the env-indexed
|
|
191
|
+
role it is applying (`ready`, `claimed`, `blocked`, `review`, `done`) — plus `env:<KEY>` when the role is the env-indexed
|
|
193
192
|
`done`. This layer then resolves that role against config and the team's own
|
|
194
193
|
catalog, and sends the ID **it** resolved.
|
|
195
194
|
|
|
@@ -174,8 +174,8 @@ export const resolveStateWriteTarget = ({
|
|
|
174
174
|
return refuse(
|
|
175
175
|
REFUSALS.MISSING_ROLE,
|
|
176
176
|
"no lifecycle role was declared. Every `stateId` write must name the role " +
|
|
177
|
-
"it is applying (ready | claimed | blocked | review | done
|
|
178
|
-
"
|
|
177
|
+
"it is applying (ready | claimed | blocked | review | done) so the " +
|
|
178
|
+
"configured target can be resolved instead of trusted."
|
|
179
179
|
);
|
|
180
180
|
|
|
181
181
|
// The environment key belongs to exactly one shape: an env-indexed `done`.
|
|
@@ -71,10 +71,13 @@ import {
|
|
|
71
71
|
parseArgs,
|
|
72
72
|
parseConfig,
|
|
73
73
|
readPath,
|
|
74
|
-
resolveRole,
|
|
75
74
|
} from "./resolve-lifecycle-role.mjs";
|
|
76
75
|
|
|
77
|
-
/**
|
|
76
|
+
/**
|
|
77
|
+
* The QA-failure signal. Historically applied by the retired `lisa-qa-fail`
|
|
78
|
+
* skill; now applied by a human or by whatever a project uses for QA, and read
|
|
79
|
+
* by rework triage.
|
|
80
|
+
*/
|
|
78
81
|
export const QA_FAILURE_SIGNAL = "qa-failure";
|
|
79
82
|
|
|
80
83
|
/** The human-gate signal: applied at filing, read by every intake sweep. */
|
|
@@ -190,8 +193,13 @@ const verdictOf = body => {
|
|
|
190
193
|
};
|
|
191
194
|
|
|
192
195
|
/**
|
|
193
|
-
* Role names whose occupancy proves the QA failure was resolved:
|
|
194
|
-
*
|
|
196
|
+
* Role names whose occupancy proves the QA failure was resolved: every
|
|
197
|
+
* environment rung of the terminal `done` map.
|
|
198
|
+
*
|
|
199
|
+
* Previously this also resolved a `qa.certified` role. That role was retired
|
|
200
|
+
* along with the QA acceptance skills that were its only writers, so reaching a
|
|
201
|
+
* `done` rung is now the whole proof. A project that wants a distinct
|
|
202
|
+
* post-QA state expresses it as a `done` rung.
|
|
195
203
|
*
|
|
196
204
|
* @param {object} options inputs
|
|
197
205
|
* @param {string} options.vendor `jira` | `linear` | `github`
|
|
@@ -199,16 +207,21 @@ const verdictOf = body => {
|
|
|
199
207
|
* @returns {string[]} configured role names, empty when none are bound
|
|
200
208
|
*/
|
|
201
209
|
export const voidingRoles = ({ vendor, config }) => {
|
|
202
|
-
const certified = resolveRole({
|
|
203
|
-
role: "qa.certified",
|
|
204
|
-
vendor,
|
|
205
|
-
global: config,
|
|
206
|
-
});
|
|
207
210
|
const root = VENDOR_ROOTS[vendor];
|
|
208
211
|
const doneMap = root ? readPath(config, `${root}.done`) : undefined;
|
|
212
|
+
// `done` has two sanctioned shapes: an env-indexed map, and a single scalar
|
|
213
|
+
// state for a project with one terminal rung. Every other reader handles
|
|
214
|
+
// both — linear-state-write-target.mjs:147, lifecycle-label-trust.mjs:213,
|
|
215
|
+
// queue-status-build-readers.mjs:315 — and this one must too. Missing the
|
|
216
|
+
// scalar here returns NO voiding roles at all, which holds a QA failure live
|
|
217
|
+
// forever on exactly the projects with the simplest config.
|
|
209
218
|
const done =
|
|
210
|
-
|
|
211
|
-
|
|
219
|
+
typeof doneMap === "string"
|
|
220
|
+
? [doneMap]
|
|
221
|
+
: doneMap && typeof doneMap === "object"
|
|
222
|
+
? Object.values(doneMap)
|
|
223
|
+
: [];
|
|
224
|
+
return done.filter(
|
|
212
225
|
name => typeof name === "string" && name.trim().length > 0
|
|
213
226
|
);
|
|
214
227
|
};
|
|
@@ -80,12 +80,7 @@ export const REQUIRED_ROLES = Object.freeze([
|
|
|
80
80
|
* Roles a project MAY bind. Omitting one means the lifecycle skips that
|
|
81
81
|
* transition. These have NO built-in default — that is the whole point of R1.
|
|
82
82
|
*/
|
|
83
|
-
export const OPTIONAL_ROLES = Object.freeze([
|
|
84
|
-
"review",
|
|
85
|
-
"qa.queue",
|
|
86
|
-
"qa.certified",
|
|
87
|
-
"human_needed",
|
|
88
|
-
]);
|
|
83
|
+
export const OPTIONAL_ROLES = Object.freeze(["review", "human_needed"]);
|
|
89
84
|
|
|
90
85
|
/** Where each vendor keeps its build lifecycle role map. */
|
|
91
86
|
export const VENDOR_ROOTS = Object.freeze({
|
|
@@ -155,7 +150,7 @@ export const parseConfig = file => {
|
|
|
155
150
|
* built-in default tier: see R1 in the module docblock.
|
|
156
151
|
*
|
|
157
152
|
* @param {object} options resolution inputs
|
|
158
|
-
* @param {string} options.role role name (`ready`, `review`, `
|
|
153
|
+
* @param {string} options.role role name (`ready`, `review`, `human_needed`, …)
|
|
159
154
|
* @param {string} options.vendor one of `jira` | `linear` | `github`
|
|
160
155
|
* @param {"read" | "write"} [options.intent] what the caller will do with it
|
|
161
156
|
* @param {string} [options.env] env key when resolving the env-keyed `done` map
|
|
@@ -188,8 +188,7 @@ Consumers pass business-shaped arguments only; they do not embed GraphQL.
|
|
|
188
188
|
|
|
189
189
|
**This layer does not accept a state to write. It resolves one.** A `save-issue`
|
|
190
190
|
that changes the workflow state declares `lifecycle_role:<ROLE>` — the semantic
|
|
191
|
-
role it is applying (`ready`, `claimed`, `blocked`, `review`, `done
|
|
192
|
-
`qa.queue`, `qa.certified`) — plus `env:<KEY>` when the role is the env-indexed
|
|
191
|
+
role it is applying (`ready`, `claimed`, `blocked`, `review`, `done`) — plus `env:<KEY>` when the role is the env-indexed
|
|
193
192
|
`done`. This layer then resolves that role against config and the team's own
|
|
194
193
|
catalog, and sends the ID **it** resolved.
|
|
195
194
|
|
|
@@ -174,8 +174,8 @@ export const resolveStateWriteTarget = ({
|
|
|
174
174
|
return refuse(
|
|
175
175
|
REFUSALS.MISSING_ROLE,
|
|
176
176
|
"no lifecycle role was declared. Every `stateId` write must name the role " +
|
|
177
|
-
"it is applying (ready | claimed | blocked | review | done
|
|
178
|
-
"
|
|
177
|
+
"it is applying (ready | claimed | blocked | review | done) so the " +
|
|
178
|
+
"configured target can be resolved instead of trusted."
|
|
179
179
|
);
|
|
180
180
|
|
|
181
181
|
// The environment key belongs to exactly one shape: an env-indexed `done`.
|
|
@@ -71,10 +71,13 @@ import {
|
|
|
71
71
|
parseArgs,
|
|
72
72
|
parseConfig,
|
|
73
73
|
readPath,
|
|
74
|
-
resolveRole,
|
|
75
74
|
} from "./resolve-lifecycle-role.mjs";
|
|
76
75
|
|
|
77
|
-
/**
|
|
76
|
+
/**
|
|
77
|
+
* The QA-failure signal. Historically applied by the retired `lisa-qa-fail`
|
|
78
|
+
* skill; now applied by a human or by whatever a project uses for QA, and read
|
|
79
|
+
* by rework triage.
|
|
80
|
+
*/
|
|
78
81
|
export const QA_FAILURE_SIGNAL = "qa-failure";
|
|
79
82
|
|
|
80
83
|
/** The human-gate signal: applied at filing, read by every intake sweep. */
|
|
@@ -190,8 +193,13 @@ const verdictOf = body => {
|
|
|
190
193
|
};
|
|
191
194
|
|
|
192
195
|
/**
|
|
193
|
-
* Role names whose occupancy proves the QA failure was resolved:
|
|
194
|
-
*
|
|
196
|
+
* Role names whose occupancy proves the QA failure was resolved: every
|
|
197
|
+
* environment rung of the terminal `done` map.
|
|
198
|
+
*
|
|
199
|
+
* Previously this also resolved a `qa.certified` role. That role was retired
|
|
200
|
+
* along with the QA acceptance skills that were its only writers, so reaching a
|
|
201
|
+
* `done` rung is now the whole proof. A project that wants a distinct
|
|
202
|
+
* post-QA state expresses it as a `done` rung.
|
|
195
203
|
*
|
|
196
204
|
* @param {object} options inputs
|
|
197
205
|
* @param {string} options.vendor `jira` | `linear` | `github`
|
|
@@ -199,16 +207,21 @@ const verdictOf = body => {
|
|
|
199
207
|
* @returns {string[]} configured role names, empty when none are bound
|
|
200
208
|
*/
|
|
201
209
|
export const voidingRoles = ({ vendor, config }) => {
|
|
202
|
-
const certified = resolveRole({
|
|
203
|
-
role: "qa.certified",
|
|
204
|
-
vendor,
|
|
205
|
-
global: config,
|
|
206
|
-
});
|
|
207
210
|
const root = VENDOR_ROOTS[vendor];
|
|
208
211
|
const doneMap = root ? readPath(config, `${root}.done`) : undefined;
|
|
212
|
+
// `done` has two sanctioned shapes: an env-indexed map, and a single scalar
|
|
213
|
+
// state for a project with one terminal rung. Every other reader handles
|
|
214
|
+
// both — linear-state-write-target.mjs:147, lifecycle-label-trust.mjs:213,
|
|
215
|
+
// queue-status-build-readers.mjs:315 — and this one must too. Missing the
|
|
216
|
+
// scalar here returns NO voiding roles at all, which holds a QA failure live
|
|
217
|
+
// forever on exactly the projects with the simplest config.
|
|
209
218
|
const done =
|
|
210
|
-
|
|
211
|
-
|
|
219
|
+
typeof doneMap === "string"
|
|
220
|
+
? [doneMap]
|
|
221
|
+
: doneMap && typeof doneMap === "object"
|
|
222
|
+
? Object.values(doneMap)
|
|
223
|
+
: [];
|
|
224
|
+
return done.filter(
|
|
212
225
|
name => typeof name === "string" && name.trim().length > 0
|
|
213
226
|
);
|
|
214
227
|
};
|
|
@@ -80,12 +80,7 @@ export const REQUIRED_ROLES = Object.freeze([
|
|
|
80
80
|
* Roles a project MAY bind. Omitting one means the lifecycle skips that
|
|
81
81
|
* transition. These have NO built-in default — that is the whole point of R1.
|
|
82
82
|
*/
|
|
83
|
-
export const OPTIONAL_ROLES = Object.freeze([
|
|
84
|
-
"review",
|
|
85
|
-
"qa.queue",
|
|
86
|
-
"qa.certified",
|
|
87
|
-
"human_needed",
|
|
88
|
-
]);
|
|
83
|
+
export const OPTIONAL_ROLES = Object.freeze(["review", "human_needed"]);
|
|
89
84
|
|
|
90
85
|
/** Where each vendor keeps its build lifecycle role map. */
|
|
91
86
|
export const VENDOR_ROOTS = Object.freeze({
|
|
@@ -155,7 +150,7 @@ export const parseConfig = file => {
|
|
|
155
150
|
* built-in default tier: see R1 in the module docblock.
|
|
156
151
|
*
|
|
157
152
|
* @param {object} options resolution inputs
|
|
158
|
-
* @param {string} options.role role name (`ready`, `review`, `
|
|
153
|
+
* @param {string} options.role role name (`ready`, `review`, `human_needed`, …)
|
|
159
154
|
* @param {string} options.vendor one of `jira` | `linear` | `github`
|
|
160
155
|
* @param {"read" | "write"} [options.intent] what the caller will do with it
|
|
161
156
|
* @param {string} [options.env] env key when resolving the env-keyed `done` map
|
|
@@ -188,8 +188,7 @@ Consumers pass business-shaped arguments only; they do not embed GraphQL.
|
|
|
188
188
|
|
|
189
189
|
**This layer does not accept a state to write. It resolves one.** A `save-issue`
|
|
190
190
|
that changes the workflow state declares `lifecycle_role:<ROLE>` — the semantic
|
|
191
|
-
role it is applying (`ready`, `claimed`, `blocked`, `review`, `done
|
|
192
|
-
`qa.queue`, `qa.certified`) — plus `env:<KEY>` when the role is the env-indexed
|
|
191
|
+
role it is applying (`ready`, `claimed`, `blocked`, `review`, `done`) — plus `env:<KEY>` when the role is the env-indexed
|
|
193
192
|
`done`. This layer then resolves that role against config and the team's own
|
|
194
193
|
catalog, and sends the ID **it** resolved.
|
|
195
194
|
|