@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
|
@@ -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: refuse agent writes to files Lisa overwrites on every apply.
|
|
3
6
|
#
|
|
4
7
|
# Lisa ships templates in three modes, and only one of them is unsafe to edit:
|
|
@@ -566,6 +569,7 @@ EOF
|
|
|
566
569
|
import os
|
|
567
570
|
import re
|
|
568
571
|
import shlex
|
|
572
|
+
import sys
|
|
569
573
|
|
|
570
574
|
command = os.environ.get("MANAGED_EDIT_COMMAND", "")
|
|
571
575
|
project = os.environ.get("MANAGED_EDIT_PROJECT", "") or os.getcwd()
|
|
@@ -576,6 +580,7 @@ project = os.environ.get("MANAGED_EDIT_PROJECT", "") or os.getcwd()
|
|
|
576
580
|
FOLLOW_MAX_BYTES = 262144
|
|
577
581
|
FOLLOW_MAX_FILES = 8
|
|
578
582
|
FOLLOW_MAX_DEPTH = 3
|
|
583
|
+
ENV_SPLIT_UNRESOLVED = 42
|
|
579
584
|
|
|
580
585
|
# Spelled with chr() rather than backslash escapes on purpose. This source is
|
|
581
586
|
# embedded in a shell heredoc and copied verbatim through several generators
|
|
@@ -607,7 +612,7 @@ FOLLOW_WRAPPERS = {
|
|
|
607
612
|
# positional count: the walk below re-enters its assignment skip on the
|
|
608
613
|
# next iteration and steps over as many as are present.
|
|
609
614
|
"env": (
|
|
610
|
-
frozenset({"-C", "--chdir", "-P", "-
|
|
615
|
+
frozenset({"-C", "--chdir", "-P", "-u", "--unset"}),
|
|
611
616
|
0,
|
|
612
617
|
),
|
|
613
618
|
"exec": (frozenset({"-a"}), 0),
|
|
@@ -741,6 +746,31 @@ def statements(tokens):
|
|
|
741
746
|
return grouped
|
|
742
747
|
|
|
743
748
|
|
|
749
|
+
class UnresolvedEnvSplit(ValueError):
|
|
750
|
+
"""Split-string syntax whose executed arguments cannot be proven here."""
|
|
751
|
+
|
|
752
|
+
|
|
753
|
+
def parse_env_split(split_string):
|
|
754
|
+
"""Parse only the env -S subset shared with ordinary quoted arguments.
|
|
755
|
+
|
|
756
|
+
GNU env has its own escapes, comments and environment interpolation. Do
|
|
757
|
+
not pretend shlex implements those, or invent environment values in a
|
|
758
|
+
pre-execution guard. The operator can spell the resulting command directly.
|
|
759
|
+
|
|
760
|
+
Args:
|
|
761
|
+
split_string: The literal argument supplied to env's split option.
|
|
762
|
+
|
|
763
|
+
Returns:
|
|
764
|
+
Arguments for the supported subset; otherwise raises UnresolvedEnvSplit.
|
|
765
|
+
"""
|
|
766
|
+
if any(marker in split_string for marker in (BACKSLASH, "#", "$", chr(96), chr(11), chr(12))):
|
|
767
|
+
raise UnresolvedEnvSplit("escapes, comments, shell substitution, variable expansion or control whitespace")
|
|
768
|
+
try:
|
|
769
|
+
return shlex.split(split_string, comments=False, posix=True)
|
|
770
|
+
except ValueError as error:
|
|
771
|
+
raise UnresolvedEnvSplit("unbalanced quoting") from error
|
|
772
|
+
|
|
773
|
+
|
|
744
774
|
def command_word(statement):
|
|
745
775
|
"""The program a statement runs, and the tokens after it.
|
|
746
776
|
|
|
@@ -757,6 +787,7 @@ def command_word(statement):
|
|
|
757
787
|
its command word is itself the executed script.
|
|
758
788
|
"""
|
|
759
789
|
index = 0
|
|
790
|
+
split_expansions = 0
|
|
760
791
|
while index < len(statement):
|
|
761
792
|
token = statement[index]
|
|
762
793
|
if "=" in token and not token.startswith(("=", "-")):
|
|
@@ -772,6 +803,36 @@ def command_word(statement):
|
|
|
772
803
|
if option == "--":
|
|
773
804
|
index += 1
|
|
774
805
|
break
|
|
806
|
+
# env -S inserts the split string back into env's argument list;
|
|
807
|
+
# it is executable input, not an option value to discard. Keep
|
|
808
|
+
# shell -c's quoted operand intact while expanding the env layer.
|
|
809
|
+
# The known no-operand flags can be combined before S (-vS/-ivS).
|
|
810
|
+
# Stop at S: the rest belongs to its argument, not more flags.
|
|
811
|
+
short_split = re.match(r"^-[iv0]*S(.*)$", option)
|
|
812
|
+
if program == "env" and (
|
|
813
|
+
option == "--split-string"
|
|
814
|
+
or option.startswith("--split-string=")
|
|
815
|
+
or short_split is not None
|
|
816
|
+
):
|
|
817
|
+
consumed = 1
|
|
818
|
+
if option == "--split-string" or (
|
|
819
|
+
short_split is not None and not short_split.group(1)
|
|
820
|
+
):
|
|
821
|
+
if index + 1 >= len(statement):
|
|
822
|
+
raise UnresolvedEnvSplit("missing split-string operand")
|
|
823
|
+
split_string = statement[index + 1]
|
|
824
|
+
consumed = 2
|
|
825
|
+
elif option.startswith("--split-string="):
|
|
826
|
+
split_string = option.split("=", 1)[1]
|
|
827
|
+
else:
|
|
828
|
+
split_string = short_split.group(1)
|
|
829
|
+
if split_expansions >= 64:
|
|
830
|
+
raise UnresolvedEnvSplit("nested split-string limit")
|
|
831
|
+
expanded = parse_env_split(split_string)
|
|
832
|
+
statement = [token] + expanded + statement[index + consumed :]
|
|
833
|
+
split_expansions += 1
|
|
834
|
+
index = 0
|
|
835
|
+
break
|
|
775
836
|
index += 2 if option in separate else 1
|
|
776
837
|
index += positional
|
|
777
838
|
return (None, None, [])
|
|
@@ -985,7 +1046,11 @@ def collect(text, depth, seen, out):
|
|
|
985
1046
|
|
|
986
1047
|
|
|
987
1048
|
targets = []
|
|
988
|
-
|
|
1049
|
+
try:
|
|
1050
|
+
collect(command, 0, set(), targets)
|
|
1051
|
+
except UnresolvedEnvSplit as error:
|
|
1052
|
+
sys.stderr.write(str(error) + NEWLINE)
|
|
1053
|
+
sys.exit(ENV_SPLIT_UNRESOLVED)
|
|
989
1054
|
for target in targets:
|
|
990
1055
|
cleaned = target.strip().strip("'\"")
|
|
991
1056
|
if cleaned:
|
|
@@ -1003,6 +1068,15 @@ PY
|
|
|
1003
1068
|
else
|
|
1004
1069
|
analyzer_status=$?
|
|
1005
1070
|
fi
|
|
1071
|
+
if [ "$analyzer_status" -eq 42 ]; then
|
|
1072
|
+
printf 'Blocked: cannot resolve env --split-string for managed-file protection.\n' >&2
|
|
1073
|
+
printf 'Use an explicit command without split-string escapes, comments or variable expansion.\n' >&2
|
|
1074
|
+
while IFS= read -r analyzer_line; do
|
|
1075
|
+
[ -n "$analyzer_line" ] && printf ' %s\n' "$analyzer_line" >&2
|
|
1076
|
+
done <"$analyzer_stderr"
|
|
1077
|
+
rm -f "$analyzer_stderr"
|
|
1078
|
+
exit 2
|
|
1079
|
+
fi
|
|
1006
1080
|
if [ "$analyzer_status" -ne 0 ]; then
|
|
1007
1081
|
printf 'block-managed-file-edits: Bash analyzer failed (exit %s); Bash write protection is NOT active\n' "$analyzer_status" >&2
|
|
1008
1082
|
while IFS= read -r analyzer_line; do
|
|
@@ -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 commands that bypass git's verification hooks.
|
|
3
6
|
# Bypassing pre-commit/pre-push hooks (which exist for a reason) is blocked in
|
|
4
7
|
# all of its forms; the fix is to address the underlying issue, not silence the
|
|
@@ -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')"
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"support-file-resolver.d.ts","sourceRoot":"","sources":["../../src/opencode/support-file-resolver.ts"],"names":[],"mappings":"AAGA;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,GACf,MAAM,
|
|
1
|
+
{"version":3,"file":"support-file-resolver.d.ts","sourceRoot":"","sources":["../../src/opencode/support-file-resolver.ts"],"names":[],"mappings":"AAGA;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,GACf,MAAM,CAeR"}
|
|
@@ -11,6 +11,8 @@ export function resolveSupportFile(moduleUrl, filename) {
|
|
|
11
11
|
const bundled = path.join(moduleDir, "plugin-templates", filename);
|
|
12
12
|
if (path.basename(path.dirname(moduleDir)) === "dist")
|
|
13
13
|
return bundled;
|
|
14
|
-
|
|
14
|
+
// Generated hooks carry the same ownership banner as the dispatcher copy;
|
|
15
|
+
// raw authoring sources do not, so their literal-byte memo keys would differ.
|
|
16
|
+
return path.resolve(moduleDir, "..", "..", "plugins", "lisa", "hooks", filename);
|
|
15
17
|
}
|
|
16
18
|
//# sourceMappingURL=support-file-resolver.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"support-file-resolver.js","sourceRoot":"","sources":["../../src/opencode/support-file-resolver.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB,CAChC,SAAiB,EACjB,QAAgB;IAEhB,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,CAAC;IACzD,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,kBAAkB,EAAE,QAAQ,CAAC,CAAC;IACnE,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,KAAK,MAAM;QAAE,OAAO,OAAO,CAAC;IACtE,OAAO,IAAI,CAAC,OAAO,CACjB,SAAS,EACT,IAAI,EACJ,IAAI,EACJ,SAAS,EACT,
|
|
1
|
+
{"version":3,"file":"support-file-resolver.js","sourceRoot":"","sources":["../../src/opencode/support-file-resolver.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB,CAChC,SAAiB,EACjB,QAAgB;IAEhB,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,CAAC;IACzD,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,kBAAkB,EAAE,QAAQ,CAAC,CAAC;IACnE,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,KAAK,MAAM;QAAE,OAAO,OAAO,CAAC;IACtE,0EAA0E;IAC1E,8EAA8E;IAC9E,OAAO,IAAI,CAAC,OAAO,CACjB,SAAS,EACT,IAAI,EACJ,IAAI,EACJ,SAAS,EACT,MAAM,EACN,OAAO,EACP,QAAQ,CACT,CAAC;AACJ,CAAC"}
|
|
@@ -152,31 +152,33 @@ const isPriorTag = tag =>
|
|
|
152
152
|
* removed, and the tags that were retired.
|
|
153
153
|
*/
|
|
154
154
|
const stripPriorBlocks = contents => {
|
|
155
|
-
const
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
155
|
+
const result = contents.split("\n").reduce(
|
|
156
|
+
(state, line) => {
|
|
157
|
+
if (state.dropping === null) {
|
|
158
|
+
const begin = /@generated begin (\S+)/.exec(line);
|
|
159
|
+
if (begin && isPriorTag(begin[1])) {
|
|
160
|
+
return {
|
|
161
|
+
...state,
|
|
162
|
+
dropping: begin[1],
|
|
163
|
+
retired: [...state.retired, begin[1]],
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
return { ...state, kept: [...state.kept, line] };
|
|
166
167
|
}
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
168
|
+
// Inside a doomed block: drop through its own end marker, and only its
|
|
169
|
+
// own. Keying the end on the tag we opened with means a nested or
|
|
170
|
+
// adjacent block belonging to something else cannot close ours early.
|
|
171
|
+
return line.includes(`@generated end ${state.dropping}`)
|
|
172
|
+
? { ...state, dropping: null }
|
|
173
|
+
: state;
|
|
174
|
+
},
|
|
175
|
+
{ kept: [], retired: [], dropping: null }
|
|
176
|
+
);
|
|
175
177
|
// An unterminated block would otherwise swallow the rest of the file. Losing
|
|
176
178
|
// MainActivity to a truncated marker is far worse than leaving a stale block
|
|
177
179
|
// in place, so this fails closed by keeping the original.
|
|
178
|
-
if (dropping !== null) return { contents, retired: [] };
|
|
179
|
-
return { contents: kept.join("\n"), retired };
|
|
180
|
+
if (result.dropping !== null) return { contents, retired: [] };
|
|
181
|
+
return { contents: result.kept.join("\n"), retired: result.retired };
|
|
180
182
|
};
|
|
181
183
|
|
|
182
184
|
const mergeOrThrow = contents => {
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"⚠️ `required_contexts` SHIPS EMPTY AND UNSTAMPED ON PURPOSE. Lisa cannot know what YOUR ruleset requires, and an earlier version of this seed shipped a guess that was measured WRONG (#2476): it claimed `🔗 Work-Item Traceability` was required when no ruleset required it, and omitted six contexts that were. Until `ruleset.baseline_fetched_at` carries the date you transcribed the real list, the guard reports NOT CHECKED rather than answering from fiction.",
|
|
6
6
|
"To arm it: gh api repos/OWNER/NAME/rulesets --jq '.[] | \"\\\\(.id) \\\\(.name)\"' to find the ids, then gh api repos/OWNER/NAME/rulesets/ID --jq '.rules[] | select(.type==\"required_status_checks\") | .parameters.required_status_checks[].context' for the contexts. Paste them into `required_contexts` BYTE FOR BYTE, fill in `ruleset.repo` / `ruleset.ids`, and set `baseline_fetched_at` to today.",
|
|
7
7
|
"A transcription NEVER EXPIRES. Trust is presence-based: a non-empty, parseable `baseline_fetched_at` means somebody read the list off a live ruleset, and it is believed; an empty or unreadable one means it was never transcribed, and the guard refuses to answer. A ninety-day ceiling used to sit here alongside a scheduled workflow that re-read the live ruleset and re-stamped this file. Both were removed (#3599) because that workflow needed a standing `administration:read` token in every repository. A deadline with no refresh mechanism is an obligation nobody can discharge, and a guard that reliably expires into NOT CHECKED looks healthy right up until it has been quietly inert for a quarter. The consequence is stated plainly: if this list and your live ruleset drift apart, you find out by consequence rather than by check. Re-transcribe when you change your ruleset.",
|
|
8
|
-
"Lisa's quality.yml runs the
|
|
8
|
+
"Lisa's quality.yml runs the OUTCOME arm (`--outcomes`) on every pull request: it fails when a context in `required_contexts` concluded `skipped`, which GitHub counts as satisfied. It also FAILS while `required_contexts` is untranscribed, IN EVERY ENFORCEMENT MODE, because examining no required context is not a pass. This seed ships `\"enforcement\": \"warn\"`, which downgrades the vestigial `skip_jobs` token findings to reports — it does not downgrade either of those. Transcribe the list, then delete the key.",
|
|
9
9
|
"`skip_jobs` is matched as an exact comma-delimited token and GitHub Actions expression syntax has no string-replace, so write the list with no spaces: `skip_jobs: 'a,b'`, never `skip_jobs: 'a, b'`. A spaced token matches nothing and the job runs — reported as `whitespace_in_skip_token`.",
|
|
10
10
|
"`_example_required_contexts` below is a STARTING POINT FOR TYPING, never read by the guard. Verify every line against your own ruleset before promoting any of it.",
|
|
11
11
|
"THE FAMILY: required-and-red is loud; required-and-vacuous is not; advisory-and-stale is invisible. All three are one gate reporting satisfied without proving anything. `required_contexts` + `skip_job_declarations` above cover the SKIPPED variant; `evidence_bearing_checks` below covers the VACUOUS one.",
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"⚠️ `required_contexts` SHIPS EMPTY AND UNSTAMPED ON PURPOSE. Lisa cannot know what YOUR ruleset requires, and an earlier version of this seed shipped a guess that was measured WRONG (#2476): it claimed `🔗 Work-Item Traceability` was required when no ruleset required it, and omitted six contexts that were. Until `ruleset.baseline_fetched_at` carries the date you transcribed the real list, the guard reports NOT CHECKED rather than answering from fiction.",
|
|
6
6
|
"To arm it: gh api repos/OWNER/NAME/rulesets --jq '.[] | \"\\\\(.id) \\\\(.name)\"' to find the ids, then gh api repos/OWNER/NAME/rulesets/ID --jq '.rules[] | select(.type==\"required_status_checks\") | .parameters.required_status_checks[].context' for the contexts. Paste them into `required_contexts` BYTE FOR BYTE, fill in `ruleset.repo` / `ruleset.ids`, and set `baseline_fetched_at` to today.",
|
|
7
7
|
"A transcription NEVER EXPIRES. Trust is presence-based: a non-empty, parseable `baseline_fetched_at` means somebody read the list off a live ruleset, and it is believed; an empty or unreadable one means it was never transcribed, and the guard refuses to answer. A ninety-day ceiling used to sit here alongside a scheduled workflow that re-read the live ruleset and re-stamped this file. Both were removed (#3599) because that workflow needed a standing `administration:read` token in every repository. A deadline with no refresh mechanism is an obligation nobody can discharge, and a guard that reliably expires into NOT CHECKED looks healthy right up until it has been quietly inert for a quarter. The consequence is stated plainly: if this list and your live ruleset drift apart, you find out by consequence rather than by check. Re-transcribe when you change your ruleset.",
|
|
8
|
-
"Lisa's quality.yml runs the
|
|
8
|
+
"Lisa's quality.yml runs the OUTCOME arm (`--outcomes`) on every pull request: it fails when a context in `required_contexts` concluded `skipped`, which GitHub counts as satisfied. It also FAILS while `required_contexts` is untranscribed, IN EVERY ENFORCEMENT MODE, because examining no required context is not a pass. This seed ships `\"enforcement\": \"warn\"`, which downgrades the vestigial `skip_jobs` token findings to reports — it does not downgrade either of those. Transcribe the list, then delete the key.",
|
|
9
9
|
"`skip_jobs` is matched as an exact comma-delimited token and GitHub Actions expression syntax has no string-replace, so write the list with no spaces: `skip_jobs: 'a,b'`, never `skip_jobs: 'a, b'`. A spaced token matches nothing and the job runs — reported as `whitespace_in_skip_token`.",
|
|
10
10
|
"`_example_required_contexts` below is a STARTING POINT FOR TYPING, never read by the guard. Verify every line against your own ruleset before promoting any of it.",
|
|
11
11
|
"THE FAMILY: required-and-red is loud; required-and-vacuous is not; advisory-and-stale is invisible. All three are one gate reporting satisfied without proving anything. `required_contexts` + `skip_job_declarations` above cover the SKIPPED variant; `evidence_bearing_checks` below covers the VACUOUS one.",
|
package/package.json
CHANGED
|
@@ -187,7 +187,7 @@
|
|
|
187
187
|
"zod-validation-error": "^4.0.0"
|
|
188
188
|
},
|
|
189
189
|
"name": "@codyswann/lisa",
|
|
190
|
-
"version": "4.55.
|
|
190
|
+
"version": "4.55.4",
|
|
191
191
|
"description": "Claude Code governance framework that applies guardrails, guidance, and automated enforcement to projects",
|
|
192
192
|
"main": "dist/index.js",
|
|
193
193
|
"exports": {
|
|
@@ -336,7 +336,7 @@
|
|
|
336
336
|
"test": "tests"
|
|
337
337
|
},
|
|
338
338
|
"types": "./dist/index.d.ts",
|
|
339
|
-
"lisaReleaseCommit": "
|
|
340
|
-
"gitHead": "
|
|
341
|
-
"lisaReleaseTag": "v4.55.
|
|
339
|
+
"lisaReleaseCommit": "940ce1ffd27231b14136425ecc43d44b11354f00",
|
|
340
|
+
"gitHead": "940ce1ffd27231b14136425ecc43d44b11354f00",
|
|
341
|
+
"lisaReleaseTag": "v4.55.4"
|
|
342
342
|
}
|
|
@@ -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
|