@codyswann/lisa 4.54.13 → 4.55.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-contents/.gitattributes +8 -0
- package/all/copy-overwrite/scripts/check-orphaned-branches.mjs +78 -9
- package/all/copy-overwrite/scripts/check-third-party-action-pins.mjs +17 -1
- package/all/copy-overwrite/scripts/lib/process-tree-runner.mjs +194 -7
- package/all/copy-overwrite/scripts/lisa-enforcement-fallback.sh +31 -0
- package/all/copy-overwrite/scripts/lisa-hooks/block-blind-automerge.sh +81 -2
- package/all/copy-overwrite/scripts/lisa-hooks/block-direct-issue-create.sh +293 -8
- package/all/copy-overwrite/scripts/lisa-hooks/block-instruction-file-edits.sh +21 -0
- package/all/copy-overwrite/scripts/lisa-hooks/block-managed-file-edits.sh +78 -15
- package/all/copy-overwrite/scripts/lisa-hooks/block-no-verify.sh +21 -0
- package/all/copy-overwrite/scripts/lisa-hooks/block-shell-json-parsing.sh +21 -0
- package/all/copy-overwrite/scripts/lisa-hooks/guard-dedupe.bash +340 -0
- package/all/copy-overwrite/scripts/lisa-hooks/parity-safety-net.sh +29 -1
- package/all/copy-overwrite/scripts/lisa-hooks/worktree-binding-guard.mjs +183 -1
- package/all/copy-overwrite/scripts/lisa-hooks/worktree-binding-guard.sh +21 -0
- package/all/copy-overwrite/scripts/lisa-postinstall.mjs +21 -1
- package/all/copy-overwrite/scripts/lisa-run-gates.mjs +100 -5
- package/all/copy-overwrite/scripts/lisa-work-item.mjs +1085 -80
- package/all/create-only/.github/workflows/continuous-gates.yml +7 -0
- package/cdk/create-only/.github/workflows/ci.yml +7 -0
- package/cdk/create-only/.github/workflows/deploy.yml +21 -0
- package/dist/cli/apply.d.ts.map +1 -1
- package/dist/cli/apply.js +9 -1
- package/dist/cli/apply.js.map +1 -1
- package/dist/cli/doctor-apply-deletions.d.ts +61 -0
- package/dist/cli/doctor-apply-deletions.d.ts.map +1 -0
- package/dist/cli/doctor-apply-deletions.js +137 -0
- package/dist/cli/doctor-apply-deletions.js.map +1 -0
- package/dist/cli/doctor-cdk-preset-adoption.d.ts +15 -0
- package/dist/cli/doctor-cdk-preset-adoption.d.ts.map +1 -0
- package/dist/cli/doctor-cdk-preset-adoption.js +316 -0
- package/dist/cli/doctor-cdk-preset-adoption.js.map +1 -0
- package/dist/cli/doctor-config-shadowing.d.ts +22 -0
- package/dist/cli/doctor-config-shadowing.d.ts.map +1 -0
- package/dist/cli/doctor-config-shadowing.js +123 -0
- package/dist/cli/doctor-config-shadowing.js.map +1 -0
- package/dist/cli/doctor-rails-deploy-intent.d.ts +15 -0
- package/dist/cli/doctor-rails-deploy-intent.d.ts.map +1 -0
- package/dist/cli/doctor-rails-deploy-intent.js +197 -0
- package/dist/cli/doctor-rails-deploy-intent.js.map +1 -0
- package/dist/cli/doctor-seeded-artifacts.d.ts +12 -0
- package/dist/cli/doctor-seeded-artifacts.d.ts.map +1 -0
- package/dist/cli/doctor-seeded-artifacts.js +54 -0
- package/dist/cli/doctor-seeded-artifacts.js.map +1 -0
- package/dist/cli/doctor-stale-banner-scan.d.ts +44 -0
- package/dist/cli/doctor-stale-banner-scan.d.ts.map +1 -0
- package/dist/cli/doctor-stale-banner-scan.js +152 -0
- package/dist/cli/doctor-stale-banner-scan.js.map +1 -0
- package/dist/cli/doctor-stale-managed-banner.d.ts +19 -0
- package/dist/cli/doctor-stale-managed-banner.d.ts.map +1 -0
- package/dist/cli/doctor-stale-managed-banner.js +198 -0
- package/dist/cli/doctor-stale-managed-banner.js.map +1 -0
- package/dist/cli/doctor.d.ts.map +1 -1
- package/dist/cli/doctor.js +16 -0
- package/dist/cli/doctor.js.map +1 -1
- package/dist/cli/ui-detected-stacks.d.ts.map +1 -1
- package/dist/cli/ui-detected-stacks.js +3 -2
- package/dist/cli/ui-detected-stacks.js.map +1 -1
- package/dist/cli/update-check.d.ts.map +1 -1
- package/dist/cli/update-check.js +14 -0
- package/dist/cli/update-check.js.map +1 -1
- package/dist/cli/worktree-liveness.d.ts +5 -0
- package/dist/cli/worktree-liveness.d.ts.map +1 -1
- package/dist/cli/worktree-liveness.js +7 -6
- package/dist/cli/worktree-liveness.js.map +1 -1
- package/dist/cli/worktree-ownership.d.ts +13 -0
- package/dist/cli/worktree-ownership.d.ts.map +1 -1
- package/dist/cli/worktree-ownership.js +14 -0
- package/dist/cli/worktree-ownership.js.map +1 -1
- package/dist/configs/eslint/base.d.ts +34 -0
- package/dist/configs/eslint/base.d.ts.map +1 -1
- package/dist/configs/eslint/base.js +34 -0
- package/dist/configs/eslint/base.js.map +1 -1
- package/dist/core/apply-receipt.d.ts +65 -0
- package/dist/core/apply-receipt.d.ts.map +1 -1
- package/dist/core/apply-receipt.js +62 -2
- package/dist/core/apply-receipt.js.map +1 -1
- package/dist/core/cdk-preset-adoption.d.ts +136 -0
- package/dist/core/cdk-preset-adoption.d.ts.map +1 -0
- package/dist/core/cdk-preset-adoption.js +135 -0
- package/dist/core/cdk-preset-adoption.js.map +1 -0
- package/dist/core/config-shadowing.d.ts +36 -0
- package/dist/core/config-shadowing.d.ts.map +1 -1
- package/dist/core/config-shadowing.js +38 -0
- package/dist/core/config-shadowing.js.map +1 -1
- package/dist/core/config.d.ts +11 -0
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js.map +1 -1
- package/dist/core/learnings-merge-driver.d.ts +10 -0
- package/dist/core/learnings-merge-driver.d.ts.map +1 -1
- package/dist/core/learnings-merge-driver.js +18 -0
- package/dist/core/learnings-merge-driver.js.map +1 -1
- package/dist/core/lisa-owned-hash-ledger.d.ts.map +1 -1
- package/dist/core/lisa-owned-hash-ledger.js +136 -0
- package/dist/core/lisa-owned-hash-ledger.js.map +1 -1
- package/dist/core/lisa.d.ts.map +1 -1
- package/dist/core/lisa.js +9 -1
- package/dist/core/lisa.js.map +1 -1
- package/dist/core/nightly-e2e-guard-behavior-certificate.d.ts +5 -5
- package/dist/core/nightly-e2e-guard-behavior-certificate.js +7 -7
- package/dist/core/nightly-e2e-guard-behavior-certificate.js.map +1 -1
- package/dist/core/ownership-header.d.ts +74 -0
- package/dist/core/ownership-header.d.ts.map +1 -0
- package/dist/core/ownership-header.js +76 -0
- package/dist/core/ownership-header.js.map +1 -0
- package/dist/core/rails-deploy-production-intent.d.ts +36 -0
- package/dist/core/rails-deploy-production-intent.d.ts.map +1 -0
- package/dist/core/rails-deploy-production-intent.js +79 -0
- package/dist/core/rails-deploy-production-intent.js.map +1 -0
- package/dist/core/stale-managed-banner.d.ts +78 -0
- package/dist/core/stale-managed-banner.d.ts.map +1 -0
- package/dist/core/stale-managed-banner.js +118 -0
- package/dist/core/stale-managed-banner.js.map +1 -0
- package/dist/core/two-channel-delivery-scan.d.ts +33 -1
- package/dist/core/two-channel-delivery-scan.d.ts.map +1 -1
- package/dist/core/two-channel-delivery-scan.js +133 -6
- package/dist/core/two-channel-delivery-scan.js.map +1 -1
- package/dist/core/two-channel-delivery.d.ts +101 -4
- package/dist/core/two-channel-delivery.d.ts.map +1 -1
- package/dist/core/two-channel-delivery.js +121 -13
- package/dist/core/two-channel-delivery.js.map +1 -1
- package/dist/core/two-channel-staleness.d.ts +137 -0
- package/dist/core/two-channel-staleness.d.ts.map +1 -0
- package/dist/core/two-channel-staleness.js +268 -0
- package/dist/core/two-channel-staleness.js.map +1 -0
- package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
- package/dist/core/upstream-evidence-manifest.js +265 -121
- package/dist/core/upstream-evidence-manifest.js.map +1 -1
- package/dist/core/workflow-deletion-ownership.d.ts +6 -24
- package/dist/core/workflow-deletion-ownership.d.ts.map +1 -1
- package/dist/core/workflow-deletion-ownership.js +22 -42
- package/dist/core/workflow-deletion-ownership.js.map +1 -1
- package/dist/detection/detectors/cdk.d.ts.map +1 -1
- package/dist/detection/detectors/cdk.js +2 -1
- package/dist/detection/detectors/cdk.js.map +1 -1
- package/dist/health/template-inspection.d.ts.map +1 -1
- package/dist/health/template-inspection.js +2 -1
- package/dist/health/template-inspection.js.map +1 -1
- package/dist/migrations/ensure-lisa-postinstall.d.ts +16 -0
- package/dist/migrations/ensure-lisa-postinstall.d.ts.map +1 -1
- package/dist/migrations/ensure-lisa-postinstall.js +16 -0
- package/dist/migrations/ensure-lisa-postinstall.js.map +1 -1
- package/dist/migrations/ensure-pinned-reusable-workflow-refs.d.ts +2 -2
- package/dist/migrations/ensure-pinned-reusable-workflow-refs.d.ts.map +1 -1
- package/dist/migrations/ensure-pinned-reusable-workflow-refs.js +98 -34
- package/dist/migrations/ensure-pinned-reusable-workflow-refs.js.map +1 -1
- package/dist/migrations/ensure-playwright-dedicated-caller.d.ts.map +1 -1
- package/dist/migrations/ensure-playwright-dedicated-caller.js +1 -0
- package/dist/migrations/ensure-playwright-dedicated-caller.js.map +1 -1
- package/dist/opencode/hooks-installer.d.ts.map +1 -1
- package/dist/opencode/hooks-installer.js +1 -0
- package/dist/opencode/hooks-installer.js.map +1 -1
- package/dist/opencode/plugin-templates/block-managed-file-edits.sh +78 -15
- package/dist/opencode/plugin-templates/block-no-verify.sh +21 -0
- package/dist/opencode/plugin-templates/guard-dedupe.bash +337 -0
- package/dist/opencode/plugin-templates/lisa-block-direct-issue-create.ts +242 -55
- package/dist/opencode/plugin-templates/parity-safety-net.sh +29 -1
- package/dist/strategies/package-lisa.d.ts.map +1 -1
- package/dist/strategies/package-lisa.js +2 -1
- package/dist/strategies/package-lisa.js.map +1 -1
- package/dist/utils/path-utils.d.ts +29 -0
- package/dist/utils/path-utils.d.ts.map +1 -1
- package/dist/utils/path-utils.js +41 -0
- package/dist/utils/path-utils.js.map +1 -1
- package/expo/create-only/.github/workflows/ci.yml +21 -0
- package/expo/create-only/.github/workflows/deploy.yml +28 -0
- package/expo/create-only/.github/workflows/maestro-e2e.yml +7 -0
- package/expo/create-only/.github/workflows/nightly-e2e-bypass-reaper.yml +124 -13
- package/expo/create-only/.github/workflows/nightly-e2e-health.yml +7 -0
- package/expo/create-only/.github/workflows/nightly-e2e-report.yml +7 -0
- package/expo/create-only/.github/workflows/nightly-e2e-tracking.yml +8 -0
- package/expo/create-only/.github/workflows/playwright-e2e.yml +7 -0
- package/harper-fabric/copy-overwrite/.github/workflows/ci.yml +7 -0
- package/harper-fabric/create-only/.github/workflows/deploy.yml +14 -0
- package/nestjs/create-only/.github/workflows/ci.yml +14 -0
- package/nestjs/create-only/.github/workflows/deploy.yml +28 -0
- package/package.json +10 -5
- package/phaser/copy-overwrite/.github/workflows/ci.yml +7 -0
- package/plugins/lisa/.claude-plugin/plugin.json +28 -1
- package/plugins/lisa/.codex-plugin/hooks.json +27 -0
- package/plugins/lisa/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa/.codex-plugin/skills/lisa-drive-pr-to-merge/SKILL.md +130 -19
- package/plugins/lisa/.codex-plugin/skills/lisa-github-build-intake/SKILL.md +27 -4
- package/plugins/lisa/.codex-plugin/skills/lisa-github-prd-intake/SKILL.md +1 -1
- package/plugins/lisa/.codex-plugin/skills/lisa-github-validate-issue/SKILL.md +22 -0
- package/plugins/lisa/.codex-plugin/skills/lisa-github-verify/SKILL.md +14 -0
- package/plugins/lisa/.codex-plugin/skills/lisa-github-write-issue/SKILL.md +51 -0
- package/plugins/lisa/.codex-plugin/skills/lisa-intake/SKILL.md +1 -1
- package/plugins/lisa/.codex-plugin/skills/lisa-jira-build-intake/SKILL.md +27 -4
- package/plugins/lisa/.codex-plugin/skills/lisa-jira-validate-ticket/SKILL.md +22 -0
- package/plugins/lisa/.codex-plugin/skills/lisa-jira-verify/SKILL.md +14 -0
- package/plugins/lisa/.codex-plugin/skills/lisa-jira-write-ticket/SKILL.md +51 -0
- package/plugins/lisa/.codex-plugin/skills/lisa-linear-access/SKILL.md +55 -2
- package/plugins/lisa/.codex-plugin/skills/lisa-linear-build-intake/SKILL.md +27 -4
- package/plugins/lisa/.codex-plugin/skills/lisa-linear-prd-intake/SKILL.md +47 -30
- package/plugins/lisa/.codex-plugin/skills/lisa-linear-to-tracker/SKILL.md +3 -3
- package/plugins/lisa/.codex-plugin/skills/lisa-linear-validate-issue/SKILL.md +22 -0
- package/plugins/lisa/.codex-plugin/skills/lisa-linear-verify/SKILL.md +14 -0
- package/plugins/lisa/.codex-plugin/skills/lisa-linear-write-issue/SKILL.md +54 -3
- package/plugins/lisa/.codex-plugin/skills/lisa-prd-ticket-coverage/SKILL.md +2 -2
- package/plugins/lisa/.codex-plugin/skills/lisa-qa-clear/SKILL.md +19 -7
- package/plugins/lisa/.codex-plugin/skills/lisa-qa-fail/SKILL.md +28 -3
- package/plugins/lisa/.codex-plugin/skills/lisa-qa-queue/SKILL.md +28 -3
- package/plugins/lisa/.codex-plugin/skills/lisa-repair-intake/SKILL.md +94 -24
- package/plugins/lisa/.codex-plugin/skills/lisa-rework-triage/SKILL.md +32 -2
- package/plugins/lisa/.codex-plugin/skills/lisa-setup-linear/SKILL.md +4 -4
- package/plugins/lisa/.codex-plugin/skills/lisa-track/SKILL.md +1 -1
- package/plugins/lisa/.codex-plugin/skills/lisa-tracker-build-intake/SKILL.md +9 -0
- package/plugins/lisa/agents/linear-prd-intake.md +8 -8
- package/plugins/lisa/hooks/block-blind-automerge.sh +81 -2
- package/plugins/lisa/hooks/block-direct-issue-create.agy.sh +64 -16
- package/plugins/lisa/hooks/block-direct-issue-create.sh +293 -8
- package/plugins/lisa/hooks/block-instruction-file-edits.sh +21 -0
- package/plugins/lisa/hooks/block-managed-file-edits.sh +78 -15
- package/plugins/lisa/hooks/block-no-verify.sh +21 -0
- package/plugins/lisa/hooks/block-shell-json-parsing.sh +21 -0
- package/plugins/lisa/hooks/failure-signature-index.mjs +240 -5
- package/plugins/lisa/hooks/guard-dedupe.bash +337 -0
- package/plugins/lisa/hooks/inject-rules.sh +13 -5
- package/plugins/lisa/hooks/operational-hazards.mjs +736 -0
- package/plugins/lisa/hooks/operational-hazards.sh +28 -0
- package/plugins/lisa/hooks/parity-safety-net.sh +29 -1
- package/plugins/lisa/hooks/threshold-ratchet-compare.mjs +102 -21
- package/plugins/lisa/hooks/threshold-ratchet-families.mjs +130 -2
- package/plugins/lisa/hooks/threshold-ratchet.mjs +63 -13
- package/plugins/lisa/hooks/worktree-binding-guard.mjs +183 -1
- package/plugins/lisa/hooks/worktree-binding-guard.sh +21 -0
- package/plugins/lisa/rules/eager/00-rule-index.md +1 -0
- package/plugins/lisa/rules/eager/operational-hazards.md +50 -0
- package/plugins/lisa/rules/eager/tracked-work.md +1 -1
- package/plugins/lisa/rules/reference/config-resolution.md +1 -1
- package/plugins/lisa/rules/reference/leaf-only-lifecycle.md +1 -1
- package/plugins/lisa/rules/reference/operational-hazards.md +115 -0
- package/plugins/lisa/rules/reference/work-item-trailer-definition.md +129 -0
- package/plugins/lisa/scripts/intake-blocker-reprobe.mjs +407 -26
- package/plugins/lisa/scripts/qa-signal-lifecycle.mjs +507 -0
- package/plugins/lisa/skills/lisa-drive-pr-to-merge/SKILL.md +130 -19
- package/plugins/lisa/skills/lisa-github-build-intake/SKILL.md +27 -4
- package/plugins/lisa/skills/lisa-github-prd-intake/SKILL.md +1 -1
- package/plugins/lisa/skills/lisa-github-validate-issue/SKILL.md +22 -0
- package/plugins/lisa/skills/lisa-github-verify/SKILL.md +14 -0
- package/plugins/lisa/skills/lisa-github-write-issue/SKILL.md +51 -0
- package/plugins/lisa/skills/lisa-intake/SKILL.md +1 -1
- package/plugins/lisa/skills/lisa-jira-build-intake/SKILL.md +27 -4
- package/plugins/lisa/skills/lisa-jira-validate-ticket/SKILL.md +22 -0
- package/plugins/lisa/skills/lisa-jira-verify/SKILL.md +14 -0
- package/plugins/lisa/skills/lisa-jira-write-ticket/SKILL.md +51 -0
- package/plugins/lisa/skills/lisa-linear-access/SKILL.md +55 -2
- package/plugins/lisa/skills/lisa-linear-build-intake/SKILL.md +27 -4
- package/plugins/lisa/skills/lisa-linear-prd-intake/SKILL.md +48 -31
- package/plugins/lisa/skills/lisa-linear-to-tracker/SKILL.md +3 -3
- package/plugins/lisa/skills/lisa-linear-validate-issue/SKILL.md +22 -0
- package/plugins/lisa/skills/lisa-linear-verify/SKILL.md +14 -0
- package/plugins/lisa/skills/lisa-linear-write-issue/SKILL.md +54 -3
- package/plugins/lisa/skills/lisa-prd-ticket-coverage/SKILL.md +2 -2
- package/plugins/lisa/skills/lisa-qa-clear/SKILL.md +19 -7
- package/plugins/lisa/skills/lisa-qa-fail/SKILL.md +28 -3
- package/plugins/lisa/skills/lisa-qa-queue/SKILL.md +28 -3
- package/plugins/lisa/skills/lisa-repair-intake/SKILL.md +94 -24
- package/plugins/lisa/skills/lisa-rework-triage/SKILL.md +32 -2
- package/plugins/lisa/skills/lisa-setup-linear/SKILL.md +5 -5
- package/plugins/lisa/skills/lisa-track/SKILL.md +1 -1
- package/plugins/lisa/skills/lisa-tracker-build-intake/SKILL.md +9 -0
- package/plugins/lisa-agy/agents/linear-prd-intake.md +8 -8
- package/plugins/lisa-agy/hooks/block-blind-automerge.sh +81 -2
- package/plugins/lisa-agy/hooks/block-direct-issue-create.agy.sh +64 -16
- package/plugins/lisa-agy/hooks/block-direct-issue-create.sh +293 -8
- package/plugins/lisa-agy/hooks/block-instruction-file-edits.sh +21 -0
- package/plugins/lisa-agy/hooks/block-managed-file-edits.sh +78 -15
- package/plugins/lisa-agy/hooks/block-shell-json-parsing.sh +21 -0
- package/plugins/lisa-agy/hooks/guard-dedupe.bash +337 -0
- package/plugins/lisa-agy/hooks/parity-safety-net.sh +29 -1
- package/plugins/lisa-agy/hooks.json +1 -1
- package/plugins/lisa-agy/plugin.json +1 -1
- package/plugins/lisa-agy/scripts/intake-blocker-reprobe.mjs +407 -26
- package/plugins/lisa-agy/scripts/qa-signal-lifecycle.mjs +507 -0
- package/plugins/lisa-agy/skills/lisa-drive-pr-to-merge/SKILL.md +130 -19
- package/plugins/lisa-agy/skills/lisa-github-build-intake/SKILL.md +27 -4
- package/plugins/lisa-agy/skills/lisa-github-prd-intake/SKILL.md +1 -1
- package/plugins/lisa-agy/skills/lisa-github-validate-issue/SKILL.md +22 -0
- package/plugins/lisa-agy/skills/lisa-github-verify/SKILL.md +14 -0
- package/plugins/lisa-agy/skills/lisa-github-write-issue/SKILL.md +51 -0
- package/plugins/lisa-agy/skills/lisa-intake/SKILL.md +1 -1
- package/plugins/lisa-agy/skills/lisa-jira-build-intake/SKILL.md +27 -4
- package/plugins/lisa-agy/skills/lisa-jira-validate-ticket/SKILL.md +22 -0
- package/plugins/lisa-agy/skills/lisa-jira-verify/SKILL.md +14 -0
- package/plugins/lisa-agy/skills/lisa-jira-write-ticket/SKILL.md +51 -0
- package/plugins/lisa-agy/skills/lisa-linear-access/SKILL.md +55 -2
- package/plugins/lisa-agy/skills/lisa-linear-build-intake/SKILL.md +27 -4
- package/plugins/lisa-agy/skills/lisa-linear-prd-intake/SKILL.md +48 -31
- package/plugins/lisa-agy/skills/lisa-linear-to-tracker/SKILL.md +3 -3
- package/plugins/lisa-agy/skills/lisa-linear-validate-issue/SKILL.md +22 -0
- package/plugins/lisa-agy/skills/lisa-linear-verify/SKILL.md +14 -0
- package/plugins/lisa-agy/skills/lisa-linear-write-issue/SKILL.md +54 -3
- package/plugins/lisa-agy/skills/lisa-prd-ticket-coverage/SKILL.md +2 -2
- package/plugins/lisa-agy/skills/lisa-qa-clear/SKILL.md +19 -7
- package/plugins/lisa-agy/skills/lisa-qa-fail/SKILL.md +28 -3
- package/plugins/lisa-agy/skills/lisa-qa-queue/SKILL.md +28 -3
- package/plugins/lisa-agy/skills/lisa-repair-intake/SKILL.md +94 -24
- package/plugins/lisa-agy/skills/lisa-rework-triage/SKILL.md +32 -2
- package/plugins/lisa-agy/skills/lisa-setup-linear/SKILL.md +5 -5
- package/plugins/lisa-agy/skills/lisa-track/SKILL.md +1 -1
- package/plugins/lisa-agy/skills/lisa-tracker-build-intake/SKILL.md +9 -0
- 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 +19 -1
- package/plugins/lisa-copilot/agents/linear-prd-intake.agent.md +8 -8
- package/plugins/lisa-copilot/hooks/block-blind-automerge.sh +81 -2
- package/plugins/lisa-copilot/hooks/block-direct-issue-create.sh +293 -8
- package/plugins/lisa-copilot/hooks/block-instruction-file-edits.sh +21 -0
- package/plugins/lisa-copilot/hooks/block-managed-file-edits.sh +78 -15
- package/plugins/lisa-copilot/hooks/block-no-verify.sh +21 -0
- package/plugins/lisa-copilot/hooks/block-shell-json-parsing.sh +21 -0
- package/plugins/lisa-copilot/hooks/failure-signature-index.mjs +240 -5
- package/plugins/lisa-copilot/hooks/guard-dedupe.bash +337 -0
- package/plugins/lisa-copilot/hooks/inject-rules.sh +13 -5
- package/plugins/lisa-copilot/hooks/operational-hazards.mjs +736 -0
- package/plugins/lisa-copilot/hooks/operational-hazards.sh +28 -0
- package/plugins/lisa-copilot/hooks/parity-safety-net.sh +29 -1
- package/plugins/lisa-copilot/hooks/threshold-ratchet-compare.mjs +102 -21
- package/plugins/lisa-copilot/hooks/threshold-ratchet-families.mjs +130 -2
- package/plugins/lisa-copilot/hooks/threshold-ratchet.mjs +63 -13
- package/plugins/lisa-copilot/hooks/worktree-binding-guard.mjs +183 -1
- package/plugins/lisa-copilot/hooks/worktree-binding-guard.sh +21 -0
- package/plugins/lisa-copilot/rules/eager/00-rule-index.md +1 -0
- package/plugins/lisa-copilot/rules/eager/operational-hazards.md +50 -0
- package/plugins/lisa-copilot/rules/eager/tracked-work.md +1 -1
- package/plugins/lisa-copilot/rules/reference/config-resolution.md +1 -1
- package/plugins/lisa-copilot/rules/reference/leaf-only-lifecycle.md +1 -1
- package/plugins/lisa-copilot/rules/reference/operational-hazards.md +115 -0
- package/plugins/lisa-copilot/rules/reference/work-item-trailer-definition.md +129 -0
- package/plugins/lisa-copilot/scripts/intake-blocker-reprobe.mjs +407 -26
- package/plugins/lisa-copilot/scripts/qa-signal-lifecycle.mjs +507 -0
- package/plugins/lisa-copilot/skills/lisa-drive-pr-to-merge/SKILL.md +130 -19
- package/plugins/lisa-copilot/skills/lisa-github-build-intake/SKILL.md +27 -4
- package/plugins/lisa-copilot/skills/lisa-github-prd-intake/SKILL.md +1 -1
- package/plugins/lisa-copilot/skills/lisa-github-validate-issue/SKILL.md +22 -0
- package/plugins/lisa-copilot/skills/lisa-github-verify/SKILL.md +14 -0
- package/plugins/lisa-copilot/skills/lisa-github-write-issue/SKILL.md +51 -0
- package/plugins/lisa-copilot/skills/lisa-intake/SKILL.md +1 -1
- package/plugins/lisa-copilot/skills/lisa-jira-build-intake/SKILL.md +27 -4
- package/plugins/lisa-copilot/skills/lisa-jira-validate-ticket/SKILL.md +22 -0
- package/plugins/lisa-copilot/skills/lisa-jira-verify/SKILL.md +14 -0
- package/plugins/lisa-copilot/skills/lisa-jira-write-ticket/SKILL.md +51 -0
- package/plugins/lisa-copilot/skills/lisa-linear-access/SKILL.md +55 -2
- package/plugins/lisa-copilot/skills/lisa-linear-build-intake/SKILL.md +27 -4
- package/plugins/lisa-copilot/skills/lisa-linear-prd-intake/SKILL.md +48 -31
- package/plugins/lisa-copilot/skills/lisa-linear-to-tracker/SKILL.md +3 -3
- package/plugins/lisa-copilot/skills/lisa-linear-validate-issue/SKILL.md +22 -0
- package/plugins/lisa-copilot/skills/lisa-linear-verify/SKILL.md +14 -0
- package/plugins/lisa-copilot/skills/lisa-linear-write-issue/SKILL.md +54 -3
- package/plugins/lisa-copilot/skills/lisa-prd-ticket-coverage/SKILL.md +2 -2
- package/plugins/lisa-copilot/skills/lisa-qa-clear/SKILL.md +19 -7
- package/plugins/lisa-copilot/skills/lisa-qa-fail/SKILL.md +28 -3
- package/plugins/lisa-copilot/skills/lisa-qa-queue/SKILL.md +28 -3
- package/plugins/lisa-copilot/skills/lisa-repair-intake/SKILL.md +94 -24
- package/plugins/lisa-copilot/skills/lisa-rework-triage/SKILL.md +32 -2
- package/plugins/lisa-copilot/skills/lisa-setup-linear/SKILL.md +5 -5
- package/plugins/lisa-copilot/skills/lisa-track/SKILL.md +1 -1
- package/plugins/lisa-copilot/skills/lisa-tracker-build-intake/SKILL.md +9 -0
- package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cursor/agents/linear-prd-intake.md +8 -8
- package/plugins/lisa-cursor/hooks/block-blind-automerge.sh +81 -2
- package/plugins/lisa-cursor/hooks/block-direct-issue-create.sh +293 -8
- package/plugins/lisa-cursor/hooks/block-instruction-file-edits.sh +21 -0
- package/plugins/lisa-cursor/hooks/block-managed-file-edits.sh +78 -15
- package/plugins/lisa-cursor/hooks/block-no-verify.sh +21 -0
- package/plugins/lisa-cursor/hooks/block-shell-json-parsing.sh +21 -0
- package/plugins/lisa-cursor/hooks/failure-signature-index.mjs +240 -5
- package/plugins/lisa-cursor/hooks/guard-dedupe.bash +337 -0
- package/plugins/lisa-cursor/hooks/hooks.json +10 -0
- package/plugins/lisa-cursor/hooks/operational-hazards.mjs +736 -0
- package/plugins/lisa-cursor/hooks/operational-hazards.sh +28 -0
- package/plugins/lisa-cursor/hooks/parity-safety-net.sh +29 -1
- package/plugins/lisa-cursor/hooks/threshold-ratchet-compare.mjs +102 -21
- package/plugins/lisa-cursor/hooks/threshold-ratchet-families.mjs +130 -2
- package/plugins/lisa-cursor/hooks/threshold-ratchet.mjs +63 -13
- package/plugins/lisa-cursor/hooks/worktree-binding-guard.mjs +183 -1
- package/plugins/lisa-cursor/hooks/worktree-binding-guard.sh +21 -0
- package/plugins/lisa-cursor/rules/00-rule-index.mdc +1 -0
- package/plugins/lisa-cursor/rules/config-resolution-reference.mdc +1 -1
- package/plugins/lisa-cursor/rules/leaf-only-lifecycle-reference.mdc +1 -1
- package/plugins/lisa-cursor/rules/operational-hazards-reference.mdc +120 -0
- package/plugins/lisa-cursor/rules/operational-hazards.mdc +55 -0
- package/plugins/lisa-cursor/rules/tracked-work.mdc +1 -1
- package/plugins/lisa-cursor/rules/work-item-trailer-definition-reference.mdc +134 -0
- package/plugins/lisa-cursor/scripts/intake-blocker-reprobe.mjs +407 -26
- package/plugins/lisa-cursor/scripts/qa-signal-lifecycle.mjs +507 -0
- package/plugins/lisa-cursor/skills/lisa-drive-pr-to-merge/SKILL.md +130 -19
- package/plugins/lisa-cursor/skills/lisa-github-build-intake/SKILL.md +27 -4
- package/plugins/lisa-cursor/skills/lisa-github-prd-intake/SKILL.md +1 -1
- package/plugins/lisa-cursor/skills/lisa-github-validate-issue/SKILL.md +22 -0
- package/plugins/lisa-cursor/skills/lisa-github-verify/SKILL.md +14 -0
- package/plugins/lisa-cursor/skills/lisa-github-write-issue/SKILL.md +51 -0
- package/plugins/lisa-cursor/skills/lisa-intake/SKILL.md +1 -1
- package/plugins/lisa-cursor/skills/lisa-jira-build-intake/SKILL.md +27 -4
- package/plugins/lisa-cursor/skills/lisa-jira-validate-ticket/SKILL.md +22 -0
- package/plugins/lisa-cursor/skills/lisa-jira-verify/SKILL.md +14 -0
- package/plugins/lisa-cursor/skills/lisa-jira-write-ticket/SKILL.md +51 -0
- package/plugins/lisa-cursor/skills/lisa-linear-access/SKILL.md +55 -2
- package/plugins/lisa-cursor/skills/lisa-linear-build-intake/SKILL.md +27 -4
- package/plugins/lisa-cursor/skills/lisa-linear-prd-intake/SKILL.md +48 -31
- package/plugins/lisa-cursor/skills/lisa-linear-to-tracker/SKILL.md +3 -3
- package/plugins/lisa-cursor/skills/lisa-linear-validate-issue/SKILL.md +22 -0
- package/plugins/lisa-cursor/skills/lisa-linear-verify/SKILL.md +14 -0
- package/plugins/lisa-cursor/skills/lisa-linear-write-issue/SKILL.md +54 -3
- package/plugins/lisa-cursor/skills/lisa-prd-ticket-coverage/SKILL.md +2 -2
- package/plugins/lisa-cursor/skills/lisa-qa-clear/SKILL.md +19 -7
- package/plugins/lisa-cursor/skills/lisa-qa-fail/SKILL.md +28 -3
- package/plugins/lisa-cursor/skills/lisa-qa-queue/SKILL.md +28 -3
- package/plugins/lisa-cursor/skills/lisa-repair-intake/SKILL.md +94 -24
- package/plugins/lisa-cursor/skills/lisa-rework-triage/SKILL.md +32 -2
- package/plugins/lisa-cursor/skills/lisa-setup-linear/SKILL.md +5 -5
- package/plugins/lisa-cursor/skills/lisa-track/SKILL.md +1 -1
- package/plugins/lisa-cursor/skills/lisa-tracker-build-intake/SKILL.md +9 -0
- 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/hooks/inject-rules.sh +14 -3
- package/plugins/lisa-harper-fabric/rules/eager/harper-fabric.md +31 -0
- 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-copilot/hooks/inject-rules.sh +14 -3
- package/plugins/lisa-harper-fabric-copilot/rules/eager/harper-fabric.md +31 -0
- package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-cursor/rules/harper-fabric-reference.mdc +57 -0
- package/plugins/lisa-harper-fabric-cursor/rules/harper-fabric.mdc +32 -53
- 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/hooks/inject-rules.sh +14 -3
- package/plugins/lisa-phaser/rules/eager/phaser.md +44 -0
- package/plugins/lisa-phaser-agy/plugin.json +1 -1
- package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser-copilot/hooks/inject-rules.sh +14 -3
- package/plugins/lisa-phaser-copilot/rules/eager/phaser.md +44 -0
- package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser-cursor/rules/phaser-reference.mdc +189 -0
- package/plugins/lisa-phaser-cursor/rules/phaser.mdc +45 -185
- package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/hooks/inject-rules.sh +14 -4
- package/plugins/lisa-rails/rules/eager/rails-conventions.md +23 -0
- package/plugins/lisa-rails-agy/plugin.json +1 -1
- package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails-copilot/hooks/inject-rules.sh +14 -4
- package/plugins/lisa-rails-copilot/rules/eager/rails-conventions.md +23 -0
- package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails-cursor/rules/rails-conventions-reference.mdc +181 -0
- package/plugins/lisa-rails-cursor/rules/rails-conventions.mdc +24 -177
- 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 +1 -0
- package/plugins/src/base/.claude-plugin/plugin.json +27 -0
- package/plugins/src/base/agents/linear-prd-intake.md +8 -8
- package/plugins/src/base/hooks/block-blind-automerge.sh +81 -2
- package/plugins/src/base/hooks/block-direct-issue-create.agy.sh +64 -16
- package/plugins/src/base/hooks/block-direct-issue-create.sh +293 -8
- package/plugins/src/base/hooks/block-instruction-file-edits.sh +21 -0
- package/plugins/src/base/hooks/block-managed-file-edits.sh +78 -15
- package/plugins/src/base/hooks/block-no-verify.sh +21 -0
- package/plugins/src/base/hooks/block-shell-json-parsing.sh +21 -0
- package/plugins/src/base/hooks/failure-signature-index.mjs +240 -5
- package/plugins/src/base/hooks/guard-dedupe.bash +337 -0
- package/plugins/src/base/hooks/inject-rules.sh +13 -5
- package/plugins/src/base/hooks/operational-hazards.mjs +736 -0
- package/plugins/src/base/hooks/operational-hazards.sh +28 -0
- package/plugins/src/base/hooks/parity-safety-net.sh +29 -1
- package/plugins/src/base/hooks/threshold-ratchet-compare.mjs +102 -21
- package/plugins/src/base/hooks/threshold-ratchet-families.mjs +130 -2
- package/plugins/src/base/hooks/threshold-ratchet.mjs +63 -13
- package/plugins/src/base/hooks/worktree-binding-guard.mjs +183 -1
- package/plugins/src/base/hooks/worktree-binding-guard.sh +21 -0
- package/plugins/src/base/rules/eager/00-rule-index.md +1 -0
- package/plugins/src/base/rules/eager/operational-hazards.md +50 -0
- package/plugins/src/base/rules/eager/tracked-work.md +1 -1
- package/plugins/src/base/rules/reference/config-resolution.md +1 -1
- package/plugins/src/base/rules/reference/leaf-only-lifecycle.md +1 -1
- package/plugins/src/base/rules/reference/operational-hazards.md +115 -0
- package/plugins/src/base/rules/reference/work-item-trailer-definition.md +129 -0
- package/plugins/src/base/scripts/intake-blocker-reprobe.mjs +407 -26
- package/plugins/src/base/scripts/qa-signal-lifecycle.mjs +507 -0
- package/plugins/src/base/skills/lisa-drive-pr-to-merge/SKILL.md +130 -19
- package/plugins/src/base/skills/lisa-github-build-intake/SKILL.md +27 -4
- package/plugins/src/base/skills/lisa-github-prd-intake/SKILL.md +1 -1
- package/plugins/src/base/skills/lisa-github-validate-issue/SKILL.md +22 -0
- package/plugins/src/base/skills/lisa-github-verify/SKILL.md +14 -0
- package/plugins/src/base/skills/lisa-github-write-issue/SKILL.md +51 -0
- package/plugins/src/base/skills/lisa-intake/SKILL.md +1 -1
- package/plugins/src/base/skills/lisa-jira-build-intake/SKILL.md +27 -4
- package/plugins/src/base/skills/lisa-jira-validate-ticket/SKILL.md +22 -0
- package/plugins/src/base/skills/lisa-jira-verify/SKILL.md +14 -0
- package/plugins/src/base/skills/lisa-jira-write-ticket/SKILL.md +51 -0
- package/plugins/src/base/skills/lisa-linear-access/SKILL.md +55 -2
- package/plugins/src/base/skills/lisa-linear-build-intake/SKILL.md +27 -4
- package/plugins/src/base/skills/lisa-linear-prd-intake/SKILL.md +48 -31
- package/plugins/src/base/skills/lisa-linear-to-tracker/SKILL.md +3 -3
- package/plugins/src/base/skills/lisa-linear-validate-issue/SKILL.md +22 -0
- package/plugins/src/base/skills/lisa-linear-verify/SKILL.md +14 -0
- package/plugins/src/base/skills/lisa-linear-write-issue/SKILL.md +54 -3
- package/plugins/src/base/skills/lisa-prd-ticket-coverage/SKILL.md +2 -2
- package/plugins/src/base/skills/lisa-qa-clear/SKILL.md +19 -7
- package/plugins/src/base/skills/lisa-qa-fail/SKILL.md +28 -3
- package/plugins/src/base/skills/lisa-qa-queue/SKILL.md +28 -3
- package/plugins/src/base/skills/lisa-repair-intake/SKILL.md +94 -24
- package/plugins/src/base/skills/lisa-rework-triage/SKILL.md +32 -2
- package/plugins/src/base/skills/lisa-setup-linear/SKILL.md +5 -5
- package/plugins/src/base/skills/lisa-track/SKILL.md +1 -1
- package/plugins/src/base/skills/lisa-tracker-build-intake/SKILL.md +9 -0
- package/plugins/src/harper-fabric/hooks/inject-rules.sh +14 -3
- package/plugins/src/harper-fabric/rules/eager/harper-fabric.md +31 -0
- package/plugins/src/phaser/hooks/inject-rules.sh +14 -3
- package/plugins/src/phaser/rules/eager/phaser.md +44 -0
- package/plugins/src/rails/hooks/inject-rules.sh +14 -4
- package/plugins/src/rails/rules/eager/rails-conventions.md +23 -0
- package/rails/copy-overwrite/scripts/check-threshold-ratchet.mjs +63 -13
- package/rails/copy-overwrite/scripts/threshold-ratchet-compare.mjs +102 -21
- package/rails/copy-overwrite/scripts/threshold-ratchet-families.mjs +130 -2
- package/rails/create-only/.github/workflows/ci.yml +8 -0
- package/rails/create-only/.github/workflows/deploy.yml +22 -0
- package/scripts/build-plugins.sh +2 -1
- package/scripts/check-engine-floor.mjs +361 -0
- package/scripts/check-guard-parity-notes.mjs +709 -0
- package/scripts/check-template-workflow-refs.mjs +9 -0
- package/scripts/check-third-party-action-pins.mjs +17 -1
- package/scripts/check-workflow-contract-assertions.mjs +480 -0
- package/scripts/copy-opencode-plugin-templates.mjs +1 -0
- package/scripts/deployed-guard-advice.mjs +636 -0
- package/scripts/generate-agy-plugin-artifacts.mjs +35 -10
- package/scripts/generate-export-surface.mjs +105 -19
- package/scripts/generate-two-channel-couplings.ts +143 -212
- package/scripts/lisa-enforcement-fallback.sh +31 -0
- package/scripts/measure-scripts-profile-gap.mts +361 -0
- package/scripts/mutation-performance-measure.mjs +21 -5
- package/scripts/reconcile-release-tags.mjs +65 -84
- package/scripts/two-channel-couplings.json +302 -70
- package/scripts/workflow-contract-assertion.sh +47 -0
- package/typescript/copy-overwrite/.lintstagedrc.json +1 -0
- package/typescript/copy-overwrite/eslint.ignore.config.json +1 -0
- package/typescript/copy-overwrite/scripts/check-nightly-e2e-health.mjs +527 -53
- package/typescript/copy-overwrite/scripts/check-skipped-required-checks.mjs +301 -13
- package/typescript/copy-overwrite/scripts/check-threshold-ratchet.mjs +63 -13
- package/typescript/copy-overwrite/scripts/threshold-ratchet-compare.mjs +102 -21
- package/typescript/copy-overwrite/scripts/threshold-ratchet-families.mjs +130 -2
- package/typescript/create-only/.github/workflows/ci.yml +7 -0
- /package/plugins/lisa-harper-fabric/rules/{harper-fabric.md → reference/harper-fabric.md} +0 -0
- /package/plugins/lisa-harper-fabric-copilot/rules/{harper-fabric.md → reference/harper-fabric.md} +0 -0
- /package/plugins/lisa-phaser/rules/{phaser.md → reference/phaser.md} +0 -0
- /package/plugins/lisa-phaser-copilot/rules/{phaser.md → reference/phaser.md} +0 -0
- /package/plugins/lisa-rails/rules/{rails-conventions.md → reference/rails-conventions.md} +0 -0
- /package/plugins/lisa-rails-copilot/rules/{rails-conventions.md → reference/rails-conventions.md} +0 -0
- /package/plugins/src/harper-fabric/rules/{harper-fabric.md → reference/harper-fabric.md} +0 -0
- /package/plugins/src/phaser/rules/{phaser.md → reference/phaser.md} +0 -0
- /package/plugins/src/rails/rules/{rails-conventions.md → reference/rails-conventions.md} +0 -0
|
@@ -39,6 +39,14 @@
|
|
|
39
39
|
* - a ratification matching no live coupling, because a permission left
|
|
40
40
|
* behind after its subject is gone is inherited for free by the next path
|
|
41
41
|
* that happens to match;
|
|
42
|
+
* - a ledgered coupling with no recorded STALENESS decision (#3687) — the
|
|
43
|
+
* one field a new coupling cannot be added without, because its detection
|
|
44
|
+
* is derived and therefore free while the decision costs a sentence;
|
|
45
|
+
* - a staleness decision the tree refuses to support, in either direction:
|
|
46
|
+
* a claimed handshake nothing shows, or an exemption on a coupling that
|
|
47
|
+
* already has one;
|
|
48
|
+
* - a staleness decision matching no live coupling, for the same reason a
|
|
49
|
+
* stale ratification fails;
|
|
42
50
|
* - `--check` against a stale ledger;
|
|
43
51
|
* - and any run that measured nothing.
|
|
44
52
|
*
|
|
@@ -82,6 +90,13 @@ import {
|
|
|
82
90
|
isReusable,
|
|
83
91
|
scanWorkflow,
|
|
84
92
|
} from "../src/core/two-channel-delivery-scan.js";
|
|
93
|
+
import {
|
|
94
|
+
artifactStalenessSignals,
|
|
95
|
+
STALENESS_DECISIONS,
|
|
96
|
+
STALENESS_DETECTIONS,
|
|
97
|
+
type StalenessRecord,
|
|
98
|
+
type StalenessSignal,
|
|
99
|
+
} from "../src/core/two-channel-staleness.js";
|
|
85
100
|
|
|
86
101
|
/** Where the fast channel's bodies live in this repository. */
|
|
87
102
|
const WORKFLOWS_DIR = path.join(".github", "workflows");
|
|
@@ -228,52 +243,21 @@ export function buildDeliveryInventory(
|
|
|
228
243
|
);
|
|
229
244
|
}
|
|
230
245
|
|
|
231
|
-
/**
|
|
232
|
-
* The only part of a report these two functions read.
|
|
233
|
-
*
|
|
234
|
-
* Narrower than the full report on purpose: they need a key and a verdict per
|
|
235
|
-
* entry and nothing else, and a parameter that asked for the whole measurement
|
|
236
|
-
* would force every caller — including a test — to build one it does not use.
|
|
237
|
-
*/
|
|
238
|
-
interface CouplingKeySource {
|
|
239
|
-
readonly entries: readonly {
|
|
240
|
-
readonly key: string;
|
|
241
|
-
readonly verdict: string;
|
|
242
|
-
}[];
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
/** One coupling's answer to "can this notice a STALE artifact?" (#3687). */
|
|
246
|
-
export interface StalenessClassification {
|
|
247
|
-
/**
|
|
248
|
-
* What the coupling CAN detect today — an observation, not a decision.
|
|
249
|
-
*
|
|
250
|
-
* `version-handshake` asks the artifact for a contract version and compares
|
|
251
|
-
* it. `capability-probe` asks for one subcommand or flag and infers age from
|
|
252
|
-
* whether it answers, which sees staleness at exactly one point and is blind
|
|
253
|
-
* above that floor — the CodySwannGT/lisa#3477 defect. `existence-only`
|
|
254
|
-
* cannot see age at all.
|
|
255
|
-
*/
|
|
256
|
-
readonly detects: "version-handshake" | "capability-probe" | "existence-only";
|
|
257
|
-
/**
|
|
258
|
-
* Why the current level is acceptable. Required unless a handshake exists.
|
|
259
|
-
*
|
|
260
|
-
* This is the DECISION half, kept separate from `detects` on purpose: a
|
|
261
|
-
* coupling that cannot see age and is fine that way (an advisory read, an
|
|
262
|
-
* artifact carrying no verdict-bearing logic) is a different fact from one
|
|
263
|
-
* that cannot see age and should. Collapsing them into a single
|
|
264
|
-
* "not-needed" token would lose exactly the distinction the sweep exists to
|
|
265
|
-
* record, and would let an unexamined default wear the same word as a
|
|
266
|
-
* considered exemption.
|
|
267
|
-
*/
|
|
268
|
-
readonly reason?: string;
|
|
269
|
-
}
|
|
270
|
-
|
|
271
246
|
/** The ledger's hand-authored half plus its derived half. */
|
|
272
247
|
interface Ledger {
|
|
273
248
|
readonly ratified: Readonly<Record<string, string>>;
|
|
274
|
-
|
|
249
|
+
/**
|
|
250
|
+
* The staleness decision recorded for each ledgered coupling.
|
|
251
|
+
*
|
|
252
|
+
* Hand-authored, and required. The DETECTION beside each coupling below is
|
|
253
|
+
* derived from the tree on every run; this is the half a person has to
|
|
254
|
+
* answer, which is what stops entry 24 from inheriting "nobody looked".
|
|
255
|
+
*/
|
|
256
|
+
readonly staleness: Readonly<Record<string, StalenessRecord>>;
|
|
275
257
|
readonly inspected: TwoChannelReport["inspected"];
|
|
276
258
|
readonly counts: TwoChannelReport["counts"];
|
|
259
|
+
readonly detectionCounts: TwoChannelReport["detectionCounts"];
|
|
260
|
+
readonly decisionCounts: TwoChannelReport["decisionCounts"];
|
|
277
261
|
readonly couplings: readonly {
|
|
278
262
|
readonly key: string;
|
|
279
263
|
readonly workflow: string;
|
|
@@ -282,172 +266,47 @@ interface Ledger {
|
|
|
282
266
|
readonly verdict: string;
|
|
283
267
|
readonly remedy: string;
|
|
284
268
|
readonly guarded: boolean;
|
|
269
|
+
readonly handling: readonly string[];
|
|
270
|
+
readonly detection: string;
|
|
271
|
+
readonly stalenessSignals: readonly string[];
|
|
272
|
+
readonly decision: string | null;
|
|
273
|
+
readonly reason: string | null;
|
|
285
274
|
readonly lanes: readonly string[];
|
|
286
275
|
readonly detail: string;
|
|
287
276
|
}[];
|
|
288
277
|
}
|
|
289
278
|
|
|
290
279
|
/**
|
|
291
|
-
*
|
|
280
|
+
* The ledger as it currently stands, or an empty one when there is none.
|
|
292
281
|
* @param ledgerPath - Absolute path to the ledger
|
|
293
|
-
* @returns
|
|
282
|
+
* @returns Whatever the file holds, unvalidated
|
|
294
283
|
*/
|
|
295
|
-
function
|
|
284
|
+
function readLedger(ledgerPath: string): Partial<Ledger> {
|
|
296
285
|
if (!existsSync(ledgerPath)) return {};
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
return parsed?.ratified ?? {};
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
/**
|
|
304
|
-
* Read the staleness classifications already recorded (#3687).
|
|
305
|
-
*
|
|
306
|
-
* Exactly the shape `readRatified` uses, and for the same reason: the ledger is
|
|
307
|
-
* a DERIVED artifact regenerated in-commit, so a hand-authored field survives
|
|
308
|
-
* only if the generator reads the previous version before rewriting it. This is
|
|
309
|
-
* the established local precedent for persisting a human decision inside a
|
|
310
|
-
* generated file, which is why the classification lives here rather than in a
|
|
311
|
-
* new sidecar nobody would remember to update.
|
|
312
|
-
* @param ledgerPath - Absolute path to the ledger
|
|
313
|
-
* @returns The classifications, keyed `<workflow>::<path>`
|
|
314
|
-
*/
|
|
315
|
-
function readStaleness(
|
|
316
|
-
ledgerPath: string
|
|
317
|
-
): Readonly<Record<string, StalenessClassification>> {
|
|
318
|
-
if (!existsSync(ledgerPath)) return {};
|
|
319
|
-
const parsed = JSON.parse(readFileSync(ledgerPath, "utf8")) as
|
|
320
|
-
| Partial<Ledger>
|
|
321
|
-
| undefined;
|
|
322
|
-
return parsed?.staleness ?? {};
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
/**
|
|
326
|
-
* The verdict for a coupling the package channel already covers.
|
|
327
|
-
*
|
|
328
|
-
* Those are omitted from the ledger, so every question this file asks about a
|
|
329
|
-
* live coupling has to exclude them — named once so the three sites cannot
|
|
330
|
-
* disagree about which verdict that is.
|
|
331
|
-
*/
|
|
332
|
-
const PACKAGE_BACKED = "package-backed";
|
|
333
|
-
|
|
334
|
-
/** The `detects` value meaning the coupling asks for a contract version. */
|
|
335
|
-
const VERSION_HANDSHAKE = "version-handshake";
|
|
336
|
-
|
|
337
|
-
/** The `detects` value meaning it infers age from one subcommand or flag. */
|
|
338
|
-
const CAPABILITY_PROBE = "capability-probe";
|
|
339
|
-
|
|
340
|
-
/** The `detects` value meaning it can see presence and nothing else. */
|
|
341
|
-
const EXISTENCE_ONLY = "existence-only";
|
|
342
|
-
|
|
343
|
-
/** The `detects` values a classification may carry. */
|
|
344
|
-
const DETECTS = new Set([VERSION_HANDSHAKE, CAPABILITY_PROBE, EXISTENCE_ONLY]);
|
|
345
|
-
|
|
346
|
-
/**
|
|
347
|
-
* The floor a stated reason must clear to be a reason rather than a label.
|
|
348
|
-
*
|
|
349
|
-
* A floor, not a proof — no check tells a real argument from filler. What it
|
|
350
|
-
* buys is that "n/a", "ok" and an empty string cannot stand in for the decision
|
|
351
|
-
* this field exists to record.
|
|
352
|
-
*/
|
|
353
|
-
const MIN_REASON_CHARACTERS = 40;
|
|
354
|
-
|
|
355
|
-
/**
|
|
356
|
-
* Every problem with the staleness half, as operator-readable paragraphs.
|
|
357
|
-
*
|
|
358
|
-
* THREE refusals, and the first is the one that makes this a standing property
|
|
359
|
-
* rather than a one-time sweep: a coupling with no classification fails, so
|
|
360
|
-
* entry 25 cannot silently inherit "nobody looked". A sweep decays the moment
|
|
361
|
-
* somebody adds an entry; a required field does not.
|
|
362
|
-
* @param report - The measurement
|
|
363
|
-
* @param staleness - The recorded classifications
|
|
364
|
-
* @returns Problem paragraphs, empty when the staleness half is sound
|
|
365
|
-
*/
|
|
366
|
-
export function stalenessProblems(
|
|
367
|
-
report: CouplingKeySource,
|
|
368
|
-
staleness: Readonly<Record<string, StalenessClassification>>
|
|
369
|
-
): readonly string[] {
|
|
370
|
-
const live = new Set(
|
|
371
|
-
report.entries
|
|
372
|
-
.filter(entry => entry.verdict !== PACKAGE_BACKED)
|
|
373
|
-
.map(entry => entry.key)
|
|
286
|
+
return (
|
|
287
|
+
(JSON.parse(readFileSync(ledgerPath, "utf8")) as Partial<Ledger> | null) ??
|
|
288
|
+
{}
|
|
374
289
|
);
|
|
375
|
-
const missing = [...live]
|
|
376
|
-
.filter(key => staleness[key] === undefined)
|
|
377
|
-
.map(
|
|
378
|
-
key =>
|
|
379
|
-
`\nUNCLASSIFIED COUPLING ${key}\n No staleness classification. Every ` +
|
|
380
|
-
`coupling must record whether it can detect a STALE artifact, not only ` +
|
|
381
|
-
`an absent one — absence skips and posts nothing, while present-and-old ` +
|
|
382
|
-
`posts a verdict from superseded logic that every reader believes. Add ` +
|
|
383
|
-
`a "staleness" entry with "detects" (version-handshake | ` +
|
|
384
|
-
`capability-probe | existence-only) and, unless it is a handshake, a ` +
|
|
385
|
-
`"reason" saying why that is acceptable here.`
|
|
386
|
-
);
|
|
387
|
-
const orphaned = Object.keys(staleness)
|
|
388
|
-
.filter(key => !live.has(key))
|
|
389
|
-
.map(
|
|
390
|
-
key =>
|
|
391
|
-
`\nSTALE CLASSIFICATION ${key}\n Nothing reads this path any more, so ` +
|
|
392
|
-
`the classification is an unexamined judgement the next matching path ` +
|
|
393
|
-
`would inherit. Delete it from ${LEDGER_PATH}.`
|
|
394
|
-
);
|
|
395
|
-
const malformed = Object.entries(staleness)
|
|
396
|
-
.filter(([key]) => live.has(key))
|
|
397
|
-
.flatMap(([key, value]) => describeMalformed(key, value));
|
|
398
|
-
return [...missing, ...orphaned, ...malformed];
|
|
399
290
|
}
|
|
400
291
|
|
|
401
292
|
/**
|
|
402
|
-
*
|
|
403
|
-
* @param
|
|
404
|
-
* @
|
|
405
|
-
* @returns Problem paragraphs for this entry
|
|
293
|
+
* Read the ratifications already recorded, so regenerating never drops them.
|
|
294
|
+
* @param ledgerPath - Absolute path to the ledger
|
|
295
|
+
* @returns The ratification reasons, keyed `<workflow>::<path>`
|
|
406
296
|
*/
|
|
407
|
-
function
|
|
408
|
-
|
|
409
|
-
value: StalenessClassification
|
|
410
|
-
): readonly string[] {
|
|
411
|
-
if (!DETECTS.has(value?.detects)) {
|
|
412
|
-
return [
|
|
413
|
-
`\nMALFORMED CLASSIFICATION ${key}\n "detects" is ` +
|
|
414
|
-
`${JSON.stringify(value?.detects)}; expected one of ` +
|
|
415
|
-
`${[...DETECTS].join(", ")}.`,
|
|
416
|
-
];
|
|
417
|
-
}
|
|
418
|
-
if (value.detects === VERSION_HANDSHAKE) return [];
|
|
419
|
-
const reason = typeof value.reason === "string" ? value.reason.trim() : "";
|
|
420
|
-
return reason.length >= MIN_REASON_CHARACTERS
|
|
421
|
-
? []
|
|
422
|
-
: [
|
|
423
|
-
`\nUNREASONED CLASSIFICATION ${key}\n "detects" is ` +
|
|
424
|
-
`"${value.detects}", which cannot see how old the artifact is, and no ` +
|
|
425
|
-
`"reason" of at least ${MIN_REASON_CHARACTERS} characters says why ` +
|
|
426
|
-
`that is acceptable here. A recorded decision and an unexamined ` +
|
|
427
|
-
`default must not look the same.`,
|
|
428
|
-
];
|
|
297
|
+
function readRatified(ledgerPath: string): Readonly<Record<string, string>> {
|
|
298
|
+
return readLedger(ledgerPath).ratified ?? {};
|
|
429
299
|
}
|
|
430
300
|
|
|
431
301
|
/**
|
|
432
|
-
*
|
|
433
|
-
* @param
|
|
434
|
-
* @
|
|
435
|
-
* @returns A sentence naming how much of the fleet can see age
|
|
302
|
+
* Read the staleness decisions already recorded.
|
|
303
|
+
* @param ledgerPath - Absolute path to the ledger
|
|
304
|
+
* @returns The decisions, keyed `<workflow>::<path>`
|
|
436
305
|
*/
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
)
|
|
441
|
-
const live = report.entries.filter(entry => entry.verdict !== PACKAGE_BACKED);
|
|
442
|
-
const tally = (kind: string): number =>
|
|
443
|
-
live.filter(entry => staleness[entry.key]?.detects === kind).length;
|
|
444
|
-
const handshake = tally(VERSION_HANDSHAKE);
|
|
445
|
-
return (
|
|
446
|
-
` staleness detection: ${handshake} of ${live.length} coupling(s) can see ` +
|
|
447
|
-
`how old the artifact is (${VERSION_HANDSHAKE}); ${tally(CAPABILITY_PROBE)} ` +
|
|
448
|
-
`detect it at one floor only (${CAPABILITY_PROBE}); ${tally(EXISTENCE_ONLY)} ` +
|
|
449
|
-
`detect absence only (${EXISTENCE_ONLY}).`
|
|
450
|
-
);
|
|
306
|
+
function readClassified(
|
|
307
|
+
ledgerPath: string
|
|
308
|
+
): Readonly<Record<string, StalenessRecord>> {
|
|
309
|
+
return readLedger(ledgerPath).staleness ?? {};
|
|
451
310
|
}
|
|
452
311
|
|
|
453
312
|
/**
|
|
@@ -464,15 +323,17 @@ export function stalenessCoverage(
|
|
|
464
323
|
function toLedger(
|
|
465
324
|
report: TwoChannelReport,
|
|
466
325
|
ratified: Readonly<Record<string, string>>,
|
|
467
|
-
|
|
326
|
+
classified: Readonly<Record<string, StalenessRecord>>
|
|
468
327
|
): Ledger {
|
|
469
328
|
return {
|
|
470
329
|
ratified,
|
|
471
|
-
staleness,
|
|
330
|
+
staleness: classified,
|
|
472
331
|
inspected: report.inspected,
|
|
473
332
|
counts: report.counts,
|
|
333
|
+
detectionCounts: report.detectionCounts,
|
|
334
|
+
decisionCounts: report.decisionCounts,
|
|
474
335
|
couplings: report.entries
|
|
475
|
-
.filter(entry => entry.verdict !==
|
|
336
|
+
.filter(entry => entry.verdict !== "package-backed")
|
|
476
337
|
.map(entry => ({
|
|
477
338
|
key: entry.key,
|
|
478
339
|
workflow: entry.workflow,
|
|
@@ -481,6 +342,11 @@ function toLedger(
|
|
|
481
342
|
verdict: entry.verdict,
|
|
482
343
|
remedy: entry.remedy,
|
|
483
344
|
guarded: entry.guarded,
|
|
345
|
+
handling: entry.handling,
|
|
346
|
+
detection: entry.detection,
|
|
347
|
+
stalenessSignals: entry.staleness,
|
|
348
|
+
decision: entry.decision,
|
|
349
|
+
reason: entry.reason,
|
|
484
350
|
lanes: entry.lanes,
|
|
485
351
|
detail: entry.detail,
|
|
486
352
|
})),
|
|
@@ -495,12 +361,27 @@ function toLedger(
|
|
|
495
361
|
export function measure(root: string): {
|
|
496
362
|
readonly report: TwoChannelReport;
|
|
497
363
|
readonly ratified: Readonly<Record<string, string>>;
|
|
498
|
-
readonly
|
|
364
|
+
readonly classified: Readonly<Record<string, StalenessRecord>>;
|
|
499
365
|
} {
|
|
500
366
|
const workflowsDir = path.join(root, WORKFLOWS_DIR);
|
|
501
367
|
const inventory = buildDeliveryInventory(root);
|
|
502
368
|
const lanesFor = (callerPath: string): readonly string[] =>
|
|
503
369
|
inventory.get(callerPath) ?? [];
|
|
370
|
+
const artifactSignalsFor = (
|
|
371
|
+
callerPath: string
|
|
372
|
+
): readonly StalenessSignal[] | null => {
|
|
373
|
+
const lanes = lanesFor(callerPath);
|
|
374
|
+
// No lane ships this path, so there is no artifact to ask. Returning [] —
|
|
375
|
+
// "it carries no version tokens" — would be the same bytes as a measured
|
|
376
|
+
// negative, which is the exact collapse this ledger exists to refuse.
|
|
377
|
+
if (lanes.length === 0) return null;
|
|
378
|
+
const signals = lanes.flatMap(lane =>
|
|
379
|
+
artifactStalenessSignals(
|
|
380
|
+
readFileSync(path.join(root, lane, callerPath), "utf8")
|
|
381
|
+
)
|
|
382
|
+
);
|
|
383
|
+
return [...new Set(signals)];
|
|
384
|
+
};
|
|
504
385
|
const names = existsSync(workflowsDir)
|
|
505
386
|
? readdirSync(workflowsDir)
|
|
506
387
|
.filter(name => name.endsWith(".yml") || name.endsWith(".yaml"))
|
|
@@ -519,6 +400,7 @@ export function measure(root: string): {
|
|
|
519
400
|
workflow: entry.name,
|
|
520
401
|
text: entry.text,
|
|
521
402
|
lanesFor,
|
|
403
|
+
artifactSignalsFor,
|
|
522
404
|
}),
|
|
523
405
|
}));
|
|
524
406
|
const couplings: readonly CouplingInput[] = scanned.flatMap(
|
|
@@ -534,9 +416,10 @@ export function measure(root: string): {
|
|
|
534
416
|
inventory: inventory.size,
|
|
535
417
|
},
|
|
536
418
|
ratified: readRatified(path.join(root, LEDGER_PATH)),
|
|
419
|
+
classified: readClassified(path.join(root, LEDGER_PATH)),
|
|
537
420
|
}),
|
|
538
421
|
ratified: readRatified(path.join(root, LEDGER_PATH)),
|
|
539
|
-
|
|
422
|
+
classified: readClassified(path.join(root, LEDGER_PATH)),
|
|
540
423
|
};
|
|
541
424
|
}
|
|
542
425
|
|
|
@@ -545,10 +428,7 @@ export function measure(root: string): {
|
|
|
545
428
|
* @param report - The measurement
|
|
546
429
|
* @returns The report text
|
|
547
430
|
*/
|
|
548
|
-
function humanReport(
|
|
549
|
-
report: TwoChannelReport,
|
|
550
|
-
staleness: Readonly<Record<string, StalenessClassification>>
|
|
551
|
-
): string {
|
|
431
|
+
function humanReport(report: TwoChannelReport): string {
|
|
552
432
|
const counts = report.inspected;
|
|
553
433
|
const header =
|
|
554
434
|
`two-channel delivery: inspected ${counts.workflows} reusable workflow(s), ` +
|
|
@@ -568,12 +448,64 @@ function humanReport(
|
|
|
568
448
|
`inherit. Delete it from ${LEDGER_PATH}.`
|
|
569
449
|
)
|
|
570
450
|
.join("");
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
451
|
+
return `${header}\n${verdicts}\n${stalenessReport(report)}${findings}${stale}`;
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
/**
|
|
455
|
+
* The staleness half of the report: the fleet tally and anything unanswered.
|
|
456
|
+
*
|
|
457
|
+
* Every line carries its denominator. "10 can detect staleness" is a number
|
|
458
|
+
* somebody can believe without knowing whether it is out of 12 or out of 700,
|
|
459
|
+
* and a coverage figure nobody can size is the shape of report this repository
|
|
460
|
+
* has been burned by before.
|
|
461
|
+
* @param report - The measurement
|
|
462
|
+
* @returns The staleness section
|
|
463
|
+
*/
|
|
464
|
+
function stalenessReport(report: TwoChannelReport): string {
|
|
465
|
+
const total = report.classifiable;
|
|
466
|
+
const handshakes = report.detectionCounts["version-handshake"];
|
|
467
|
+
const probes = report.detectionCounts["capability-probe"];
|
|
468
|
+
const blind =
|
|
469
|
+
report.detectionCounts["existence-only"] +
|
|
470
|
+
report.detectionCounts["no-probe"];
|
|
471
|
+
const unchecked = report.detectionCounts.unchecked;
|
|
472
|
+
const headline =
|
|
473
|
+
`staleness detection: ${handshakes}/${total} coupling(s) can detect a stale ` +
|
|
474
|
+
`artifact (version handshake); ${probes}/${total} detect it at one capability ` +
|
|
475
|
+
`floor only; ${blind}/${total} detect absence at most and never age; ` +
|
|
476
|
+
`${unchecked}/${total} could not be checked (nothing is delivered at the path, ` +
|
|
477
|
+
`so there is no artifact to ask).`;
|
|
478
|
+
const detections = STALENESS_DETECTIONS.map(
|
|
479
|
+
detection => ` ${detection}: ${report.detectionCounts[detection]}`
|
|
480
|
+
).join("\n");
|
|
481
|
+
const decisions = STALENESS_DECISIONS.map(
|
|
482
|
+
decision => ` decision ${decision}: ${report.decisionCounts[decision]}`
|
|
483
|
+
).join("\n");
|
|
484
|
+
const unclassified = report.unclassified
|
|
485
|
+
.map(
|
|
486
|
+
key =>
|
|
487
|
+
`\nUNCLASSIFIED ${key}\n No staleness decision is recorded for this ` +
|
|
488
|
+
`coupling. Its detection is derived on every run and costs nobody ` +
|
|
489
|
+
`anything; the decision is the half a person has to make. Add an entry ` +
|
|
490
|
+
`under "staleness" in ${LEDGER_PATH} with a decision of ` +
|
|
491
|
+
`${STALENESS_DECISIONS.join(" | ")} and, unless it is \`handshake\`, a reason.`
|
|
492
|
+
)
|
|
493
|
+
.join("");
|
|
494
|
+
const contradictions = report.contradictions
|
|
495
|
+
.map(sentence => `\nCONTRADICTED DECISION ${sentence}`)
|
|
496
|
+
.join("");
|
|
497
|
+
const malformed = report.malformed
|
|
498
|
+
.map(sentence => `\nMALFORMED DECISION ${sentence}`)
|
|
499
|
+
.join("");
|
|
500
|
+
const staleDecisions = report.staleClassifications
|
|
501
|
+
.map(
|
|
502
|
+
key =>
|
|
503
|
+
`\nSTALE STALENESS DECISION ${key}\n Nothing reads this path any more, ` +
|
|
504
|
+
`so the decision is an unexamined exemption the next matching path would ` +
|
|
505
|
+
`inherit. Delete it from ${LEDGER_PATH}.`
|
|
506
|
+
)
|
|
507
|
+
.join("");
|
|
508
|
+
return `${headline}\n${detections}\n${decisions}${unclassified}${contradictions}${malformed}${staleDecisions}`;
|
|
577
509
|
}
|
|
578
510
|
|
|
579
511
|
/**
|
|
@@ -587,9 +519,9 @@ export function main(argv: readonly string[]): number {
|
|
|
587
519
|
process.stderr.write(`error: --root does not exist: ${options.root}\n`);
|
|
588
520
|
return EXIT_OPERATIONAL;
|
|
589
521
|
}
|
|
590
|
-
const { report, ratified,
|
|
522
|
+
const { report, ratified, classified } = measure(options.root);
|
|
591
523
|
process.stdout.write(
|
|
592
|
-
`${options.json ? JSON.stringify(report, null, 2) : humanReport(report
|
|
524
|
+
`${options.json ? JSON.stringify(report, null, 2) : humanReport(report)}\n`
|
|
593
525
|
);
|
|
594
526
|
if (!report.measured) {
|
|
595
527
|
process.stderr.write(
|
|
@@ -600,7 +532,7 @@ export function main(argv: readonly string[]): number {
|
|
|
600
532
|
return EXIT_OPERATIONAL;
|
|
601
533
|
}
|
|
602
534
|
const ledgerPath = path.join(options.root, LEDGER_PATH);
|
|
603
|
-
const rendered = `${JSON.stringify(toLedger(report, ratified,
|
|
535
|
+
const rendered = `${JSON.stringify(toLedger(report, ratified, classified), null, 2)}\n`;
|
|
604
536
|
const current = existsSync(ledgerPath)
|
|
605
537
|
? readFileSync(ledgerPath, "utf8")
|
|
606
538
|
: "";
|
|
@@ -616,14 +548,13 @@ export function main(argv: readonly string[]): number {
|
|
|
616
548
|
mkdirSync(path.dirname(ledgerPath), { recursive: true });
|
|
617
549
|
writeFileSync(ledgerPath, rendered);
|
|
618
550
|
}
|
|
619
|
-
// The staleness half fails in BOTH modes, exactly as findings do. A gate you
|
|
620
|
-
// can regenerate your way past is not a gate: regenerating records a coupling,
|
|
621
|
-
// it does not classify one, and `toLedger` carries the map through untouched
|
|
622
|
-
// rather than inventing a default for a new entry (#3687).
|
|
623
551
|
const failed =
|
|
624
552
|
report.findings.length > 0 ||
|
|
625
553
|
report.staleRatifications.length > 0 ||
|
|
626
|
-
|
|
554
|
+
report.unclassified.length > 0 ||
|
|
555
|
+
report.contradictions.length > 0 ||
|
|
556
|
+
report.malformed.length > 0 ||
|
|
557
|
+
report.staleClassifications.length > 0 ||
|
|
627
558
|
ledgerStale;
|
|
628
559
|
return failed ? 1 : 0;
|
|
629
560
|
}
|
|
@@ -829,6 +829,37 @@ if [ "$notice_due" -eq 1 ]; then
|
|
|
829
829
|
fi
|
|
830
830
|
fi
|
|
831
831
|
|
|
832
|
+
# ---------------------------------------------------------------------------
|
|
833
|
+
# One evaluation per guard per tool call
|
|
834
|
+
#
|
|
835
|
+
# The guards below are also registered individually by the plugin manifest, so
|
|
836
|
+
# on a machine where both channels are live each one runs twice for a single
|
|
837
|
+
# tool call. `guard-dedupe.bash`, sourced by each guard, lets the second copy
|
|
838
|
+
# replay the first copy's ALLOW instead of recomputing it — and only when the
|
|
839
|
+
# two copies are byte-identical, on the identical payload, within the identical
|
|
840
|
+
# tool call. Nothing above is de-registered for it, because plugin-hook liveness
|
|
841
|
+
# is not observable from disk and standing down on a disk guess is how this
|
|
842
|
+
# dispatcher once switched enforcement off silently (CodySwannGT/lisa#3814).
|
|
843
|
+
#
|
|
844
|
+
# What is handed down here is only the state directory. `$notice_temp_base` has
|
|
845
|
+
# already been resolved physically and had every parent checked for ownership
|
|
846
|
+
# and mode, so the eight guards this loop spawns inherit that work instead of
|
|
847
|
+
# repeating it eight times. A guard reached by the plugin channel has no such
|
|
848
|
+
# parent and resolves its own; a guard that finds this variable unusable does
|
|
849
|
+
# the same. Exported only when the chain was trusted, so an untrusted TMPDIR
|
|
850
|
+
# hands down nothing rather than handing down a bad path.
|
|
851
|
+
if [ -n "$notice_temp_base" ] && [ "$notice_state_trusted" -eq 1 ]; then
|
|
852
|
+
guard_memo_dir="$notice_temp_base/lisa-guard-memo-$notice_uid"
|
|
853
|
+
if [ ! -e "$guard_memo_dir" ] && [ ! -L "$guard_memo_dir" ]; then
|
|
854
|
+
(umask 077 && mkdir "$guard_memo_dir") 2>/dev/null || true
|
|
855
|
+
fi
|
|
856
|
+
if [ -d "$guard_memo_dir" ] && [ ! -L "$guard_memo_dir" ] && \
|
|
857
|
+
[ -O "$guard_memo_dir" ]; then
|
|
858
|
+
export LISA_GUARD_MEMO_DIR="$guard_memo_dir"
|
|
859
|
+
export LISA_GUARD_MEMO_UID="$notice_uid"
|
|
860
|
+
fi
|
|
861
|
+
fi
|
|
862
|
+
|
|
832
863
|
# ---------------------------------------------------------------------------
|
|
833
864
|
# Dispatch
|
|
834
865
|
status=0
|