@codyswann/lisa 4.55.2 → 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 +86 -75
- 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 -6
- 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/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 -6
- 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/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 -6
- 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/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 -6
- 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/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 -6
- 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/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 -6
- 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
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lisa-openclaw",
|
|
3
|
-
"version": "4.55.
|
|
3
|
+
"version": "4.55.3",
|
|
4
4
|
"description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Cody Swann"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lisa-openclaw",
|
|
3
|
-
"version": "4.55.
|
|
3
|
+
"version": "4.55.3",
|
|
4
4
|
"description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, across Claude and Codex.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Cody Swann"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lisa-openclaw",
|
|
3
|
-
"version": "4.55.
|
|
3
|
+
"version": "4.55.3",
|
|
4
4
|
"description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Cody Swann"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lisa-openclaw",
|
|
3
|
-
"version": "4.55.
|
|
3
|
+
"version": "4.55.3",
|
|
4
4
|
"description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Cody Swann"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lisa-openclaw",
|
|
3
|
-
"version": "4.55.
|
|
3
|
+
"version": "4.55.3",
|
|
4
4
|
"description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Cody Swann"
|
|
@@ -16,6 +16,17 @@
|
|
|
16
16
|
"all/copy-overwrite/scripts/lisa-hooks/worktree-binding-guard.sh",
|
|
17
17
|
"expo/copy-overwrite/scripts/lib/bounded-spawn.mjs",
|
|
18
18
|
"expo/copy-overwrite/scripts/lib/invoked-as-script.mjs",
|
|
19
|
+
"plugins/lisa/hooks/block-blind-automerge.sh",
|
|
20
|
+
"plugins/lisa/hooks/block-direct-issue-create.sh",
|
|
21
|
+
"plugins/lisa/hooks/block-instruction-file-edits.sh",
|
|
22
|
+
"plugins/lisa/hooks/block-managed-file-edits.sh",
|
|
23
|
+
"plugins/lisa/hooks/block-no-verify.sh",
|
|
24
|
+
"plugins/lisa/hooks/block-shell-json-parsing.sh",
|
|
25
|
+
"plugins/lisa/hooks/guard-dedupe.bash",
|
|
26
|
+
"plugins/lisa/hooks/parity-safety-net-heredoc.py",
|
|
27
|
+
"plugins/lisa/hooks/parity-safety-net.sh",
|
|
28
|
+
"plugins/lisa/hooks/worktree-binding-guard.mjs",
|
|
29
|
+
"plugins/lisa/hooks/worktree-binding-guard.sh",
|
|
19
30
|
"rails/copy-overwrite/scripts/check-threshold-ratchet.mjs",
|
|
20
31
|
"rails/copy-overwrite/scripts/threshold-ratchet-compare.mjs",
|
|
21
32
|
"rails/copy-overwrite/scripts/threshold-ratchet-families.mjs",
|
|
@@ -280,7 +280,8 @@ NODE_ID_PATTERN = re.compile(r"^[A-Za-z0-9_=-]+$")
|
|
|
280
280
|
NODE_QUERY = (
|
|
281
281
|
"query($id:ID!){node(id:$id){... on PullRequest"
|
|
282
282
|
"{number url reviewDecision state baseRefName "
|
|
283
|
-
"commits(last:1){nodes{commit{statusCheckRollup{contexts(first:100){
|
|
283
|
+
"commits(last:1){nodes{commit{statusCheckRollup{contexts(first:100){"
|
|
284
|
+
"pageInfo{hasNextPage} nodes{"
|
|
284
285
|
"__typename ... on CheckRun{name conclusion} "
|
|
285
286
|
"... on StatusContext{context state}"
|
|
286
287
|
"}}}}}}}}}"
|
|
@@ -294,9 +295,13 @@ NODE_QUERY = (
|
|
|
294
295
|
# checks, which is genuinely not failing and gets an empty list. A node without
|
|
295
296
|
# the scaffolding is a probe that never asked, and it must leave the key absent
|
|
296
297
|
# so the re-target path can tell the two apart instead of reading both as green.
|
|
298
|
+
# A truncated page is equally unreadable: a failing check may be on the next
|
|
299
|
+
# page, so a green first page cannot authorize an uncovered-base re-target.
|
|
297
300
|
NODE_JQ = (
|
|
298
301
|
"if .data.node == null then null else .data.node as $n "
|
|
299
|
-
"| if ($n
|
|
302
|
+
"| if ($n.commits.nodes[0].commit.statusCheckRollup.contexts.pageInfo.hasNextPage == true) "
|
|
303
|
+
"then ($n | del(.commits)) "
|
|
304
|
+
"elif ($n | has(\"commits\")) then ($n | del(.commits)) "
|
|
300
305
|
"+ {statusCheckRollup: "
|
|
301
306
|
"((($n.commits.nodes[0].commit.statusCheckRollup.contexts.nodes)) // [])} "
|
|
302
307
|
"else $n end end"
|
|
@@ -1024,9 +1029,9 @@ not read the pull request's checks.
|
|
|
1024
1029
|
|
|
1025
1030
|
That ref has ZERO required status checks, so the one thing standing between the
|
|
1026
1031
|
move and a permission-free gate bypass is whether the PR is currently failing —
|
|
1027
|
-
and the probe returned no `statusCheckRollup
|
|
1028
|
-
empty one. Reporting the move as the sanctioned green-PR
|
|
1029
|
-
|
|
1032
|
+
and the probe returned no complete `statusCheckRollup`. An absent or truncated
|
|
1033
|
+
rollup is not an empty one. Reporting the move as the sanctioned green-PR
|
|
1034
|
+
batching case here would claim a result the probe did not establish.
|
|
1030
1035
|
|
|
1031
1036
|
Re-target through `gh pr edit --base` instead, which reads the checks, or fix
|
|
1032
1037
|
the probe. Do not report the PR as batched until something has actually looked.
|
|
@@ -2106,6 +2106,10 @@ def unparseable_reads_only(text):
|
|
|
2106
2106
|
Returns:
|
|
2107
2107
|
True when every segment's command word is a known reader.
|
|
2108
2108
|
"""
|
|
2109
|
+
# Unlexable operands cannot be certified as data when shell substitutions
|
|
2110
|
+
# may execute inside them. Preserve the plain apostrophe reader exemption.
|
|
2111
|
+
if any(operator in text for operator in ("$(", "`", "<(", ">(")):
|
|
2112
|
+
return False
|
|
2109
2113
|
words = raw_command_words(text)
|
|
2110
2114
|
return bool(words) and all(word in READ_ONLY_PROGRAMS for word in words)
|
|
2111
2115
|
|
|
@@ -566,6 +566,7 @@ EOF
|
|
|
566
566
|
import os
|
|
567
567
|
import re
|
|
568
568
|
import shlex
|
|
569
|
+
import sys
|
|
569
570
|
|
|
570
571
|
command = os.environ.get("MANAGED_EDIT_COMMAND", "")
|
|
571
572
|
project = os.environ.get("MANAGED_EDIT_PROJECT", "") or os.getcwd()
|
|
@@ -576,6 +577,7 @@ project = os.environ.get("MANAGED_EDIT_PROJECT", "") or os.getcwd()
|
|
|
576
577
|
FOLLOW_MAX_BYTES = 262144
|
|
577
578
|
FOLLOW_MAX_FILES = 8
|
|
578
579
|
FOLLOW_MAX_DEPTH = 3
|
|
580
|
+
ENV_SPLIT_UNRESOLVED = 42
|
|
579
581
|
|
|
580
582
|
# Spelled with chr() rather than backslash escapes on purpose. This source is
|
|
581
583
|
# embedded in a shell heredoc and copied verbatim through several generators
|
|
@@ -607,7 +609,7 @@ FOLLOW_WRAPPERS = {
|
|
|
607
609
|
# positional count: the walk below re-enters its assignment skip on the
|
|
608
610
|
# next iteration and steps over as many as are present.
|
|
609
611
|
"env": (
|
|
610
|
-
frozenset({"-C", "--chdir", "-P", "-
|
|
612
|
+
frozenset({"-C", "--chdir", "-P", "-u", "--unset"}),
|
|
611
613
|
0,
|
|
612
614
|
),
|
|
613
615
|
"exec": (frozenset({"-a"}), 0),
|
|
@@ -741,6 +743,31 @@ def statements(tokens):
|
|
|
741
743
|
return grouped
|
|
742
744
|
|
|
743
745
|
|
|
746
|
+
class UnresolvedEnvSplit(ValueError):
|
|
747
|
+
"""Split-string syntax whose executed arguments cannot be proven here."""
|
|
748
|
+
|
|
749
|
+
|
|
750
|
+
def parse_env_split(split_string):
|
|
751
|
+
"""Parse only the env -S subset shared with ordinary quoted arguments.
|
|
752
|
+
|
|
753
|
+
GNU env has its own escapes, comments and environment interpolation. Do
|
|
754
|
+
not pretend shlex implements those, or invent environment values in a
|
|
755
|
+
pre-execution guard. The operator can spell the resulting command directly.
|
|
756
|
+
|
|
757
|
+
Args:
|
|
758
|
+
split_string: The literal argument supplied to env's split option.
|
|
759
|
+
|
|
760
|
+
Returns:
|
|
761
|
+
Arguments for the supported subset; otherwise raises UnresolvedEnvSplit.
|
|
762
|
+
"""
|
|
763
|
+
if any(marker in split_string for marker in (BACKSLASH, "#", "$", chr(96), chr(11), chr(12))):
|
|
764
|
+
raise UnresolvedEnvSplit("escapes, comments, shell substitution, variable expansion or control whitespace")
|
|
765
|
+
try:
|
|
766
|
+
return shlex.split(split_string, comments=False, posix=True)
|
|
767
|
+
except ValueError as error:
|
|
768
|
+
raise UnresolvedEnvSplit("unbalanced quoting") from error
|
|
769
|
+
|
|
770
|
+
|
|
744
771
|
def command_word(statement):
|
|
745
772
|
"""The program a statement runs, and the tokens after it.
|
|
746
773
|
|
|
@@ -757,6 +784,7 @@ def command_word(statement):
|
|
|
757
784
|
its command word is itself the executed script.
|
|
758
785
|
"""
|
|
759
786
|
index = 0
|
|
787
|
+
split_expansions = 0
|
|
760
788
|
while index < len(statement):
|
|
761
789
|
token = statement[index]
|
|
762
790
|
if "=" in token and not token.startswith(("=", "-")):
|
|
@@ -772,6 +800,36 @@ def command_word(statement):
|
|
|
772
800
|
if option == "--":
|
|
773
801
|
index += 1
|
|
774
802
|
break
|
|
803
|
+
# env -S inserts the split string back into env's argument list;
|
|
804
|
+
# it is executable input, not an option value to discard. Keep
|
|
805
|
+
# shell -c's quoted operand intact while expanding the env layer.
|
|
806
|
+
# The known no-operand flags can be combined before S (-vS/-ivS).
|
|
807
|
+
# Stop at S: the rest belongs to its argument, not more flags.
|
|
808
|
+
short_split = re.match(r"^-[iv0]*S(.*)$", option)
|
|
809
|
+
if program == "env" and (
|
|
810
|
+
option == "--split-string"
|
|
811
|
+
or option.startswith("--split-string=")
|
|
812
|
+
or short_split is not None
|
|
813
|
+
):
|
|
814
|
+
consumed = 1
|
|
815
|
+
if option == "--split-string" or (
|
|
816
|
+
short_split is not None and not short_split.group(1)
|
|
817
|
+
):
|
|
818
|
+
if index + 1 >= len(statement):
|
|
819
|
+
raise UnresolvedEnvSplit("missing split-string operand")
|
|
820
|
+
split_string = statement[index + 1]
|
|
821
|
+
consumed = 2
|
|
822
|
+
elif option.startswith("--split-string="):
|
|
823
|
+
split_string = option.split("=", 1)[1]
|
|
824
|
+
else:
|
|
825
|
+
split_string = short_split.group(1)
|
|
826
|
+
if split_expansions >= 64:
|
|
827
|
+
raise UnresolvedEnvSplit("nested split-string limit")
|
|
828
|
+
expanded = parse_env_split(split_string)
|
|
829
|
+
statement = [token] + expanded + statement[index + consumed :]
|
|
830
|
+
split_expansions += 1
|
|
831
|
+
index = 0
|
|
832
|
+
break
|
|
775
833
|
index += 2 if option in separate else 1
|
|
776
834
|
index += positional
|
|
777
835
|
return (None, None, [])
|
|
@@ -985,7 +1043,11 @@ def collect(text, depth, seen, out):
|
|
|
985
1043
|
|
|
986
1044
|
|
|
987
1045
|
targets = []
|
|
988
|
-
|
|
1046
|
+
try:
|
|
1047
|
+
collect(command, 0, set(), targets)
|
|
1048
|
+
except UnresolvedEnvSplit as error:
|
|
1049
|
+
sys.stderr.write(str(error) + NEWLINE)
|
|
1050
|
+
sys.exit(ENV_SPLIT_UNRESOLVED)
|
|
989
1051
|
for target in targets:
|
|
990
1052
|
cleaned = target.strip().strip("'\"")
|
|
991
1053
|
if cleaned:
|
|
@@ -1003,6 +1065,15 @@ PY
|
|
|
1003
1065
|
else
|
|
1004
1066
|
analyzer_status=$?
|
|
1005
1067
|
fi
|
|
1068
|
+
if [ "$analyzer_status" -eq 42 ]; then
|
|
1069
|
+
printf 'Blocked: cannot resolve env --split-string for managed-file protection.\n' >&2
|
|
1070
|
+
printf 'Use an explicit command without split-string escapes, comments or variable expansion.\n' >&2
|
|
1071
|
+
while IFS= read -r analyzer_line; do
|
|
1072
|
+
[ -n "$analyzer_line" ] && printf ' %s\n' "$analyzer_line" >&2
|
|
1073
|
+
done <"$analyzer_stderr"
|
|
1074
|
+
rm -f "$analyzer_stderr"
|
|
1075
|
+
exit 2
|
|
1076
|
+
fi
|
|
1006
1077
|
if [ "$analyzer_status" -ne 0 ]; then
|
|
1007
1078
|
printf 'block-managed-file-edits: Bash analyzer failed (exit %s); Bash write protection is NOT active\n' "$analyzer_status" >&2
|
|
1008
1079
|
while IFS= read -r analyzer_line; do
|
|
@@ -51,12 +51,9 @@
|
|
|
51
51
|
# refusal reaching the agent without the message that explains it. On a
|
|
52
52
|
# refusal every channel evaluates and speaks exactly as it does today.
|
|
53
53
|
#
|
|
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.
|
|
54
|
+
# State ownership, modes and ancestry are verified before channel discovery.
|
|
55
|
+
# After that validation the channel check uses only builtins, and returns
|
|
56
|
+
# before digesting code or sizing the transcript unless another channel is live.
|
|
60
57
|
|
|
61
58
|
# Key this guard would memoise under, once computed. Empty means "record
|
|
62
59
|
# nothing on exit".
|
|
@@ -74,14 +71,25 @@ lisa_guard_memo_ready=0
|
|
|
74
71
|
# Digest tool for the memo key, resolved once. Empty disables the memo.
|
|
75
72
|
lisa_guard_memo_digest_tool=""
|
|
76
73
|
|
|
77
|
-
#
|
|
78
|
-
#
|
|
79
|
-
#
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
74
|
+
# Read ownership and all permission bits without accepting output from a
|
|
75
|
+
# failed platform-specific stat invocation.
|
|
76
|
+
# $1 - directory; sets lisa_guard_memo_owner and lisa_guard_memo_mode
|
|
77
|
+
lisa_guard_memo_stat() {
|
|
78
|
+
local facts=""
|
|
79
|
+
facts="$(stat -c '%u %a' "$1" 2>/dev/null)" ||
|
|
80
|
+
facts="$(stat -f '%u %p' "$1" 2>/dev/null)" || return 1
|
|
81
|
+
lisa_guard_memo_owner="${facts%% *}"
|
|
82
|
+
lisa_guard_memo_mode="${facts#* }"
|
|
83
|
+
case "$lisa_guard_memo_owner:$lisa_guard_memo_mode" in
|
|
84
|
+
*[!0-9:]* | :* | *:) return 1 ;;
|
|
85
|
+
esac
|
|
86
|
+
case "$lisa_guard_memo_mode" in *[!0-7]*) return 1 ;; esac
|
|
87
|
+
lisa_guard_memo_mode=$((8#$lisa_guard_memo_mode & 8#7777))
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
# Memo leaves must be private even when a sticky shared temp ancestor is safe.
|
|
91
|
+
# Ownership alone allows another local account to plant a session/allow file
|
|
92
|
+
# in an owned but group- or world-writable directory.
|
|
85
93
|
#
|
|
86
94
|
# $1 - candidate directory
|
|
87
95
|
lisa_guard_memo_dir_usable() {
|
|
@@ -89,23 +97,42 @@ lisa_guard_memo_dir_usable() {
|
|
|
89
97
|
[ -d "$1" ] || return 1
|
|
90
98
|
[ ! -L "$1" ] || return 1
|
|
91
99
|
[ -O "$1" ] || return 1
|
|
100
|
+
lisa_guard_memo_stat "$1" || return 1
|
|
101
|
+
[ $((lisa_guard_memo_mode & 8#0022)) -eq 0 ]
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
# Resolve parents physically and verify every ancestor. Plugin hooks do not
|
|
105
|
+
# inherit the dispatcher's trust walk, and exported paths are still inputs.
|
|
106
|
+
# $1 - candidate memo base; sets lisa_guard_memo_base only on success
|
|
107
|
+
lisa_guard_memo_trust_base() {
|
|
108
|
+
lisa_guard_memo_dir_usable "$1" || return 1
|
|
109
|
+
local physical=""
|
|
110
|
+
physical="$(cd "$1" 2>/dev/null && pwd -P)" || return 1
|
|
111
|
+
local current="$physical"
|
|
112
|
+
while :; do
|
|
113
|
+
lisa_guard_memo_stat "$current" || return 1
|
|
114
|
+
[ "$lisa_guard_memo_owner" = 0 ] || [ -O "$current" ] || return 1
|
|
115
|
+
if [ $((lisa_guard_memo_mode & 8#0022)) -ne 0 ] &&
|
|
116
|
+
[ $((lisa_guard_memo_mode & 8#1000)) -eq 0 ]; then
|
|
117
|
+
return 1
|
|
118
|
+
fi
|
|
119
|
+
[ "$current" != / ] || break
|
|
120
|
+
current="${current%/*}"
|
|
121
|
+
[ -n "$current" ] || current=/
|
|
122
|
+
done
|
|
123
|
+
lisa_guard_memo_base="$physical"
|
|
92
124
|
}
|
|
93
125
|
|
|
94
126
|
# Establish the memo base directory.
|
|
95
127
|
#
|
|
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.
|
|
128
|
+
# Preferred source is `LISA_GUARD_MEMO_DIR`, exported by the dispatcher. Both
|
|
129
|
+
# this input and the plugin channel's TMPDIR fallback receive the same trust
|
|
130
|
+
# checks. Missing state is created privately; untrusted state disables memo use.
|
|
103
131
|
lisa_guard_memo_resolve_base() {
|
|
104
132
|
[ -z "$lisa_guard_memo_base" ] || return 0
|
|
105
133
|
|
|
106
134
|
local candidate="${LISA_GUARD_MEMO_DIR:-}"
|
|
107
|
-
if
|
|
108
|
-
lisa_guard_memo_base="$candidate"
|
|
135
|
+
if lisa_guard_memo_trust_base "$candidate"; then
|
|
109
136
|
return 0
|
|
110
137
|
fi
|
|
111
138
|
|
|
@@ -118,8 +145,7 @@ lisa_guard_memo_resolve_base() {
|
|
|
118
145
|
if [ ! -e "$candidate" ] && [ ! -L "$candidate" ]; then
|
|
119
146
|
(umask 077 && mkdir -p "$candidate") 2>/dev/null || true
|
|
120
147
|
fi
|
|
121
|
-
if
|
|
122
|
-
lisa_guard_memo_base="$candidate"
|
|
148
|
+
if lisa_guard_memo_trust_base "$candidate"; then
|
|
123
149
|
return 0
|
|
124
150
|
fi
|
|
125
151
|
return 1
|
|
@@ -165,6 +191,7 @@ lisa_guard_memo_sweep() {
|
|
|
165
191
|
#
|
|
166
192
|
# $1 - guard name, used only to name the memo file
|
|
167
193
|
# $2 - the raw tool payload this guard was handed on stdin
|
|
194
|
+
# Remaining arguments - files containing delegated verdict code
|
|
168
195
|
lisa_guard_dedupe() {
|
|
169
196
|
local guard_name="${1:-}"
|
|
170
197
|
local payload="${2:-}"
|
|
@@ -194,8 +221,7 @@ lisa_guard_dedupe() {
|
|
|
194
221
|
fresh_session=1
|
|
195
222
|
fi
|
|
196
223
|
fi
|
|
197
|
-
|
|
198
|
-
[ ! -L "$session_dir" ] || return 0
|
|
224
|
+
lisa_guard_memo_dir_usable "$session_dir" || return 0
|
|
199
225
|
|
|
200
226
|
# Swept once, by the process that created the session directory, so a
|
|
201
227
|
# long-lived machine does not accumulate memo state. Off the hot path by
|
|
@@ -278,11 +304,18 @@ lisa_guard_dedupe() {
|
|
|
278
304
|
case "$transcript_size" in "" | *[!0-9]*) return 0 ;; esac
|
|
279
305
|
|
|
280
306
|
# One command substitution, covering everything the verdict depends on: the
|
|
281
|
-
# guard's own bytes, this library
|
|
307
|
+
# guard's own bytes, this library, delegated code, payload, and call identity.
|
|
308
|
+
# Keep literal bytes (including trailing newlines), and propagate every read
|
|
309
|
+
# failure. A successful digest of a partial stream is not proof of identity.
|
|
282
310
|
local key=""
|
|
283
311
|
key="$(
|
|
312
|
+
set -o pipefail
|
|
284
313
|
{
|
|
285
|
-
|
|
314
|
+
local source_file=""
|
|
315
|
+
for source_file in "$self_script" "${BASH_SOURCE[0]}" "${@:3}"; do
|
|
316
|
+
cat "$source_file" 2>/dev/null || exit 1
|
|
317
|
+
printf '\0'
|
|
318
|
+
done
|
|
286
319
|
printf '\n%s\n' "$payload"
|
|
287
320
|
printf '%s\n' "$transcript_size"
|
|
288
321
|
} | if [ "$lisa_guard_memo_digest_tool" = "shasum" ]; then
|
|
@@ -293,6 +326,7 @@ lisa_guard_dedupe() {
|
|
|
293
326
|
)" || key=""
|
|
294
327
|
key="${key%% *}"
|
|
295
328
|
case "$key" in "" | *[!0-9a-f]*) return 0 ;; esac
|
|
329
|
+
[ "${#key}" -eq 64 ] || return 0
|
|
296
330
|
|
|
297
331
|
# One memo file per guard per session, rewritten as the call moves on, so the
|
|
298
332
|
# state directory stays a fixed size however long a session runs. A saturated
|
|
@@ -136,7 +136,8 @@ if [ -r "$lisa_guard_dedupe_lib" ]; then
|
|
|
136
136
|
# shellcheck source=guard-dedupe.bash
|
|
137
137
|
. "$lisa_guard_dedupe_lib"
|
|
138
138
|
trap 'lisa_guard_dedupe_record $?' EXIT
|
|
139
|
-
lisa_guard_dedupe parity-safety-net "$input"
|
|
139
|
+
lisa_guard_dedupe parity-safety-net "$input" \
|
|
140
|
+
"$lisa_guard_hook_dir/parity-safety-net-heredoc.py"
|
|
140
141
|
fi
|
|
141
142
|
|
|
142
143
|
tool_name="$(printf '%s' "$input" | jq -r '.tool_name // empty')"
|