@codyswann/lisa 4.48.0 → 4.50.0
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-conflict-markers.mjs +4 -1
- package/all/copy-overwrite/scripts/lib/gate-failure-diagnosis.mjs +163 -0
- package/all/copy-overwrite/scripts/lisa-enforcement-fallback.sh +178 -1
- package/all/copy-overwrite/scripts/lisa-hooks/block-direct-issue-create.sh +89 -10
- package/all/copy-overwrite/scripts/lisa-hooks/parity-safety-net.sh +44 -0
- package/all/copy-overwrite/scripts/lisa-lint-staged-preflight.mjs +1 -1
- package/all/copy-overwrite/scripts/lisa-run-gates.mjs +24 -24
- package/all/copy-overwrite/scripts/lisa-work-item.mjs +490 -81
- package/cdk/package-lisa/package.lisa.json +45 -15
- package/dist/configs/vitest/base.d.ts +71 -1
- package/dist/configs/vitest/base.d.ts.map +1 -1
- package/dist/configs/vitest/base.js +141 -23
- package/dist/configs/vitest/base.js.map +1 -1
- package/dist/configs/vitest/fleet-admission-global-setup.d.ts +34 -0
- package/dist/configs/vitest/fleet-admission-global-setup.d.ts.map +1 -0
- package/dist/configs/vitest/fleet-admission-global-setup.js +123 -0
- package/dist/configs/vitest/fleet-admission-global-setup.js.map +1 -0
- package/dist/configs/vitest/fleet-admission.d.ts +129 -0
- package/dist/configs/vitest/fleet-admission.d.ts.map +1 -0
- package/dist/configs/vitest/fleet-admission.js +239 -0
- package/dist/configs/vitest/fleet-admission.js.map +1 -0
- package/dist/configs/vitest/synthesis-scratch-reclaim.d.ts +86 -0
- package/dist/configs/vitest/synthesis-scratch-reclaim.d.ts.map +1 -0
- package/dist/configs/vitest/synthesis-scratch-reclaim.js +226 -0
- package/dist/configs/vitest/synthesis-scratch-reclaim.js.map +1 -0
- package/dist/core/lisa-owned-hash-ledger.d.ts.map +1 -1
- package/dist/core/lisa-owned-hash-ledger.js +76 -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 +129 -228
- package/dist/core/upstream-evidence-manifest.js.map +1 -1
- package/dist/opencode/plugin-templates/lisa-block-direct-issue-create.ts +45 -1
- package/dist/opencode/plugin-templates/parity-safety-net.sh +44 -0
- package/expo/package-lisa/package.lisa.json +83 -53
- package/harper-fabric/package-lisa/package.lisa.json +62 -32
- package/nestjs/package-lisa/package.lisa.json +57 -27
- package/npm-package/package-lisa/package.lisa.json +43 -7
- package/package.json +11 -7
- package/phaser/copy-overwrite/ast-grep/rules/no-day-truncating-file-age-predicate.yml +50 -0
- package/phaser/package-lisa/package.lisa.json +62 -32
- 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-drive-pr-to-merge/SKILL.md +17 -1
- package/plugins/lisa/.codex-plugin/skills/lisa-github-build-intake/SKILL.md +4 -0
- package/plugins/lisa/.codex-plugin/skills/lisa-jira-build-intake/SKILL.md +4 -0
- package/plugins/lisa/.codex-plugin/skills/lisa-linear-build-intake/SKILL.md +4 -0
- package/plugins/lisa/.codex-plugin/skills/lisa-repair-intake/SKILL.md +4 -1
- package/plugins/lisa/hooks/block-direct-issue-create.sh +89 -10
- package/plugins/lisa/hooks/discharge-work-item-gates.sh +7 -1
- package/plugins/lisa/hooks/parity-safety-net.sh +44 -0
- package/plugins/lisa/hooks/threshold-ratchet-families.mjs +12 -0
- package/plugins/lisa/rules/eager/00-rule-index.md +79 -0
- package/plugins/lisa/rules/eager/base-rules.md +10 -0
- package/plugins/lisa/rules/eager/config-resolution.md +1 -88
- package/plugins/lisa/rules/reference/automation-runbook-contract.md +97 -0
- package/plugins/lisa/rules/reference/bdd-e2e-coverage.md +56 -0
- package/plugins/lisa/rules/reference/blocker-containment.md +58 -0
- package/plugins/lisa/rules/reference/claim-archaeology.md +42 -0
- package/plugins/lisa/rules/reference/claim-evidence-mapping.md +83 -0
- package/plugins/lisa/rules/reference/claim-time-guards.md +37 -0
- package/plugins/lisa/rules/reference/config-resolution.md +97 -0
- package/plugins/lisa/rules/reference/control-reachability.md +44 -0
- package/plugins/lisa/rules/reference/convergent-review.md +31 -0
- package/plugins/lisa/rules/reference/credential-substrate-precedence.md +57 -0
- package/plugins/lisa/rules/reference/dependency-decision-records.md +37 -0
- package/plugins/lisa/rules/reference/dependency-internalization-kit.md +47 -0
- package/plugins/lisa/rules/reference/dependency-trust-classes.md +48 -0
- package/plugins/lisa/rules/reference/deployed-state-readback.md +52 -0
- package/plugins/lisa/rules/reference/derived-branch-plan.md +52 -0
- package/plugins/lisa/rules/reference/design-source-of-truth.md +43 -0
- package/plugins/lisa/rules/reference/design-value-binding.md +103 -0
- package/plugins/lisa/rules/reference/documentation-source-paths.md +18 -0
- package/plugins/lisa/rules/reference/leaf-only-lifecycle.md +75 -0
- package/plugins/lisa/rules/reference/observability-audit.md +20 -0
- package/plugins/lisa/rules/reference/prd-definition-of-ready.md +37 -0
- package/plugins/lisa/rules/reference/prd-lifecycle-rollup.md +36 -0
- package/plugins/lisa/rules/reference/pre-flight-autofill.md +88 -0
- package/plugins/lisa/rules/reference/promotion-contract.md +21 -0
- package/plugins/lisa/rules/reference/readiness-rubric.md +63 -0
- package/plugins/lisa/rules/reference/ready-role-filing.md +34 -0
- package/plugins/lisa/rules/reference/rejection-detection.md +69 -0
- package/plugins/lisa/rules/reference/repo-scope-split.md +48 -0
- package/plugins/lisa/rules/reference/reset-seed-coverage.md +55 -0
- package/plugins/lisa/rules/reference/usage-accounting.md +38 -0
- package/plugins/lisa/rules/reference/work-item-definition-of-ready.md +32 -0
- package/plugins/lisa/scripts/intake-blocker-reprobe.mjs +158 -1
- package/plugins/lisa/skills/lisa-drive-pr-to-merge/SKILL.md +17 -1
- package/plugins/lisa/skills/lisa-github-build-intake/SKILL.md +4 -0
- package/plugins/lisa/skills/lisa-jira-build-intake/SKILL.md +4 -0
- package/plugins/lisa/skills/lisa-linear-build-intake/SKILL.md +4 -0
- package/plugins/lisa/skills/lisa-repair-intake/SKILL.md +4 -1
- package/plugins/lisa-agy/hooks/block-direct-issue-create.sh +89 -10
- package/plugins/lisa-agy/hooks/parity-safety-net.sh +44 -0
- package/plugins/lisa-agy/plugin.json +1 -1
- package/plugins/lisa-agy/scripts/intake-blocker-reprobe.mjs +158 -1
- package/plugins/lisa-agy/skills/lisa-drive-pr-to-merge/SKILL.md +17 -1
- package/plugins/lisa-agy/skills/lisa-github-build-intake/SKILL.md +4 -0
- package/plugins/lisa-agy/skills/lisa-jira-build-intake/SKILL.md +4 -0
- package/plugins/lisa-agy/skills/lisa-linear-build-intake/SKILL.md +4 -0
- package/plugins/lisa-agy/skills/lisa-repair-intake/SKILL.md +4 -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-direct-issue-create.sh +89 -10
- package/plugins/lisa-copilot/hooks/discharge-work-item-gates.sh +7 -1
- package/plugins/lisa-copilot/hooks/parity-safety-net.sh +44 -0
- package/plugins/lisa-copilot/hooks/threshold-ratchet-families.mjs +12 -0
- package/plugins/lisa-copilot/rules/eager/00-rule-index.md +79 -0
- package/plugins/lisa-copilot/rules/eager/base-rules.md +10 -0
- package/plugins/lisa-copilot/rules/eager/config-resolution.md +1 -88
- package/plugins/lisa-copilot/rules/reference/automation-runbook-contract.md +97 -0
- package/plugins/lisa-copilot/rules/reference/bdd-e2e-coverage.md +56 -0
- package/plugins/lisa-copilot/rules/reference/blocker-containment.md +58 -0
- package/plugins/lisa-copilot/rules/reference/claim-archaeology.md +42 -0
- package/plugins/lisa-copilot/rules/reference/claim-evidence-mapping.md +83 -0
- package/plugins/lisa-copilot/rules/reference/claim-time-guards.md +37 -0
- package/plugins/lisa-copilot/rules/reference/config-resolution.md +97 -0
- package/plugins/lisa-copilot/rules/reference/control-reachability.md +44 -0
- package/plugins/lisa-copilot/rules/reference/convergent-review.md +31 -0
- package/plugins/lisa-copilot/rules/reference/credential-substrate-precedence.md +57 -0
- package/plugins/lisa-copilot/rules/reference/dependency-decision-records.md +37 -0
- package/plugins/lisa-copilot/rules/reference/dependency-internalization-kit.md +47 -0
- package/plugins/lisa-copilot/rules/reference/dependency-trust-classes.md +48 -0
- package/plugins/lisa-copilot/rules/reference/deployed-state-readback.md +52 -0
- package/plugins/lisa-copilot/rules/reference/derived-branch-plan.md +52 -0
- package/plugins/lisa-copilot/rules/reference/design-source-of-truth.md +43 -0
- package/plugins/lisa-copilot/rules/reference/design-value-binding.md +103 -0
- package/plugins/lisa-copilot/rules/reference/documentation-source-paths.md +18 -0
- package/plugins/lisa-copilot/rules/reference/leaf-only-lifecycle.md +75 -0
- package/plugins/lisa-copilot/rules/reference/observability-audit.md +20 -0
- package/plugins/lisa-copilot/rules/reference/prd-definition-of-ready.md +37 -0
- package/plugins/lisa-copilot/rules/reference/prd-lifecycle-rollup.md +36 -0
- package/plugins/lisa-copilot/rules/reference/pre-flight-autofill.md +88 -0
- package/plugins/lisa-copilot/rules/reference/promotion-contract.md +21 -0
- package/plugins/lisa-copilot/rules/reference/readiness-rubric.md +63 -0
- package/plugins/lisa-copilot/rules/reference/ready-role-filing.md +34 -0
- package/plugins/lisa-copilot/rules/reference/rejection-detection.md +69 -0
- package/plugins/lisa-copilot/rules/reference/repo-scope-split.md +48 -0
- package/plugins/lisa-copilot/rules/reference/reset-seed-coverage.md +55 -0
- package/plugins/lisa-copilot/rules/reference/usage-accounting.md +38 -0
- package/plugins/lisa-copilot/rules/reference/work-item-definition-of-ready.md +32 -0
- package/plugins/lisa-copilot/scripts/intake-blocker-reprobe.mjs +158 -1
- package/plugins/lisa-copilot/skills/lisa-drive-pr-to-merge/SKILL.md +17 -1
- package/plugins/lisa-copilot/skills/lisa-github-build-intake/SKILL.md +4 -0
- package/plugins/lisa-copilot/skills/lisa-jira-build-intake/SKILL.md +4 -0
- package/plugins/lisa-copilot/skills/lisa-linear-build-intake/SKILL.md +4 -0
- package/plugins/lisa-copilot/skills/lisa-repair-intake/SKILL.md +4 -1
- package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cursor/hooks/block-direct-issue-create.sh +89 -10
- package/plugins/lisa-cursor/hooks/discharge-work-item-gates.sh +7 -1
- package/plugins/lisa-cursor/hooks/parity-safety-net.sh +44 -0
- package/plugins/lisa-cursor/hooks/threshold-ratchet-families.mjs +12 -0
- package/plugins/lisa-cursor/rules/00-rule-index.mdc +84 -0
- package/plugins/lisa-cursor/rules/automation-runbook-contract-reference.mdc +97 -0
- package/plugins/lisa-cursor/rules/base-rules.mdc +10 -0
- package/plugins/lisa-cursor/rules/bdd-e2e-coverage-reference.mdc +56 -0
- package/plugins/lisa-cursor/rules/blocker-containment-reference.mdc +58 -0
- package/plugins/lisa-cursor/rules/claim-archaeology-reference.mdc +42 -0
- package/plugins/lisa-cursor/rules/claim-evidence-mapping-reference.mdc +83 -0
- package/plugins/lisa-cursor/rules/claim-time-guards-reference.mdc +37 -0
- package/plugins/lisa-cursor/rules/config-resolution-reference.mdc +97 -0
- package/plugins/lisa-cursor/rules/config-resolution.mdc +1 -88
- package/plugins/lisa-cursor/rules/control-reachability-reference.mdc +44 -0
- package/plugins/lisa-cursor/rules/convergent-review-reference.mdc +31 -0
- package/plugins/lisa-cursor/rules/credential-substrate-precedence-reference.mdc +57 -0
- package/plugins/lisa-cursor/rules/dependency-decision-records-reference.mdc +37 -0
- package/plugins/lisa-cursor/rules/dependency-internalization-kit-reference.mdc +47 -0
- package/plugins/lisa-cursor/rules/dependency-trust-classes-reference.mdc +48 -0
- package/plugins/lisa-cursor/rules/deployed-state-readback-reference.mdc +52 -0
- package/plugins/lisa-cursor/rules/derived-branch-plan-reference.mdc +52 -0
- package/plugins/lisa-cursor/rules/design-source-of-truth-reference.mdc +43 -0
- package/plugins/lisa-cursor/rules/design-value-binding-reference.mdc +103 -0
- package/plugins/lisa-cursor/rules/documentation-source-paths-reference.mdc +18 -0
- package/plugins/lisa-cursor/rules/leaf-only-lifecycle-reference.mdc +75 -0
- package/plugins/lisa-cursor/rules/observability-audit-reference.mdc +20 -0
- package/plugins/lisa-cursor/rules/prd-definition-of-ready-reference.mdc +37 -0
- package/plugins/lisa-cursor/rules/prd-lifecycle-rollup-reference.mdc +36 -0
- package/plugins/lisa-cursor/rules/pre-flight-autofill-reference.mdc +88 -0
- package/plugins/lisa-cursor/rules/promotion-contract-reference.mdc +21 -0
- package/plugins/lisa-cursor/rules/readiness-rubric-reference.mdc +63 -0
- package/plugins/lisa-cursor/rules/ready-role-filing-reference.mdc +34 -0
- package/plugins/lisa-cursor/rules/rejection-detection-reference.mdc +69 -0
- package/plugins/lisa-cursor/rules/repo-scope-split-reference.mdc +48 -0
- package/plugins/lisa-cursor/rules/reset-seed-coverage-reference.mdc +55 -0
- package/plugins/lisa-cursor/rules/usage-accounting-reference.mdc +38 -0
- package/plugins/lisa-cursor/rules/work-item-definition-of-ready-reference.mdc +32 -0
- package/plugins/lisa-cursor/scripts/intake-blocker-reprobe.mjs +158 -1
- package/plugins/lisa-cursor/skills/lisa-drive-pr-to-merge/SKILL.md +17 -1
- package/plugins/lisa-cursor/skills/lisa-github-build-intake/SKILL.md +4 -0
- package/plugins/lisa-cursor/skills/lisa-jira-build-intake/SKILL.md +4 -0
- package/plugins/lisa-cursor/skills/lisa-linear-build-intake/SKILL.md +4 -0
- package/plugins/lisa-cursor/skills/lisa-repair-intake/SKILL.md +4 -1
- package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-expo-agy/plugin.json +1 -1
- package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs-agy/plugin.json +1 -1
- package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw-agy/plugin.json +1 -1
- package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser-agy/plugin.json +1 -1
- package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-rails-agy/plugin.json +1 -1
- package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript-agy/plugin.json +1 -1
- package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki-agy/plugin.json +1 -1
- package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/src/base/hooks/block-direct-issue-create.sh +89 -10
- package/plugins/src/base/hooks/discharge-work-item-gates.sh +7 -1
- package/plugins/src/base/hooks/parity-safety-net.sh +44 -0
- package/plugins/src/base/hooks/threshold-ratchet-families.mjs +12 -0
- package/plugins/src/base/rules/eager/00-rule-index.md +79 -0
- package/plugins/src/base/rules/eager/base-rules.md +10 -0
- package/plugins/src/base/rules/eager/config-resolution.md +1 -88
- package/plugins/src/base/rules/reference/automation-runbook-contract.md +97 -0
- package/plugins/src/base/rules/reference/bdd-e2e-coverage.md +56 -0
- package/plugins/src/base/rules/reference/blocker-containment.md +58 -0
- package/plugins/src/base/rules/reference/claim-archaeology.md +42 -0
- package/plugins/src/base/rules/reference/claim-evidence-mapping.md +83 -0
- package/plugins/src/base/rules/reference/claim-time-guards.md +37 -0
- package/plugins/src/base/rules/reference/config-resolution.md +97 -0
- package/plugins/src/base/rules/reference/control-reachability.md +44 -0
- package/plugins/src/base/rules/reference/convergent-review.md +31 -0
- package/plugins/src/base/rules/reference/credential-substrate-precedence.md +57 -0
- package/plugins/src/base/rules/reference/dependency-decision-records.md +37 -0
- package/plugins/src/base/rules/reference/dependency-internalization-kit.md +47 -0
- package/plugins/src/base/rules/reference/dependency-trust-classes.md +48 -0
- package/plugins/src/base/rules/reference/deployed-state-readback.md +52 -0
- package/plugins/src/base/rules/reference/derived-branch-plan.md +52 -0
- package/plugins/src/base/rules/reference/design-source-of-truth.md +43 -0
- package/plugins/src/base/rules/reference/design-value-binding.md +103 -0
- package/plugins/src/base/rules/reference/documentation-source-paths.md +18 -0
- package/plugins/src/base/rules/reference/leaf-only-lifecycle.md +75 -0
- package/plugins/src/base/rules/reference/observability-audit.md +20 -0
- package/plugins/src/base/rules/reference/prd-definition-of-ready.md +37 -0
- package/plugins/src/base/rules/reference/prd-lifecycle-rollup.md +36 -0
- package/plugins/src/base/rules/reference/pre-flight-autofill.md +88 -0
- package/plugins/src/base/rules/reference/promotion-contract.md +21 -0
- package/plugins/src/base/rules/reference/readiness-rubric.md +63 -0
- package/plugins/src/base/rules/reference/ready-role-filing.md +34 -0
- package/plugins/src/base/rules/reference/rejection-detection.md +69 -0
- package/plugins/src/base/rules/reference/repo-scope-split.md +48 -0
- package/plugins/src/base/rules/reference/reset-seed-coverage.md +55 -0
- package/plugins/src/base/rules/reference/usage-accounting.md +38 -0
- package/plugins/src/base/rules/reference/work-item-definition-of-ready.md +32 -0
- package/plugins/src/base/scripts/intake-blocker-reprobe.mjs +158 -1
- package/plugins/src/base/skills/lisa-drive-pr-to-merge/SKILL.md +17 -1
- package/plugins/src/base/skills/lisa-github-build-intake/SKILL.md +4 -0
- package/plugins/src/base/skills/lisa-jira-build-intake/SKILL.md +4 -0
- package/plugins/src/base/skills/lisa-linear-build-intake/SKILL.md +4 -0
- package/plugins/src/base/skills/lisa-repair-intake/SKILL.md +4 -1
- package/rails/copy-overwrite/ast-grep/rules/no-day-truncating-file-age-predicate.yml +50 -0
- package/rails/copy-overwrite/scripts/threshold-ratchet-families.mjs +12 -0
- package/scripts/check-eager-rule-budget.mjs +176 -0
- package/scripts/check-generated-artifact-merge-coverage.mjs +7 -0
- package/scripts/check-rules-pairing.sh +45 -14
- package/scripts/check-shipped-surface-removals.mjs +851 -0
- package/scripts/cleanup-worktrees.sh +69 -16
- package/scripts/generate-export-surface.mjs +318 -0
- package/scripts/lib/shipped-surface.mjs +212 -0
- package/scripts/lisa-enforcement-fallback.sh +178 -1
- package/scripts/remedy-conformance.mjs +435 -0
- package/scripts/two-channel-couplings.json +2 -2
- package/typescript/copy-contents/.husky/pre-push +147 -2
- package/typescript/copy-overwrite/ast-grep/rules/no-day-truncating-file-age-predicate.yml +50 -0
- package/typescript/copy-overwrite/audit.ignore.config.json +0 -10
- package/typescript/copy-overwrite/scripts/lisa-mutation.mjs +180 -29
- package/typescript/copy-overwrite/scripts/threshold-ratchet-families.mjs +12 -0
- package/typescript/package-lisa/package.lisa.json +72 -42
- package/plugins/lisa/rules/eager/automation-runbook-contract.md +0 -92
- package/plugins/lisa/rules/eager/bdd-e2e-coverage.md +0 -51
- package/plugins/lisa/rules/eager/blocker-containment.md +0 -53
- package/plugins/lisa/rules/eager/claim-archaeology.md +0 -37
- package/plugins/lisa/rules/eager/claim-evidence-mapping.md +0 -78
- package/plugins/lisa/rules/eager/claim-time-guards.md +0 -32
- package/plugins/lisa/rules/eager/control-reachability.md +0 -39
- package/plugins/lisa/rules/eager/convergent-review.md +0 -24
- package/plugins/lisa/rules/eager/credential-substrate-precedence.md +0 -54
- package/plugins/lisa/rules/eager/dependency-decision-records.md +0 -32
- package/plugins/lisa/rules/eager/dependency-internalization-kit.md +0 -42
- package/plugins/lisa/rules/eager/dependency-trust-classes.md +0 -43
- package/plugins/lisa/rules/eager/deployed-state-readback.md +0 -47
- package/plugins/lisa/rules/eager/derived-branch-plan.md +0 -47
- package/plugins/lisa/rules/eager/design-source-of-truth.md +0 -38
- package/plugins/lisa/rules/eager/design-value-binding.md +0 -98
- package/plugins/lisa/rules/eager/documentation-source-paths.md +0 -13
- package/plugins/lisa/rules/eager/factory-model.md +0 -41
- package/plugins/lisa/rules/eager/leaf-only-lifecycle.md +0 -70
- package/plugins/lisa/rules/eager/observability-audit.md +0 -15
- package/plugins/lisa/rules/eager/prd-definition-of-ready.md +0 -32
- package/plugins/lisa/rules/eager/prd-lifecycle-rollup.md +0 -31
- package/plugins/lisa/rules/eager/pre-flight-autofill.md +0 -84
- package/plugins/lisa/rules/eager/project-learnings.md +0 -22
- package/plugins/lisa/rules/eager/promotion-contract.md +0 -18
- package/plugins/lisa/rules/eager/readiness-rubric.md +0 -58
- package/plugins/lisa/rules/eager/ready-role-filing.md +0 -29
- package/plugins/lisa/rules/eager/rejection-detection.md +0 -64
- package/plugins/lisa/rules/eager/repo-scope-split.md +0 -43
- package/plugins/lisa/rules/eager/reset-seed-coverage.md +0 -50
- package/plugins/lisa/rules/eager/usage-accounting.md +0 -33
- package/plugins/lisa/rules/eager/work-item-definition-of-ready.md +0 -27
- package/plugins/lisa-copilot/rules/eager/automation-runbook-contract.md +0 -92
- package/plugins/lisa-copilot/rules/eager/bdd-e2e-coverage.md +0 -51
- package/plugins/lisa-copilot/rules/eager/blocker-containment.md +0 -53
- package/plugins/lisa-copilot/rules/eager/claim-archaeology.md +0 -37
- package/plugins/lisa-copilot/rules/eager/claim-evidence-mapping.md +0 -78
- package/plugins/lisa-copilot/rules/eager/claim-time-guards.md +0 -32
- package/plugins/lisa-copilot/rules/eager/control-reachability.md +0 -39
- package/plugins/lisa-copilot/rules/eager/convergent-review.md +0 -24
- package/plugins/lisa-copilot/rules/eager/credential-substrate-precedence.md +0 -54
- package/plugins/lisa-copilot/rules/eager/dependency-decision-records.md +0 -32
- package/plugins/lisa-copilot/rules/eager/dependency-internalization-kit.md +0 -42
- package/plugins/lisa-copilot/rules/eager/dependency-trust-classes.md +0 -43
- package/plugins/lisa-copilot/rules/eager/deployed-state-readback.md +0 -47
- package/plugins/lisa-copilot/rules/eager/derived-branch-plan.md +0 -47
- package/plugins/lisa-copilot/rules/eager/design-source-of-truth.md +0 -38
- package/plugins/lisa-copilot/rules/eager/design-value-binding.md +0 -98
- package/plugins/lisa-copilot/rules/eager/documentation-source-paths.md +0 -13
- package/plugins/lisa-copilot/rules/eager/factory-model.md +0 -41
- package/plugins/lisa-copilot/rules/eager/leaf-only-lifecycle.md +0 -70
- package/plugins/lisa-copilot/rules/eager/observability-audit.md +0 -15
- package/plugins/lisa-copilot/rules/eager/prd-definition-of-ready.md +0 -32
- package/plugins/lisa-copilot/rules/eager/prd-lifecycle-rollup.md +0 -31
- package/plugins/lisa-copilot/rules/eager/pre-flight-autofill.md +0 -84
- package/plugins/lisa-copilot/rules/eager/project-learnings.md +0 -22
- package/plugins/lisa-copilot/rules/eager/promotion-contract.md +0 -18
- package/plugins/lisa-copilot/rules/eager/readiness-rubric.md +0 -58
- package/plugins/lisa-copilot/rules/eager/ready-role-filing.md +0 -29
- package/plugins/lisa-copilot/rules/eager/rejection-detection.md +0 -64
- package/plugins/lisa-copilot/rules/eager/repo-scope-split.md +0 -43
- package/plugins/lisa-copilot/rules/eager/reset-seed-coverage.md +0 -50
- package/plugins/lisa-copilot/rules/eager/usage-accounting.md +0 -33
- package/plugins/lisa-copilot/rules/eager/work-item-definition-of-ready.md +0 -27
- package/plugins/lisa-cursor/rules/automation-runbook-contract.mdc +0 -97
- package/plugins/lisa-cursor/rules/bdd-e2e-coverage.mdc +0 -56
- package/plugins/lisa-cursor/rules/blocker-containment.mdc +0 -58
- package/plugins/lisa-cursor/rules/claim-archaeology.mdc +0 -42
- package/plugins/lisa-cursor/rules/claim-evidence-mapping.mdc +0 -83
- package/plugins/lisa-cursor/rules/claim-time-guards.mdc +0 -37
- package/plugins/lisa-cursor/rules/control-reachability.mdc +0 -44
- package/plugins/lisa-cursor/rules/convergent-review.mdc +0 -29
- package/plugins/lisa-cursor/rules/credential-substrate-precedence.mdc +0 -59
- package/plugins/lisa-cursor/rules/dependency-decision-records.mdc +0 -37
- package/plugins/lisa-cursor/rules/dependency-internalization-kit.mdc +0 -47
- package/plugins/lisa-cursor/rules/dependency-trust-classes.mdc +0 -48
- package/plugins/lisa-cursor/rules/deployed-state-readback.mdc +0 -52
- package/plugins/lisa-cursor/rules/derived-branch-plan.mdc +0 -52
- package/plugins/lisa-cursor/rules/design-source-of-truth.mdc +0 -43
- package/plugins/lisa-cursor/rules/design-value-binding.mdc +0 -103
- package/plugins/lisa-cursor/rules/documentation-source-paths.mdc +0 -18
- package/plugins/lisa-cursor/rules/factory-model.mdc +0 -46
- package/plugins/lisa-cursor/rules/leaf-only-lifecycle.mdc +0 -75
- package/plugins/lisa-cursor/rules/observability-audit.mdc +0 -20
- package/plugins/lisa-cursor/rules/prd-definition-of-ready.mdc +0 -37
- package/plugins/lisa-cursor/rules/prd-lifecycle-rollup.mdc +0 -36
- package/plugins/lisa-cursor/rules/pre-flight-autofill.mdc +0 -89
- package/plugins/lisa-cursor/rules/project-learnings.mdc +0 -27
- package/plugins/lisa-cursor/rules/promotion-contract.mdc +0 -23
- package/plugins/lisa-cursor/rules/readiness-rubric.mdc +0 -63
- package/plugins/lisa-cursor/rules/ready-role-filing.mdc +0 -34
- package/plugins/lisa-cursor/rules/rejection-detection.mdc +0 -69
- package/plugins/lisa-cursor/rules/repo-scope-split.mdc +0 -48
- package/plugins/lisa-cursor/rules/reset-seed-coverage.mdc +0 -55
- package/plugins/lisa-cursor/rules/usage-accounting.mdc +0 -38
- package/plugins/lisa-cursor/rules/work-item-definition-of-ready.mdc +0 -32
- package/plugins/src/base/rules/eager/automation-runbook-contract.md +0 -92
- package/plugins/src/base/rules/eager/bdd-e2e-coverage.md +0 -51
- package/plugins/src/base/rules/eager/blocker-containment.md +0 -53
- package/plugins/src/base/rules/eager/claim-archaeology.md +0 -37
- package/plugins/src/base/rules/eager/claim-evidence-mapping.md +0 -78
- package/plugins/src/base/rules/eager/claim-time-guards.md +0 -32
- package/plugins/src/base/rules/eager/control-reachability.md +0 -39
- package/plugins/src/base/rules/eager/convergent-review.md +0 -24
- package/plugins/src/base/rules/eager/credential-substrate-precedence.md +0 -54
- package/plugins/src/base/rules/eager/dependency-decision-records.md +0 -32
- package/plugins/src/base/rules/eager/dependency-internalization-kit.md +0 -42
- package/plugins/src/base/rules/eager/dependency-trust-classes.md +0 -43
- package/plugins/src/base/rules/eager/deployed-state-readback.md +0 -47
- package/plugins/src/base/rules/eager/derived-branch-plan.md +0 -47
- package/plugins/src/base/rules/eager/design-source-of-truth.md +0 -38
- package/plugins/src/base/rules/eager/design-value-binding.md +0 -98
- package/plugins/src/base/rules/eager/documentation-source-paths.md +0 -13
- package/plugins/src/base/rules/eager/factory-model.md +0 -41
- package/plugins/src/base/rules/eager/leaf-only-lifecycle.md +0 -70
- package/plugins/src/base/rules/eager/observability-audit.md +0 -15
- package/plugins/src/base/rules/eager/prd-definition-of-ready.md +0 -32
- package/plugins/src/base/rules/eager/prd-lifecycle-rollup.md +0 -31
- package/plugins/src/base/rules/eager/pre-flight-autofill.md +0 -84
- package/plugins/src/base/rules/eager/project-learnings.md +0 -22
- package/plugins/src/base/rules/eager/promotion-contract.md +0 -18
- package/plugins/src/base/rules/eager/readiness-rubric.md +0 -58
- package/plugins/src/base/rules/eager/ready-role-filing.md +0 -29
- package/plugins/src/base/rules/eager/rejection-detection.md +0 -64
- package/plugins/src/base/rules/eager/repo-scope-split.md +0 -43
- package/plugins/src/base/rules/eager/reset-seed-coverage.md +0 -50
- package/plugins/src/base/rules/eager/usage-accounting.md +0 -33
- package/plugins/src/base/rules/eager/work-item-definition-of-ready.md +0 -27
|
@@ -494,6 +494,82 @@ project_dir = os.environ.get("LISA_GUARD_PROJECT_DIR", "")
|
|
|
494
494
|
OVERRIDE_NAME = "LISA_ALLOW_DIRECT_ISSUE_CREATE"
|
|
495
495
|
HUMAN_GATE_MARKER = "[lisa-human-gate]"
|
|
496
496
|
|
|
497
|
+
# Decoration a hold declaration may sit behind, and nothing more: whitespace,
|
|
498
|
+
# blockquote arrows, list bullets or numbers, emphasis, an opening HTML
|
|
499
|
+
# comment. One character class plus two optional groups, deliberately not a
|
|
500
|
+
# nested quantifier — this runs over untrusted issue bodies.
|
|
501
|
+
HUMAN_GATE_DECORATION = re.compile(r"^[ \t>*_+#-]*(?:\d+[.)][ \t]*)?(?:<!--[ \t]*)?[ \t]*")
|
|
502
|
+
HUMAN_GATE_FENCE = re.compile(r"```.*?```", re.DOTALL)
|
|
503
|
+
HUMAN_GATE_CODE_SPAN = re.compile(r"`[^`\n]*`")
|
|
504
|
+
|
|
505
|
+
|
|
506
|
+
def declares_human_gate(text):
|
|
507
|
+
"""Whether a text DECLARES a hold rather than mentioning one.
|
|
508
|
+
|
|
509
|
+
The comment this replaces said the marker is matched anywhere because it
|
|
510
|
+
"has no other meaning, so its presence in the title or body IS the
|
|
511
|
+
declaration". That was true when written and is false now: the marker
|
|
512
|
+
acquired a second meaning -- being discussed -- the moment the feature
|
|
513
|
+
became something people file tickets about, and a ticket about the marker
|
|
514
|
+
then declares a hold on itself (CodySwannGT/lisa#3815).
|
|
515
|
+
|
|
516
|
+
A declaration is POSITIONAL: the marker leads its line, behind at most the
|
|
517
|
+
decoration above, with fenced blocks and inline code spans removed first
|
|
518
|
+
because that is how the marker is written ABOUT. The same rule the intake
|
|
519
|
+
matcher applies, so the two surfaces cannot disagree about one body.
|
|
520
|
+
|
|
521
|
+
NOTE the direction here differs from the intake matcher's. There a match
|
|
522
|
+
HOLDS an item, so a false positive parks work. Here a match ADMITS a
|
|
523
|
+
filing, so a false positive is a hole -- which makes this the tightening
|
|
524
|
+
direction on both sides at once.
|
|
525
|
+
|
|
526
|
+
Args:
|
|
527
|
+
text: Any candidate text -- one argv value, a body file, a payload.
|
|
528
|
+
|
|
529
|
+
Returns:
|
|
530
|
+
True when some line of the text declares a hold.
|
|
531
|
+
"""
|
|
532
|
+
if not text:
|
|
533
|
+
return False
|
|
534
|
+
body = HUMAN_GATE_CODE_SPAN.sub("", HUMAN_GATE_FENCE.sub("", str(text)))
|
|
535
|
+
for line in body.split("\n"):
|
|
536
|
+
if HUMAN_GATE_DECORATION.sub("", line, count=1).startswith(
|
|
537
|
+
HUMAN_GATE_MARKER
|
|
538
|
+
):
|
|
539
|
+
return True
|
|
540
|
+
if _comment_carries_marker(line):
|
|
541
|
+
return True
|
|
542
|
+
return False
|
|
543
|
+
|
|
544
|
+
|
|
545
|
+
def _comment_carries_marker(line):
|
|
546
|
+
"""Whether an HTML comment on this line carries the marker.
|
|
547
|
+
|
|
548
|
+
The second accepted form, and the one this guard needs most: its inputs
|
|
549
|
+
are not markdown documents. A `--body` value is a single line, and a shell
|
|
550
|
+
script writes its declaration as `# <!-- ... -->`, so a purely
|
|
551
|
+
line-leading rule would refuse two declarations people have already
|
|
552
|
+
written -- both of which are in this repository's own test corpus.
|
|
553
|
+
|
|
554
|
+
It is not a loosening. An HTML comment is invisible when rendered, so
|
|
555
|
+
nobody wraps one around the marker in order to TALK about it; a quotation
|
|
556
|
+
has to be visible to be a quotation. Measured over this repository's 42
|
|
557
|
+
matching issue bodies, adding this branch changes not one verdict.
|
|
558
|
+
|
|
559
|
+
Args:
|
|
560
|
+
line: One line of text.
|
|
561
|
+
|
|
562
|
+
Returns:
|
|
563
|
+
True when some comment on the line contains the marker.
|
|
564
|
+
"""
|
|
565
|
+
segments = line.split("<!--")
|
|
566
|
+
for segment in segments[1:]:
|
|
567
|
+
close = segment.find("-->")
|
|
568
|
+
inside = segment if close == -1 else segment[:close]
|
|
569
|
+
if HUMAN_GATE_MARKER in inside:
|
|
570
|
+
return True
|
|
571
|
+
return False
|
|
572
|
+
|
|
497
573
|
# ---------------------------------------------------------------------------
|
|
498
574
|
# WHY THIS IS A TOKEN SCAN AND NOT A PROGRAM RESOLVER
|
|
499
575
|
#
|
|
@@ -580,7 +656,7 @@ LABEL_FLAGS = {"--label", "--labels", "--add-label", "--status", "--state"}
|
|
|
580
656
|
# None — container: state rolls up from children
|
|
581
657
|
#
|
|
582
658
|
# It is a marker with no other meaning, so it is matched wherever the payload
|
|
583
|
-
# reaches —
|
|
659
|
+
# reaches — the asymmetry `HUMAN_GATE_MARKER` gets, and for the related
|
|
584
660
|
# reason. Reading the declaration the writer already emits is also what keeps
|
|
585
661
|
# the guard and the skill from drifting apart a second time: there is one
|
|
586
662
|
# string, defined in one rule, and both read it.
|
|
@@ -1223,7 +1299,7 @@ def text_declares_readiness(text):
|
|
|
1223
1299
|
Returns:
|
|
1224
1300
|
True when the text declares build-ready or a human gate.
|
|
1225
1301
|
"""
|
|
1226
|
-
if
|
|
1302
|
+
if declares_human_gate(text):
|
|
1227
1303
|
return True
|
|
1228
1304
|
for role in (ready_role, upstream_ready_role, default_ready_role):
|
|
1229
1305
|
if not role:
|
|
@@ -1267,7 +1343,7 @@ def scope_declaration(text, state_role_ok):
|
|
|
1267
1343
|
Returns:
|
|
1268
1344
|
True when the text carries a whole-scope declaration.
|
|
1269
1345
|
"""
|
|
1270
|
-
if
|
|
1346
|
+
if declares_human_gate(text):
|
|
1271
1347
|
return True
|
|
1272
1348
|
return bool(state_role_ok and LIFECYCLE_ROLE_READY.search(text))
|
|
1273
1349
|
|
|
@@ -1497,20 +1573,23 @@ def declares_readiness(raw_args, roles, extra="", state_role_ok=False):
|
|
|
1497
1573
|
candidates = [part.strip().strip("'\"") for part in raw.split(",")]
|
|
1498
1574
|
if role in candidates:
|
|
1499
1575
|
return True
|
|
1500
|
-
#
|
|
1501
|
-
#
|
|
1502
|
-
#
|
|
1503
|
-
#
|
|
1504
|
-
|
|
1576
|
+
# Checked per ARGV VALUE rather than against `" ".join(args)`, and that is
|
|
1577
|
+
# what makes the positional rule mean anything here. Joining first destroys
|
|
1578
|
+
# position: after a join, no value's line start survives except the first
|
|
1579
|
+
# argument's, so "the marker leads its line" would be decided by argument
|
|
1580
|
+
# order. A `--title` value is its own single line, which is exactly the
|
|
1581
|
+
# unit the rule is about -- and titles must keep being read, since this
|
|
1582
|
+
# guard reads them and the intake matcher does not.
|
|
1583
|
+
if any(declares_human_gate(value) for value in args):
|
|
1505
1584
|
return True
|
|
1506
1585
|
for path in body_file_paths(args):
|
|
1507
1586
|
try:
|
|
1508
1587
|
with open(path, encoding="utf-8", errors="replace") as handle:
|
|
1509
|
-
if
|
|
1588
|
+
if declares_human_gate(handle.read()):
|
|
1510
1589
|
return True
|
|
1511
1590
|
except OSError:
|
|
1512
1591
|
continue
|
|
1513
|
-
if extra
|
|
1592
|
+
if declares_human_gate(extra):
|
|
1514
1593
|
return True
|
|
1515
1594
|
# The state-based path. Scoped by `state_role_ok` rather than checked
|
|
1516
1595
|
# unconditionally, so this adds a compliant command where none existed and
|
|
@@ -31,8 +31,14 @@ COMMAND="$(printf '%s' "$JSON_INPUT" | jq -r '.tool_input.command // empty' 2>/d
|
|
|
31
31
|
|
|
32
32
|
# `gh pr create` opens one; `gh pr edit` is the other way a body comes to carry
|
|
33
33
|
# — or lose — its declaration. Both change the answer to gate 4.
|
|
34
|
+
#
|
|
35
|
+
# `gh pr reopen` is here because a work item can hold more than one pull
|
|
36
|
+
# request, and a reopened one is a named case: it was closed, so nothing has
|
|
37
|
+
# discharged its gates since, and it is now live again with no CI run to reveal
|
|
38
|
+
# that. Its backlink no longer displaces anyone else's, so re-running the
|
|
39
|
+
# discharge for it is free (CodySwannGT/lisa#3916).
|
|
34
40
|
case "$COMMAND" in
|
|
35
|
-
*"gh pr create"* | *"gh pr edit"*) ;;
|
|
41
|
+
*"gh pr create"* | *"gh pr edit"* | *"gh pr reopen"*) ;;
|
|
36
42
|
*) exit 0 ;;
|
|
37
43
|
esac
|
|
38
44
|
|
|
@@ -26,6 +26,11 @@
|
|
|
26
26
|
# divergence: upstream blocks unconditionally; Lisa allows clean-tree resets.
|
|
27
27
|
# Residual risk (documented, accepted): the dirty check runs in the hook's
|
|
28
28
|
# cwd at hook time, so a `cd elsewhere && git reset --hard` evades it.
|
|
29
|
+
# - `git read-tree` with an update flag AND `--reset` while the working tree
|
|
30
|
+
# is dirty (issue #3978): the plumbing spelling of the same discard, on the
|
|
31
|
+
# same condition, printing the same remedy. Index-only `read-tree`, and
|
|
32
|
+
# `read-tree -m -u` without `--reset` (which git itself refuses rather than
|
|
33
|
+
# clobber a modified file), stay allowed. Lisa-only guard.
|
|
29
34
|
# - `git rebase --abort`/`--quit` while the in-progress rebase holds
|
|
30
35
|
# human-made conflict resolutions (AUTO_MERGE discriminator; issue #1956).
|
|
31
36
|
# Clean or untouched rebase state stays abortable; the apply backend and a
|
|
@@ -1819,6 +1824,45 @@ $DESTRUCTIVE_GUIDANCE"
|
|
|
1819
1824
|
fi
|
|
1820
1825
|
fi
|
|
1821
1826
|
|
|
1827
|
+
# 3a. `git read-tree` with BOTH an update flag and `--reset`, on the same dirty
|
|
1828
|
+
# tree — the plumbing spelling of guard 3 (issue #3978). It resets the index
|
|
1829
|
+
# and writes the result into the working tree, discarding tracked
|
|
1830
|
+
# modifications: the identical destruction, reached through a command that
|
|
1831
|
+
# carries no `--hard` and no `reset` subcommand, so every pattern in
|
|
1832
|
+
# guard 3 misses it. A guard an agent can walk around is a guard that stops
|
|
1833
|
+
# the honest caller and not the one looking for a way through, and this
|
|
1834
|
+
# spelling is strictly worse than the blocked one — it discards WITHOUT
|
|
1835
|
+
# preserving, which is exactly the property guard 3's remedy supplies. Both
|
|
1836
|
+
# refusals therefore print the same $PRESERVE_GUIDANCE, so what they teach
|
|
1837
|
+
# cannot drift apart.
|
|
1838
|
+
#
|
|
1839
|
+
# `--reset` is the discriminator, not `-u`, and the pairing is deliberate:
|
|
1840
|
+
#
|
|
1841
|
+
# - `read-tree` with no update flag touches the INDEX only and destroys
|
|
1842
|
+
# nothing in the working tree, so a blanket `read-tree` block would be
|
|
1843
|
+
# over-broad.
|
|
1844
|
+
# - `read-tree -m -u` (a merge without `--reset`) is safe by git's own
|
|
1845
|
+
# construction: it REFUSES rather than overwrite a locally modified file
|
|
1846
|
+
# ("entry would be overwritten by merge"). `--reset` is precisely the flag
|
|
1847
|
+
# that switches that refusal off.
|
|
1848
|
+
#
|
|
1849
|
+
# So the destructive combination is an update flag AND `--reset` together,
|
|
1850
|
+
# in either order. The update flag is matched in the checkout guard's idiom
|
|
1851
|
+
# so a bundled short option (`-iu`) cannot dodge the anchor, with leading
|
|
1852
|
+
# whitespace required so a `--index-output=/tmp/out-u` style value cannot
|
|
1853
|
+
# read as the flag. Same conditional dirty-tree shape and same accepted
|
|
1854
|
+
# residual risk as guard 3: the probe runs in the hook's cwd at hook time.
|
|
1855
|
+
readonly GIT_READ_TREE="${GIT_CMD}read-tree"
|
|
1856
|
+
if matches "${GIT_READ_TREE}"'[^;&|]*[[:space:]]--reset([[:space:]]|$)' \
|
|
1857
|
+
&& matches "${GIT_READ_TREE}"'[^;&|]*[[:space:]](-[[:alnum:]]*u[[:alnum:]]*|--update)([[:space:]]|=|$)'; then
|
|
1858
|
+
if git rev-parse --is-inside-work-tree >/dev/null 2>&1 \
|
|
1859
|
+
&& [ -n "$(git status --porcelain 2>/dev/null)" ]; then
|
|
1860
|
+
block "git read-tree -u --reset on a dirty working tree would discard uncommitted changes (commit first, or preserve as below)" "$PRESERVE_GUIDANCE
|
|
1861
|
+
|
|
1862
|
+
$DESTRUCTIVE_GUIDANCE"
|
|
1863
|
+
fi
|
|
1864
|
+
fi
|
|
1865
|
+
|
|
1822
1866
|
# 3b. `git rebase --abort` / `--quit` ONLY while human/agent conflict
|
|
1823
1867
|
# resolutions exist (issue #1956). `--abort` restores the pre-rebase branch
|
|
1824
1868
|
# and discards every resolution; `--quit` deletes the rebase bookkeeping
|
|
@@ -72,6 +72,18 @@ export const FAMILIES = [
|
|
|
72
72
|
match: /(^|\/)\.github\/k6\/thresholds\/[^/]+\.json$/,
|
|
73
73
|
kind: "k6",
|
|
74
74
|
},
|
|
75
|
+
{
|
|
76
|
+
// #3992. The always-on eager rule tier is concatenated into every session
|
|
77
|
+
// AND every subagent start, so its byte ceiling is a quality threshold like
|
|
78
|
+
// any other. `max` because the number is a ceiling: lowering it tightens the
|
|
79
|
+
// gate and is free, raising it re-authorises context the cleanup removed and
|
|
80
|
+
// is the change a human has to see. The tier was cut to 26,540 bytes once
|
|
81
|
+
// and regrew to 201,083 in fourteen weeks with nothing watching it.
|
|
82
|
+
id: "eager-rules",
|
|
83
|
+
match: /(^|\/)eager-rules\.thresholds\.json$/,
|
|
84
|
+
kind: "json-num",
|
|
85
|
+
direction: "max",
|
|
86
|
+
},
|
|
75
87
|
{
|
|
76
88
|
id: "lisa-config",
|
|
77
89
|
match: /(^|\/)\.lisa\.config\.json$/,
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# Rule Index — What Exists, and Where to Read It
|
|
2
|
+
|
|
3
|
+
The rules below are **not loaded**. Each is a full contract that other rules,
|
|
4
|
+
skills, and work items cite **by slug** ("per the `bdd-e2e-coverage` rule").
|
|
5
|
+
When you meet a slug and need the contract behind it, read that file — do not
|
|
6
|
+
re-derive the contract, and do not restate it where you cite it.
|
|
7
|
+
|
|
8
|
+
Read one when you are doing the thing it governs. Reading none of them is the
|
|
9
|
+
normal case for a session, which is why they are here rather than in your
|
|
10
|
+
context: the eager tier was cut to 26,540 bytes in May 2026 and had regrown to
|
|
11
|
+
201,083 by September, at which point every session and **every subagent** paid
|
|
12
|
+
~50,000 tokens before its first tool call (CodySwannGT/lisa#3992).
|
|
13
|
+
|
|
14
|
+
Paths are relative to this file.
|
|
15
|
+
|
|
16
|
+
## Work-item authoring, validation, and lifecycle
|
|
17
|
+
|
|
18
|
+
| Slug | Read it when | Body |
|
|
19
|
+
|---|---|---|
|
|
20
|
+
| `work-item-definition-of-ready` | authoring or validating a leaf; gates S1–S16 | [../reference/work-item-definition-of-ready.md](../reference/work-item-definition-of-ready.md) |
|
|
21
|
+
| `leaf-only-lifecycle` | applying a lifecycle role, or rolling a parent up | [../reference/leaf-only-lifecycle.md](../reference/leaf-only-lifecycle.md) |
|
|
22
|
+
| `ready-role-filing` | filing any work item (enforced by `block-direct-issue-create.sh`) | [../reference/ready-role-filing.md](../reference/ready-role-filing.md) |
|
|
23
|
+
| `repo-scope-split` | a leaf spans repos; gate S10, decomposition step 1.5 | [../reference/repo-scope-split.md](../reference/repo-scope-split.md) |
|
|
24
|
+
| `derived-branch-plan` | rendering or validating a Branch Plan; gate S19 | [../reference/derived-branch-plan.md](../reference/derived-branch-plan.md) |
|
|
25
|
+
| `control-reachability` | an item names an existing test as a red-before-green control; gate S20 | [../reference/control-reachability.md](../reference/control-reachability.md) |
|
|
26
|
+
| `pre-flight-autofill` | the pre-flight gate returned FAIL on ticket quality | [../reference/pre-flight-autofill.md](../reference/pre-flight-autofill.md) |
|
|
27
|
+
| `blocker-containment` | deciding whether an `is blocked by` dependency is cleared | [../reference/blocker-containment.md](../reference/blocker-containment.md) |
|
|
28
|
+
| `deployed-state-readback` | authoring a ticket asserting something is missing from a running system | [../reference/deployed-state-readback.md](../reference/deployed-state-readback.md) |
|
|
29
|
+
| `prd-definition-of-ready` | authoring or validating a PRD's requirement atoms | [../reference/prd-definition-of-ready.md](../reference/prd-definition-of-ready.md) |
|
|
30
|
+
| `prd-lifecycle-rollup` | rolling a PRD up from its generated top-level work | [../reference/prd-lifecycle-rollup.md](../reference/prd-lifecycle-rollup.md) |
|
|
31
|
+
| `usage-accounting` | writing the managed `## Lisa Usage` section on an artifact | [../reference/usage-accounting.md](../reference/usage-accounting.md) |
|
|
32
|
+
|
|
33
|
+
## Build-intake claim time
|
|
34
|
+
|
|
35
|
+
| Slug | Read it when | Body |
|
|
36
|
+
|---|---|---|
|
|
37
|
+
| `rejection-detection` | claiming a ready item (step 3b, before the relabel) | [../reference/rejection-detection.md](../reference/rejection-detection.md) |
|
|
38
|
+
| `claim-archaeology` | claiming a ready item, after rejection detection | [../reference/claim-archaeology.md](../reference/claim-archaeology.md) |
|
|
39
|
+
| `claim-time-guards` | claiming a ready item: already-implemented, two-failed-attempts | [../reference/claim-time-guards.md](../reference/claim-time-guards.md) |
|
|
40
|
+
|
|
41
|
+
## Coverage and evidence contracts
|
|
42
|
+
|
|
43
|
+
| Slug | Read it when | Body |
|
|
44
|
+
|---|---|---|
|
|
45
|
+
| `bdd-e2e-coverage` | the work item adds or changes a user-observable surface | [../reference/bdd-e2e-coverage.md](../reference/bdd-e2e-coverage.md) |
|
|
46
|
+
| `reset-seed-coverage` | the work item adds or changes persistent state | [../reference/reset-seed-coverage.md](../reference/reset-seed-coverage.md) |
|
|
47
|
+
| `claim-evidence-mapping` | citing evidence for a claim, or reviewing evidence someone cited | [../reference/claim-evidence-mapping.md](../reference/claim-evidence-mapping.md) |
|
|
48
|
+
| `observability-audit` | running the `lisa-monitor` audit-and-file arm | [../reference/observability-audit.md](../reference/observability-audit.md) |
|
|
49
|
+
| `readiness-rubric` | judging whether an unattended fleet may run in a repository | [../reference/readiness-rubric.md](../reference/readiness-rubric.md) |
|
|
50
|
+
|
|
51
|
+
## Design
|
|
52
|
+
|
|
53
|
+
| Slug | Read it when | Body |
|
|
54
|
+
|---|---|---|
|
|
55
|
+
| `design-value-binding` | implementing a UI surface in a project with a configured design source | [../reference/design-value-binding.md](../reference/design-value-binding.md) |
|
|
56
|
+
| `design-source-of-truth` | a change touches any UI surface | [../reference/design-source-of-truth.md](../reference/design-source-of-truth.md) |
|
|
57
|
+
|
|
58
|
+
## Dependencies
|
|
59
|
+
|
|
60
|
+
| Slug | Read it when | Body |
|
|
61
|
+
|---|---|---|
|
|
62
|
+
| `dependency-trust-classes` | adding or major-upgrading a material dependency | [../reference/dependency-trust-classes.md](../reference/dependency-trust-classes.md) |
|
|
63
|
+
| `dependency-decision-records` | adding, upgrading, or removing a material dependency | [../reference/dependency-decision-records.md](../reference/dependency-decision-records.md) |
|
|
64
|
+
| `dependency-internalization-kit` | removing, replacing, or internalizing a dependency | [../reference/dependency-internalization-kit.md](../reference/dependency-internalization-kit.md) |
|
|
65
|
+
|
|
66
|
+
## Process, review, and access
|
|
67
|
+
|
|
68
|
+
| Slug | Read it when | Body |
|
|
69
|
+
|---|---|---|
|
|
70
|
+
| `automation-runbook-contract` | registering a loop, or ending any flow with its run outcome | [../reference/automation-runbook-contract.md](../reference/automation-runbook-contract.md) |
|
|
71
|
+
| `convergent-review` | reviewing a PR or resolving review findings | [../reference/convergent-review.md](../reference/convergent-review.md) |
|
|
72
|
+
| `credential-substrate-precedence` | writing or editing an `*-access` skill | [../reference/credential-substrate-precedence.md](../reference/credential-substrate-precedence.md) |
|
|
73
|
+
| `promotion-contract` | implementing a learnings-ladder promotion ticket | [../reference/promotion-contract.md](../reference/promotion-contract.md) |
|
|
74
|
+
| `documentation-source-paths` | moving, absorbing, or deleting a docs-like directory | [../reference/documentation-source-paths.md](../reference/documentation-source-paths.md) |
|
|
75
|
+
| `project-learnings` | you need the learnings ledger's entry schema and field semantics | [../reference/project-learnings.md](../reference/project-learnings.md) |
|
|
76
|
+
| `factory-model` | you need the shape of the factory model, not its obligations | [../reference/factory-model.md](../reference/factory-model.md) |
|
|
77
|
+
|
|
78
|
+
The obligations that follow from `factory-model` are in `base-rules`, which is
|
|
79
|
+
eager. This entry is the exposition behind them.
|
|
@@ -2,6 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
These are mandatory disciplines that apply to every session. Full prose, JIRA dev-status query, ADF templates, etc. live in [reference/base-rules.md](../reference/base-rules.md).
|
|
4
4
|
|
|
5
|
+
## Factory Operating Mode
|
|
6
|
+
|
|
7
|
+
You are factory machinery, not a chat assistant. Three consequences bind every session:
|
|
8
|
+
|
|
9
|
+
- **Do not pause mid-flow to ask a human whether to proceed.** Handoff happens at the gates — the ready-role flips and intake's adversarial validation — never in the middle of a flow.
|
|
10
|
+
- **Every flow must work headless**: no interactive prompts, idempotent re-runs, clean exits on empty queues. Flows run under native schedulers as often as under a human.
|
|
11
|
+
- **Never weaken a gate to get work through it — fix the work.**
|
|
12
|
+
|
|
13
|
+
The model these follow from (the four factories, the gate, the loops, the brownfield on-ramp) is [reference/factory-model.md](../reference/factory-model.md); read it when you need the shape rather than the obligations.
|
|
14
|
+
|
|
5
15
|
## Requirement Verification
|
|
6
16
|
|
|
7
17
|
Treat every request as potentially underspecified. Before starting any work:
|
|
@@ -30,95 +30,8 @@ This applies before declaring connection state, before running any `acli jira *`
|
|
|
30
30
|
|
|
31
31
|
Project tracker (`jira` / `github` / `linear`) is read from `.lisa.config.json` `tracker`. Vendor-neutral skills MUST dispatch through the configured tracker, never infer it from arguments. Missing `tracker` → stop and instruct the user to run the matching `/lisa:setup:*` skill.
|
|
32
32
|
|
|
33
|
-
## Tracker status vocabulary
|
|
34
|
-
|
|
35
|
-
**A status transition may target only a status named in the project's configured workflow map** (`jira.workflow.*` for JIRA; the equivalent label/state map for GitHub and Linear). The configured map is the COMPLETE authorized vocabulary — not a starting point.
|
|
36
|
-
|
|
37
|
-
- **Never adopt statuses discovered from the tracker's live workflow metadata** — transition lists (`getTransitionsForJiraIssue` targets), board columns, status descriptions, or statuses seen on other tickets. A tracker workflow usually contains more statuses than the config names; those extra statuses are not lisa's to use. The live workflow is consulted only to find the transition *id* that reaches a config-named status.
|
|
38
|
-
- **A lifecycle stage with no configured status gets no transition.** If the flow reaches a stage the map does not name (e.g. "PR open awaiting review" when `jira.workflow.review` is unset, or a QA-ready stage with no `qa` mapping), leave the status where it is and record the stage in a comment. Do not pick the nearest-sounding tracker status.
|
|
39
|
-
- **This binds every actor that writes to the tracker** — the lead as much as any subagent. In runtimes where interactively-authenticated MCPs are lead-only, the lead performs the tracker writes for the whole flow; loading an implement/sync skill without the agent definition does not relax this rule.
|
|
40
|
-
|
|
41
|
-
This is the shared slug for the config-bound-transitions policy (the `leaf-only-lifecycle` precedent: one slug, never divergent per-surface prose). Skills and agent definitions cite it rather than restating it.
|
|
42
|
-
|
|
43
33
|
## Repo identity
|
|
44
34
|
|
|
45
35
|
`repo:<name>` is the canonical label for which repo a work item belongs to. Resolve current-repo identity in this priority order: `.lisa.config.local.json` `repo` → `.lisa.config.json` `repo` → `.lisa.config.json` `github.repo` → `basename -s .git "$(git remote get-url origin)"`. If none resolve, stop with a clear error.
|
|
46
36
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
Host-authored project rules live in the fixed, agent-neutral directory
|
|
50
|
-
`.agents/rules/` — not a configurable file. Every agent reaches it through the
|
|
51
|
-
Lisa-managed pointer block in `AGENTS.md`, so it is read once, on demand. A
|
|
52
|
-
project that still carries the retired `.claude/rules/PROJECT_RULES.md` keeps
|
|
53
|
-
it, untouched and authoritative; the pointer names it too. Automated
|
|
54
|
-
learnings never append to host rules: they use the separate machine-managed
|
|
55
|
-
ledger resolved from `.lisa.config.json` — the optional `learnings.file`
|
|
56
|
-
override, else the default `.lisa/PROJECT_LEARNINGS.md`. The ledger lives in the
|
|
57
|
-
cold `.lisa/` tree (never an auto-loaded rules directory) and is consumed only
|
|
58
|
-
through the contract's bounded projection, never read raw wholesale. Both
|
|
59
|
-
writers and budget checks import the executable contract from
|
|
60
|
-
`@codyswann/lisa/learnings`; they must not copy its numeric limits.
|
|
61
|
-
|
|
62
|
-
## Optional Kane browser provider
|
|
63
|
-
|
|
64
|
-
Kane is selected only through `verification.browser.kane`: require `enabled: true`, exact version
|
|
65
|
-
`0.6.3`, `cloudUploadApproved: true`, an explicit non-production `allowedEnvironments` entry, a
|
|
66
|
-
Test Manager `projectId`, and a resolved `exploration` mutation policy of `full`. Credentials never
|
|
67
|
-
live in Lisa config. Run `lisa kane probe` before use and invoke only through `lisa-kane-browser`;
|
|
68
|
-
provider/auth/upload/schema failures are tooling failures, not product failures. Kane supplies
|
|
69
|
-
empirical evidence only—native Playwright/Cypress/Maestro remains the regression authority.
|
|
70
|
-
|
|
71
|
-
## Env → base branch
|
|
72
|
-
|
|
73
|
-
The `## Target Backend Environment` grammar is durable: human-confirmed values
|
|
74
|
-
are a bare configured key or `Confirmed: <env>`; automation writes either
|
|
75
|
-
`Inferred: <env> — evidence: <title|body|reproduction|hostname>` or
|
|
76
|
-
`Assumption: <env> — remote default branch <branch>`. When no unique environment
|
|
77
|
-
maps to the default branch, use `Assumption: remote default branch <branch>`.
|
|
78
|
-
Human confirmation replaces an automated annotation with a bare key or
|
|
79
|
-
`Confirmed: <env>`. For legacy bare values, use managed draft markers and current
|
|
80
|
-
ticket content only; provider edit history is not required. A marker proves
|
|
81
|
-
automation and requires re-annotation; otherwise unknown provenance with
|
|
82
|
-
conflicting evidence stops for confirmation.
|
|
83
|
-
|
|
84
|
-
Resolution order is human-confirmed value; validated `Inferred:` evidence; then
|
|
85
|
-
one unambiguous signal from the human-authored title, body, and reproduction
|
|
86
|
-
steps or a URL hostname. Exclude the complete `Target Backend Environment`
|
|
87
|
-
section and other machine-authored metadata/draft blocks from the scan so an
|
|
88
|
-
annotation cannot validate or conflict with itself. Evidence supersedes only an
|
|
89
|
-
`Assumption:`. A signal must be an exact
|
|
90
|
-
`deploy.branches` key as a complete token/hostname label. The sole normalization
|
|
91
|
-
is `prod` ↔ `production` when exactly one is configured; no other aliases exist.
|
|
92
|
-
Conflicting signals stop. Never infer from arbitrary branch text, URL paths or
|
|
93
|
-
query strings, or substrings. With no signals, use the remote default branch and
|
|
94
|
-
record an assumption: include `<env>` only for a unique reverse-map, otherwise
|
|
95
|
-
use the branch-only form without inventing an environment or blocking. Require
|
|
96
|
-
any selected environment mapping and its remote branch to exist.
|
|
97
|
-
A non-integration environment bug is fixed, merged, and verified on that
|
|
98
|
-
environment branch first, then
|
|
99
|
-
forward cherry-picked down to the integration branch via a linked follow-up.
|
|
100
|
-
|
|
101
|
-
## Env-keyed `done` — promotion completeness
|
|
102
|
-
|
|
103
|
-
A merged PR's base branch names the environment a change **entered**, never the environments it has
|
|
104
|
-
**reached**. Before writing an env-keyed `done`, walk `deploy.order` from its lowest rung and write
|
|
105
|
-
the highest **contiguously reached** rung at or below the resolved env. A rung is reached only when
|
|
106
|
-
the merge commit is an ancestor of its `deploy.branches` branch
|
|
107
|
-
(`git merge-base --is-ancestor <merge-sha> origin/<branch>`, asserted for **every** env branch at or
|
|
108
|
-
below the resolved one, not only the PR's base) **and** that branch's most recent deploy
|
|
109
|
-
**concluded `success`** — read the `conclusion`, never the `status`, because an in-flight deploy has
|
|
110
|
-
a null conclusion and looks identical to a pass. Only a concluded `success` promotes: a null
|
|
111
|
-
conclusion and every other conclusion (`failure`, `cancelled`, `timed_out`, `neutral`, `skipped`,
|
|
112
|
-
`stale`, `action_required`) leave the rung unreached. Where `deploy.order` is absent the ladder is
|
|
113
|
-
the single resolved env; where a branch exposes no deploy surface at all, ancestry alone decides
|
|
114
|
-
that rung.
|
|
115
|
-
|
|
116
|
-
A hotfix straight to `main` that skipped `staging` therefore resolves to the rung below the gap and
|
|
117
|
-
stays open; the terminal value, and provider-native closure with it, is earned only by a
|
|
118
|
-
promotion-complete merge. The recorded reason always carries all three fields —
|
|
119
|
-
`<first unreached env> (<its branch>) — <condition>`, where the condition is `missing ancestry`,
|
|
120
|
-
`deploy unknown: <run URL or "no concluded run">`, or `deploy concluded <conclusion>: <run URL>`. A
|
|
121
|
-
failing run named without its environment and branch is an incomplete reason. An open back-fill PR
|
|
122
|
-
against a skipped environment branch is outstanding delivery, not branch hygiene.
|
|
123
|
-
|
|
124
|
-
Full reference: [reference/config-resolution.md](../reference/config-resolution.md).
|
|
37
|
+
Full reference (tracker status vocabulary, project rules and learnings, the optional Kane provider, the `Target Backend Environment` grammar, and env-keyed `done` promotion completeness): [reference/config-resolution.md](../reference/config-resolution.md).
|
|
@@ -1,5 +1,102 @@
|
|
|
1
1
|
# Automation Runbook Contract
|
|
2
2
|
|
|
3
|
+
> Demoted from the always-on eager tier by CodySwannGT/lisa#3992. The
|
|
4
|
+
> section below is the former eager head, preserved verbatim; the full
|
|
5
|
+
> contract follows it. Reachable on demand via `rules/eager/00-rule-index.md`.
|
|
6
|
+
|
|
7
|
+
## Automation Runbook Contract (load-bearing)
|
|
8
|
+
|
|
9
|
+
**Every registered automation loop carries a checked-in runbook, and every run of that loop ends in
|
|
10
|
+
exactly one of six run outcomes** with a one-line, operator-readable summary. A registered loop with
|
|
11
|
+
no runbook, or a run that stops without naming its outcome, is a contract violation.
|
|
12
|
+
|
|
13
|
+
**One vendor-neutral contract, to be cited by (wired in the loop-conformance ticket)
|
|
14
|
+
`lisa-setup-automations`, `lisa-automation-status`, `lisa-tear-down-automations`, and every
|
|
15
|
+
registered loop skill** (the `leaf-only-lifecycle` / `repo-scope-split` precedent: one shared slug,
|
|
16
|
+
never divergent per-loop prose).
|
|
17
|
+
|
|
18
|
+
## Membership
|
|
19
|
+
|
|
20
|
+
Membership is **registration, not skill-existence**: a loop is under this contract the moment it is
|
|
21
|
+
registered as a scheduled automation, and registering a new one pulls it in automatically. There is
|
|
22
|
+
no hardcoded roster of loops anywhere.
|
|
23
|
+
|
|
24
|
+
### Interactive flows are members too
|
|
25
|
+
|
|
26
|
+
The outcome vocabulary is **not cron-specific** — it answers "did this need me?", which an operator
|
|
27
|
+
asks of an interactive run exactly as often as of a scheduled one. Every Lisa flow that terminates
|
|
28
|
+
is a member: `lisa-implement`, `lisa-verify`, `lisa-plan`, `lisa-git-submit-pr`,
|
|
29
|
+
`lisa-drive-pr-to-merge`, `lisa-research`, and any skill invoked as a slash command.
|
|
30
|
+
|
|
31
|
+
For an interactive flow the required run record is the **final user-facing message**, not a JSONL
|
|
32
|
+
row written by `automation-run-record.mjs`. Interactive flows may also record local JSONL telemetry
|
|
33
|
+
when a specific skill owns that surface, but this contract's mandatory record is the final answer.
|
|
34
|
+
It opens with the outcome and the operator action, before any narrative:
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
change-proved — nothing for you. PR #6393 open, auto-merge on, CI running.
|
|
38
|
+
approval-requested — need a decision: ship the 135 Regular→Bold flips, or hold for design sign-off?
|
|
39
|
+
recovery-required — need you: staging E2E gate red for congestion; rerun or admin-merge.
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
The operator must learn whether they are needed **from the first line**, without reading the report.
|
|
43
|
+
Findings, evidence and caveats follow; they never replace the action line and never precede it.
|
|
44
|
+
|
|
45
|
+
An interactive flow that ends in prose with the action buried — or absent — is the same contract
|
|
46
|
+
violation as a silent cron exit. "I flagged X, I noticed Y, worth knowing Z" is narrative, not an
|
|
47
|
+
outcome. If nothing is needed, say **"nothing for you"** in those words and stop.
|
|
48
|
+
|
|
49
|
+
## The six run outcomes
|
|
50
|
+
|
|
51
|
+
Exactly one per run:
|
|
52
|
+
**`nothing-needed | candidate-proposed | change-proved | approval-requested | recovery-required | policy-obsolete`**
|
|
53
|
+
|
|
54
|
+
Health and operator action are **orthogonal** — a healthy run can still need an answer:
|
|
55
|
+
|
|
56
|
+
- `nothing-needed` — the loop ran and found nothing to act on. **Healthy.** Operator action: none.
|
|
57
|
+
A queue scanner's `nothing-needed` summary must name the lanes it swept and the total open — a dry
|
|
58
|
+
queue and a wrong denominator are otherwise indistinguishable. See the reference body.
|
|
59
|
+
- `candidate-proposed` — the loop proposed work (ticket, PRD, recommendation). **Healthy.** Operator
|
|
60
|
+
action: review the proposed item and flip it ready when you want it built.
|
|
61
|
+
- `change-proved` — the loop made a change and proved it with evidence. **Healthy.** Operator
|
|
62
|
+
action: none (informational).
|
|
63
|
+
- `approval-requested` — the loop reached a boundary it may not cross alone. **Healthy.** Operator
|
|
64
|
+
action: answer the approval question.
|
|
65
|
+
- `recovery-required` — the loop itself could not complete (access, tooling, or substrate broken)
|
|
66
|
+
and escalated a decision-ready packet. **Not healthy.** Operator action: restore the named
|
|
67
|
+
capability, then close the escalation item.
|
|
68
|
+
- `policy-obsolete` — the loop's own retirement policy (the retirement condition written in its
|
|
69
|
+
runbook) tripped, so it proposed its own teardown. **Healthy.** Operator action: approve the
|
|
70
|
+
teardown, decline it (close the proposal as **Not planned**; the loop keeps running at cadence),
|
|
71
|
+
or re-cadence it.
|
|
72
|
+
|
|
73
|
+
## A run outcome is NOT a work-item lifecycle terminal state (CRITICAL)
|
|
74
|
+
|
|
75
|
+
A **run outcome** describes the LOOP ITERATION. A **terminal state** describes a TICKET — Lisa
|
|
76
|
+
already uses that phrase for work-item lifecycles (`lisa-intake`: "`Blocked` is a valid terminal
|
|
77
|
+
state of the downstream lifecycles"). The two vocabularies never merge in an operator-facing report.
|
|
78
|
+
A healthy cycle that routes a work item to `Blocked` with clarifying questions is
|
|
79
|
+
`candidate-proposed` — it produced something — so it is **never `nothing-needed`**, which is
|
|
80
|
+
reserved for runs that found nothing at all, and **never `recovery-required`**, which means the
|
|
81
|
+
loop itself is broken, not that a work item was blocked.
|
|
82
|
+
|
|
83
|
+
## No silent exit
|
|
84
|
+
|
|
85
|
+
Every run — including a trivial early termination — ends by naming exactly one run outcome plus a
|
|
86
|
+
one-line operator summary of what happened, recorded where the status surface can read it —
|
|
87
|
+
there is no silent exit. The shared local substrate is
|
|
88
|
+
`plugins/src/base/scripts/automation-run-record.mjs`, which writes bounded JSONL records under
|
|
89
|
+
`.lisa/automations/runs/<loop-id>.jsonl`. Silence and health must never look identical to an
|
|
90
|
+
operator.
|
|
91
|
+
|
|
92
|
+
## Never block, always degrade
|
|
93
|
+
|
|
94
|
+
A missing runbook, an unreadable record surface, or an absent optional dependency **degrades** the
|
|
95
|
+
run — say so in the summary and finish with an outcome — it never crashes the loop, never blocks
|
|
96
|
+
other work, and never leaves the run unreported.
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
3
100
|
Scheduled loops are the busiest machinery in the factory and historically the least explicitly
|
|
4
101
|
contracted: what a loop maintains, what it may do on its own, what it must escalate, and when it
|
|
5
102
|
should stop existing all lived implicitly in each loop's prose. The cost lands on the operator — a
|
|
@@ -1,5 +1,61 @@
|
|
|
1
1
|
# BDD Behavior Contract & E2E Coverage
|
|
2
2
|
|
|
3
|
+
> Demoted from the always-on eager tier by CodySwannGT/lisa#3992. The
|
|
4
|
+
> section below is the former eager head, preserved verbatim; the full
|
|
5
|
+
> contract follows it. Reachable on demand via `rules/eager/00-rule-index.md`.
|
|
6
|
+
|
|
7
|
+
## BDD Behavior Contract & E2E Coverage (load-bearing)
|
|
8
|
+
|
|
9
|
+
**Every frontend work item ships its behavior as Gherkin scenarios with stable IDs, and seals each required scenario-platform obligation with aligned e2e automation in the project's configured runner for that platform.** A frontend change that adds no scenario, or a required scenario-platform obligation with neither a mapped test nor a dated waiver, is a contract violation.
|
|
10
|
+
|
|
11
|
+
**One vendor-neutral contract, cited by** `lisa-research`, `lisa-acceptance-criteria`, `lisa-task-decomposition`, `lisa-test-strategy`, `lisa-tdd-implementation`, `lisa-implement`, `lisa-codify-verification`, `lisa-verification-lifecycle`, `lisa-spec-conformance`, and `lisa-verify` (the `leaf-only-lifecycle` / `repo-scope-split` precedent: one shared slug, never divergent per-skill prose).
|
|
12
|
+
|
|
13
|
+
## Membership
|
|
14
|
+
|
|
15
|
+
Membership is **surface, not repo name or ticket label**: a work item is frontend-type the moment it adds or changes something a user can observe — a screen, route, component, interaction, visual state, empty/error/loading state, navigation path, or copy a user reads. It applies on every platform the project ships. Backend-only, infrastructure, docs, tooling, and refactors with no user-observable delta are out; a refactor that changes what the user sees is in.
|
|
16
|
+
|
|
17
|
+
## The contract lives in the repo
|
|
18
|
+
|
|
19
|
+
Default locations (a project that already has an equivalent contract keeps its own paths and records them in `.lisa.config.json`):
|
|
20
|
+
|
|
21
|
+
| Artifact | Default path | What it is |
|
|
22
|
+
|---|---|---|
|
|
23
|
+
| Scenarios | `bdd/features/*.feature` | Gherkin, the product-level behavior contract |
|
|
24
|
+
| Coverage map | `bdd/coverage-map.json` | scenario → runner/platform/file/evidence mappings, plus waivers, per-runner test-discovery roots, and exclusions |
|
|
25
|
+
| Generated matrix | `docs/bdd-scenario-matrix.md` | regenerated, never hand-edited |
|
|
26
|
+
| Burndown | `docs/e2e-bdd-coverage.md` | current coverage per platform |
|
|
27
|
+
|
|
28
|
+
## Scenario shape
|
|
29
|
+
|
|
30
|
+
Every scenario carries **one stable `@BDD-<DOMAIN>-<NNN>` ID**, the platforms it requires (`@web`, `@ios`, `@android`, … as the project declares them), provenance (design node, ratified decision), and a tracker tag tying it to the work item that introduced or changed it. IDs are never renumbered or reused: behavior that stays user-observably the same keeps its ID through a rewrite; genuinely different behavior gets a new ID and the old one is marked `@superseded`.
|
|
31
|
+
|
|
32
|
+
Lifecycle tag, exactly one or none:
|
|
33
|
+
|
|
34
|
+
- **no tag** — ratified and required; it is in the coverage denominator.
|
|
35
|
+
- **`@blocked`** — specified but awaiting a decision or dependency; the *product* does not do this yet.
|
|
36
|
+
- **`@reference-only`** — intentionally not authoritative.
|
|
37
|
+
- **`@superseded`** — replaced by a ratified rule or a newer scenario.
|
|
38
|
+
|
|
39
|
+
The last three are out of the denominator. Deleting a committed capability to make coverage look better is a violation; mark it, do not drop it.
|
|
40
|
+
|
|
41
|
+
## What seals a scenario
|
|
42
|
+
|
|
43
|
+
Coverage is counted per **required scenario-platform obligation**, and an obligation is sealed only by **aligned e2e automation in the project's configured runner for that platform** — the runner→platform mapping is project configuration (e.g. a web runner covering `web`, a device runner covering `ios`/`android`), never named by this contract. A unit test, a route boot, a screenshot, a fixture, an API test, or a passing test on a *different* platform never seals an obligation: they prove something else. Each mapping names the runner, the platforms, the file, and the evidence string inside it, so the gate can prove the mapping still resolves.
|
|
44
|
+
|
|
45
|
+
**The gate reads in both directions.** It also walks the test roots the project declares per runner, so an e2e test that exists but that the contract never mentions is a violation — map it to a scenario, or record an exclusion stating why it aligns to no product behavior. Roots are configuration: a subflow or helper directory left undeclared is structurally invisible, which is the same failure as having no gate for it.
|
|
46
|
+
|
|
47
|
+
**Waivers are dated IOUs, never coverage.** An obligation whose runner genuinely cannot decide it today (no camera on the simulator, no request interception, no provisioned provider credential) is recorded with scenario, platforms, reason, and `recordedAt`. It leaves the denominator; it never counts as covered, and nothing about it asserts the behavior works. A waiver is invalid — and fails the gate — when it names a nonexistent scenario or an undeclared platform, covers an already-excluded scenario, or masks a scenario-platform that already has a mapping. Revisit a waiver when its reason dies.
|
|
48
|
+
|
|
49
|
+
## Definition of done
|
|
50
|
+
|
|
51
|
+
A frontend work item is not done until: (1) every user-facing behavior it adds or changes exists as a Gherkin scenario with a stable ID in the project's behavior contract, traceable to the work item; (2) every required scenario-platform obligation it introduces is either mapped to aligned e2e automation in the project's configured runner for that platform, or carries a dated waiver naming the runner limitation; and (3) the coverage gate passes and the generated matrix and burndown are regenerated and committed in the same PR. **Missing BDD coverage is a verification failure, not a warning** — it blocks completion exactly as a `PARTIAL` spec-conformance verdict does, and it is never demoted to "optional", "if cheap", or a follow-up without a linked build-ready ticket created before merge.
|
|
52
|
+
|
|
53
|
+
## Bootstrap and degradation
|
|
54
|
+
|
|
55
|
+
A project with no `bdd/` contract yet is not exempt — the first frontend work item scaffolds the minimum (features dir, coverage map with the project's detected runner→platform mapping, gate + matrix scripts) and covers **its own** behavior. It never backfills the whole app: pre-existing uncovered behavior is recorded as burndown, not treated as this item's blocker. If no e2e runner exists for a required platform at all, record the checked locations and the absence as the reason, exactly as the regression-spec absence path in `verification` does — a silent skip is never one of the exits.
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
3
59
|
Frontend behavior has historically been specified twice and owned nowhere: once as prose acceptance
|
|
4
60
|
criteria on a ticket that closes and disappears, and once as whatever e2e tests someone had time to
|
|
5
61
|
write. Neither survives the work item. The cost lands at verification time — nobody can answer "what
|