@codyswann/lisa 4.55.1 → 4.55.3
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 +89 -139
- 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 +18 -10
- package/plugins/lisa/.codex-plugin/skills/lisa-jira-build-intake/SKILL.md +18 -9
- package/plugins/lisa/.codex-plugin/skills/lisa-linear-access/SKILL.md +45 -7
- package/plugins/lisa/.codex-plugin/skills/lisa-linear-build-intake/SKILL.md +18 -7
- 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 +3 -34
- 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 +46 -6
- 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 +18 -4
- 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 +1 -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/linear-state-write-target.mjs +2 -2
- package/plugins/lisa/scripts/qa-signal-lifecycle.mjs +24 -11
- package/plugins/lisa/scripts/resolve-lifecycle-role.mjs +2 -7
- package/plugins/lisa/skills/lisa-github-build-intake/SKILL.md +18 -10
- package/plugins/lisa/skills/lisa-jira-build-intake/SKILL.md +18 -9
- package/plugins/lisa/skills/lisa-linear-access/SKILL.md +45 -7
- package/plugins/lisa/skills/lisa-linear-build-intake/SKILL.md +18 -7
- 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 +3 -34
- package/plugins/lisa/skills/lisa-prd-ticket-coverage/SKILL.md +2 -2
- package/plugins/lisa/skills/lisa-repair-intake/SKILL.md +46 -6
- 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 +18 -4
- 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/linear-state-write-target.mjs +2 -2
- package/plugins/lisa-agy/scripts/qa-signal-lifecycle.mjs +24 -11
- package/plugins/lisa-agy/scripts/resolve-lifecycle-role.mjs +2 -7
- package/plugins/lisa-agy/skills/lisa-github-build-intake/SKILL.md +18 -10
- package/plugins/lisa-agy/skills/lisa-jira-build-intake/SKILL.md +18 -9
- package/plugins/lisa-agy/skills/lisa-linear-access/SKILL.md +45 -7
- package/plugins/lisa-agy/skills/lisa-linear-build-intake/SKILL.md +18 -7
- 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 +3 -34
- package/plugins/lisa-agy/skills/lisa-prd-ticket-coverage/SKILL.md +2 -2
- package/plugins/lisa-agy/skills/lisa-repair-intake/SKILL.md +46 -6
- 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 +18 -4
- 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 +1 -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/linear-state-write-target.mjs +2 -2
- package/plugins/lisa-copilot/scripts/qa-signal-lifecycle.mjs +24 -11
- package/plugins/lisa-copilot/scripts/resolve-lifecycle-role.mjs +2 -7
- package/plugins/lisa-copilot/skills/lisa-github-build-intake/SKILL.md +18 -10
- package/plugins/lisa-copilot/skills/lisa-jira-build-intake/SKILL.md +18 -9
- package/plugins/lisa-copilot/skills/lisa-linear-access/SKILL.md +45 -7
- package/plugins/lisa-copilot/skills/lisa-linear-build-intake/SKILL.md +18 -7
- 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 +3 -34
- package/plugins/lisa-copilot/skills/lisa-prd-ticket-coverage/SKILL.md +2 -2
- package/plugins/lisa-copilot/skills/lisa-repair-intake/SKILL.md +46 -6
- 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 +18 -4
- 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 +1 -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/linear-state-write-target.mjs +2 -2
- package/plugins/lisa-cursor/scripts/qa-signal-lifecycle.mjs +24 -11
- package/plugins/lisa-cursor/scripts/resolve-lifecycle-role.mjs +2 -7
- package/plugins/lisa-cursor/skills/lisa-github-build-intake/SKILL.md +18 -10
- package/plugins/lisa-cursor/skills/lisa-jira-build-intake/SKILL.md +18 -9
- package/plugins/lisa-cursor/skills/lisa-linear-access/SKILL.md +45 -7
- package/plugins/lisa-cursor/skills/lisa-linear-build-intake/SKILL.md +18 -7
- 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 +3 -34
- package/plugins/lisa-cursor/skills/lisa-prd-ticket-coverage/SKILL.md +2 -2
- package/plugins/lisa-cursor/skills/lisa-repair-intake/SKILL.md +46 -6
- 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 +18 -4
- 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 +1 -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/linear-state-write-target.mjs +2 -2
- package/plugins/src/base/scripts/qa-signal-lifecycle.mjs +24 -11
- package/plugins/src/base/scripts/resolve-lifecycle-role.mjs +2 -7
- package/plugins/src/base/skills/lisa-github-build-intake/SKILL.md +18 -10
- package/plugins/src/base/skills/lisa-jira-build-intake/SKILL.md +18 -9
- package/plugins/src/base/skills/lisa-linear-access/SKILL.md +45 -7
- package/plugins/src/base/skills/lisa-linear-build-intake/SKILL.md +18 -7
- 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 +3 -34
- package/plugins/src/base/skills/lisa-prd-ticket-coverage/SKILL.md +2 -2
- package/plugins/src/base/skills/lisa-repair-intake/SKILL.md +46 -6
- 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 +18 -4
- 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
- package/plugins/lisa/.codex-plugin/skills/lisa-qa-checklist/SKILL.md +0 -70
- package/plugins/lisa/.codex-plugin/skills/lisa-qa-checklist/agents/openai.yaml +0 -4
- package/plugins/lisa/.codex-plugin/skills/lisa-qa-clear/SKILL.md +0 -86
- package/plugins/lisa/.codex-plugin/skills/lisa-qa-clear/agents/openai.yaml +0 -4
- package/plugins/lisa/.codex-plugin/skills/lisa-qa-fail/SKILL.md +0 -119
- package/plugins/lisa/.codex-plugin/skills/lisa-qa-fail/agents/openai.yaml +0 -4
- package/plugins/lisa/.codex-plugin/skills/lisa-qa-queue/SKILL.md +0 -94
- package/plugins/lisa/.codex-plugin/skills/lisa-qa-queue/agents/openai.yaml +0 -4
- package/plugins/lisa/commands/qa-checklist.md +0 -6
- package/plugins/lisa/commands/qa-clear.md +0 -6
- package/plugins/lisa/commands/qa-fail.md +0 -6
- package/plugins/lisa/commands/qa-queue.md +0 -6
- package/plugins/lisa/skills/lisa-qa-checklist/SKILL.md +0 -70
- package/plugins/lisa/skills/lisa-qa-checklist/agents/openai.yaml +0 -4
- package/plugins/lisa/skills/lisa-qa-clear/SKILL.md +0 -86
- package/plugins/lisa/skills/lisa-qa-clear/agents/openai.yaml +0 -4
- package/plugins/lisa/skills/lisa-qa-fail/SKILL.md +0 -119
- package/plugins/lisa/skills/lisa-qa-fail/agents/openai.yaml +0 -4
- package/plugins/lisa/skills/lisa-qa-queue/SKILL.md +0 -94
- package/plugins/lisa/skills/lisa-qa-queue/agents/openai.yaml +0 -4
- package/plugins/lisa-agy/commands/lisa/qa-checklist.md +0 -6
- package/plugins/lisa-agy/commands/lisa/qa-clear.md +0 -6
- package/plugins/lisa-agy/commands/lisa/qa-fail.md +0 -6
- package/plugins/lisa-agy/commands/lisa/qa-queue.md +0 -6
- package/plugins/lisa-agy/skills/lisa-qa-checklist/SKILL.md +0 -70
- package/plugins/lisa-agy/skills/lisa-qa-clear/SKILL.md +0 -86
- package/plugins/lisa-agy/skills/lisa-qa-fail/SKILL.md +0 -119
- package/plugins/lisa-agy/skills/lisa-qa-queue/SKILL.md +0 -94
- package/plugins/lisa-copilot/commands/lisa/qa-checklist.md +0 -6
- package/plugins/lisa-copilot/commands/lisa/qa-clear.md +0 -6
- package/plugins/lisa-copilot/commands/lisa/qa-fail.md +0 -6
- package/plugins/lisa-copilot/commands/lisa/qa-queue.md +0 -6
- package/plugins/lisa-copilot/skills/lisa-qa-checklist/SKILL.md +0 -70
- package/plugins/lisa-copilot/skills/lisa-qa-clear/SKILL.md +0 -86
- package/plugins/lisa-copilot/skills/lisa-qa-fail/SKILL.md +0 -119
- package/plugins/lisa-copilot/skills/lisa-qa-queue/SKILL.md +0 -94
- package/plugins/lisa-cursor/commands/lisa/qa-checklist.md +0 -6
- package/plugins/lisa-cursor/commands/lisa/qa-clear.md +0 -6
- package/plugins/lisa-cursor/commands/lisa/qa-fail.md +0 -6
- package/plugins/lisa-cursor/commands/lisa/qa-queue.md +0 -6
- package/plugins/lisa-cursor/skills/lisa-qa-checklist/SKILL.md +0 -70
- package/plugins/lisa-cursor/skills/lisa-qa-clear/SKILL.md +0 -86
- package/plugins/lisa-cursor/skills/lisa-qa-fail/SKILL.md +0 -119
- package/plugins/lisa-cursor/skills/lisa-qa-queue/SKILL.md +0 -94
- package/plugins/src/base/commands/qa-checklist.md +0 -6
- package/plugins/src/base/commands/qa-clear.md +0 -6
- package/plugins/src/base/commands/qa-fail.md +0 -6
- package/plugins/src/base/commands/qa-queue.md +0 -6
- package/plugins/src/base/skills/lisa-qa-checklist/SKILL.md +0 -70
- package/plugins/src/base/skills/lisa-qa-clear/SKILL.md +0 -86
- package/plugins/src/base/skills/lisa-qa-fail/SKILL.md +0 -119
- package/plugins/src/base/skills/lisa-qa-queue/SKILL.md +0 -94
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
|
+
# This file is managed by Lisa and IS replaced on each `lisa` run.
|
|
3
|
+
# Do not edit directly — durable changes belong upstream in Lisa.
|
|
4
|
+
|
|
2
5
|
# PreToolUse hook for Bash: blocks structural JSON parsing with text tools.
|
|
3
6
|
# Text tools (grep/sed/cut/awk) break on valid JSON — multiline values, escaped
|
|
4
7
|
# quotes, reordered keys, nested objects — producing silently wrong output
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
# This file is managed by Lisa and IS replaced on each `lisa` run.
|
|
2
|
+
# Do not edit directly — durable changes belong upstream in Lisa.
|
|
3
|
+
|
|
1
4
|
# shellcheck shell=bash
|
|
2
5
|
# Evaluate a dual-channel guard once per tool call, without de-registering it.
|
|
3
6
|
#
|
|
@@ -51,12 +54,9 @@
|
|
|
51
54
|
# refusal reaching the agent without the message that explains it. On a
|
|
52
55
|
# refusal every channel evaluates and speaks exactly as it does today.
|
|
53
56
|
#
|
|
54
|
-
#
|
|
55
|
-
#
|
|
56
|
-
#
|
|
57
|
-
# unless a second channel has actually been seen. The digest, and the one `stat`
|
|
58
|
-
# that feeds it the per-call discriminator, are reached only where a second
|
|
59
|
-
# channel is live, which is exactly where they are repaid.
|
|
57
|
+
# State ownership, modes and ancestry are verified before channel discovery.
|
|
58
|
+
# After that validation the channel check uses only builtins, and returns
|
|
59
|
+
# before digesting code or sizing the transcript unless another channel is live.
|
|
60
60
|
|
|
61
61
|
# Key this guard would memoise under, once computed. Empty means "record
|
|
62
62
|
# nothing on exit".
|
|
@@ -74,14 +74,25 @@ lisa_guard_memo_ready=0
|
|
|
74
74
|
# Digest tool for the memo key, resolved once. Empty disables the memo.
|
|
75
75
|
lisa_guard_memo_digest_tool=""
|
|
76
76
|
|
|
77
|
-
#
|
|
78
|
-
#
|
|
79
|
-
#
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
77
|
+
# Read ownership and all permission bits without accepting output from a
|
|
78
|
+
# failed platform-specific stat invocation.
|
|
79
|
+
# $1 - directory; sets lisa_guard_memo_owner and lisa_guard_memo_mode
|
|
80
|
+
lisa_guard_memo_stat() {
|
|
81
|
+
local facts=""
|
|
82
|
+
facts="$(stat -c '%u %a' "$1" 2>/dev/null)" ||
|
|
83
|
+
facts="$(stat -f '%u %p' "$1" 2>/dev/null)" || return 1
|
|
84
|
+
lisa_guard_memo_owner="${facts%% *}"
|
|
85
|
+
lisa_guard_memo_mode="${facts#* }"
|
|
86
|
+
case "$lisa_guard_memo_owner:$lisa_guard_memo_mode" in
|
|
87
|
+
*[!0-9:]* | :* | *:) return 1 ;;
|
|
88
|
+
esac
|
|
89
|
+
case "$lisa_guard_memo_mode" in *[!0-7]*) return 1 ;; esac
|
|
90
|
+
lisa_guard_memo_mode=$((8#$lisa_guard_memo_mode & 8#7777))
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
# Memo leaves must be private even when a sticky shared temp ancestor is safe.
|
|
94
|
+
# Ownership alone allows another local account to plant a session/allow file
|
|
95
|
+
# in an owned but group- or world-writable directory.
|
|
85
96
|
#
|
|
86
97
|
# $1 - candidate directory
|
|
87
98
|
lisa_guard_memo_dir_usable() {
|
|
@@ -89,23 +100,42 @@ lisa_guard_memo_dir_usable() {
|
|
|
89
100
|
[ -d "$1" ] || return 1
|
|
90
101
|
[ ! -L "$1" ] || return 1
|
|
91
102
|
[ -O "$1" ] || return 1
|
|
103
|
+
lisa_guard_memo_stat "$1" || return 1
|
|
104
|
+
[ $((lisa_guard_memo_mode & 8#0022)) -eq 0 ]
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
# Resolve parents physically and verify every ancestor. Plugin hooks do not
|
|
108
|
+
# inherit the dispatcher's trust walk, and exported paths are still inputs.
|
|
109
|
+
# $1 - candidate memo base; sets lisa_guard_memo_base only on success
|
|
110
|
+
lisa_guard_memo_trust_base() {
|
|
111
|
+
lisa_guard_memo_dir_usable "$1" || return 1
|
|
112
|
+
local physical=""
|
|
113
|
+
physical="$(cd "$1" 2>/dev/null && pwd -P)" || return 1
|
|
114
|
+
local current="$physical"
|
|
115
|
+
while :; do
|
|
116
|
+
lisa_guard_memo_stat "$current" || return 1
|
|
117
|
+
[ "$lisa_guard_memo_owner" = 0 ] || [ -O "$current" ] || return 1
|
|
118
|
+
if [ $((lisa_guard_memo_mode & 8#0022)) -ne 0 ] &&
|
|
119
|
+
[ $((lisa_guard_memo_mode & 8#1000)) -eq 0 ]; then
|
|
120
|
+
return 1
|
|
121
|
+
fi
|
|
122
|
+
[ "$current" != / ] || break
|
|
123
|
+
current="${current%/*}"
|
|
124
|
+
[ -n "$current" ] || current=/
|
|
125
|
+
done
|
|
126
|
+
lisa_guard_memo_base="$physical"
|
|
92
127
|
}
|
|
93
128
|
|
|
94
129
|
# Establish the memo base directory.
|
|
95
130
|
#
|
|
96
|
-
# Preferred source is `LISA_GUARD_MEMO_DIR`, exported by the dispatcher
|
|
97
|
-
#
|
|
98
|
-
#
|
|
99
|
-
# reached by the plugin channel has no such parent, so it creates the directory
|
|
100
|
-
# itself under `TMPDIR` — private by umask, and used only when this user owns
|
|
101
|
-
# it. If neither works the memo is unavailable and every guard evaluates, which
|
|
102
|
-
# is today's behaviour.
|
|
131
|
+
# Preferred source is `LISA_GUARD_MEMO_DIR`, exported by the dispatcher. Both
|
|
132
|
+
# this input and the plugin channel's TMPDIR fallback receive the same trust
|
|
133
|
+
# checks. Missing state is created privately; untrusted state disables memo use.
|
|
103
134
|
lisa_guard_memo_resolve_base() {
|
|
104
135
|
[ -z "$lisa_guard_memo_base" ] || return 0
|
|
105
136
|
|
|
106
137
|
local candidate="${LISA_GUARD_MEMO_DIR:-}"
|
|
107
|
-
if
|
|
108
|
-
lisa_guard_memo_base="$candidate"
|
|
138
|
+
if lisa_guard_memo_trust_base "$candidate"; then
|
|
109
139
|
return 0
|
|
110
140
|
fi
|
|
111
141
|
|
|
@@ -118,8 +148,7 @@ lisa_guard_memo_resolve_base() {
|
|
|
118
148
|
if [ ! -e "$candidate" ] && [ ! -L "$candidate" ]; then
|
|
119
149
|
(umask 077 && mkdir -p "$candidate") 2>/dev/null || true
|
|
120
150
|
fi
|
|
121
|
-
if
|
|
122
|
-
lisa_guard_memo_base="$candidate"
|
|
151
|
+
if lisa_guard_memo_trust_base "$candidate"; then
|
|
123
152
|
return 0
|
|
124
153
|
fi
|
|
125
154
|
return 1
|
|
@@ -165,6 +194,7 @@ lisa_guard_memo_sweep() {
|
|
|
165
194
|
#
|
|
166
195
|
# $1 - guard name, used only to name the memo file
|
|
167
196
|
# $2 - the raw tool payload this guard was handed on stdin
|
|
197
|
+
# Remaining arguments - files containing delegated verdict code
|
|
168
198
|
lisa_guard_dedupe() {
|
|
169
199
|
local guard_name="${1:-}"
|
|
170
200
|
local payload="${2:-}"
|
|
@@ -194,8 +224,7 @@ lisa_guard_dedupe() {
|
|
|
194
224
|
fresh_session=1
|
|
195
225
|
fi
|
|
196
226
|
fi
|
|
197
|
-
|
|
198
|
-
[ ! -L "$session_dir" ] || return 0
|
|
227
|
+
lisa_guard_memo_dir_usable "$session_dir" || return 0
|
|
199
228
|
|
|
200
229
|
# Swept once, by the process that created the session directory, so a
|
|
201
230
|
# long-lived machine does not accumulate memo state. Off the hot path by
|
|
@@ -278,11 +307,18 @@ lisa_guard_dedupe() {
|
|
|
278
307
|
case "$transcript_size" in "" | *[!0-9]*) return 0 ;; esac
|
|
279
308
|
|
|
280
309
|
# One command substitution, covering everything the verdict depends on: the
|
|
281
|
-
# guard's own bytes, this library
|
|
310
|
+
# guard's own bytes, this library, delegated code, payload, and call identity.
|
|
311
|
+
# Keep literal bytes (including trailing newlines), and propagate every read
|
|
312
|
+
# failure. A successful digest of a partial stream is not proof of identity.
|
|
282
313
|
local key=""
|
|
283
314
|
key="$(
|
|
315
|
+
set -o pipefail
|
|
284
316
|
{
|
|
285
|
-
|
|
317
|
+
local source_file=""
|
|
318
|
+
for source_file in "$self_script" "${BASH_SOURCE[0]}" "${@:3}"; do
|
|
319
|
+
cat "$source_file" 2>/dev/null || exit 1
|
|
320
|
+
printf '\0'
|
|
321
|
+
done
|
|
286
322
|
printf '\n%s\n' "$payload"
|
|
287
323
|
printf '%s\n' "$transcript_size"
|
|
288
324
|
} | if [ "$lisa_guard_memo_digest_tool" = "shasum" ]; then
|
|
@@ -293,6 +329,7 @@ lisa_guard_dedupe() {
|
|
|
293
329
|
)" || key=""
|
|
294
330
|
key="${key%% *}"
|
|
295
331
|
case "$key" in "" | *[!0-9a-f]*) return 0 ;; esac
|
|
332
|
+
[ "${#key}" -eq 64 ] || return 0
|
|
296
333
|
|
|
297
334
|
# One memo file per guard per session, rewritten as the call moves on, so the
|
|
298
335
|
# state directory stays a fixed size however long a session runs. A saturated
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
|
+
# This file is managed by Lisa and IS replaced on each `lisa` run.
|
|
3
|
+
# Do not edit directly — durable changes belong upstream in Lisa.
|
|
4
|
+
|
|
2
5
|
"""Classify the only heredoc forms whose payload is non-executable text.
|
|
3
6
|
|
|
4
7
|
SCOPE — read this before hardening anything here (issue #1993).
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
|
+
# This file is managed by Lisa and IS replaced on each `lisa` run.
|
|
3
|
+
# Do not edit directly — durable changes belong upstream in Lisa.
|
|
4
|
+
|
|
2
5
|
# PreToolUse hook for Bash: a safety net that blocks destructive shell commands
|
|
3
6
|
# before they run. Lisa-native reimplementation of the upstream
|
|
4
7
|
# `safety-net@cc-marketplace` plugin's PreToolUse Bash-guard (parity work,
|
|
@@ -136,7 +139,8 @@ if [ -r "$lisa_guard_dedupe_lib" ]; then
|
|
|
136
139
|
# shellcheck source=guard-dedupe.bash
|
|
137
140
|
. "$lisa_guard_dedupe_lib"
|
|
138
141
|
trap 'lisa_guard_dedupe_record $?' EXIT
|
|
139
|
-
lisa_guard_dedupe parity-safety-net "$input"
|
|
142
|
+
lisa_guard_dedupe parity-safety-net "$input" \
|
|
143
|
+
"$lisa_guard_hook_dir/parity-safety-net-heredoc.py"
|
|
140
144
|
fi
|
|
141
145
|
|
|
142
146
|
tool_name="$(printf '%s' "$input" | jq -r '.tool_name // empty')"
|
|
@@ -174,8 +174,8 @@ export const resolveStateWriteTarget = ({
|
|
|
174
174
|
return refuse(
|
|
175
175
|
REFUSALS.MISSING_ROLE,
|
|
176
176
|
"no lifecycle role was declared. Every `stateId` write must name the role " +
|
|
177
|
-
"it is applying (ready | claimed | blocked | review | done
|
|
178
|
-
"
|
|
177
|
+
"it is applying (ready | claimed | blocked | review | done) so the " +
|
|
178
|
+
"configured target can be resolved instead of trusted."
|
|
179
179
|
);
|
|
180
180
|
|
|
181
181
|
// The environment key belongs to exactly one shape: an env-indexed `done`.
|
|
@@ -71,10 +71,13 @@ import {
|
|
|
71
71
|
parseArgs,
|
|
72
72
|
parseConfig,
|
|
73
73
|
readPath,
|
|
74
|
-
resolveRole,
|
|
75
74
|
} from "./resolve-lifecycle-role.mjs";
|
|
76
75
|
|
|
77
|
-
/**
|
|
76
|
+
/**
|
|
77
|
+
* The QA-failure signal. Historically applied by the retired `lisa-qa-fail`
|
|
78
|
+
* skill; now applied by a human or by whatever a project uses for QA, and read
|
|
79
|
+
* by rework triage.
|
|
80
|
+
*/
|
|
78
81
|
export const QA_FAILURE_SIGNAL = "qa-failure";
|
|
79
82
|
|
|
80
83
|
/** The human-gate signal: applied at filing, read by every intake sweep. */
|
|
@@ -190,8 +193,13 @@ const verdictOf = body => {
|
|
|
190
193
|
};
|
|
191
194
|
|
|
192
195
|
/**
|
|
193
|
-
* Role names whose occupancy proves the QA failure was resolved:
|
|
194
|
-
*
|
|
196
|
+
* Role names whose occupancy proves the QA failure was resolved: every
|
|
197
|
+
* environment rung of the terminal `done` map.
|
|
198
|
+
*
|
|
199
|
+
* Previously this also resolved a `qa.certified` role. That role was retired
|
|
200
|
+
* along with the QA acceptance skills that were its only writers, so reaching a
|
|
201
|
+
* `done` rung is now the whole proof. A project that wants a distinct
|
|
202
|
+
* post-QA state expresses it as a `done` rung.
|
|
195
203
|
*
|
|
196
204
|
* @param {object} options inputs
|
|
197
205
|
* @param {string} options.vendor `jira` | `linear` | `github`
|
|
@@ -199,16 +207,21 @@ const verdictOf = body => {
|
|
|
199
207
|
* @returns {string[]} configured role names, empty when none are bound
|
|
200
208
|
*/
|
|
201
209
|
export const voidingRoles = ({ vendor, config }) => {
|
|
202
|
-
const certified = resolveRole({
|
|
203
|
-
role: "qa.certified",
|
|
204
|
-
vendor,
|
|
205
|
-
global: config,
|
|
206
|
-
});
|
|
207
210
|
const root = VENDOR_ROOTS[vendor];
|
|
208
211
|
const doneMap = root ? readPath(config, `${root}.done`) : undefined;
|
|
212
|
+
// `done` has two sanctioned shapes: an env-indexed map, and a single scalar
|
|
213
|
+
// state for a project with one terminal rung. Every other reader handles
|
|
214
|
+
// both — linear-state-write-target.mjs:147, lifecycle-label-trust.mjs:213,
|
|
215
|
+
// queue-status-build-readers.mjs:315 — and this one must too. Missing the
|
|
216
|
+
// scalar here returns NO voiding roles at all, which holds a QA failure live
|
|
217
|
+
// forever on exactly the projects with the simplest config.
|
|
209
218
|
const done =
|
|
210
|
-
|
|
211
|
-
|
|
219
|
+
typeof doneMap === "string"
|
|
220
|
+
? [doneMap]
|
|
221
|
+
: doneMap && typeof doneMap === "object"
|
|
222
|
+
? Object.values(doneMap)
|
|
223
|
+
: [];
|
|
224
|
+
return done.filter(
|
|
212
225
|
name => typeof name === "string" && name.trim().length > 0
|
|
213
226
|
);
|
|
214
227
|
};
|
|
@@ -80,12 +80,7 @@ export const REQUIRED_ROLES = Object.freeze([
|
|
|
80
80
|
* Roles a project MAY bind. Omitting one means the lifecycle skips that
|
|
81
81
|
* transition. These have NO built-in default — that is the whole point of R1.
|
|
82
82
|
*/
|
|
83
|
-
export const OPTIONAL_ROLES = Object.freeze([
|
|
84
|
-
"review",
|
|
85
|
-
"qa.queue",
|
|
86
|
-
"qa.certified",
|
|
87
|
-
"human_needed",
|
|
88
|
-
]);
|
|
83
|
+
export const OPTIONAL_ROLES = Object.freeze(["review", "human_needed"]);
|
|
89
84
|
|
|
90
85
|
/** Where each vendor keeps its build lifecycle role map. */
|
|
91
86
|
export const VENDOR_ROOTS = Object.freeze({
|
|
@@ -155,7 +150,7 @@ export const parseConfig = file => {
|
|
|
155
150
|
* built-in default tier: see R1 in the module docblock.
|
|
156
151
|
*
|
|
157
152
|
* @param {object} options resolution inputs
|
|
158
|
-
* @param {string} options.role role name (`ready`, `review`, `
|
|
153
|
+
* @param {string} options.role role name (`ready`, `review`, `human_needed`, …)
|
|
159
154
|
* @param {string} options.vendor one of `jira` | `linear` | `github`
|
|
160
155
|
* @param {"read" | "write"} [options.intent] what the caller will do with it
|
|
161
156
|
* @param {string} [options.env] env key when resolving the env-keyed `done` map
|
|
@@ -215,9 +215,15 @@ nothing survives, exit on the denominator-stated summary from `summarizeDryLane`
|
|
|
215
215
|
A blocker is a **claim with a timestamp, not a fact** — it goes stale the moment its condition comes
|
|
216
216
|
true, and nothing re-read one before this phase. For each `$BLOCKED` candidate:
|
|
217
217
|
|
|
218
|
-
1. **
|
|
219
|
-
|
|
220
|
-
|
|
218
|
+
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 })`
|
|
221
|
+
and retain its plan. Apply human-marker cleanup only as planned; defer any ready-role restoration
|
|
222
|
+
until steps 2–5 have cleared the remaining blockers (map the role to the vendor's state or label).
|
|
223
|
+
A still-active hold is never auto-selected, whatever any probe says. An absent or unreadable
|
|
224
|
+
comment history cannot discharge a hold. A release removes only the human hold: continue the
|
|
225
|
+
remaining blocker checks below before selecting the item.
|
|
226
|
+
|
|
221
227
|
2. **Extract the stated discharge condition**, then **probe it**. Machine-testable conditions — a
|
|
222
228
|
version on trunk, a published package, a CI run history, an advisory's patched status — rot
|
|
223
229
|
fastest and are cheapest to check. A human decision is not machine-testable; leave it.
|
|
@@ -335,8 +341,9 @@ other gate's verdict — however conclusive — may promote an item a person par
|
|
|
335
341
|
is the same repair the leaf-only gate already performs for a ready item that must not be
|
|
336
342
|
dispatched.
|
|
337
343
|
4. **On `claimable: true` for an item that still carries a hold, RELEASE it — do not just proceed.**
|
|
338
|
-
|
|
339
|
-
|
|
344
|
+
This ready-lane candidate can retain a historical body marker and a human-needed label.
|
|
345
|
+
This step reconciles only candidates still in the ready lane; released holds outside it are
|
|
346
|
+
recovered by `lisa-repair-intake` step 2b (or Phase 2.5 when included in this cycle). Call
|
|
340
347
|
`planHumanGateRelease({ labels, body, comments, humanNeededLabel, readyLabel, lifecycleLabels, alreadyNotified })`
|
|
341
348
|
and apply exactly the actions it returns: remove the configured human-needed marker, add the
|
|
342
349
|
configured ready role back, and post `formatHumanGateReleaseNote()` once. It is the exact inverse
|
|
@@ -369,11 +376,12 @@ GitHub Issues live in one repo by definition, so the scanned repo's issues are u
|
|
|
369
376
|
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
377
|
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
378
|
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
|
|
379
|
+
- **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.
|
|
380
|
+
- **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.
|
|
381
|
+
- **Exactly one other repository** (`repo:<other>`) → **skip**, leaving the item ready for that repo's intake.
|
|
382
|
+
- **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.
|
|
383
|
+
- **Single-repo leaf for the current repo** → fall through to 3a and 3b.
|
|
384
|
+
|
|
377
385
|
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
386
|
|
|
379
387
|
#### 3a. Leaf-only claim gate (repair containers)
|
|
@@ -189,9 +189,15 @@ swept (see `automation-runbook-contract`).
|
|
|
189
189
|
A blocker is a **claim with a timestamp, not a fact** — it goes stale the moment its condition comes
|
|
190
190
|
true, and nothing re-read one before this phase. For each pre-work candidate outside `$READY`:
|
|
191
191
|
|
|
192
|
-
1. **
|
|
193
|
-
|
|
194
|
-
|
|
192
|
+
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 })`
|
|
195
|
+
and retain its plan. Apply human-marker cleanup only as planned; defer any ready-role restoration
|
|
196
|
+
until steps 2–5 have cleared the remaining blockers (map the role to the vendor's state or label).
|
|
197
|
+
A still-active hold is never auto-selected, whatever any probe says. An absent or unreadable
|
|
198
|
+
comment history cannot discharge a hold. A release removes only the human hold: continue the
|
|
199
|
+
remaining blocker checks below before selecting the item.
|
|
200
|
+
|
|
195
201
|
2. **Extract the stated discharge condition**, then **probe it**. Machine-testable conditions — a
|
|
196
202
|
version on trunk, a published package, a CI run history, an advisory's patched status — rot
|
|
197
203
|
fastest and are cheapest to check. A human decision is not machine-testable; leave it.
|
|
@@ -240,8 +246,9 @@ other gate's verdict — however conclusive — may promote an item a person par
|
|
|
240
246
|
is the same repair the leaf-only gate already performs for a ready item that must not be
|
|
241
247
|
dispatched.
|
|
242
248
|
4. **On `claimable: true` for an item that still carries a hold, RELEASE it — do not just proceed.**
|
|
243
|
-
|
|
244
|
-
|
|
249
|
+
This ready-lane candidate can retain a historical body marker and a human-needed label.
|
|
250
|
+
This step reconciles only candidates still in the ready lane; released holds outside it are
|
|
251
|
+
recovered by `lisa-repair-intake` step 2b (or Phase 2.5 when included in this cycle). Call
|
|
245
252
|
`planHumanGateRelease({ labels, body, comments, humanNeededLabel, readyLabel, lifecycleLabels, alreadyNotified })`
|
|
246
253
|
and apply exactly the actions it returns: remove the configured human-needed marker, add the
|
|
247
254
|
configured ready role back, and post `formatHumanGateReleaseNote()` once. It is the exact inverse
|
|
@@ -274,10 +281,12 @@ A JIRA project can oversee multiple repos (`frontend` / `backend` / `infrastruct
|
|
|
274
281
|
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
282
|
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
283
|
3. **Per candidate, apply the repo-scope decision (`repo-scope-split`):**
|
|
277
|
-
-
|
|
278
|
-
- **
|
|
279
|
-
- **
|
|
280
|
-
- **
|
|
284
|
+
- **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.
|
|
285
|
+
- **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.
|
|
286
|
+
- **Exactly one other repository** (`repo:<other>`) → **skip**, leaving the item ready for that repo's intake.
|
|
287
|
+
- **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.
|
|
288
|
+
- **Single-repo leaf for the current repo** → fall through to 3a and 3b.
|
|
289
|
+
|
|
281
290
|
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
291
|
|
|
283
292
|
#### 3a. Leaf-only claim gate (skip / safe-block containers)
|
|
@@ -188,8 +188,7 @@ Consumers pass business-shaped arguments only; they do not embed GraphQL.
|
|
|
188
188
|
|
|
189
189
|
**This layer does not accept a state to write. It resolves one.** A `save-issue`
|
|
190
190
|
that changes the workflow state declares `lifecycle_role:<ROLE>` — the semantic
|
|
191
|
-
role it is applying (`ready`, `claimed`, `blocked`, `review`, `done
|
|
192
|
-
`qa.queue`, `qa.certified`) — plus `env:<KEY>` when the role is the env-indexed
|
|
191
|
+
role it is applying (for example, `ready`, `claimed`, `blocked`, `review`, `done`; the configured role contract is authoritative) — plus `env:<KEY>` when the role is the env-indexed
|
|
193
192
|
`done`. This layer then resolves that role against config and the team's own
|
|
194
193
|
catalog, and sends the ID **it** resolved.
|
|
195
194
|
|
|
@@ -320,9 +319,9 @@ same mutation, same result shape, same error handling.
|
|
|
320
319
|
```graphql
|
|
321
320
|
# list-comments project_id:<ID> — page via pageInfo so a long-lived PRD's
|
|
322
321
|
# feedback history never silently truncates.
|
|
323
|
-
query($id:String
|
|
322
|
+
query($id:String!,$after:String){
|
|
324
323
|
project(id:$id){
|
|
325
|
-
comments(first:100){
|
|
324
|
+
comments(first:100,after:$after){
|
|
326
325
|
pageInfo{ hasNextPage endCursor }
|
|
327
326
|
nodes{ id body createdAt url user{ name } }
|
|
328
327
|
}
|
|
@@ -330,8 +329,47 @@ query($id:String!){
|
|
|
330
329
|
}
|
|
331
330
|
```
|
|
332
331
|
|
|
333
|
-
The Issue form
|
|
334
|
-
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
|
+
|
|
338
|
+
```bash
|
|
339
|
+
linear_list_comment_pages() { # issue|project id -> complete JSON node array
|
|
340
|
+
local anchor="$1" id="$2" after=null nodes='[]' seen='[]'
|
|
341
|
+
local query variables response connection cursor
|
|
342
|
+
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}}}}}'
|
|
344
|
+
while :; do
|
|
345
|
+
variables=$(jq -cn --arg id "$id" --argjson after "$after" '{id:$id,after:$after}') || return 1
|
|
346
|
+
response=$(linear_graphql "$query" "$variables") || return 1
|
|
347
|
+
connection=$(printf '%s' "$response" | jq -ce --arg anchor "$anchor" '
|
|
348
|
+
if (.errors != null and .errors != []) then error("GraphQL comments read failed")
|
|
349
|
+
else .data[$anchor].comments end |
|
|
350
|
+
if (.nodes | type) != "array" or (.pageInfo.hasNextPage | type) != "boolean"
|
|
351
|
+
then error("Incomplete comments page") else . end') || return 1
|
|
352
|
+
nodes=$(jq -cn --argjson prior "$nodes" --argjson page "$connection" '$prior + $page.nodes') || return 1
|
|
353
|
+
if [ "$(printf '%s' "$connection" | jq -r '.pageInfo.hasNextPage')" = false ]; then
|
|
354
|
+
printf '%s\n' "$nodes"
|
|
355
|
+
return 0
|
|
356
|
+
fi
|
|
357
|
+
cursor=$(printf '%s' "$connection" | jq -ce '.pageInfo.endCursor | select(type == "string" and length > 0)') || {
|
|
358
|
+
echo "Error: incomplete comments history; missing cursor" >&2; return 1;
|
|
359
|
+
}
|
|
360
|
+
if jq -en --argjson seen "$seen" --argjson cursor "$cursor" '$seen | index($cursor) != null' >/dev/null; then
|
|
361
|
+
echo "Error: incomplete comments history; repeated cursor" >&2
|
|
362
|
+
return 1
|
|
363
|
+
fi
|
|
364
|
+
seen=$(jq -cn --argjson seen "$seen" --argjson cursor "$cursor" '$seen + [$cursor]') || return 1
|
|
365
|
+
after="$cursor"
|
|
366
|
+
done
|
|
367
|
+
}
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
Call `linear_list_comment_pages project "$PROJECT_ID"` for `project_id`, or
|
|
371
|
+
`linear_list_comment_pages issue "$ISSUE_ID"` for `issue_id`. The caller receives
|
|
372
|
+
one complete node array; it must not interpret a failed command as zero comments.
|
|
335
373
|
|
|
336
374
|
**Substrate.** The Linear MCP exposes comments on Issues only, so the
|
|
337
375
|
`project_id` form resolves solely through the tier-1 `LINEAR_API_KEY` + GraphQL
|
|
@@ -340,7 +378,7 @@ That is not a gap in Linear: the precedence contract already puts GraphQL ahead
|
|
|
340
378
|
of the MCP, so the preferred substrate has always been able to do this. Only
|
|
341
379
|
this wrapper could not, which is what made callers fabricate an Issue to hold a
|
|
342
380
|
Project's comments. If tier 1 is unavailable, fail with the layer's standard
|
|
343
|
-
`Error:` result naming `save-comment project_id` — do **not** silently degrade
|
|
381
|
+
`Error:` result naming the requested `save-comment project_id` or `list-comments project_id` operation — do **not** silently degrade
|
|
344
382
|
into creating an Issue to comment on.
|
|
345
383
|
|
|
346
384
|
## `history` — transition history (read-only)
|
|
@@ -182,7 +182,15 @@ A blocker is a **claim with a timestamp, not a fact**. It is written once and go
|
|
|
182
182
|
|
|
183
183
|
For each pre-work candidate that is **not** in `$READY`:
|
|
184
184
|
|
|
185
|
-
1. **
|
|
185
|
+
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 })`
|
|
188
|
+
and retain its plan. Apply human-marker cleanup only as planned; defer any ready-role restoration
|
|
189
|
+
until steps 2–5 have cleared the remaining blockers (map the role to the vendor's state or label).
|
|
190
|
+
A still-active hold is never auto-selected, whatever any probe says. An absent or unreadable
|
|
191
|
+
comment history cannot discharge a hold. A release removes only the human hold: continue the
|
|
192
|
+
remaining blocker checks below before selecting the item.
|
|
193
|
+
|
|
186
194
|
2. **Extract the stated discharge condition** from the description or the most recent blocking comment — the sentence naming what has to become true.
|
|
187
195
|
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
196
|
4. **Classify with the shared helper** so the ordering and the evidence requirement cannot drift per vendor:
|
|
@@ -234,8 +242,9 @@ other gate's verdict — however conclusive — may promote an item a person par
|
|
|
234
242
|
is the same repair the leaf-only gate already performs for a ready item that must not be
|
|
235
243
|
dispatched.
|
|
236
244
|
4. **On `claimable: true` for an item that still carries a hold, RELEASE it — do not just proceed.**
|
|
237
|
-
|
|
238
|
-
|
|
245
|
+
This ready-lane candidate can retain a historical body marker and a human-needed label.
|
|
246
|
+
This step reconciles only candidates still in the ready lane; released holds outside it are
|
|
247
|
+
recovered by `lisa-repair-intake` step 2b (or Phase 2.5 when included in this cycle). Call
|
|
239
248
|
`planHumanGateRelease({ labels, body, comments, humanNeededLabel, readyLabel, lifecycleLabels, alreadyNotified })`
|
|
240
249
|
and apply exactly the actions it returns: remove the configured human-needed marker, add the
|
|
241
250
|
configured ready role back, and post `formatHumanGateReleaseNote()` once. It is the exact inverse
|
|
@@ -268,10 +277,12 @@ A Linear team can oversee multiple repos (`frontend` / `backend` / `infrastructu
|
|
|
268
277
|
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
278
|
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
279
|
3. **Per candidate, apply the repo-scope decision (`repo-scope-split`):**
|
|
271
|
-
-
|
|
272
|
-
- **
|
|
273
|
-
- **
|
|
274
|
-
- **
|
|
280
|
+
- **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.
|
|
281
|
+
- **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.
|
|
282
|
+
- **Exactly one other repository** (`repo:<other>`) → **skip**, leaving the item ready for that repo's intake.
|
|
283
|
+
- **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.
|
|
284
|
+
- **Single-repo leaf for the current repo** → fall through to 3a and 3b.
|
|
285
|
+
|
|
275
286
|
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
287
|
|
|
277
288
|
#### 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
|
|