@codyswann/lisa 4.55.3 → 4.55.5
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/lisa-owned-hash-ledger.d.ts.map +1 -1
- package/dist/core/lisa-owned-hash-ledger.js +6 -0
- package/dist/core/lisa-owned-hash-ledger.js.map +1 -1
- 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 +17 -15
- package/dist/core/upstream-evidence-manifest.js.map +1 -1
- package/expo/copy-overwrite/scripts/bdd/validate.mjs +84 -8
- package/expo/copy-overwrite/scripts/check-bdd-coverage.mjs +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-github-build-intake/SKILL.md +22 -7
- package/plugins/lisa/.codex-plugin/skills/lisa-github-write-issue/SKILL.md +15 -1
- package/plugins/lisa/.codex-plugin/skills/lisa-jira-build-intake/SKILL.md +21 -6
- package/plugins/lisa/.codex-plugin/skills/lisa-jira-write-ticket/SKILL.md +15 -1
- package/plugins/lisa/.codex-plugin/skills/lisa-linear-access/SKILL.md +12 -2
- package/plugins/lisa/.codex-plugin/skills/lisa-linear-build-intake/SKILL.md +20 -6
- package/plugins/lisa/.codex-plugin/skills/lisa-linear-write-issue/SKILL.md +15 -1
- package/plugins/lisa/.codex-plugin/skills/lisa-repair-intake/SKILL.md +21 -7
- package/plugins/lisa/.codex-plugin/skills/lisa-track/SKILL.md +16 -2
- package/plugins/lisa/.codex-plugin/skills/lisa-tracker-build-intake/SKILL.md +15 -1
- package/plugins/lisa/rules/reference/ready-role-filing.md +36 -0
- package/plugins/lisa/scripts/intake-blocker-reprobe.mjs +85 -17
- package/plugins/lisa/scripts/qa-signal-lifecycle.mjs +5 -2
- package/plugins/lisa/skills/lisa-github-build-intake/SKILL.md +22 -7
- package/plugins/lisa/skills/lisa-github-write-issue/SKILL.md +15 -1
- package/plugins/lisa/skills/lisa-jira-build-intake/SKILL.md +21 -6
- package/plugins/lisa/skills/lisa-jira-write-ticket/SKILL.md +15 -1
- package/plugins/lisa/skills/lisa-linear-access/SKILL.md +12 -2
- package/plugins/lisa/skills/lisa-linear-build-intake/SKILL.md +20 -6
- package/plugins/lisa/skills/lisa-linear-write-issue/SKILL.md +15 -1
- package/plugins/lisa/skills/lisa-repair-intake/SKILL.md +21 -7
- package/plugins/lisa/skills/lisa-track/SKILL.md +16 -2
- package/plugins/lisa/skills/lisa-tracker-build-intake/SKILL.md +15 -1
- package/plugins/lisa-agy/plugin.json +1 -1
- package/plugins/lisa-agy/scripts/intake-blocker-reprobe.mjs +85 -17
- package/plugins/lisa-agy/scripts/qa-signal-lifecycle.mjs +5 -2
- package/plugins/lisa-agy/skills/lisa-github-build-intake/SKILL.md +22 -7
- package/plugins/lisa-agy/skills/lisa-github-write-issue/SKILL.md +15 -1
- package/plugins/lisa-agy/skills/lisa-jira-build-intake/SKILL.md +21 -6
- package/plugins/lisa-agy/skills/lisa-jira-write-ticket/SKILL.md +15 -1
- package/plugins/lisa-agy/skills/lisa-linear-access/SKILL.md +12 -2
- package/plugins/lisa-agy/skills/lisa-linear-build-intake/SKILL.md +20 -6
- package/plugins/lisa-agy/skills/lisa-linear-write-issue/SKILL.md +15 -1
- package/plugins/lisa-agy/skills/lisa-repair-intake/SKILL.md +21 -7
- package/plugins/lisa-agy/skills/lisa-track/SKILL.md +16 -2
- package/plugins/lisa-agy/skills/lisa-tracker-build-intake/SKILL.md +15 -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-copilot/rules/reference/ready-role-filing.md +36 -0
- package/plugins/lisa-copilot/scripts/intake-blocker-reprobe.mjs +85 -17
- package/plugins/lisa-copilot/scripts/qa-signal-lifecycle.mjs +5 -2
- package/plugins/lisa-copilot/skills/lisa-github-build-intake/SKILL.md +22 -7
- package/plugins/lisa-copilot/skills/lisa-github-write-issue/SKILL.md +15 -1
- package/plugins/lisa-copilot/skills/lisa-jira-build-intake/SKILL.md +21 -6
- package/plugins/lisa-copilot/skills/lisa-jira-write-ticket/SKILL.md +15 -1
- package/plugins/lisa-copilot/skills/lisa-linear-access/SKILL.md +12 -2
- package/plugins/lisa-copilot/skills/lisa-linear-build-intake/SKILL.md +20 -6
- package/plugins/lisa-copilot/skills/lisa-linear-write-issue/SKILL.md +15 -1
- package/plugins/lisa-copilot/skills/lisa-repair-intake/SKILL.md +21 -7
- package/plugins/lisa-copilot/skills/lisa-track/SKILL.md +16 -2
- package/plugins/lisa-copilot/skills/lisa-tracker-build-intake/SKILL.md +15 -1
- package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cursor/rules/ready-role-filing-reference.mdc +36 -0
- package/plugins/lisa-cursor/scripts/intake-blocker-reprobe.mjs +85 -17
- package/plugins/lisa-cursor/scripts/qa-signal-lifecycle.mjs +5 -2
- package/plugins/lisa-cursor/skills/lisa-github-build-intake/SKILL.md +22 -7
- package/plugins/lisa-cursor/skills/lisa-github-write-issue/SKILL.md +15 -1
- package/plugins/lisa-cursor/skills/lisa-jira-build-intake/SKILL.md +21 -6
- package/plugins/lisa-cursor/skills/lisa-jira-write-ticket/SKILL.md +15 -1
- package/plugins/lisa-cursor/skills/lisa-linear-access/SKILL.md +12 -2
- package/plugins/lisa-cursor/skills/lisa-linear-build-intake/SKILL.md +20 -6
- package/plugins/lisa-cursor/skills/lisa-linear-write-issue/SKILL.md +15 -1
- package/plugins/lisa-cursor/skills/lisa-repair-intake/SKILL.md +21 -7
- package/plugins/lisa-cursor/skills/lisa-track/SKILL.md +16 -2
- package/plugins/lisa-cursor/skills/lisa-tracker-build-intake/SKILL.md +15 -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
- package/plugins/src/base/rules/reference/ready-role-filing.md +36 -0
- package/plugins/src/base/scripts/intake-blocker-reprobe.mjs +85 -17
- package/plugins/src/base/scripts/qa-signal-lifecycle.mjs +5 -2
- package/plugins/src/base/skills/lisa-github-build-intake/SKILL.md +22 -7
- package/plugins/src/base/skills/lisa-github-write-issue/SKILL.md +15 -1
- package/plugins/src/base/skills/lisa-jira-build-intake/SKILL.md +21 -6
- package/plugins/src/base/skills/lisa-jira-write-ticket/SKILL.md +15 -1
- package/plugins/src/base/skills/lisa-linear-access/SKILL.md +12 -2
- package/plugins/src/base/skills/lisa-linear-build-intake/SKILL.md +20 -6
- package/plugins/src/base/skills/lisa-linear-write-issue/SKILL.md +15 -1
- package/plugins/src/base/skills/lisa-repair-intake/SKILL.md +21 -7
- package/plugins/src/base/skills/lisa-track/SKILL.md +16 -2
- package/plugins/src/base/skills/lisa-tracker-build-intake/SKILL.md +15 -1
|
@@ -239,8 +239,8 @@ export const VOID_PREDICATES = Object.freeze({
|
|
|
239
239
|
"certified-role-reached": ({ role, resolvedRoles }) =>
|
|
240
240
|
normalize(role) !== "" &&
|
|
241
241
|
resolvedRoles.some(name => normalize(name) === normalize(role)),
|
|
242
|
-
"human-gate-release-recorded": ({ body, comments }) =>
|
|
243
|
-
humanGateDischarged({ body, comments }),
|
|
242
|
+
"human-gate-release-recorded": ({ body, comments, trustedHumanActorIds }) =>
|
|
243
|
+
humanGateDischarged({ body, comments, trustedHumanActorIds }),
|
|
244
244
|
});
|
|
245
245
|
|
|
246
246
|
/**
|
|
@@ -331,6 +331,7 @@ const labelNames = labels =>
|
|
|
331
331
|
* @param {string} [options.signal] a key of {@link SIGNALS}
|
|
332
332
|
* @param {readonly unknown[]} [options.labels] the item's labels
|
|
333
333
|
* @param {readonly unknown[]} [options.comments] comment bodies, oldest first
|
|
334
|
+
* @param {readonly unknown[]} [options.trustedHumanActorIds] explicitly trusted human author identities
|
|
334
335
|
* @param {unknown} [options.body] the item's description, for body-marker rows
|
|
335
336
|
* @param {string} [options.role] the item's current lifecycle role name
|
|
336
337
|
* @param {string} options.vendor `jira` | `linear` | `github`
|
|
@@ -341,6 +342,7 @@ export const evaluateSignal = ({
|
|
|
341
342
|
signal = QA_FAILURE_SIGNAL,
|
|
342
343
|
labels,
|
|
343
344
|
comments,
|
|
345
|
+
trustedHumanActorIds,
|
|
344
346
|
body,
|
|
345
347
|
role = "",
|
|
346
348
|
vendor,
|
|
@@ -380,6 +382,7 @@ export const evaluateSignal = ({
|
|
|
380
382
|
role,
|
|
381
383
|
body,
|
|
382
384
|
comments,
|
|
385
|
+
trustedHumanActorIds,
|
|
383
386
|
resolvedRoles: voidingRoles({ vendor, config }),
|
|
384
387
|
};
|
|
385
388
|
const unchecked = declared.voidConditions.filter(
|
|
@@ -6,6 +6,20 @@ allowed-tools: ["Skill", "Bash"]
|
|
|
6
6
|
|
|
7
7
|
# GitHub Build Intake: $ARGUMENTS
|
|
8
8
|
|
|
9
|
+
## Human-gate release authorization
|
|
10
|
+
|
|
11
|
+
A release requires a trusted human author, not just matching comment text. Follow
|
|
12
|
+
`ready-role-filing` — **Human-gate release authorization**: preserve tracker-supplied comment
|
|
13
|
+
author IDs and bot metadata, resolve `trustedHumanActorIds` only from an explicit user instruction
|
|
14
|
+
or existing human-authored trusted project policy, and pass it with structured `comments` to every
|
|
15
|
+
hold classifier, reconciliation, normalization and release planner. Never derive trust from the
|
|
16
|
+
comment body, a display name, the actor's own assertion, or an automation posting on its own behalf.
|
|
17
|
+
Missing policy, missing/unreadable author identity, raw body strings, untrusted actors and known bots
|
|
18
|
+
cannot discharge a hold. Keep the item held and report the missing authorization; do not silently
|
|
19
|
+
replace these inputs with an empty history or an inferred allowlist. Authorized matching releases
|
|
20
|
+
continue through the existing path and never override an independently declared caller hold.
|
|
21
|
+
|
|
22
|
+
|
|
9
23
|
`$ARGUMENTS` is one of:
|
|
10
24
|
|
|
11
25
|
1. A GitHub `org/repo` token (e.g., `acme/frontend-v2`).
|
|
@@ -216,8 +230,8 @@ A blocker is a **claim with a timestamp, not a fact** — it goes stale the mome
|
|
|
216
230
|
true, and nothing re-read one before this phase. For each `$BLOCKED` candidate:
|
|
217
231
|
|
|
218
232
|
1. **Read release comments before applying the human gate.** Pass all item comments, labels,
|
|
219
|
-
body and configured `humanNeededLabel` to `classifyReadyCandidate(...)`. For a discharged hold,
|
|
220
|
-
call `planHumanGateRelease({ labels, body, comments, humanNeededLabel, readyLabel, lifecycleLabels, alreadyNotified })`
|
|
233
|
+
body, `trustedHumanActorIds` and configured `humanNeededLabel` to `classifyReadyCandidate(...)`. For a discharged hold,
|
|
234
|
+
call `planHumanGateRelease({ labels, body, comments, trustedHumanActorIds, humanNeededLabel, readyLabel, lifecycleLabels, alreadyNotified })`
|
|
221
235
|
and retain its plan. Apply human-marker cleanup only as planned; defer any ready-role restoration
|
|
222
236
|
until steps 2–5 have cleared the remaining blockers (map the role to the vendor's state or label).
|
|
223
237
|
A still-active hold is never auto-selected, whatever any probe says. An absent or unreadable
|
|
@@ -227,8 +241,9 @@ true, and nothing re-read one before this phase. For each `$BLOCKED` candidate:
|
|
|
227
241
|
2. **Extract the stated discharge condition**, then **probe it**. Machine-testable conditions — a
|
|
228
242
|
version on trunk, a published package, a CI run history, an advisory's patched status — rot
|
|
229
243
|
fastest and are cheapest to check. A human decision is not machine-testable; leave it.
|
|
230
|
-
3. **Classify with `classifyPreWorkCandidate(...)`** from `scripts/intake-blocker-reprobe.mjs`.
|
|
231
|
-
|
|
244
|
+
3. **Classify with `classifyPreWorkCandidate(...)`** from `scripts/intake-blocker-reprobe.mjs`.
|
|
245
|
+
Include the structured `comments` and `trustedHumanActorIds` from step 1.
|
|
246
|
+
A discharge with no recorded evidence is not a discharge, and neither is a candidate nothing
|
|
232
247
|
probed this cycle — the helper refuses both.
|
|
233
248
|
4. **Record the result on the issue either way** via `formatReprobeNote(...)` as a comment, so the
|
|
234
249
|
next cycle reads the answer rather than re-deriving it. Keep it idempotent.
|
|
@@ -323,7 +338,7 @@ other gate's verdict — however conclusive — may promote an item a person par
|
|
|
323
338
|
drift, and a drifted gate fails *silently*, by quietly ceasing to match. Do **not** re-implement
|
|
324
339
|
the test here, and do **not** key it on `reason=`: markers in the wild carry no `reason=` key at
|
|
325
340
|
all and sit anywhere in the body, so a structured parse would miss them while appearing to work
|
|
326
|
-
on every item that happens to have one. **Pass the item's `comments` alongside its labels and
|
|
341
|
+
on every item that happens to have one. **Pass the item's structured `comments` and `trustedHumanActorIds` alongside its labels and
|
|
327
342
|
body.** A hold is ended by a release recorded in a comment, so a reader handed no comments cannot
|
|
328
343
|
see the discharge — it goes on holding an item whose question was answered weeks ago, which is
|
|
329
344
|
the defect this gate carried from the day it was written (CodySwannGT/lisa#3852). Omitting them
|
|
@@ -334,7 +349,7 @@ other gate's verdict — however conclusive — may promote an item a person par
|
|
|
334
349
|
and re-rejected every cycle forever and seen by nothing — `lisa-repair-intake` sweeps items that
|
|
335
350
|
are **not** in the ready role and excludes gated ones outright, so a ready-and-gated item falls
|
|
336
351
|
outside its filter twice over. Call
|
|
337
|
-
`planHumanGateReconciliation({ labels, body, humanNeededLabel, readyLabel, alreadyNotified })`
|
|
352
|
+
`planHumanGateReconciliation({ labels, body, comments, trustedHumanActorIds, humanNeededLabel, readyLabel, alreadyNotified })`
|
|
338
353
|
and apply exactly the actions it returns: remove `$READY`, add the configured human-needed
|
|
339
354
|
marker, and post `formatHumanGateNote()` once. The planner is idempotent by state, so an item
|
|
340
355
|
already out of the lane and already marked yields no second mutation and no second comment. This
|
|
@@ -344,7 +359,7 @@ other gate's verdict — however conclusive — may promote an item a person par
|
|
|
344
359
|
This ready-lane candidate can retain a historical body marker and a human-needed label.
|
|
345
360
|
This step reconciles only candidates still in the ready lane; released holds outside it are
|
|
346
361
|
recovered by `lisa-repair-intake` step 2b (or Phase 2.5 when included in this cycle). Call
|
|
347
|
-
`planHumanGateRelease({ labels, body, comments, humanNeededLabel, readyLabel, lifecycleLabels, alreadyNotified })`
|
|
362
|
+
`planHumanGateRelease({ labels, body, comments, trustedHumanActorIds, humanNeededLabel, readyLabel, lifecycleLabels, alreadyNotified })`
|
|
348
363
|
and apply exactly the actions it returns: remove the configured human-needed marker, add the
|
|
349
364
|
configured ready role back, and post `formatHumanGateReleaseNote()` once. It is the exact inverse
|
|
350
365
|
of step 3's planner and it refuses in both directions — an item still held plans nothing, and an
|
|
@@ -6,6 +6,20 @@ allowed-tools: ["Bash", "Skill", "Read"]
|
|
|
6
6
|
|
|
7
7
|
# Write GitHub Issue: $ARGUMENTS
|
|
8
8
|
|
|
9
|
+
## Human-gate release authorization
|
|
10
|
+
|
|
11
|
+
A release requires a trusted human author, not just matching comment text. Follow
|
|
12
|
+
`ready-role-filing` — **Human-gate release authorization**: preserve tracker-supplied comment
|
|
13
|
+
author IDs and bot metadata, resolve `trustedHumanActorIds` only from an explicit user instruction
|
|
14
|
+
or existing human-authored trusted project policy, and pass it with structured `comments` to every
|
|
15
|
+
hold classifier, reconciliation, normalization and release planner. Never derive trust from the
|
|
16
|
+
comment body, a display name, the actor's own assertion, or an automation posting on its own behalf.
|
|
17
|
+
Missing policy, missing/unreadable author identity, raw body strings, untrusted actors and known bots
|
|
18
|
+
cannot discharge a hold. Keep the item held and report the missing authorization; do not silently
|
|
19
|
+
replace these inputs with an empty history or an inferred allowlist. Authorized matching releases
|
|
20
|
+
continue through the existing path and never override an independently declared caller hold.
|
|
21
|
+
|
|
22
|
+
|
|
9
23
|
Create or update a GitHub Issue with all required relationships, metadata, and quality gates. Every section below is mandatory. Thin issues are rejected.
|
|
10
24
|
|
|
11
25
|
This skill is the GitHub counterpart of `lisa-jira-write-ticket`. The two skills share the same gates, description structure, acceptance-criteria format, and verification flow. The data-model translation is documented under "GitHub Issues data model" below — keep that table in sync with `lisa-github-validate-issue` so what one skill writes the other accepts.
|
|
@@ -323,7 +337,7 @@ If the label does not exist in the tracker, create it, or record that it could n
|
|
|
323
337
|
proceed — the marker still holds. Never file the label *instead of* the marker.
|
|
324
338
|
|
|
325
339
|
**Write a `reason=` the release can name.** The hold's reason is not decoration: a hold ends when a
|
|
326
|
-
`[lisa-human-gate-release]` comment repeating that same `reason=` is recorded on the item, and the
|
|
340
|
+
`[lisa-human-gate-release]` comment repeating that same `reason=` is recorded on the item by an authorized human, and the
|
|
327
341
|
next intake sweep then takes the marker label off and puts the item back in the build-ready role on
|
|
328
342
|
its own. Matching is per-reason so that a hold declared *after* an earlier release is not born
|
|
329
343
|
discharged. A keyless hold is legal and is discharged by a keyless release; a hold whose reason is a
|
|
@@ -6,6 +6,20 @@ allowed-tools: ["Skill", "Bash"]
|
|
|
6
6
|
|
|
7
7
|
# JIRA Build Intake: $ARGUMENTS
|
|
8
8
|
|
|
9
|
+
## Human-gate release authorization
|
|
10
|
+
|
|
11
|
+
A release requires a trusted human author, not just matching comment text. Follow
|
|
12
|
+
`ready-role-filing` — **Human-gate release authorization**: preserve tracker-supplied comment
|
|
13
|
+
author IDs and bot metadata, resolve `trustedHumanActorIds` only from an explicit user instruction
|
|
14
|
+
or existing human-authored trusted project policy, and pass it with structured `comments` to every
|
|
15
|
+
hold classifier, reconciliation, normalization and release planner. Never derive trust from the
|
|
16
|
+
comment body, a display name, the actor's own assertion, or an automation posting on its own behalf.
|
|
17
|
+
Missing policy, missing/unreadable author identity, raw body strings, untrusted actors and known bots
|
|
18
|
+
cannot discharge a hold. Keep the item held and report the missing authorization; do not silently
|
|
19
|
+
replace these inputs with an empty history or an inferred allowlist. Authorized matching releases
|
|
20
|
+
continue through the existing path and never override an independently declared caller hold.
|
|
21
|
+
|
|
22
|
+
|
|
9
23
|
All Atlassian operations in this skill go through `lisa-atlassian-access`. Do not call MCP tools or `acli` directly.
|
|
10
24
|
|
|
11
25
|
`$ARGUMENTS` is one of:
|
|
@@ -190,8 +204,8 @@ A blocker is a **claim with a timestamp, not a fact** — it goes stale the mome
|
|
|
190
204
|
true, and nothing re-read one before this phase. For each pre-work candidate outside `$READY`:
|
|
191
205
|
|
|
192
206
|
1. **Read release comments before applying the human gate.** Pass all item comments, labels,
|
|
193
|
-
body and configured `humanNeededLabel` to `classifyReadyCandidate(...)`. For a discharged hold,
|
|
194
|
-
call `planHumanGateRelease({ labels, body, comments, humanNeededLabel, readyLabel, lifecycleLabels, alreadyNotified })`
|
|
207
|
+
body, `trustedHumanActorIds` and configured `humanNeededLabel` to `classifyReadyCandidate(...)`. For a discharged hold,
|
|
208
|
+
call `planHumanGateRelease({ labels, body, comments, trustedHumanActorIds, humanNeededLabel, readyLabel, lifecycleLabels, alreadyNotified })`
|
|
195
209
|
and retain its plan. Apply human-marker cleanup only as planned; defer any ready-role restoration
|
|
196
210
|
until steps 2–5 have cleared the remaining blockers (map the role to the vendor's state or label).
|
|
197
211
|
A still-active hold is never auto-selected, whatever any probe says. An absent or unreadable
|
|
@@ -202,7 +216,8 @@ true, and nothing re-read one before this phase. For each pre-work candidate out
|
|
|
202
216
|
version on trunk, a published package, a CI run history, an advisory's patched status — rot
|
|
203
217
|
fastest and are cheapest to check. A human decision is not machine-testable; leave it.
|
|
204
218
|
3. **Classify with `classifyPreWorkCandidate(...)`** from
|
|
205
|
-
`scripts/intake-blocker-reprobe.mjs
|
|
219
|
+
`scripts/intake-blocker-reprobe.mjs`, including the structured `comments` and
|
|
220
|
+
`trustedHumanActorIds` from step 1. A discharge with no recorded evidence is not a discharge,
|
|
206
221
|
and neither is a candidate nothing probed this cycle — the helper refuses both.
|
|
207
222
|
4. **Record the result on the ticket either way** via `formatReprobeNote(...)` as a comment, so the
|
|
208
223
|
next cycle reads the answer rather than re-deriving it. Keep it idempotent.
|
|
@@ -228,7 +243,7 @@ other gate's verdict — however conclusive — may promote an item a person par
|
|
|
228
243
|
drift, and a drifted gate fails *silently*, by quietly ceasing to match. Do **not** re-implement
|
|
229
244
|
the test here, and do **not** key it on `reason=`: markers in the wild carry no `reason=` key at
|
|
230
245
|
all and sit anywhere in the body, so a structured parse would miss them while appearing to work
|
|
231
|
-
on every item that happens to have one. **Pass the item's `comments` alongside its labels and
|
|
246
|
+
on every item that happens to have one. **Pass the item's structured `comments` and `trustedHumanActorIds` alongside its labels and
|
|
232
247
|
body.** A hold is ended by a release recorded in a comment, so a reader handed no comments cannot
|
|
233
248
|
see the discharge — it goes on holding an item whose question was answered weeks ago, which is
|
|
234
249
|
the defect this gate carried from the day it was written (CodySwannGT/lisa#3852). Omitting them
|
|
@@ -239,7 +254,7 @@ other gate's verdict — however conclusive — may promote an item a person par
|
|
|
239
254
|
and re-rejected every cycle forever and seen by nothing — `lisa-repair-intake` sweeps items that
|
|
240
255
|
are **not** in the ready role and excludes gated ones outright, so a ready-and-gated item falls
|
|
241
256
|
outside its filter twice over. Call
|
|
242
|
-
`planHumanGateReconciliation({ labels, body, humanNeededLabel, readyLabel, alreadyNotified })`
|
|
257
|
+
`planHumanGateReconciliation({ labels, body, comments, trustedHumanActorIds, humanNeededLabel, readyLabel, alreadyNotified })`
|
|
243
258
|
and apply exactly the actions it returns: remove `$READY`, add the configured human-needed
|
|
244
259
|
marker, and post `formatHumanGateNote()` once. The planner is idempotent by state, so an item
|
|
245
260
|
already out of the lane and already marked yields no second mutation and no second comment. This
|
|
@@ -249,7 +264,7 @@ other gate's verdict — however conclusive — may promote an item a person par
|
|
|
249
264
|
This ready-lane candidate can retain a historical body marker and a human-needed label.
|
|
250
265
|
This step reconciles only candidates still in the ready lane; released holds outside it are
|
|
251
266
|
recovered by `lisa-repair-intake` step 2b (or Phase 2.5 when included in this cycle). Call
|
|
252
|
-
`planHumanGateRelease({ labels, body, comments, humanNeededLabel, readyLabel, lifecycleLabels, alreadyNotified })`
|
|
267
|
+
`planHumanGateRelease({ labels, body, comments, trustedHumanActorIds, humanNeededLabel, readyLabel, lifecycleLabels, alreadyNotified })`
|
|
253
268
|
and apply exactly the actions it returns: remove the configured human-needed marker, add the
|
|
254
269
|
configured ready role back, and post `formatHumanGateReleaseNote()` once. It is the exact inverse
|
|
255
270
|
of step 3's planner and it refuses in both directions — an item still held plans nothing, and an
|
|
@@ -6,6 +6,20 @@ allowed-tools: ["Bash", "Skill"]
|
|
|
6
6
|
|
|
7
7
|
# Write JIRA Ticket: $ARGUMENTS
|
|
8
8
|
|
|
9
|
+
## Human-gate release authorization
|
|
10
|
+
|
|
11
|
+
A release requires a trusted human author, not just matching comment text. Follow
|
|
12
|
+
`ready-role-filing` — **Human-gate release authorization**: preserve tracker-supplied comment
|
|
13
|
+
author IDs and bot metadata, resolve `trustedHumanActorIds` only from an explicit user instruction
|
|
14
|
+
or existing human-authored trusted project policy, and pass it with structured `comments` to every
|
|
15
|
+
hold classifier, reconciliation, normalization and release planner. Never derive trust from the
|
|
16
|
+
comment body, a display name, the actor's own assertion, or an automation posting on its own behalf.
|
|
17
|
+
Missing policy, missing/unreadable author identity, raw body strings, untrusted actors and known bots
|
|
18
|
+
cannot discharge a hold. Keep the item held and report the missing authorization; do not silently
|
|
19
|
+
replace these inputs with an empty history or an inferred allowlist. Authorized matching releases
|
|
20
|
+
continue through the existing path and never override an independently declared caller hold.
|
|
21
|
+
|
|
22
|
+
|
|
9
23
|
All Atlassian operations in this skill go through `lisa-atlassian-access`. Do not call MCP tools or `acli` directly.
|
|
10
24
|
|
|
11
25
|
Create or update a JIRA ticket with all required relationships, metadata, and quality gates. Every section below is mandatory. Thin tickets are rejected.
|
|
@@ -308,7 +322,7 @@ If the label does not exist in the tracker, create it, or record that it could n
|
|
|
308
322
|
proceed — the marker still holds. Never file the label *instead of* the marker.
|
|
309
323
|
|
|
310
324
|
**Write a `reason=` the release can name.** The hold's reason is not decoration: a hold ends when a
|
|
311
|
-
`[lisa-human-gate-release]` comment repeating that same `reason=` is recorded on the item, and the
|
|
325
|
+
`[lisa-human-gate-release]` comment repeating that same `reason=` is recorded on the item by an authorized human, and the
|
|
312
326
|
next intake sweep then takes the marker label off and puts the item back in the build-ready role on
|
|
313
327
|
its own. Matching is per-reason so that a hold declared *after* an earlier release is not born
|
|
314
328
|
discharged. A keyless hold is legal and is discharged by a keyless release; a hold whose reason is a
|
|
@@ -323,7 +323,7 @@ query($id:String!,$after:String){
|
|
|
323
323
|
project(id:$id){
|
|
324
324
|
comments(first:100,after:$after){
|
|
325
325
|
pageInfo{ hasNextPage endCursor }
|
|
326
|
-
nodes{ id body createdAt url user{ name } }
|
|
326
|
+
nodes{ id body createdAt url user{ id name } botActor{ __typename } }
|
|
327
327
|
}
|
|
328
328
|
}
|
|
329
329
|
}
|
|
@@ -334,13 +334,16 @@ arguments and node shape. For **both** anchors, use this access-layer adapter wi
|
|
|
334
334
|
`linear_graphql` above; it accumulates every page and prints no partial history.
|
|
335
335
|
A read succeeds only after `hasNextPage` is false. Errors, malformed pages, and
|
|
336
336
|
missing or repeated continuation cursors fail the whole read.
|
|
337
|
+
Preserve `botActor` with each comment: its non-null presence identifies automation,
|
|
338
|
+
even if `user.id` is trusted. When normalizing comments, carry it forward or set
|
|
339
|
+
`isBot: true`; never discard this metadata before release authorization.
|
|
337
340
|
|
|
338
341
|
```bash
|
|
339
342
|
linear_list_comment_pages() { # issue|project id -> complete JSON node array
|
|
340
343
|
local anchor="$1" id="$2" after=null nodes='[]' seen='[]'
|
|
341
344
|
local query variables response connection cursor
|
|
342
345
|
case "$anchor" in issue|project) ;; *) echo "Error: invalid comment anchor" >&2; return 1 ;; esac
|
|
343
|
-
query='query($id:String!,$after:String){'"$anchor"'(id:$id){comments(first:100,after:$after){pageInfo{hasNextPage endCursor} nodes{id body createdAt url user{name}}}}}'
|
|
346
|
+
query='query($id:String!,$after:String){'"$anchor"'(id:$id){comments(first:100,after:$after){pageInfo{hasNextPage endCursor} nodes{id body createdAt url user{id name} botActor{__typename}}}}}'
|
|
344
347
|
while :; do
|
|
345
348
|
variables=$(jq -cn --arg id "$id" --argjson after "$after" '{id:$id,after:$after}') || return 1
|
|
346
349
|
response=$(linear_graphql "$query" "$variables") || return 1
|
|
@@ -367,6 +370,13 @@ linear_list_comment_pages() { # issue|project id -> complete JSON node array
|
|
|
367
370
|
}
|
|
368
371
|
```
|
|
369
372
|
|
|
373
|
+
Keep the returned comment objects intact when a caller evaluates a human-gate release. The
|
|
374
|
+
`user.id` is the stable author identity; `user.name` is display text and never authorizes release.
|
|
375
|
+
Pass structured comments and an independently supplied `trustedHumanActorIds` allowlist to the
|
|
376
|
+
shared gate helpers (`ready-role-filing` — Human-gate release authorization). A body-only projection
|
|
377
|
+
loses identity and cannot discharge a hold. Preserve any explicit bot metadata from the provider;
|
|
378
|
+
if identity or trusted policy is unavailable, leave the hold active.
|
|
379
|
+
|
|
370
380
|
Call `linear_list_comment_pages project "$PROJECT_ID"` for `project_id`, or
|
|
371
381
|
`linear_list_comment_pages issue "$ISSUE_ID"` for `issue_id`. The caller receives
|
|
372
382
|
one complete node array; it must not interpret a failed command as zero comments.
|
|
@@ -6,6 +6,20 @@ allowed-tools: ["Skill", "Bash"]
|
|
|
6
6
|
|
|
7
7
|
# Linear Build Intake: $ARGUMENTS
|
|
8
8
|
|
|
9
|
+
## Human-gate release authorization
|
|
10
|
+
|
|
11
|
+
A release requires a trusted human author, not just matching comment text. Follow
|
|
12
|
+
`ready-role-filing` — **Human-gate release authorization**: preserve tracker-supplied comment
|
|
13
|
+
author IDs and bot metadata, resolve `trustedHumanActorIds` only from an explicit user instruction
|
|
14
|
+
or existing human-authored trusted project policy, and pass it with structured `comments` to every
|
|
15
|
+
hold classifier, reconciliation, normalization and release planner. Never derive trust from the
|
|
16
|
+
comment body, a display name, the actor's own assertion, or an automation posting on its own behalf.
|
|
17
|
+
Missing policy, missing/unreadable author identity, raw body strings, untrusted actors and known bots
|
|
18
|
+
cannot discharge a hold. Keep the item held and report the missing authorization; do not silently
|
|
19
|
+
replace these inputs with an empty history or an inferred allowlist. Authorized matching releases
|
|
20
|
+
continue through the existing path and never override an independently declared caller hold.
|
|
21
|
+
|
|
22
|
+
|
|
9
23
|
`$ARGUMENTS` is one of:
|
|
10
24
|
|
|
11
25
|
1. A Linear team key (e.g. `ENG`) — scans that team for ready Issues.
|
|
@@ -183,8 +197,8 @@ A blocker is a **claim with a timestamp, not a fact**. It is written once and go
|
|
|
183
197
|
For each pre-work candidate that is **not** in `$READY`:
|
|
184
198
|
|
|
185
199
|
1. **Read release comments before applying the human gate.** Pass all item comments, labels,
|
|
186
|
-
body and configured `humanNeededLabel` to `classifyReadyCandidate(...)`. For a discharged hold,
|
|
187
|
-
call `planHumanGateRelease({ labels, body, comments, humanNeededLabel, readyLabel, lifecycleLabels, alreadyNotified })`
|
|
200
|
+
body, `trustedHumanActorIds` and configured `humanNeededLabel` to `classifyReadyCandidate(...)`. For a discharged hold,
|
|
201
|
+
call `planHumanGateRelease({ labels, body, comments, trustedHumanActorIds, humanNeededLabel, readyLabel, lifecycleLabels, alreadyNotified })`
|
|
188
202
|
and retain its plan. Apply human-marker cleanup only as planned; defer any ready-role restoration
|
|
189
203
|
until steps 2–5 have cleared the remaining blockers (map the role to the vendor's state or label).
|
|
190
204
|
A still-active hold is never auto-selected, whatever any probe says. An absent or unreadable
|
|
@@ -196,7 +210,7 @@ For each pre-work candidate that is **not** in `$READY`:
|
|
|
196
210
|
4. **Classify with the shared helper** so the ordering and the evidence requirement cannot drift per vendor:
|
|
197
211
|
|
|
198
212
|
```text
|
|
199
|
-
classifyPreWorkCandidate({ laneType, labels, body, humanNeededLabel, statedBlocker, probe })
|
|
213
|
+
classifyPreWorkCandidate({ laneType, labels, body, comments, trustedHumanActorIds, humanNeededLabel, statedBlocker, probe })
|
|
200
214
|
→ { selectable, reason, humanGated, evidence }
|
|
201
215
|
```
|
|
202
216
|
|
|
@@ -224,7 +238,7 @@ other gate's verdict — however conclusive — may promote an item a person par
|
|
|
224
238
|
drift, and a drifted gate fails *silently*, by quietly ceasing to match. Do **not** re-implement
|
|
225
239
|
the test here, and do **not** key it on `reason=`: markers in the wild carry no `reason=` key at
|
|
226
240
|
all and sit anywhere in the body, so a structured parse would miss them while appearing to work
|
|
227
|
-
on every item that happens to have one. **Pass the item's `comments` alongside its labels and
|
|
241
|
+
on every item that happens to have one. **Pass the item's structured `comments` and `trustedHumanActorIds` alongside its labels and
|
|
228
242
|
body.** A hold is ended by a release recorded in a comment, so a reader handed no comments cannot
|
|
229
243
|
see the discharge — it goes on holding an item whose question was answered weeks ago, which is
|
|
230
244
|
the defect this gate carried from the day it was written (CodySwannGT/lisa#3852). Omitting them
|
|
@@ -235,7 +249,7 @@ other gate's verdict — however conclusive — may promote an item a person par
|
|
|
235
249
|
and re-rejected every cycle forever and seen by nothing — `lisa-repair-intake` sweeps items that
|
|
236
250
|
are **not** in the ready role and excludes gated ones outright, so a ready-and-gated item falls
|
|
237
251
|
outside its filter twice over. Call
|
|
238
|
-
`planHumanGateReconciliation({ labels, body, humanNeededLabel, readyLabel, alreadyNotified })`
|
|
252
|
+
`planHumanGateReconciliation({ labels, body, comments, trustedHumanActorIds, humanNeededLabel, readyLabel, alreadyNotified })`
|
|
239
253
|
and apply exactly the actions it returns: remove `$READY`, add the configured human-needed
|
|
240
254
|
marker, and post `formatHumanGateNote()` once. The planner is idempotent by state, so an item
|
|
241
255
|
already out of the lane and already marked yields no second mutation and no second comment. This
|
|
@@ -245,7 +259,7 @@ other gate's verdict — however conclusive — may promote an item a person par
|
|
|
245
259
|
This ready-lane candidate can retain a historical body marker and a human-needed label.
|
|
246
260
|
This step reconciles only candidates still in the ready lane; released holds outside it are
|
|
247
261
|
recovered by `lisa-repair-intake` step 2b (or Phase 2.5 when included in this cycle). Call
|
|
248
|
-
`planHumanGateRelease({ labels, body, comments, humanNeededLabel, readyLabel, lifecycleLabels, alreadyNotified })`
|
|
262
|
+
`planHumanGateRelease({ labels, body, comments, trustedHumanActorIds, humanNeededLabel, readyLabel, lifecycleLabels, alreadyNotified })`
|
|
249
263
|
and apply exactly the actions it returns: remove the configured human-needed marker, add the
|
|
250
264
|
configured ready role back, and post `formatHumanGateReleaseNote()` once. It is the exact inverse
|
|
251
265
|
of step 3's planner and it refuses in both directions — an item still held plans nothing, and an
|
|
@@ -6,6 +6,20 @@ allowed-tools: ["Bash", "Skill"]
|
|
|
6
6
|
|
|
7
7
|
# Write Linear Work Item: $ARGUMENTS
|
|
8
8
|
|
|
9
|
+
## Human-gate release authorization
|
|
10
|
+
|
|
11
|
+
A release requires a trusted human author, not just matching comment text. Follow
|
|
12
|
+
`ready-role-filing` — **Human-gate release authorization**: preserve tracker-supplied comment
|
|
13
|
+
author IDs and bot metadata, resolve `trustedHumanActorIds` only from an explicit user instruction
|
|
14
|
+
or existing human-authored trusted project policy, and pass it with structured `comments` to every
|
|
15
|
+
hold classifier, reconciliation, normalization and release planner. Never derive trust from the
|
|
16
|
+
comment body, a display name, the actor's own assertion, or an automation posting on its own behalf.
|
|
17
|
+
Missing policy, missing/unreadable author identity, raw body strings, untrusted actors and known bots
|
|
18
|
+
cannot discharge a hold. Keep the item held and report the missing authorization; do not silently
|
|
19
|
+
replace these inputs with an empty history or an inferred allowlist. Authorized matching releases
|
|
20
|
+
continue through the existing path and never override an independently declared caller hold.
|
|
21
|
+
|
|
22
|
+
|
|
9
23
|
Create or update a Linear work item — Project (for Epics), Issue (for Stories), or sub-Issue (for Sub-tasks) — with all required relationships, metadata, and quality gates. Every section below is mandatory. Thin items are rejected.
|
|
10
24
|
|
|
11
25
|
Repository name for scoped comments: `basename $(git rev-parse --show-toplevel)`.
|
|
@@ -304,7 +318,7 @@ proceed — the marker still holds. Never file the label *instead of* the marker
|
|
|
304
318
|
**Every marker reader must consult comments.** Use `classifyReadyCandidate` with labels, body, comments and the configured human-needed label, then `planHumanGateRelease` for any release actions. A historical body marker alone is not an active hold after its matching release; unreadable comments leave a hold in place.
|
|
305
319
|
|
|
306
320
|
**Write a `reason=` the release can name.** The hold's reason is not decoration: a hold ends when a
|
|
307
|
-
`[lisa-human-gate-release]` comment repeating that same `reason=` is recorded on the item, and the
|
|
321
|
+
`[lisa-human-gate-release]` comment repeating that same `reason=` is recorded on the item by an authorized human, and the
|
|
308
322
|
next intake sweep then takes the marker label off and puts the item back in the build-ready role on
|
|
309
323
|
its own. Matching is per-reason so that a hold declared *after* an earlier release is not born
|
|
310
324
|
discharged. A keyless hold is legal and is discharged by a keyless release; a hold whose reason is a
|
|
@@ -6,6 +6,20 @@ allowed-tools: ["Skill", "Bash", "Read", "Write", "Edit"]
|
|
|
6
6
|
|
|
7
7
|
# Repair Intake: $ARGUMENTS
|
|
8
8
|
|
|
9
|
+
## Human-gate release authorization
|
|
10
|
+
|
|
11
|
+
A release requires a trusted human author, not just matching comment text. Follow
|
|
12
|
+
`ready-role-filing` — **Human-gate release authorization**: preserve tracker-supplied comment
|
|
13
|
+
author IDs and bot metadata, resolve `trustedHumanActorIds` only from an explicit user instruction
|
|
14
|
+
or existing human-authored trusted project policy, and pass it with structured `comments` to every
|
|
15
|
+
hold classifier, reconciliation, normalization and release planner. Never derive trust from the
|
|
16
|
+
comment body, a display name, the actor's own assertion, or an automation posting on its own behalf.
|
|
17
|
+
Missing policy, missing/unreadable author identity, raw body strings, untrusted actors and known bots
|
|
18
|
+
cannot discharge a hold. Keep the item held and report the missing authorization; do not silently
|
|
19
|
+
replace these inputs with an empty history or an inferred allowlist. Authorized matching releases
|
|
20
|
+
continue through the existing path and never override an independently declared caller hold.
|
|
21
|
+
|
|
22
|
+
|
|
9
23
|
Run one batch-**repair** cycle against the queue identified by `$ARGUMENTS`, or by merged GitHub
|
|
10
24
|
config when the queue is omitted and a GitHub source/tracker default is resolvable. Where `lisa-intake`
|
|
11
25
|
scans the `ready` role and moves work *forward*, repair-intake scans the **stuck and
|
|
@@ -1071,7 +1085,7 @@ with labels like `build-ready`, or with no Lisa status label at all, that are in
|
|
|
1071
1085
|
`intake_mode=build`, every non-PRD issue is normalized as a build ticket. If `intake_mode=both`,
|
|
1072
1086
|
classify PRDs first and normalize all remaining issues as build tickets.
|
|
1073
1087
|
2a. **Ask whether a person is holding it, before anything else.** Call
|
|
1074
|
-
`planLabelNormalization({ labels, body, comments, humanNeededLabel, lifecycleLabels, readyLabel })` from
|
|
1088
|
+
`planLabelNormalization({ labels, body, comments, trustedHumanActorIds, humanNeededLabel, lifecycleLabels, readyLabel })` from
|
|
1075
1089
|
`scripts/intake-blocker-reprobe.mjs` for every candidate and apply exactly the verdict it
|
|
1076
1090
|
returns. Do **not** re-implement the test here and do **not** decide held-ness from labels
|
|
1077
1091
|
alone: the vendor writers stamp the `[lisa-human-gate]` marker into the body of a deliberate
|
|
@@ -1088,7 +1102,7 @@ with labels like `build-ready`, or with no Lisa status label at all, that are in
|
|
|
1088
1102
|
the safe failure direction without the latch. Count these under `held_for_person`, never under
|
|
1089
1103
|
`normalized_ready`.
|
|
1090
1104
|
|
|
1091
|
-
**Pass the item's `comments`.** The planner reads a recorded `[lisa-human-gate-release]` comment
|
|
1105
|
+
**Pass the item's `comments` with author identity and `trustedHumanActorIds`.** The planner reads a recorded `[lisa-human-gate-release]` comment
|
|
1092
1106
|
as the discharge of the hold naming the same `reason=`, and an item read without its comments is
|
|
1093
1107
|
an item whose discharge cannot be seen. That fails closed — it stays held — which is the safe
|
|
1094
1108
|
direction and precisely why the omission is invisible.
|
|
@@ -1102,7 +1116,7 @@ with labels like `build-ready`, or with no Lisa status label at all, that are in
|
|
|
1102
1116
|
|
|
1103
1117
|
Enumerate items carrying the configured `human_needed` marker **or** a `[lisa-human-gate]` marker
|
|
1104
1118
|
in the body, and for each call
|
|
1105
|
-
`planHumanGateRelease({ labels, body, comments, humanNeededLabel, readyLabel, lifecycleLabels, alreadyNotified })`
|
|
1119
|
+
`planHumanGateRelease({ labels, body, comments, trustedHumanActorIds, humanNeededLabel, readyLabel, lifecycleLabels, alreadyNotified })`
|
|
1106
1120
|
from `scripts/intake-blocker-reprobe.mjs`. Apply exactly the actions it returns: remove the
|
|
1107
1121
|
human-needed marker, add the configured build `ready` label back, and post
|
|
1108
1122
|
`formatHumanGateReleaseNote()` once. Do **not** re-implement the discharge test, and do **not**
|
|
@@ -1119,10 +1133,10 @@ with labels like `build-ready`, or with no Lisa status label at all, that are in
|
|
|
1119
1133
|
item carries no other configured lifecycle label.
|
|
1120
1134
|
|
|
1121
1135
|
This is a genuine exception to "never remove a `human_needed` marker this skill did not apply",
|
|
1122
|
-
and the exception is narrow enough to state exactly:
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1136
|
+
and the exception is narrow enough to state exactly: the release author must first be verified against `trustedHumanActorIds`; only then does the
|
|
1137
|
+
matching release satisfy the hold's stated void condition. The actor who originally applied the
|
|
1138
|
+
marker does not need to match that authorized release author. The general rule
|
|
1139
|
+
stands because "stale" is otherwise a judgment about the block's kind; here an authorized matching release is required; arbitrary matching text is not enough.
|
|
1126
1140
|
|
|
1127
1141
|
**Never edit a description to clear a hold**, here or anywhere. The only body write this plugin
|
|
1128
1142
|
has is a whole-body replacement, so deleting one line means rewriting the record and hoping
|
|
@@ -6,6 +6,20 @@ allowed-tools: ["Skill", "Bash", "Read"]
|
|
|
6
6
|
|
|
7
7
|
# Track Work: $ARGUMENTS
|
|
8
8
|
|
|
9
|
+
## Human-gate release authorization
|
|
10
|
+
|
|
11
|
+
A release requires a trusted human author, not just matching comment text. Follow
|
|
12
|
+
`ready-role-filing` — **Human-gate release authorization**: preserve tracker-supplied comment
|
|
13
|
+
author IDs and bot metadata, resolve `trustedHumanActorIds` only from an explicit user instruction
|
|
14
|
+
or existing human-authored trusted project policy, and pass it with structured `comments` to every
|
|
15
|
+
hold classifier, reconciliation, normalization and release planner. Never derive trust from the
|
|
16
|
+
comment body, a display name, the actor's own assertion, or an automation posting on its own behalf.
|
|
17
|
+
Missing policy, missing/unreadable author identity, raw body strings, untrusted actors and known bots
|
|
18
|
+
cannot discharge a hold. Keep the item held and report the missing authorization; do not silently
|
|
19
|
+
replace these inputs with an empty history or an inferred allowlist. Authorized matching releases
|
|
20
|
+
continue through the existing path and never override an independently declared caller hold.
|
|
21
|
+
|
|
22
|
+
|
|
9
23
|
Establish the tracked-work invariant before any durable project mutation. Discussion and read-only orientation may proceed without this skill; code, configuration, documentation, research artifacts, plans, investigation findings, tests, commits, and pull requests may not.
|
|
10
24
|
|
|
11
25
|
This flow must return exactly one canonical `(tracker_provider, work_item_ref)` pair or fail closed. It never returns an unvalidated textual guess.
|
|
@@ -45,7 +59,7 @@ This is intentionally conservative: ambiguity creates one explicit work item ins
|
|
|
45
59
|
## Phase 3 — Claim and bind
|
|
46
60
|
|
|
47
61
|
The work item is **held** when the caller declared a `human_gate`, independently of any item history,
|
|
48
|
-
or `classifyReadyCandidate({ labels, body, comments, humanNeededLabel })` from the shipped
|
|
62
|
+
or `classifyReadyCandidate({ labels, body, comments, trustedHumanActorIds, humanNeededLabel })` from the shipped
|
|
49
63
|
`scripts/intake-blocker-reprobe.mjs` returns `claimable: false`. Pass the complete live comment
|
|
50
64
|
history so a matching `[lisa-human-gate-release]` discharges the historical body marker. Never
|
|
51
65
|
reimplement heldness as a substring test or as the negation of `planHumanGateRelease().released`:
|
|
@@ -58,7 +72,7 @@ A held item stops the flow here, whatever roles or labels it carries. Do not inv
|
|
|
58
72
|
and carry its reason verbatim in `gate_reason` (null for a keyless hold), then stop.
|
|
59
73
|
|
|
60
74
|
For a discharged item, call
|
|
61
|
-
`planHumanGateRelease({ labels, body, comments, humanNeededLabel, readyLabel, lifecycleLabels, alreadyNotified })`
|
|
75
|
+
`planHumanGateRelease({ labels, body, comments, trustedHumanActorIds, humanNeededLabel, readyLabel, lifecycleLabels, alreadyNotified })`
|
|
62
76
|
and apply only the returned actions before claiming. Keep the body marker as history; a release
|
|
63
77
|
never overrides a new caller-declared hold or another eligibility check.
|
|
64
78
|
|
|
@@ -6,6 +6,20 @@ allowed-tools: ["Skill", "Bash", "Read"]
|
|
|
6
6
|
|
|
7
7
|
# Tracker Build Intake: $ARGUMENTS
|
|
8
8
|
|
|
9
|
+
## Human-gate release authorization
|
|
10
|
+
|
|
11
|
+
A release requires a trusted human author, not just matching comment text. Follow
|
|
12
|
+
`ready-role-filing` — **Human-gate release authorization**: preserve tracker-supplied comment
|
|
13
|
+
author IDs and bot metadata, resolve `trustedHumanActorIds` only from an explicit user instruction
|
|
14
|
+
or existing human-authored trusted project policy, and pass it with structured `comments` to every
|
|
15
|
+
hold classifier, reconciliation, normalization and release planner. Never derive trust from the
|
|
16
|
+
comment body, a display name, the actor's own assertion, or an automation posting on its own behalf.
|
|
17
|
+
Missing policy, missing/unreadable author identity, raw body strings, untrusted actors and known bots
|
|
18
|
+
cannot discharge a hold. Keep the item held and report the missing authorization; do not silently
|
|
19
|
+
replace these inputs with an empty history or an inferred allowlist. Authorized matching releases
|
|
20
|
+
continue through the existing path and never override an independently declared caller hold.
|
|
21
|
+
|
|
22
|
+
|
|
9
23
|
Thin dispatcher. Resolves the configured destination tracker and delegates to the matching vendor build-queue scanner.
|
|
10
24
|
|
|
11
25
|
See the `config-resolution` rule for configuration and dispatch table.
|
|
@@ -63,7 +77,7 @@ blocker re-probe carries an absolute human gate: an item carrying the configured
|
|
|
63
77
|
or a `[lisa-human-gate]` marker is never auto-selected, whatever a probe returns.
|
|
64
78
|
|
|
65
79
|
That gate has an inverse, and it is forwarded identically: a hold ends when a
|
|
66
|
-
`[lisa-human-gate-release]` comment naming the same `reason=` is recorded on the item. Every vendor
|
|
80
|
+
`[lisa-human-gate-release]` comment naming the same `reason=` is recorded on the item by an authorized human. Every vendor
|
|
67
81
|
scanner passes the item's `comments` into the gate helpers so the discharge is visible, and calls
|
|
68
82
|
`planHumanGateRelease(...)` to take the marker off and put the item back in the queue. **No vendor
|
|
69
83
|
scanner clears a hold by editing the description** — the only body write any of them has is a
|