@codyswann/lisa 4.55.2 → 4.55.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/all/copy-overwrite/scripts/check-orphaned-branches.mjs +49 -13
- package/all/copy-overwrite/scripts/lisa-enforcement-fallback.sh +9 -1
- package/all/copy-overwrite/scripts/lisa-hooks/block-blind-automerge.sh +10 -5
- package/all/copy-overwrite/scripts/lisa-hooks/block-direct-issue-create.sh +4 -0
- package/all/copy-overwrite/scripts/lisa-hooks/block-managed-file-edits.sh +73 -2
- package/all/copy-overwrite/scripts/lisa-hooks/guard-dedupe.bash +63 -29
- package/all/copy-overwrite/scripts/lisa-hooks/parity-safety-net.sh +2 -1
- package/all/copy-overwrite/scripts/lisa-hooks/worktree-binding-guard.sh +2 -1
- package/all/copy-overwrite/scripts/lisa-run-gates.mjs +7 -2
- package/all/copy-overwrite/scripts/lisa-work-item.mjs +50 -14
- package/dist/core/lisa-owned-hash-ledger.d.ts.map +1 -1
- package/dist/core/lisa-owned-hash-ledger.js +36 -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 +92 -80
- package/dist/core/upstream-evidence-manifest.js.map +1 -1
- package/dist/opencode/plugin-templates/block-managed-file-edits.sh +76 -2
- package/dist/opencode/plugin-templates/block-no-verify.sh +3 -0
- package/dist/opencode/plugin-templates/guard-dedupe.bash +66 -29
- package/dist/opencode/plugin-templates/parity-safety-net-heredoc.py +3 -0
- package/dist/opencode/plugin-templates/parity-safety-net.sh +5 -1
- package/dist/opencode/support-file-resolver.d.ts.map +1 -1
- package/dist/opencode/support-file-resolver.js +3 -1
- package/dist/opencode/support-file-resolver.js.map +1 -1
- package/expo/copy-overwrite/plugins/withAndroidSplashNoClientExit.js +23 -21
- package/expo/create-only/.github/required-checks.json +1 -1
- package/nestjs/create-only/.github/required-checks.json +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 +38 -15
- 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 +37 -13
- 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 +56 -7
- package/plugins/lisa/.codex-plugin/skills/lisa-linear-build-intake/SKILL.md +36 -11
- package/plugins/lisa/.codex-plugin/skills/lisa-linear-prd-intake/SKILL.md +12 -2
- package/plugins/lisa/.codex-plugin/skills/lisa-linear-validate-issue/SKILL.md +1 -18
- package/plugins/lisa/.codex-plugin/skills/lisa-linear-verify/SKILL.md +0 -17
- package/plugins/lisa/.codex-plugin/skills/lisa-linear-write-issue/SKILL.md +18 -35
- package/plugins/lisa/.codex-plugin/skills/lisa-prd-ticket-coverage/SKILL.md +2 -2
- package/plugins/lisa/.codex-plugin/skills/lisa-repair-intake/SKILL.md +66 -12
- package/plugins/lisa/.codex-plugin/skills/lisa-rework-triage/SKILL.md +2 -1
- package/plugins/lisa/.codex-plugin/skills/lisa-secrets-access/scripts/providers.mjs +2 -1
- package/plugins/lisa/.codex-plugin/skills/lisa-setup-linear/SKILL.md +1 -1
- package/plugins/lisa/.codex-plugin/skills/lisa-setup-remote-env/scripts/preflight-tools.mjs +7 -2
- package/plugins/lisa/.codex-plugin/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +11 -4
- package/plugins/lisa/.codex-plugin/skills/lisa-setup-remote-env/scripts/toolchain.mjs +17 -5
- package/plugins/lisa/.codex-plugin/skills/lisa-track/SKILL.md +32 -4
- package/plugins/lisa/.codex-plugin/skills/lisa-tracker-build-intake/SKILL.md +15 -1
- package/plugins/lisa/hooks/block-blind-automerge.sh +13 -5
- package/plugins/lisa/hooks/block-direct-issue-create.sh +7 -0
- package/plugins/lisa/hooks/block-instruction-file-edits.sh +3 -0
- package/plugins/lisa/hooks/block-managed-file-edits.sh +76 -2
- package/plugins/lisa/hooks/block-no-verify.sh +3 -0
- package/plugins/lisa/hooks/block-shell-json-parsing.sh +3 -0
- package/plugins/lisa/hooks/guard-dedupe.bash +66 -29
- package/plugins/lisa/hooks/parity-safety-net-heredoc.py +3 -0
- package/plugins/lisa/hooks/parity-safety-net.sh +5 -1
- package/plugins/lisa/hooks/worktree-binding-guard.mjs +3 -0
- package/plugins/lisa/hooks/worktree-binding-guard.sh +5 -1
- package/plugins/lisa/rules/eager/00-rule-index.md +1 -0
- package/plugins/lisa/rules/eager/base-rules.md +3 -1
- package/plugins/lisa/rules/eager/withdrawn-rulings.md +14 -3
- package/plugins/lisa/rules/reference/automation-runbook-contract.md +1 -1
- package/plugins/lisa/rules/reference/bdd-e2e-coverage.md +1 -1
- package/plugins/lisa/rules/reference/blocker-containment.md +3 -3
- package/plugins/lisa/rules/reference/claim-archaeology.md +1 -1
- package/plugins/lisa/rules/reference/claim-evidence-mapping.md +1 -1
- package/plugins/lisa/rules/reference/claim-time-guards.md +1 -1
- package/plugins/lisa/rules/reference/control-reachability.md +1 -1
- package/plugins/lisa/rules/reference/convergent-review.md +1 -1
- package/plugins/lisa/rules/reference/credential-substrate-precedence.md +1 -1
- package/plugins/lisa/rules/reference/dependency-decision-records.md +1 -1
- package/plugins/lisa/rules/reference/dependency-internalization-kit.md +1 -1
- package/plugins/lisa/rules/reference/dependency-trust-classes.md +1 -1
- package/plugins/lisa/rules/reference/deployed-state-readback.md +1 -1
- package/plugins/lisa/rules/reference/derived-branch-plan.md +1 -1
- package/plugins/lisa/rules/reference/design-source-of-truth.md +1 -1
- package/plugins/lisa/rules/reference/design-value-binding.md +1 -1
- package/plugins/lisa/rules/reference/documentation-source-paths.md +1 -1
- package/plugins/lisa/rules/reference/leaf-only-lifecycle.md +1 -1
- package/plugins/lisa/rules/reference/observability-audit.md +1 -1
- package/plugins/lisa/rules/reference/prd-definition-of-ready.md +1 -1
- package/plugins/lisa/rules/reference/prd-lifecycle-rollup.md +1 -1
- package/plugins/lisa/rules/reference/pre-flight-autofill.md +1 -1
- package/plugins/lisa/rules/reference/promotion-contract.md +1 -1
- package/plugins/lisa/rules/reference/readiness-rubric.md +1 -1
- package/plugins/lisa/rules/reference/ready-role-filing.md +37 -1
- package/plugins/lisa/rules/reference/rejection-detection.md +1 -1
- package/plugins/lisa/rules/reference/repo-scope-split.md +9 -10
- package/plugins/lisa/rules/reference/reset-seed-coverage.md +1 -1
- package/plugins/lisa/rules/reference/usage-accounting.md +1 -1
- package/plugins/lisa/rules/reference/work-item-definition-of-ready.md +1 -1
- 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 +38 -15
- package/plugins/lisa/skills/lisa-github-write-issue/SKILL.md +15 -1
- package/plugins/lisa/skills/lisa-jira-build-intake/SKILL.md +37 -13
- package/plugins/lisa/skills/lisa-jira-write-ticket/SKILL.md +15 -1
- package/plugins/lisa/skills/lisa-linear-access/SKILL.md +56 -7
- package/plugins/lisa/skills/lisa-linear-build-intake/SKILL.md +36 -11
- package/plugins/lisa/skills/lisa-linear-prd-intake/SKILL.md +12 -2
- package/plugins/lisa/skills/lisa-linear-validate-issue/SKILL.md +1 -18
- package/plugins/lisa/skills/lisa-linear-verify/SKILL.md +0 -17
- package/plugins/lisa/skills/lisa-linear-write-issue/SKILL.md +18 -35
- package/plugins/lisa/skills/lisa-prd-ticket-coverage/SKILL.md +2 -2
- package/plugins/lisa/skills/lisa-repair-intake/SKILL.md +66 -12
- package/plugins/lisa/skills/lisa-rework-triage/SKILL.md +2 -1
- package/plugins/lisa/skills/lisa-secrets-access/scripts/providers.mjs +2 -1
- package/plugins/lisa/skills/lisa-setup-linear/SKILL.md +1 -1
- package/plugins/lisa/skills/lisa-setup-remote-env/scripts/preflight-tools.mjs +7 -2
- package/plugins/lisa/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +11 -4
- package/plugins/lisa/skills/lisa-setup-remote-env/scripts/toolchain.mjs +17 -5
- package/plugins/lisa/skills/lisa-track/SKILL.md +32 -4
- package/plugins/lisa/skills/lisa-tracker-build-intake/SKILL.md +15 -1
- package/plugins/lisa-agy/hooks/block-blind-automerge.sh +13 -5
- package/plugins/lisa-agy/hooks/block-direct-issue-create.sh +7 -0
- package/plugins/lisa-agy/hooks/block-instruction-file-edits.sh +3 -0
- package/plugins/lisa-agy/hooks/block-managed-file-edits.sh +76 -2
- package/plugins/lisa-agy/hooks/block-shell-json-parsing.sh +3 -0
- package/plugins/lisa-agy/hooks/guard-dedupe.bash +66 -29
- package/plugins/lisa-agy/hooks/parity-safety-net-heredoc.py +3 -0
- package/plugins/lisa-agy/hooks/parity-safety-net.sh +5 -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 +38 -15
- package/plugins/lisa-agy/skills/lisa-github-write-issue/SKILL.md +15 -1
- package/plugins/lisa-agy/skills/lisa-jira-build-intake/SKILL.md +37 -13
- package/plugins/lisa-agy/skills/lisa-jira-write-ticket/SKILL.md +15 -1
- package/plugins/lisa-agy/skills/lisa-linear-access/SKILL.md +56 -7
- package/plugins/lisa-agy/skills/lisa-linear-build-intake/SKILL.md +36 -11
- package/plugins/lisa-agy/skills/lisa-linear-prd-intake/SKILL.md +12 -2
- package/plugins/lisa-agy/skills/lisa-linear-validate-issue/SKILL.md +1 -18
- package/plugins/lisa-agy/skills/lisa-linear-verify/SKILL.md +0 -17
- package/plugins/lisa-agy/skills/lisa-linear-write-issue/SKILL.md +18 -35
- package/plugins/lisa-agy/skills/lisa-prd-ticket-coverage/SKILL.md +2 -2
- package/plugins/lisa-agy/skills/lisa-repair-intake/SKILL.md +66 -12
- package/plugins/lisa-agy/skills/lisa-rework-triage/SKILL.md +2 -1
- package/plugins/lisa-agy/skills/lisa-secrets-access/scripts/providers.mjs +2 -1
- package/plugins/lisa-agy/skills/lisa-setup-linear/SKILL.md +1 -1
- package/plugins/lisa-agy/skills/lisa-setup-remote-env/scripts/preflight-tools.mjs +7 -2
- package/plugins/lisa-agy/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +11 -4
- package/plugins/lisa-agy/skills/lisa-setup-remote-env/scripts/toolchain.mjs +17 -5
- package/plugins/lisa-agy/skills/lisa-track/SKILL.md +32 -4
- 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/hooks/block-blind-automerge.sh +13 -5
- package/plugins/lisa-copilot/hooks/block-direct-issue-create.sh +7 -0
- package/plugins/lisa-copilot/hooks/block-instruction-file-edits.sh +3 -0
- package/plugins/lisa-copilot/hooks/block-managed-file-edits.sh +76 -2
- package/plugins/lisa-copilot/hooks/block-no-verify.sh +3 -0
- package/plugins/lisa-copilot/hooks/block-shell-json-parsing.sh +3 -0
- package/plugins/lisa-copilot/hooks/guard-dedupe.bash +66 -29
- package/plugins/lisa-copilot/hooks/parity-safety-net-heredoc.py +3 -0
- package/plugins/lisa-copilot/hooks/parity-safety-net.sh +5 -1
- package/plugins/lisa-copilot/hooks/worktree-binding-guard.mjs +3 -0
- package/plugins/lisa-copilot/hooks/worktree-binding-guard.sh +5 -1
- package/plugins/lisa-copilot/rules/eager/00-rule-index.md +1 -0
- package/plugins/lisa-copilot/rules/eager/base-rules.md +3 -1
- package/plugins/lisa-copilot/rules/eager/withdrawn-rulings.md +14 -3
- package/plugins/lisa-copilot/rules/reference/automation-runbook-contract.md +1 -1
- package/plugins/lisa-copilot/rules/reference/bdd-e2e-coverage.md +1 -1
- package/plugins/lisa-copilot/rules/reference/blocker-containment.md +3 -3
- package/plugins/lisa-copilot/rules/reference/claim-archaeology.md +1 -1
- package/plugins/lisa-copilot/rules/reference/claim-evidence-mapping.md +1 -1
- package/plugins/lisa-copilot/rules/reference/claim-time-guards.md +1 -1
- package/plugins/lisa-copilot/rules/reference/control-reachability.md +1 -1
- package/plugins/lisa-copilot/rules/reference/convergent-review.md +1 -1
- package/plugins/lisa-copilot/rules/reference/credential-substrate-precedence.md +1 -1
- package/plugins/lisa-copilot/rules/reference/dependency-decision-records.md +1 -1
- package/plugins/lisa-copilot/rules/reference/dependency-internalization-kit.md +1 -1
- package/plugins/lisa-copilot/rules/reference/dependency-trust-classes.md +1 -1
- package/plugins/lisa-copilot/rules/reference/deployed-state-readback.md +1 -1
- package/plugins/lisa-copilot/rules/reference/derived-branch-plan.md +1 -1
- package/plugins/lisa-copilot/rules/reference/design-source-of-truth.md +1 -1
- package/plugins/lisa-copilot/rules/reference/design-value-binding.md +1 -1
- package/plugins/lisa-copilot/rules/reference/documentation-source-paths.md +1 -1
- package/plugins/lisa-copilot/rules/reference/leaf-only-lifecycle.md +1 -1
- package/plugins/lisa-copilot/rules/reference/observability-audit.md +1 -1
- package/plugins/lisa-copilot/rules/reference/prd-definition-of-ready.md +1 -1
- package/plugins/lisa-copilot/rules/reference/prd-lifecycle-rollup.md +1 -1
- package/plugins/lisa-copilot/rules/reference/pre-flight-autofill.md +1 -1
- package/plugins/lisa-copilot/rules/reference/promotion-contract.md +1 -1
- package/plugins/lisa-copilot/rules/reference/readiness-rubric.md +1 -1
- package/plugins/lisa-copilot/rules/reference/ready-role-filing.md +37 -1
- package/plugins/lisa-copilot/rules/reference/rejection-detection.md +1 -1
- package/plugins/lisa-copilot/rules/reference/repo-scope-split.md +9 -10
- package/plugins/lisa-copilot/rules/reference/reset-seed-coverage.md +1 -1
- package/plugins/lisa-copilot/rules/reference/usage-accounting.md +1 -1
- package/plugins/lisa-copilot/rules/reference/work-item-definition-of-ready.md +1 -1
- 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 +38 -15
- package/plugins/lisa-copilot/skills/lisa-github-write-issue/SKILL.md +15 -1
- package/plugins/lisa-copilot/skills/lisa-jira-build-intake/SKILL.md +37 -13
- package/plugins/lisa-copilot/skills/lisa-jira-write-ticket/SKILL.md +15 -1
- package/plugins/lisa-copilot/skills/lisa-linear-access/SKILL.md +56 -7
- package/plugins/lisa-copilot/skills/lisa-linear-build-intake/SKILL.md +36 -11
- package/plugins/lisa-copilot/skills/lisa-linear-prd-intake/SKILL.md +12 -2
- package/plugins/lisa-copilot/skills/lisa-linear-validate-issue/SKILL.md +1 -18
- package/plugins/lisa-copilot/skills/lisa-linear-verify/SKILL.md +0 -17
- package/plugins/lisa-copilot/skills/lisa-linear-write-issue/SKILL.md +18 -35
- package/plugins/lisa-copilot/skills/lisa-prd-ticket-coverage/SKILL.md +2 -2
- package/plugins/lisa-copilot/skills/lisa-repair-intake/SKILL.md +66 -12
- package/plugins/lisa-copilot/skills/lisa-rework-triage/SKILL.md +2 -1
- package/plugins/lisa-copilot/skills/lisa-secrets-access/scripts/providers.mjs +2 -1
- package/plugins/lisa-copilot/skills/lisa-setup-linear/SKILL.md +1 -1
- package/plugins/lisa-copilot/skills/lisa-setup-remote-env/scripts/preflight-tools.mjs +7 -2
- package/plugins/lisa-copilot/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +11 -4
- package/plugins/lisa-copilot/skills/lisa-setup-remote-env/scripts/toolchain.mjs +17 -5
- package/plugins/lisa-copilot/skills/lisa-track/SKILL.md +32 -4
- 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/hooks/block-blind-automerge.sh +13 -5
- package/plugins/lisa-cursor/hooks/block-direct-issue-create.sh +7 -0
- package/plugins/lisa-cursor/hooks/block-instruction-file-edits.sh +3 -0
- package/plugins/lisa-cursor/hooks/block-managed-file-edits.sh +76 -2
- package/plugins/lisa-cursor/hooks/block-no-verify.sh +3 -0
- package/plugins/lisa-cursor/hooks/block-shell-json-parsing.sh +3 -0
- package/plugins/lisa-cursor/hooks/guard-dedupe.bash +66 -29
- package/plugins/lisa-cursor/hooks/parity-safety-net-heredoc.py +3 -0
- package/plugins/lisa-cursor/hooks/parity-safety-net.sh +5 -1
- package/plugins/lisa-cursor/hooks/worktree-binding-guard.mjs +3 -0
- package/plugins/lisa-cursor/hooks/worktree-binding-guard.sh +5 -1
- package/plugins/lisa-cursor/rules/00-rule-index.mdc +1 -0
- package/plugins/lisa-cursor/rules/automation-runbook-contract-reference.mdc +1 -1
- package/plugins/lisa-cursor/rules/base-rules.mdc +3 -1
- package/plugins/lisa-cursor/rules/bdd-e2e-coverage-reference.mdc +1 -1
- package/plugins/lisa-cursor/rules/blocker-containment-reference.mdc +3 -3
- package/plugins/lisa-cursor/rules/claim-archaeology-reference.mdc +1 -1
- package/plugins/lisa-cursor/rules/claim-evidence-mapping-reference.mdc +1 -1
- package/plugins/lisa-cursor/rules/claim-time-guards-reference.mdc +1 -1
- package/plugins/lisa-cursor/rules/control-reachability-reference.mdc +1 -1
- package/plugins/lisa-cursor/rules/convergent-review-reference.mdc +1 -1
- package/plugins/lisa-cursor/rules/credential-substrate-precedence-reference.mdc +1 -1
- package/plugins/lisa-cursor/rules/dependency-decision-records-reference.mdc +1 -1
- package/plugins/lisa-cursor/rules/dependency-internalization-kit-reference.mdc +1 -1
- package/plugins/lisa-cursor/rules/dependency-trust-classes-reference.mdc +1 -1
- package/plugins/lisa-cursor/rules/deployed-state-readback-reference.mdc +1 -1
- package/plugins/lisa-cursor/rules/derived-branch-plan-reference.mdc +1 -1
- package/plugins/lisa-cursor/rules/design-source-of-truth-reference.mdc +1 -1
- package/plugins/lisa-cursor/rules/design-value-binding-reference.mdc +1 -1
- package/plugins/lisa-cursor/rules/documentation-source-paths-reference.mdc +1 -1
- package/plugins/lisa-cursor/rules/leaf-only-lifecycle-reference.mdc +1 -1
- package/plugins/lisa-cursor/rules/observability-audit-reference.mdc +1 -1
- package/plugins/lisa-cursor/rules/prd-definition-of-ready-reference.mdc +1 -1
- package/plugins/lisa-cursor/rules/prd-lifecycle-rollup-reference.mdc +1 -1
- package/plugins/lisa-cursor/rules/pre-flight-autofill-reference.mdc +1 -1
- package/plugins/lisa-cursor/rules/promotion-contract-reference.mdc +1 -1
- package/plugins/lisa-cursor/rules/readiness-rubric-reference.mdc +1 -1
- package/plugins/lisa-cursor/rules/ready-role-filing-reference.mdc +37 -1
- package/plugins/lisa-cursor/rules/rejection-detection-reference.mdc +1 -1
- package/plugins/lisa-cursor/rules/repo-scope-split-reference.mdc +9 -10
- package/plugins/lisa-cursor/rules/reset-seed-coverage-reference.mdc +1 -1
- package/plugins/lisa-cursor/rules/usage-accounting-reference.mdc +1 -1
- package/plugins/lisa-cursor/rules/withdrawn-rulings.mdc +14 -3
- package/plugins/lisa-cursor/rules/work-item-definition-of-ready-reference.mdc +1 -1
- 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 +38 -15
- package/plugins/lisa-cursor/skills/lisa-github-write-issue/SKILL.md +15 -1
- package/plugins/lisa-cursor/skills/lisa-jira-build-intake/SKILL.md +37 -13
- package/plugins/lisa-cursor/skills/lisa-jira-write-ticket/SKILL.md +15 -1
- package/plugins/lisa-cursor/skills/lisa-linear-access/SKILL.md +56 -7
- package/plugins/lisa-cursor/skills/lisa-linear-build-intake/SKILL.md +36 -11
- package/plugins/lisa-cursor/skills/lisa-linear-prd-intake/SKILL.md +12 -2
- package/plugins/lisa-cursor/skills/lisa-linear-validate-issue/SKILL.md +1 -18
- package/plugins/lisa-cursor/skills/lisa-linear-verify/SKILL.md +0 -17
- package/plugins/lisa-cursor/skills/lisa-linear-write-issue/SKILL.md +18 -35
- package/plugins/lisa-cursor/skills/lisa-prd-ticket-coverage/SKILL.md +2 -2
- package/plugins/lisa-cursor/skills/lisa-repair-intake/SKILL.md +66 -12
- package/plugins/lisa-cursor/skills/lisa-rework-triage/SKILL.md +2 -1
- package/plugins/lisa-cursor/skills/lisa-secrets-access/scripts/providers.mjs +2 -1
- package/plugins/lisa-cursor/skills/lisa-setup-linear/SKILL.md +1 -1
- package/plugins/lisa-cursor/skills/lisa-setup-remote-env/scripts/preflight-tools.mjs +7 -2
- package/plugins/lisa-cursor/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +11 -4
- package/plugins/lisa-cursor/skills/lisa-setup-remote-env/scripts/toolchain.mjs +17 -5
- package/plugins/lisa-cursor/skills/lisa-track/SKILL.md +32 -4
- 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/materialized-artifacts.json +11 -0
- package/plugins/src/base/hooks/block-blind-automerge.sh +10 -5
- package/plugins/src/base/hooks/block-direct-issue-create.sh +4 -0
- package/plugins/src/base/hooks/block-managed-file-edits.sh +73 -2
- package/plugins/src/base/hooks/guard-dedupe.bash +63 -29
- package/plugins/src/base/hooks/parity-safety-net.sh +2 -1
- package/plugins/src/base/hooks/worktree-binding-guard.sh +2 -1
- package/plugins/src/base/rules/eager/00-rule-index.md +1 -0
- package/plugins/src/base/rules/eager/base-rules.md +3 -1
- package/plugins/src/base/rules/eager/withdrawn-rulings.md +14 -3
- package/plugins/src/base/rules/reference/automation-runbook-contract.md +1 -1
- package/plugins/src/base/rules/reference/bdd-e2e-coverage.md +1 -1
- package/plugins/src/base/rules/reference/blocker-containment.md +3 -3
- package/plugins/src/base/rules/reference/claim-archaeology.md +1 -1
- package/plugins/src/base/rules/reference/claim-evidence-mapping.md +1 -1
- package/plugins/src/base/rules/reference/claim-time-guards.md +1 -1
- package/plugins/src/base/rules/reference/control-reachability.md +1 -1
- package/plugins/src/base/rules/reference/convergent-review.md +1 -1
- package/plugins/src/base/rules/reference/credential-substrate-precedence.md +1 -1
- package/plugins/src/base/rules/reference/dependency-decision-records.md +1 -1
- package/plugins/src/base/rules/reference/dependency-internalization-kit.md +1 -1
- package/plugins/src/base/rules/reference/dependency-trust-classes.md +1 -1
- package/plugins/src/base/rules/reference/deployed-state-readback.md +1 -1
- package/plugins/src/base/rules/reference/derived-branch-plan.md +1 -1
- package/plugins/src/base/rules/reference/design-source-of-truth.md +1 -1
- package/plugins/src/base/rules/reference/design-value-binding.md +1 -1
- package/plugins/src/base/rules/reference/documentation-source-paths.md +1 -1
- package/plugins/src/base/rules/reference/leaf-only-lifecycle.md +1 -1
- package/plugins/src/base/rules/reference/observability-audit.md +1 -1
- package/plugins/src/base/rules/reference/prd-definition-of-ready.md +1 -1
- package/plugins/src/base/rules/reference/prd-lifecycle-rollup.md +1 -1
- package/plugins/src/base/rules/reference/pre-flight-autofill.md +1 -1
- package/plugins/src/base/rules/reference/promotion-contract.md +1 -1
- package/plugins/src/base/rules/reference/readiness-rubric.md +1 -1
- package/plugins/src/base/rules/reference/ready-role-filing.md +37 -1
- package/plugins/src/base/rules/reference/rejection-detection.md +1 -1
- package/plugins/src/base/rules/reference/repo-scope-split.md +9 -10
- package/plugins/src/base/rules/reference/reset-seed-coverage.md +1 -1
- package/plugins/src/base/rules/reference/usage-accounting.md +1 -1
- package/plugins/src/base/rules/reference/work-item-definition-of-ready.md +1 -1
- 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 +38 -15
- package/plugins/src/base/skills/lisa-github-write-issue/SKILL.md +15 -1
- package/plugins/src/base/skills/lisa-jira-build-intake/SKILL.md +37 -13
- package/plugins/src/base/skills/lisa-jira-write-ticket/SKILL.md +15 -1
- package/plugins/src/base/skills/lisa-linear-access/SKILL.md +56 -7
- package/plugins/src/base/skills/lisa-linear-build-intake/SKILL.md +36 -11
- package/plugins/src/base/skills/lisa-linear-prd-intake/SKILL.md +12 -2
- package/plugins/src/base/skills/lisa-linear-validate-issue/SKILL.md +1 -18
- package/plugins/src/base/skills/lisa-linear-verify/SKILL.md +0 -17
- package/plugins/src/base/skills/lisa-linear-write-issue/SKILL.md +18 -35
- package/plugins/src/base/skills/lisa-prd-ticket-coverage/SKILL.md +2 -2
- package/plugins/src/base/skills/lisa-repair-intake/SKILL.md +66 -12
- package/plugins/src/base/skills/lisa-rework-triage/SKILL.md +2 -1
- package/plugins/src/base/skills/lisa-secrets-access/scripts/providers.mjs +2 -1
- package/plugins/src/base/skills/lisa-setup-linear/SKILL.md +1 -1
- package/plugins/src/base/skills/lisa-setup-remote-env/scripts/preflight-tools.mjs +7 -2
- package/plugins/src/base/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +11 -4
- package/plugins/src/base/skills/lisa-setup-remote-env/scripts/toolchain.mjs +17 -5
- package/plugins/src/base/skills/lisa-track/SKILL.md +32 -4
- package/plugins/src/base/skills/lisa-tracker-build-intake/SKILL.md +15 -1
- package/scripts/build-plugins.sh +4 -0
- package/scripts/copy-opencode-plugin-templates.mjs +5 -1
- package/scripts/lisa-enforcement-fallback.sh +9 -1
- package/scripts/two-channel-couplings.json +5 -33
- package/typescript/copy-overwrite/scripts/check-skipped-required-checks.mjs +551 -13
- package/typescript/create-only/.github/required-checks.json +1 -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`).
|
|
@@ -215,14 +229,21 @@ nothing survives, exit on the denominator-stated summary from `summarizeDryLane`
|
|
|
215
229
|
A blocker is a **claim with a timestamp, not a fact** — it goes stale the moment its condition comes
|
|
216
230
|
true, and nothing re-read one before this phase. For each `$BLOCKED` candidate:
|
|
217
231
|
|
|
218
|
-
1. **
|
|
219
|
-
|
|
220
|
-
|
|
232
|
+
1. **Read release comments before applying the human gate.** Pass all item comments, labels,
|
|
233
|
+
body, `trustedHumanActorIds` and configured `humanNeededLabel` to `classifyReadyCandidate(...)`. For a discharged hold,
|
|
234
|
+
call `planHumanGateRelease({ labels, body, comments, trustedHumanActorIds, humanNeededLabel, readyLabel, lifecycleLabels, alreadyNotified })`
|
|
235
|
+
and retain its plan. Apply human-marker cleanup only as planned; defer any ready-role restoration
|
|
236
|
+
until steps 2–5 have cleared the remaining blockers (map the role to the vendor's state or label).
|
|
237
|
+
A still-active hold is never auto-selected, whatever any probe says. An absent or unreadable
|
|
238
|
+
comment history cannot discharge a hold. A release removes only the human hold: continue the
|
|
239
|
+
remaining blocker checks below before selecting the item.
|
|
240
|
+
|
|
221
241
|
2. **Extract the stated discharge condition**, then **probe it**. Machine-testable conditions — a
|
|
222
242
|
version on trunk, a published package, a CI run history, an advisory's patched status — rot
|
|
223
243
|
fastest and are cheapest to check. A human decision is not machine-testable; leave it.
|
|
224
|
-
3. **Classify with `classifyPreWorkCandidate(...)`** from `scripts/intake-blocker-reprobe.mjs`.
|
|
225
|
-
|
|
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
|
|
226
247
|
probed this cycle — the helper refuses both.
|
|
227
248
|
4. **Record the result on the issue either way** via `formatReprobeNote(...)` as a comment, so the
|
|
228
249
|
next cycle reads the answer rather than re-deriving it. Keep it idempotent.
|
|
@@ -317,7 +338,7 @@ other gate's verdict — however conclusive — may promote an item a person par
|
|
|
317
338
|
drift, and a drifted gate fails *silently*, by quietly ceasing to match. Do **not** re-implement
|
|
318
339
|
the test here, and do **not** key it on `reason=`: markers in the wild carry no `reason=` key at
|
|
319
340
|
all and sit anywhere in the body, so a structured parse would miss them while appearing to work
|
|
320
|
-
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
|
|
321
342
|
body.** A hold is ended by a release recorded in a comment, so a reader handed no comments cannot
|
|
322
343
|
see the discharge — it goes on holding an item whose question was answered weeks ago, which is
|
|
323
344
|
the defect this gate carried from the day it was written (CodySwannGT/lisa#3852). Omitting them
|
|
@@ -328,16 +349,17 @@ other gate's verdict — however conclusive — may promote an item a person par
|
|
|
328
349
|
and re-rejected every cycle forever and seen by nothing — `lisa-repair-intake` sweeps items that
|
|
329
350
|
are **not** in the ready role and excludes gated ones outright, so a ready-and-gated item falls
|
|
330
351
|
outside its filter twice over. Call
|
|
331
|
-
`planHumanGateReconciliation({ labels, body, humanNeededLabel, readyLabel, alreadyNotified })`
|
|
352
|
+
`planHumanGateReconciliation({ labels, body, comments, trustedHumanActorIds, humanNeededLabel, readyLabel, alreadyNotified })`
|
|
332
353
|
and apply exactly the actions it returns: remove `$READY`, add the configured human-needed
|
|
333
354
|
marker, and post `formatHumanGateNote()` once. The planner is idempotent by state, so an item
|
|
334
355
|
already out of the lane and already marked yields no second mutation and no second comment. This
|
|
335
356
|
is the same repair the leaf-only gate already performs for a ready item that must not be
|
|
336
357
|
dispatched.
|
|
337
358
|
4. **On `claimable: true` for an item that still carries a hold, RELEASE it — do not just proceed.**
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
`
|
|
359
|
+
This ready-lane candidate can retain a historical body marker and a human-needed label.
|
|
360
|
+
This step reconciles only candidates still in the ready lane; released holds outside it are
|
|
361
|
+
recovered by `lisa-repair-intake` step 2b (or Phase 2.5 when included in this cycle). Call
|
|
362
|
+
`planHumanGateRelease({ labels, body, comments, trustedHumanActorIds, humanNeededLabel, readyLabel, lifecycleLabels, alreadyNotified })`
|
|
341
363
|
and apply exactly the actions it returns: remove the configured human-needed marker, add the
|
|
342
364
|
configured ready role back, and post `formatHumanGateReleaseNote()` once. It is the exact inverse
|
|
343
365
|
of step 3's planner and it refuses in both directions — an item still held plans nothing, and an
|
|
@@ -369,11 +391,12 @@ GitHub Issues live in one repo by definition, so the scanned repo's issues are u
|
|
|
369
391
|
1. **Resolve the current repo** per `config-resolution` "Repo scoping" (`.repo` → `.github.repo` → `git remote get-url origin` basename). If unresolvable, stop and report.
|
|
370
392
|
2. **Cheap path first.** Prefer candidates already carrying the `repo:<current>` label. Keep the Phase 2 scan broad so unlabeled issues are still seen, determined, and stamped.
|
|
371
393
|
3. **Per candidate, apply the repo-scope decision (`repo-scope-split`):**
|
|
372
|
-
-
|
|
373
|
-
- **
|
|
374
|
-
- **
|
|
375
|
-
- **
|
|
376
|
-
- **Single-repo leaf for the current repo** → fall through to 3a
|
|
394
|
+
- **Count distinct repository markers first**: collect all `repo:<name>` labels and, on JIRA, recognized repository components; deduplicate by repository. A container may carry multiple `repo:<name>` labels. Do not split or claim it here; send it to the leaf-only gate.
|
|
395
|
+
- **Multi-repo leaf → split, never claim.** More than one repository takes the work-time split before any wrong-repository skip. Each sibling is **build-ready** (`build_ready: true`) and stamped with its own `repo:<name>`; the current repo's sibling becomes a normal candidate.
|
|
396
|
+
- **Exactly one other repository** (`repo:<other>`) → **skip**, leaving the item ready for that repo's intake.
|
|
397
|
+
- **No repository marker** → determine target repo(s) from the ticket and code, stamp `repo:<name>` through the vendor access layer, and re-apply from the count.
|
|
398
|
+
- **Single-repo leaf for the current repo** → fall through to 3a and 3b.
|
|
399
|
+
|
|
377
400
|
4. Continue until a claimable current-repo leaf is found (claim it; one per cycle) or the candidate set is exhausted — exit cleanly on the denominator-stated summary, naming the current repo alongside the swept lanes.
|
|
378
401
|
|
|
379
402
|
#### 3a. Leaf-only claim gate (repair containers)
|
|
@@ -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:
|
|
@@ -189,14 +203,21 @@ swept (see `automation-runbook-contract`).
|
|
|
189
203
|
A blocker is a **claim with a timestamp, not a fact** — it goes stale the moment its condition comes
|
|
190
204
|
true, and nothing re-read one before this phase. For each pre-work candidate outside `$READY`:
|
|
191
205
|
|
|
192
|
-
1. **
|
|
193
|
-
|
|
194
|
-
|
|
206
|
+
1. **Read release comments before applying the human gate.** Pass all item comments, labels,
|
|
207
|
+
body, `trustedHumanActorIds` and configured `humanNeededLabel` to `classifyReadyCandidate(...)`. For a discharged hold,
|
|
208
|
+
call `planHumanGateRelease({ labels, body, comments, trustedHumanActorIds, humanNeededLabel, readyLabel, lifecycleLabels, alreadyNotified })`
|
|
209
|
+
and retain its plan. Apply human-marker cleanup only as planned; defer any ready-role restoration
|
|
210
|
+
until steps 2–5 have cleared the remaining blockers (map the role to the vendor's state or label).
|
|
211
|
+
A still-active hold is never auto-selected, whatever any probe says. An absent or unreadable
|
|
212
|
+
comment history cannot discharge a hold. A release removes only the human hold: continue the
|
|
213
|
+
remaining blocker checks below before selecting the item.
|
|
214
|
+
|
|
195
215
|
2. **Extract the stated discharge condition**, then **probe it**. Machine-testable conditions — a
|
|
196
216
|
version on trunk, a published package, a CI run history, an advisory's patched status — rot
|
|
197
217
|
fastest and are cheapest to check. A human decision is not machine-testable; leave it.
|
|
198
218
|
3. **Classify with `classifyPreWorkCandidate(...)`** from
|
|
199
|
-
`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,
|
|
200
221
|
and neither is a candidate nothing probed this cycle — the helper refuses both.
|
|
201
222
|
4. **Record the result on the ticket either way** via `formatReprobeNote(...)` as a comment, so the
|
|
202
223
|
next cycle reads the answer rather than re-deriving it. Keep it idempotent.
|
|
@@ -222,7 +243,7 @@ other gate's verdict — however conclusive — may promote an item a person par
|
|
|
222
243
|
drift, and a drifted gate fails *silently*, by quietly ceasing to match. Do **not** re-implement
|
|
223
244
|
the test here, and do **not** key it on `reason=`: markers in the wild carry no `reason=` key at
|
|
224
245
|
all and sit anywhere in the body, so a structured parse would miss them while appearing to work
|
|
225
|
-
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
|
|
226
247
|
body.** A hold is ended by a release recorded in a comment, so a reader handed no comments cannot
|
|
227
248
|
see the discharge — it goes on holding an item whose question was answered weeks ago, which is
|
|
228
249
|
the defect this gate carried from the day it was written (CodySwannGT/lisa#3852). Omitting them
|
|
@@ -233,16 +254,17 @@ other gate's verdict — however conclusive — may promote an item a person par
|
|
|
233
254
|
and re-rejected every cycle forever and seen by nothing — `lisa-repair-intake` sweeps items that
|
|
234
255
|
are **not** in the ready role and excludes gated ones outright, so a ready-and-gated item falls
|
|
235
256
|
outside its filter twice over. Call
|
|
236
|
-
`planHumanGateReconciliation({ labels, body, humanNeededLabel, readyLabel, alreadyNotified })`
|
|
257
|
+
`planHumanGateReconciliation({ labels, body, comments, trustedHumanActorIds, humanNeededLabel, readyLabel, alreadyNotified })`
|
|
237
258
|
and apply exactly the actions it returns: remove `$READY`, add the configured human-needed
|
|
238
259
|
marker, and post `formatHumanGateNote()` once. The planner is idempotent by state, so an item
|
|
239
260
|
already out of the lane and already marked yields no second mutation and no second comment. This
|
|
240
261
|
is the same repair the leaf-only gate already performs for a ready item that must not be
|
|
241
262
|
dispatched.
|
|
242
263
|
4. **On `claimable: true` for an item that still carries a hold, RELEASE it — do not just proceed.**
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
`
|
|
264
|
+
This ready-lane candidate can retain a historical body marker and a human-needed label.
|
|
265
|
+
This step reconciles only candidates still in the ready lane; released holds outside it are
|
|
266
|
+
recovered by `lisa-repair-intake` step 2b (or Phase 2.5 when included in this cycle). Call
|
|
267
|
+
`planHumanGateRelease({ labels, body, comments, trustedHumanActorIds, humanNeededLabel, readyLabel, lifecycleLabels, alreadyNotified })`
|
|
246
268
|
and apply exactly the actions it returns: remove the configured human-needed marker, add the
|
|
247
269
|
configured ready role back, and post `formatHumanGateReleaseNote()` once. It is the exact inverse
|
|
248
270
|
of step 3's planner and it refuses in both directions — an item still held plans nothing, and an
|
|
@@ -274,10 +296,12 @@ A JIRA project can oversee multiple repos (`frontend` / `backend` / `infrastruct
|
|
|
274
296
|
1. **Resolve the current repo** per `config-resolution` "Repo scoping" (`.repo` → `.github.repo` → `git remote get-url origin` basename). If unresolvable, stop and report — do not claim tickets you cannot scope.
|
|
275
297
|
2. **Cheap path first.** Phase 1's query-time pre-filter has already dropped tickets explicitly stamped for a sibling repo, so the Phase 2 result set is current-repo-labeled + unlabeled tickets. Prefer candidates already carrying `repo:<current>` — a JIRA **label**, or a **component** equal to the repo name (accepted as an alias); the pre-filter is label-only, so a ticket scoped solely by a sibling-repo **component** can still appear and is skipped here. The result set still includes unlabeled tickets so they can be determined and stamped; this gate orders/filters what remains.
|
|
276
298
|
3. **Per candidate, apply the repo-scope decision (`repo-scope-split`):**
|
|
277
|
-
-
|
|
278
|
-
- **
|
|
279
|
-
- **
|
|
280
|
-
- **
|
|
299
|
+
- **Count distinct repository markers first**: collect all `repo:<name>` labels and, on JIRA, recognized repository components; deduplicate by repository. A container may carry multiple `repo:<name>` labels. Do not split or claim it here; send it to the leaf-only gate.
|
|
300
|
+
- **Multi-repo leaf → split, never claim.** More than one repository takes the work-time split before any wrong-repository skip. Each sibling is **build-ready** (`build_ready: true`) and stamped with its own `repo:<name>`; the current repo's sibling becomes a normal candidate.
|
|
301
|
+
- **Exactly one other repository** (`repo:<other>`) → **skip**, leaving the item ready for that repo's intake.
|
|
302
|
+
- **No repository marker** → determine target repo(s) from the ticket and code, stamp `repo:<name>` through the vendor access layer, and re-apply from the count.
|
|
303
|
+
- **Single-repo leaf for the current repo** → fall through to 3a and 3b.
|
|
304
|
+
|
|
281
305
|
4. Continue until a claimable current-repo leaf is found (claim it; one per cycle) or the candidate set is exhausted — exit cleanly on the denominator-stated summary, naming the current repo alongside the swept lanes.
|
|
282
306
|
|
|
283
307
|
#### 3a. Leaf-only claim gate (skip / safe-block containers)
|
|
@@ -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
|
|
@@ -188,7 +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
|
|
191
|
+
role it is applying (for example, `ready`, `claimed`, `blocked`, `review`, `done`; the configured role contract is authoritative) — plus `env:<KEY>` when the role is the env-indexed
|
|
192
192
|
`done`. This layer then resolves that role against config and the team's own
|
|
193
193
|
catalog, and sends the ID **it** resolved.
|
|
194
194
|
|
|
@@ -319,18 +319,67 @@ same mutation, same result shape, same error handling.
|
|
|
319
319
|
```graphql
|
|
320
320
|
# list-comments project_id:<ID> — page via pageInfo so a long-lived PRD's
|
|
321
321
|
# feedback history never silently truncates.
|
|
322
|
-
query($id:String
|
|
322
|
+
query($id:String!,$after:String){
|
|
323
323
|
project(id:$id){
|
|
324
|
-
comments(first:100){
|
|
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
|
}
|
|
330
330
|
```
|
|
331
331
|
|
|
332
|
-
The Issue form
|
|
333
|
-
node shape
|
|
332
|
+
The Issue form uses `issue(id:$id)` with the same `first:100,after:$after`
|
|
333
|
+
arguments and node shape. For **both** anchors, use this access-layer adapter with
|
|
334
|
+
`linear_graphql` above; it accumulates every page and prints no partial history.
|
|
335
|
+
A read succeeds only after `hasNextPage` is false. Errors, malformed pages, and
|
|
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.
|
|
340
|
+
|
|
341
|
+
```bash
|
|
342
|
+
linear_list_comment_pages() { # issue|project id -> complete JSON node array
|
|
343
|
+
local anchor="$1" id="$2" after=null nodes='[]' seen='[]'
|
|
344
|
+
local query variables response connection cursor
|
|
345
|
+
case "$anchor" in issue|project) ;; *) echo "Error: invalid comment anchor" >&2; return 1 ;; esac
|
|
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}}}}}'
|
|
347
|
+
while :; do
|
|
348
|
+
variables=$(jq -cn --arg id "$id" --argjson after "$after" '{id:$id,after:$after}') || return 1
|
|
349
|
+
response=$(linear_graphql "$query" "$variables") || return 1
|
|
350
|
+
connection=$(printf '%s' "$response" | jq -ce --arg anchor "$anchor" '
|
|
351
|
+
if (.errors != null and .errors != []) then error("GraphQL comments read failed")
|
|
352
|
+
else .data[$anchor].comments end |
|
|
353
|
+
if (.nodes | type) != "array" or (.pageInfo.hasNextPage | type) != "boolean"
|
|
354
|
+
then error("Incomplete comments page") else . end') || return 1
|
|
355
|
+
nodes=$(jq -cn --argjson prior "$nodes" --argjson page "$connection" '$prior + $page.nodes') || return 1
|
|
356
|
+
if [ "$(printf '%s' "$connection" | jq -r '.pageInfo.hasNextPage')" = false ]; then
|
|
357
|
+
printf '%s\n' "$nodes"
|
|
358
|
+
return 0
|
|
359
|
+
fi
|
|
360
|
+
cursor=$(printf '%s' "$connection" | jq -ce '.pageInfo.endCursor | select(type == "string" and length > 0)') || {
|
|
361
|
+
echo "Error: incomplete comments history; missing cursor" >&2; return 1;
|
|
362
|
+
}
|
|
363
|
+
if jq -en --argjson seen "$seen" --argjson cursor "$cursor" '$seen | index($cursor) != null' >/dev/null; then
|
|
364
|
+
echo "Error: incomplete comments history; repeated cursor" >&2
|
|
365
|
+
return 1
|
|
366
|
+
fi
|
|
367
|
+
seen=$(jq -cn --argjson seen "$seen" --argjson cursor "$cursor" '$seen + [$cursor]') || return 1
|
|
368
|
+
after="$cursor"
|
|
369
|
+
done
|
|
370
|
+
}
|
|
371
|
+
```
|
|
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
|
+
|
|
380
|
+
Call `linear_list_comment_pages project "$PROJECT_ID"` for `project_id`, or
|
|
381
|
+
`linear_list_comment_pages issue "$ISSUE_ID"` for `issue_id`. The caller receives
|
|
382
|
+
one complete node array; it must not interpret a failed command as zero comments.
|
|
334
383
|
|
|
335
384
|
**Substrate.** The Linear MCP exposes comments on Issues only, so the
|
|
336
385
|
`project_id` form resolves solely through the tier-1 `LINEAR_API_KEY` + GraphQL
|
|
@@ -339,7 +388,7 @@ That is not a gap in Linear: the precedence contract already puts GraphQL ahead
|
|
|
339
388
|
of the MCP, so the preferred substrate has always been able to do this. Only
|
|
340
389
|
this wrapper could not, which is what made callers fabricate an Issue to hold a
|
|
341
390
|
Project's comments. If tier 1 is unavailable, fail with the layer's standard
|
|
342
|
-
`Error:` result naming `save-comment project_id` — do **not** silently degrade
|
|
391
|
+
`Error:` result naming the requested `save-comment project_id` or `list-comments project_id` operation — do **not** silently degrade
|
|
343
392
|
into creating an Issue to comment on.
|
|
344
393
|
|
|
345
394
|
## `history` — transition history (read-only)
|
|
@@ -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.
|
|
@@ -182,13 +196,21 @@ A blocker is a **claim with a timestamp, not a fact**. It is written once and go
|
|
|
182
196
|
|
|
183
197
|
For each pre-work candidate that is **not** in `$READY`:
|
|
184
198
|
|
|
185
|
-
1. **
|
|
199
|
+
1. **Read release comments before applying the human gate.** Pass all item comments, labels,
|
|
200
|
+
body, `trustedHumanActorIds` and configured `humanNeededLabel` to `classifyReadyCandidate(...)`. For a discharged hold,
|
|
201
|
+
call `planHumanGateRelease({ labels, body, comments, trustedHumanActorIds, humanNeededLabel, readyLabel, lifecycleLabels, alreadyNotified })`
|
|
202
|
+
and retain its plan. Apply human-marker cleanup only as planned; defer any ready-role restoration
|
|
203
|
+
until steps 2–5 have cleared the remaining blockers (map the role to the vendor's state or label).
|
|
204
|
+
A still-active hold is never auto-selected, whatever any probe says. An absent or unreadable
|
|
205
|
+
comment history cannot discharge a hold. A release removes only the human hold: continue the
|
|
206
|
+
remaining blocker checks below before selecting the item.
|
|
207
|
+
|
|
186
208
|
2. **Extract the stated discharge condition** from the description or the most recent blocking comment — the sentence naming what has to become true.
|
|
187
209
|
3. **Probe it.** Machine-testable conditions are the ones that rot fastest and are cheapest to check: a version on trunk (`git show origin/<trunk>:<manifest>`), a published package, a run history (`gh run list`), an advisory's patched status. A condition that is a human decision is not machine-testable — leave it and move on.
|
|
188
210
|
4. **Classify with the shared helper** so the ordering and the evidence requirement cannot drift per vendor:
|
|
189
211
|
|
|
190
212
|
```text
|
|
191
|
-
classifyPreWorkCandidate({ laneType, labels, body, humanNeededLabel, statedBlocker, probe })
|
|
213
|
+
classifyPreWorkCandidate({ laneType, labels, body, comments, trustedHumanActorIds, humanNeededLabel, statedBlocker, probe })
|
|
192
214
|
→ { selectable, reason, humanGated, evidence }
|
|
193
215
|
```
|
|
194
216
|
|
|
@@ -216,7 +238,7 @@ other gate's verdict — however conclusive — may promote an item a person par
|
|
|
216
238
|
drift, and a drifted gate fails *silently*, by quietly ceasing to match. Do **not** re-implement
|
|
217
239
|
the test here, and do **not** key it on `reason=`: markers in the wild carry no `reason=` key at
|
|
218
240
|
all and sit anywhere in the body, so a structured parse would miss them while appearing to work
|
|
219
|
-
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
|
|
220
242
|
body.** A hold is ended by a release recorded in a comment, so a reader handed no comments cannot
|
|
221
243
|
see the discharge — it goes on holding an item whose question was answered weeks ago, which is
|
|
222
244
|
the defect this gate carried from the day it was written (CodySwannGT/lisa#3852). Omitting them
|
|
@@ -227,16 +249,17 @@ other gate's verdict — however conclusive — may promote an item a person par
|
|
|
227
249
|
and re-rejected every cycle forever and seen by nothing — `lisa-repair-intake` sweeps items that
|
|
228
250
|
are **not** in the ready role and excludes gated ones outright, so a ready-and-gated item falls
|
|
229
251
|
outside its filter twice over. Call
|
|
230
|
-
`planHumanGateReconciliation({ labels, body, humanNeededLabel, readyLabel, alreadyNotified })`
|
|
252
|
+
`planHumanGateReconciliation({ labels, body, comments, trustedHumanActorIds, humanNeededLabel, readyLabel, alreadyNotified })`
|
|
231
253
|
and apply exactly the actions it returns: remove `$READY`, add the configured human-needed
|
|
232
254
|
marker, and post `formatHumanGateNote()` once. The planner is idempotent by state, so an item
|
|
233
255
|
already out of the lane and already marked yields no second mutation and no second comment. This
|
|
234
256
|
is the same repair the leaf-only gate already performs for a ready item that must not be
|
|
235
257
|
dispatched.
|
|
236
258
|
4. **On `claimable: true` for an item that still carries a hold, RELEASE it — do not just proceed.**
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
`
|
|
259
|
+
This ready-lane candidate can retain a historical body marker and a human-needed label.
|
|
260
|
+
This step reconciles only candidates still in the ready lane; released holds outside it are
|
|
261
|
+
recovered by `lisa-repair-intake` step 2b (or Phase 2.5 when included in this cycle). Call
|
|
262
|
+
`planHumanGateRelease({ labels, body, comments, trustedHumanActorIds, humanNeededLabel, readyLabel, lifecycleLabels, alreadyNotified })`
|
|
240
263
|
and apply exactly the actions it returns: remove the configured human-needed marker, add the
|
|
241
264
|
configured ready role back, and post `formatHumanGateReleaseNote()` once. It is the exact inverse
|
|
242
265
|
of step 3's planner and it refuses in both directions — an item still held plans nothing, and an
|
|
@@ -268,10 +291,12 @@ A Linear team can oversee multiple repos (`frontend` / `backend` / `infrastructu
|
|
|
268
291
|
1. **Resolve the current repo** per `config-resolution` "Repo scoping" (`.repo` → `.github.repo` → `git remote get-url origin` basename). If unresolvable, stop and report.
|
|
269
292
|
2. **Cheap path first.** Prefer candidates already carrying the `repo:<current>` label. Keep the Phase 2 scan broad so unlabeled Issues are still seen, determined, and stamped.
|
|
270
293
|
3. **Per candidate, apply the repo-scope decision (`repo-scope-split`):**
|
|
271
|
-
-
|
|
272
|
-
- **
|
|
273
|
-
- **
|
|
274
|
-
- **
|
|
294
|
+
- **Count distinct repository markers first**: collect all `repo:<name>` labels and, on JIRA, recognized repository components; deduplicate by repository. A container may carry multiple `repo:<name>` labels. Do not split or claim it here; send it to the leaf-only gate.
|
|
295
|
+
- **Multi-repo leaf → split, never claim.** More than one repository takes the work-time split before any wrong-repository skip. Each sibling is **build-ready** (`build_ready: true`) and stamped with its own `repo:<name>`; the current repo's sibling becomes a normal candidate.
|
|
296
|
+
- **Exactly one other repository** (`repo:<other>`) → **skip**, leaving the item ready for that repo's intake.
|
|
297
|
+
- **No repository marker** → determine target repo(s) from the ticket and code, stamp `repo:<name>` through the vendor access layer, and re-apply from the count.
|
|
298
|
+
- **Single-repo leaf for the current repo** → fall through to 3a and 3b.
|
|
299
|
+
|
|
275
300
|
4. Continue until a claimable current-repo leaf is found (claim it; one per cycle) or the candidate set is exhausted — exit cleanly on the denominator-stated summary, naming the current repo alongside the swept lanes.
|
|
276
301
|
|
|
277
302
|
#### 3a. Leaf-only claim gate (skip / safe-block containers)
|
|
@@ -130,6 +130,16 @@ Select the first ready project returned by Phase 2 and process only that project
|
|
|
130
130
|
|
|
131
131
|
#### 3a. Claim
|
|
132
132
|
|
|
133
|
+
**Preflight project comments before any claim or destination-ticket creation.** Through
|
|
134
|
+
`lisa-linear-access`, resolve an identity-matched tier-1 GraphQL credential and the
|
|
135
|
+
`save-comment project_id` adapter, then read the candidate's complete project comment
|
|
136
|
+
history with `list-comments project_id:<id>`. The issue-only MCP is insufficient for
|
|
137
|
+
this flow. If the required credential, adapter or read is unavailable, return the
|
|
138
|
+
layer's `Error:` naming the project-comment operation and leave the project ready;
|
|
139
|
+
create no tickets and no substitute comment-holder Issue. This is a read-only
|
|
140
|
+
capability preflight, not a test comment. It establishes the available transport;
|
|
141
|
+
later permission changes or write failures still follow the normal error handler.
|
|
142
|
+
|
|
133
143
|
Transition labels via `lisa-linear-access operation: save-project({id, labels})`: pass the full new label set with `$READY` removed and `$IN_REVIEW` added. This is the idempotency lock — a re-entrant cycle running concurrently won't see this project because its query filters on `label: "$READY"`.
|
|
134
144
|
|
|
135
145
|
If the update fails (permission error, race condition), log it and skip this project. Do not proceed to validation on a project you didn't successfully claim.
|
|
@@ -152,7 +162,7 @@ This call also indirectly invokes `lisa-tracker-source-artifacts` (artifact extr
|
|
|
152
162
|
|
|
153
163
|
1. Re-invoke `lisa-linear-to-tracker` with `dry_run: false` to actually write the tickets. This re-runs Phases 1-5 and runs the preservation gate (Phase 5.5).
|
|
154
164
|
2. Capture the created ticket keys from the skill's output.
|
|
155
|
-
3. Post a comment on the project via `lisa-linear-access operation: save-comment project_id:<id>` listing the created tickets (epic, stories, sub-tasks) with
|
|
165
|
+
3. Post a comment on the project via `lisa-linear-access operation: save-comment project_id:<id>` listing the created tickets (epic, stories, sub-tasks) with the URLs returned by the configured destination tracker. Lead with: `"Ticketed by Claude. Created N tickets — see below. Add the $SHIPPED label to the Linear project after the work is delivered."`
|
|
156
166
|
4. Transition labels: remove `$IN_REVIEW`, add `$TICKETED` via `save_project`.
|
|
157
167
|
5. **Run Phase 3e (coverage audit)** before considering this PRD done.
|
|
158
168
|
|
|
@@ -396,6 +406,6 @@ Before this skill can run against a Linear workspace or team, the team must adop
|
|
|
396
406
|
1. Apply the `ready` label (default: `prd-ready`) to projects that are ready for ticketing (replaces the Notion `Status = Ready` flip and the Confluence `prd-ready` page label).
|
|
397
407
|
2. Reserve `in_review`, `blocked`, `ticketed` (defaults: `prd-in-review`, `prd-blocked`, `prd-ticketed`) for this skill — humans should not set them manually except to recover from an error.
|
|
398
408
|
3. (Optional but recommended) Add the `draft` and `shipped` labels (defaults: `prd-draft`, `prd-shipped`) for in-progress PRDs and delivered work respectively, so the full lifecycle is visible at a glance.
|
|
399
|
-
4. The labels must exist as **project labels** in Linear (`
|
|
409
|
+
4. The labels must exist as **project labels** in Linear (`list-project-labels` should return them). Issue-level labels with the same names won't work; Linear keeps the two label kinds separate.
|
|
400
410
|
|
|
401
411
|
If the workspace hasn't adopted these labels, the first run exits with a label-convention error (not the idle empty-set message) — this distinguishes a setup issue from a genuinely empty queue so operators know to apply the convention rather than assuming there is no work. See Phase 2 for how the skill detects this case.
|
|
@@ -91,24 +91,7 @@ prd_source: "https://notion.so/..." # set when the Issue was generated from a
|
|
|
91
91
|
|
|
92
92
|
If the caller passes only an identifier, fetch the item via `lisa-linear-access operation: get-issue` (Issue) or `lisa-linear-access operation: get-project` (Project), derive the same fields from the fetched data — including `runtime_behavior_change` (derived from the `## Target Backend Environment` declaration per `derived-branch-plan`, and authoritative over any caller assertion), `build_ready` (the Issue's state is the configured `ready` state) and `child_refs` (sub-issues, project-member issues, plus `blocked_by` parentage, resolved as in `lisa-linear-read-issue`) so S15 can classify the item — then run gates.
|
|
93
93
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
This is a supported entry point, not only an internal step of a caller flow.
|
|
97
|
-
Point it at a live issue and it fetches and validates the stored state:
|
|
98
|
-
|
|
99
|
-
```text
|
|
100
|
-
Skill(lisa-linear-validate-issue) with ENG-1234
|
|
101
|
-
```
|
|
102
|
-
|
|
103
|
-
Use it whenever the issue reached the tracker by some path other than
|
|
104
|
-
`lisa-linear-write-issue` — a team's own script, a workflow step, a cron, anything holding the
|
|
105
|
-
credentials but no skill runtime. Those paths get neither the pre-write nor the
|
|
106
|
-
post-write gate, and their own read-back substitutes for neither: a read-back
|
|
107
|
-
proves the tracker stored what was sent, never that what was sent was any good.
|
|
108
|
-
|
|
109
|
-
The gate definitions live here on purpose, so every caller picks up a change
|
|
110
|
-
automatically. Running this skill by hand is the same gate the write path runs,
|
|
111
|
-
not an approximation of it.
|
|
94
|
+
For existing items written through another path, use the [standalone entry point](#standalone-entry-point--validating-an-item-written-by-another-path). A transport read-back does not prove the stored specification passes the gates.
|
|
112
95
|
|
|
113
96
|
## Gates
|
|
114
97
|
|
|
@@ -63,20 +63,3 @@ normalize-then-compare. Byte-exact comparison of such text is forbidden.
|
|
|
63
63
|
- Never write to Linear. Read-only.
|
|
64
64
|
- Never short-circuit the validator. Always run the full gate set.
|
|
65
65
|
- If `get_issue` / `get_project` returns an access error, surface it and exit — don't pretend the item is fine.
|
|
66
|
-
|
|
67
|
-
## Comparison is semantic, never byte-exact
|
|
68
|
-
|
|
69
|
-
Re-run the validator against the live issue. Do NOT compare the stored body
|
|
70
|
-
against what was sent byte for byte.
|
|
71
|
-
|
|
72
|
-
The reason is measured rather than theoretical. Trackers normalize markdown on
|
|
73
|
-
write: `-` bullets become `*`, a bare URL is wrapped as `[url](<url>)`, bold
|
|
74
|
-
emphasis is re-segmented around inline code spans. All lossless, all
|
|
75
|
-
rendering-identical, and all of it makes a byte comparator report failure on a
|
|
76
|
-
write that was completely fine. A comparator that cannot tell vendor
|
|
77
|
-
normalization from corruption fails on healthy writes and trains its reader to
|
|
78
|
-
ignore it, which costs more than the check was ever worth.
|
|
79
|
-
|
|
80
|
-
Compare meaning: run `lisa-linear-validate-issue` against the stored item and let the gates
|
|
81
|
-
decide. Where a single field must be compared directly, normalize both sides
|
|
82
|
-
first.
|