@codyswann/lisa 4.22.8 → 4.22.10
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/lib/process-tree-runner.mjs +127 -0
- package/all/copy-overwrite/scripts/lisa-floor-collisions.mjs +63 -8
- package/all/copy-overwrite/scripts/lisa-hooks/parity-safety-net.sh +36 -6
- package/all/copy-overwrite/scripts/lisa-postinstall.mjs +35 -13
- package/all/copy-overwrite/scripts/lisa-reconcile-policy.mjs +11 -3
- package/all/copy-overwrite/scripts/lisa-run-gates.mjs +41 -8
- package/all/copy-overwrite/scripts/lisa-schema-validate.mjs +2 -2
- package/all/copy-overwrite/scripts/lisa-work-item.mjs +2 -1
- package/cdk/package-lisa/package.lisa.json +1 -1
- package/dist/core/lisa-owned-hash-ledger.d.ts.map +1 -1
- package/dist/core/lisa-owned-hash-ledger.js +24 -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/nightly-e2e-guard-behavior-certificate.js.map +1 -1
- package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
- package/dist/core/upstream-evidence-manifest.js +61 -51
- package/dist/core/upstream-evidence-manifest.js.map +1 -1
- package/dist/opencode/plugin-templates/parity-safety-net.sh +36 -6
- package/nestjs/package-lisa/package.lisa.json +1 -1
- package/package.json +3 -3
- 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-atlassian-access/SKILL.md +10 -13
- package/plugins/lisa/.codex-plugin/skills/lisa-doctor/SKILL.md +4 -2
- package/plugins/lisa/.codex-plugin/skills/lisa-drive-pr-to-merge/SKILL.md +29 -4
- package/plugins/lisa/.codex-plugin/skills/lisa-github-sync/SKILL.md +8 -3
- package/plugins/lisa/.codex-plugin/skills/lisa-jam-access/SKILL.md +7 -10
- package/plugins/lisa/.codex-plugin/skills/lisa-jira-journey/SKILL.md +5 -0
- package/plugins/lisa/.codex-plugin/skills/lisa-jira-journey/scripts/parse-plan.py +36 -2
- package/plugins/lisa/.codex-plugin/skills/lisa-jira-sync/SKILL.md +1 -1
- package/plugins/lisa/.codex-plugin/skills/lisa-linear-access/SKILL.md +8 -12
- package/plugins/lisa/.codex-plugin/skills/lisa-linear-sync/SKILL.md +1 -1
- package/plugins/lisa/.codex-plugin/skills/lisa-nightly-lower-code-complexity/SKILL.md +7 -1
- package/plugins/lisa/.codex-plugin/skills/lisa-notion-access/SKILL.md +7 -10
- package/plugins/lisa/.codex-plugin/skills/lisa-posthog-access/SKILL.md +7 -10
- package/plugins/lisa/.codex-plugin/skills/lisa-repair-intake/SKILL.md +19 -3
- package/plugins/lisa/.codex-plugin/skills/lisa-secrets-access/scripts/materialize-secrets.mjs +10 -6
- package/plugins/lisa/.codex-plugin/skills/lisa-secrets-access/scripts/publish-aws-bootstrap.mjs +95 -44
- package/plugins/lisa/.codex-plugin/skills/lisa-sentry-access/SKILL.md +7 -10
- package/plugins/lisa/.codex-plugin/skills/lisa-setup-atlassian/SKILL.md +7 -10
- package/plugins/lisa/.codex-plugin/skills/lisa-setup-linear/SKILL.md +9 -12
- package/plugins/lisa/.codex-plugin/skills/lisa-setup-notion/SKILL.md +7 -10
- package/plugins/lisa/.codex-plugin/skills/lisa-setup-remote-aws/SKILL.md +7 -2
- package/plugins/lisa/.codex-plugin/skills/lisa-setup-remote-env/SKILL.md +6 -1
- package/plugins/lisa/.codex-plugin/skills/lisa-setup-remote-env/assets/session-start.sh +19 -0
- package/plugins/lisa/.codex-plugin/skills/lisa-setup-remote-env/assets/setup.sh +1 -0
- package/plugins/lisa/.codex-plugin/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +25 -4
- package/plugins/lisa/.codex-plugin/skills/lisa-setup-workstation/scripts/bounded-child.mjs +9 -0
- package/plugins/lisa/.codex-plugin/skills/lisa-setup-workstation/scripts/workstation.mjs +29 -21
- package/plugins/lisa/.codex-plugin/skills/lisa-sonarcloud-access/SKILL.md +7 -10
- package/plugins/lisa/.codex-plugin/skills/lisa-tracker-sync/SKILL.md +1 -1
- package/plugins/lisa/hooks/parity-safety-net.sh +36 -6
- package/plugins/lisa/hooks/threshold-ratchet-families.mjs +31 -7
- package/plugins/lisa/rules/reference/base-rules.md +1 -1
- package/plugins/lisa/rules/reference/config-resolution.md +5 -14
- package/plugins/lisa/scripts/install-remote-agent-aws.mjs +5 -1
- package/plugins/lisa/scripts/rollup-blocker-classification.mjs +18 -3
- package/plugins/lisa/skills/lisa-atlassian-access/SKILL.md +10 -13
- package/plugins/lisa/skills/lisa-doctor/SKILL.md +4 -2
- package/plugins/lisa/skills/lisa-drive-pr-to-merge/SKILL.md +29 -4
- package/plugins/lisa/skills/lisa-github-sync/SKILL.md +8 -3
- package/plugins/lisa/skills/lisa-jam-access/SKILL.md +7 -10
- package/plugins/lisa/skills/lisa-jira-journey/SKILL.md +5 -0
- package/plugins/lisa/skills/lisa-jira-journey/scripts/parse-plan.py +36 -2
- package/plugins/lisa/skills/lisa-jira-sync/SKILL.md +1 -1
- package/plugins/lisa/skills/lisa-linear-access/SKILL.md +8 -12
- package/plugins/lisa/skills/lisa-linear-sync/SKILL.md +1 -1
- package/plugins/lisa/skills/lisa-nightly-lower-code-complexity/SKILL.md +7 -1
- package/plugins/lisa/skills/lisa-notion-access/SKILL.md +7 -10
- package/plugins/lisa/skills/lisa-posthog-access/SKILL.md +7 -10
- package/plugins/lisa/skills/lisa-repair-intake/SKILL.md +19 -3
- package/plugins/lisa/skills/lisa-secrets-access/scripts/materialize-secrets.mjs +10 -6
- package/plugins/lisa/skills/lisa-secrets-access/scripts/publish-aws-bootstrap.mjs +95 -44
- package/plugins/lisa/skills/lisa-sentry-access/SKILL.md +7 -10
- package/plugins/lisa/skills/lisa-setup-atlassian/SKILL.md +7 -10
- package/plugins/lisa/skills/lisa-setup-linear/SKILL.md +9 -12
- package/plugins/lisa/skills/lisa-setup-notion/SKILL.md +7 -10
- package/plugins/lisa/skills/lisa-setup-remote-aws/SKILL.md +7 -2
- package/plugins/lisa/skills/lisa-setup-remote-env/SKILL.md +6 -1
- package/plugins/lisa/skills/lisa-setup-remote-env/assets/session-start.sh +19 -0
- package/plugins/lisa/skills/lisa-setup-remote-env/assets/setup.sh +1 -0
- package/plugins/lisa/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +25 -4
- package/plugins/lisa/skills/lisa-setup-workstation/scripts/bounded-child.mjs +9 -0
- package/plugins/lisa/skills/lisa-setup-workstation/scripts/workstation.mjs +29 -21
- package/plugins/lisa/skills/lisa-sonarcloud-access/SKILL.md +7 -10
- package/plugins/lisa/skills/lisa-tracker-sync/SKILL.md +1 -1
- package/plugins/lisa-agy/hooks/parity-safety-net.sh +36 -6
- package/plugins/lisa-agy/plugin.json +1 -1
- package/plugins/lisa-agy/scripts/install-remote-agent-aws.mjs +5 -1
- package/plugins/lisa-agy/scripts/rollup-blocker-classification.mjs +18 -3
- package/plugins/lisa-agy/skills/lisa-atlassian-access/SKILL.md +10 -13
- package/plugins/lisa-agy/skills/lisa-doctor/SKILL.md +4 -2
- package/plugins/lisa-agy/skills/lisa-drive-pr-to-merge/SKILL.md +29 -4
- package/plugins/lisa-agy/skills/lisa-github-sync/SKILL.md +8 -3
- package/plugins/lisa-agy/skills/lisa-jam-access/SKILL.md +7 -10
- package/plugins/lisa-agy/skills/lisa-jira-journey/SKILL.md +5 -0
- package/plugins/lisa-agy/skills/lisa-jira-journey/scripts/parse-plan.py +36 -2
- package/plugins/lisa-agy/skills/lisa-jira-sync/SKILL.md +1 -1
- package/plugins/lisa-agy/skills/lisa-linear-access/SKILL.md +8 -12
- package/plugins/lisa-agy/skills/lisa-linear-sync/SKILL.md +1 -1
- package/plugins/lisa-agy/skills/lisa-nightly-lower-code-complexity/SKILL.md +7 -1
- package/plugins/lisa-agy/skills/lisa-notion-access/SKILL.md +7 -10
- package/plugins/lisa-agy/skills/lisa-posthog-access/SKILL.md +7 -10
- package/plugins/lisa-agy/skills/lisa-repair-intake/SKILL.md +19 -3
- package/plugins/lisa-agy/skills/lisa-secrets-access/scripts/materialize-secrets.mjs +10 -6
- package/plugins/lisa-agy/skills/lisa-secrets-access/scripts/publish-aws-bootstrap.mjs +95 -44
- package/plugins/lisa-agy/skills/lisa-sentry-access/SKILL.md +7 -10
- package/plugins/lisa-agy/skills/lisa-setup-atlassian/SKILL.md +7 -10
- package/plugins/lisa-agy/skills/lisa-setup-linear/SKILL.md +9 -12
- package/plugins/lisa-agy/skills/lisa-setup-notion/SKILL.md +7 -10
- package/plugins/lisa-agy/skills/lisa-setup-remote-aws/SKILL.md +7 -2
- package/plugins/lisa-agy/skills/lisa-setup-remote-env/SKILL.md +6 -1
- package/plugins/lisa-agy/skills/lisa-setup-remote-env/assets/session-start.sh +19 -0
- package/plugins/lisa-agy/skills/lisa-setup-remote-env/assets/setup.sh +1 -0
- package/plugins/lisa-agy/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +25 -4
- package/plugins/lisa-agy/skills/lisa-setup-workstation/scripts/bounded-child.mjs +9 -0
- package/plugins/lisa-agy/skills/lisa-setup-workstation/scripts/workstation.mjs +29 -21
- package/plugins/lisa-agy/skills/lisa-sonarcloud-access/SKILL.md +7 -10
- package/plugins/lisa-agy/skills/lisa-tracker-sync/SKILL.md +1 -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/parity-safety-net.sh +36 -6
- package/plugins/lisa-copilot/hooks/threshold-ratchet-families.mjs +31 -7
- package/plugins/lisa-copilot/rules/reference/base-rules.md +1 -1
- package/plugins/lisa-copilot/rules/reference/config-resolution.md +5 -14
- package/plugins/lisa-copilot/scripts/install-remote-agent-aws.mjs +5 -1
- package/plugins/lisa-copilot/scripts/rollup-blocker-classification.mjs +18 -3
- package/plugins/lisa-copilot/skills/lisa-atlassian-access/SKILL.md +10 -13
- package/plugins/lisa-copilot/skills/lisa-doctor/SKILL.md +4 -2
- package/plugins/lisa-copilot/skills/lisa-drive-pr-to-merge/SKILL.md +29 -4
- package/plugins/lisa-copilot/skills/lisa-github-sync/SKILL.md +8 -3
- package/plugins/lisa-copilot/skills/lisa-jam-access/SKILL.md +7 -10
- package/plugins/lisa-copilot/skills/lisa-jira-journey/SKILL.md +5 -0
- package/plugins/lisa-copilot/skills/lisa-jira-journey/scripts/parse-plan.py +36 -2
- package/plugins/lisa-copilot/skills/lisa-jira-sync/SKILL.md +1 -1
- package/plugins/lisa-copilot/skills/lisa-linear-access/SKILL.md +8 -12
- package/plugins/lisa-copilot/skills/lisa-linear-sync/SKILL.md +1 -1
- package/plugins/lisa-copilot/skills/lisa-nightly-lower-code-complexity/SKILL.md +7 -1
- package/plugins/lisa-copilot/skills/lisa-notion-access/SKILL.md +7 -10
- package/plugins/lisa-copilot/skills/lisa-posthog-access/SKILL.md +7 -10
- package/plugins/lisa-copilot/skills/lisa-repair-intake/SKILL.md +19 -3
- package/plugins/lisa-copilot/skills/lisa-secrets-access/scripts/materialize-secrets.mjs +10 -6
- package/plugins/lisa-copilot/skills/lisa-secrets-access/scripts/publish-aws-bootstrap.mjs +95 -44
- package/plugins/lisa-copilot/skills/lisa-sentry-access/SKILL.md +7 -10
- package/plugins/lisa-copilot/skills/lisa-setup-atlassian/SKILL.md +7 -10
- package/plugins/lisa-copilot/skills/lisa-setup-linear/SKILL.md +9 -12
- package/plugins/lisa-copilot/skills/lisa-setup-notion/SKILL.md +7 -10
- package/plugins/lisa-copilot/skills/lisa-setup-remote-aws/SKILL.md +7 -2
- package/plugins/lisa-copilot/skills/lisa-setup-remote-env/SKILL.md +6 -1
- package/plugins/lisa-copilot/skills/lisa-setup-remote-env/assets/session-start.sh +19 -0
- package/plugins/lisa-copilot/skills/lisa-setup-remote-env/assets/setup.sh +1 -0
- package/plugins/lisa-copilot/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +25 -4
- package/plugins/lisa-copilot/skills/lisa-setup-workstation/scripts/bounded-child.mjs +9 -0
- package/plugins/lisa-copilot/skills/lisa-setup-workstation/scripts/workstation.mjs +29 -21
- package/plugins/lisa-copilot/skills/lisa-sonarcloud-access/SKILL.md +7 -10
- package/plugins/lisa-copilot/skills/lisa-tracker-sync/SKILL.md +1 -1
- package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cursor/hooks/parity-safety-net.sh +36 -6
- package/plugins/lisa-cursor/hooks/threshold-ratchet-families.mjs +31 -7
- package/plugins/lisa-cursor/rules/base-rules-reference.mdc +1 -1
- package/plugins/lisa-cursor/rules/config-resolution-reference.mdc +5 -14
- package/plugins/lisa-cursor/scripts/install-remote-agent-aws.mjs +5 -1
- package/plugins/lisa-cursor/scripts/rollup-blocker-classification.mjs +18 -3
- package/plugins/lisa-cursor/skills/lisa-atlassian-access/SKILL.md +10 -13
- package/plugins/lisa-cursor/skills/lisa-doctor/SKILL.md +4 -2
- package/plugins/lisa-cursor/skills/lisa-drive-pr-to-merge/SKILL.md +29 -4
- package/plugins/lisa-cursor/skills/lisa-github-sync/SKILL.md +8 -3
- package/plugins/lisa-cursor/skills/lisa-jam-access/SKILL.md +7 -10
- package/plugins/lisa-cursor/skills/lisa-jira-journey/SKILL.md +5 -0
- package/plugins/lisa-cursor/skills/lisa-jira-journey/scripts/parse-plan.py +36 -2
- package/plugins/lisa-cursor/skills/lisa-jira-sync/SKILL.md +1 -1
- package/plugins/lisa-cursor/skills/lisa-linear-access/SKILL.md +8 -12
- package/plugins/lisa-cursor/skills/lisa-linear-sync/SKILL.md +1 -1
- package/plugins/lisa-cursor/skills/lisa-nightly-lower-code-complexity/SKILL.md +7 -1
- package/plugins/lisa-cursor/skills/lisa-notion-access/SKILL.md +7 -10
- package/plugins/lisa-cursor/skills/lisa-posthog-access/SKILL.md +7 -10
- package/plugins/lisa-cursor/skills/lisa-repair-intake/SKILL.md +19 -3
- package/plugins/lisa-cursor/skills/lisa-secrets-access/scripts/materialize-secrets.mjs +10 -6
- package/plugins/lisa-cursor/skills/lisa-secrets-access/scripts/publish-aws-bootstrap.mjs +95 -44
- package/plugins/lisa-cursor/skills/lisa-sentry-access/SKILL.md +7 -10
- package/plugins/lisa-cursor/skills/lisa-setup-atlassian/SKILL.md +7 -10
- package/plugins/lisa-cursor/skills/lisa-setup-linear/SKILL.md +9 -12
- package/plugins/lisa-cursor/skills/lisa-setup-notion/SKILL.md +7 -10
- package/plugins/lisa-cursor/skills/lisa-setup-remote-aws/SKILL.md +7 -2
- package/plugins/lisa-cursor/skills/lisa-setup-remote-env/SKILL.md +6 -1
- package/plugins/lisa-cursor/skills/lisa-setup-remote-env/assets/session-start.sh +19 -0
- package/plugins/lisa-cursor/skills/lisa-setup-remote-env/assets/setup.sh +1 -0
- package/plugins/lisa-cursor/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +25 -4
- package/plugins/lisa-cursor/skills/lisa-setup-workstation/scripts/bounded-child.mjs +9 -0
- package/plugins/lisa-cursor/skills/lisa-setup-workstation/scripts/workstation.mjs +29 -21
- package/plugins/lisa-cursor/skills/lisa-sonarcloud-access/SKILL.md +7 -10
- package/plugins/lisa-cursor/skills/lisa-tracker-sync/SKILL.md +1 -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/parity-safety-net.sh +36 -6
- package/plugins/src/base/hooks/threshold-ratchet-families.mjs +31 -7
- package/plugins/src/base/rules/reference/base-rules.md +1 -1
- package/plugins/src/base/rules/reference/config-resolution.md +5 -14
- package/plugins/src/base/scripts/install-remote-agent-aws.mjs +5 -1
- package/plugins/src/base/scripts/rollup-blocker-classification.mjs +18 -3
- package/plugins/src/base/skills/lisa-atlassian-access/SKILL.md +10 -13
- package/plugins/src/base/skills/lisa-doctor/SKILL.md +4 -2
- package/plugins/src/base/skills/lisa-drive-pr-to-merge/SKILL.md +29 -4
- package/plugins/src/base/skills/lisa-github-sync/SKILL.md +8 -3
- package/plugins/src/base/skills/lisa-jam-access/SKILL.md +7 -10
- package/plugins/src/base/skills/lisa-jira-journey/SKILL.md +5 -0
- package/plugins/src/base/skills/lisa-jira-journey/scripts/parse-plan.py +36 -2
- package/plugins/src/base/skills/lisa-jira-sync/SKILL.md +1 -1
- package/plugins/src/base/skills/lisa-linear-access/SKILL.md +8 -12
- package/plugins/src/base/skills/lisa-linear-sync/SKILL.md +1 -1
- package/plugins/src/base/skills/lisa-nightly-lower-code-complexity/SKILL.md +7 -1
- package/plugins/src/base/skills/lisa-notion-access/SKILL.md +7 -10
- package/plugins/src/base/skills/lisa-posthog-access/SKILL.md +7 -10
- package/plugins/src/base/skills/lisa-repair-intake/SKILL.md +19 -3
- package/plugins/src/base/skills/lisa-secrets-access/scripts/materialize-secrets.mjs +10 -6
- package/plugins/src/base/skills/lisa-secrets-access/scripts/publish-aws-bootstrap.mjs +95 -44
- package/plugins/src/base/skills/lisa-sentry-access/SKILL.md +7 -10
- package/plugins/src/base/skills/lisa-setup-atlassian/SKILL.md +7 -10
- package/plugins/src/base/skills/lisa-setup-linear/SKILL.md +9 -12
- package/plugins/src/base/skills/lisa-setup-notion/SKILL.md +7 -10
- package/plugins/src/base/skills/lisa-setup-remote-aws/SKILL.md +7 -2
- package/plugins/src/base/skills/lisa-setup-remote-env/SKILL.md +6 -1
- package/plugins/src/base/skills/lisa-setup-remote-env/assets/session-start.sh +19 -0
- package/plugins/src/base/skills/lisa-setup-remote-env/assets/setup.sh +1 -0
- package/plugins/src/base/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +25 -4
- package/plugins/src/base/skills/lisa-setup-workstation/scripts/bounded-child.mjs +9 -0
- package/plugins/src/base/skills/lisa-setup-workstation/scripts/workstation.mjs +29 -21
- package/plugins/src/base/skills/lisa-sonarcloud-access/SKILL.md +7 -10
- package/plugins/src/base/skills/lisa-tracker-sync/SKILL.md +1 -1
- package/rails/copy-overwrite/scripts/threshold-ratchet-families.mjs +31 -7
- package/scripts/lisa-remote-env/session-start.sh +19 -0
- package/scripts/lisa-remote-env/setup.sh +1 -0
- package/scripts/two-channel-couplings.json +1 -1
- package/typescript/copy-contents/.husky/pre-push +1 -1
- package/typescript/copy-overwrite/scripts/threshold-ratchet-families.mjs +31 -7
- package/typescript/package-lisa/package.lisa.json +1 -1
|
@@ -173,9 +173,9 @@ read_notion_token() {
|
|
|
173
173
|
# than "this function" is deliberate — the old wording asked for something
|
|
174
174
|
# unachievable, and an unachievable rule is one that gets quietly dropped.
|
|
175
175
|
#
|
|
176
|
-
# Ordered
|
|
177
|
-
#
|
|
178
|
-
#
|
|
176
|
+
# Ordered across trusted machine-managed substrates, ending at the installed
|
|
177
|
+
# package. Checkout-local paths are deliberately absent: a familiar generated
|
|
178
|
+
# destination is still repository-controlled executable code. The plugin
|
|
179
179
|
# rungs are the floor: `resolve-secret.mjs` ships beside this skill, so a rung
|
|
180
180
|
# pointing at it is reachable from anywhere the plugin itself is installed.
|
|
181
181
|
# Without one, a consumer repository that vendors none of the leading paths
|
|
@@ -184,12 +184,9 @@ read_notion_token() {
|
|
|
184
184
|
# lookups. This LADDER is identical in every skill that resolves a credential
|
|
185
185
|
# and `credential-resolver-ladder` fails if any copy diverges. Only what
|
|
186
186
|
# happens AFTER the ladder may differ between them.
|
|
187
|
-
local
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
.opencode/skills/lisa/lisa-secrets-access/scripts/resolve-secret.mjs
|
|
191
|
-
.codex/skills/lisa/lisa-secrets-access/scripts/resolve-secret.mjs
|
|
192
|
-
)
|
|
187
|
+
# Execute only machine-managed plugin/package resolvers. Checkout-local
|
|
188
|
+
# candidates are repository-controlled code, not trusted merely by path.
|
|
189
|
+
local candidates=()
|
|
193
190
|
if [ -n "${CLAUDE_PLUGIN_ROOT:-}" ]; then
|
|
194
191
|
candidates+=("$CLAUDE_PLUGIN_ROOT/skills/lisa-secrets-access/scripts/resolve-secret.mjs")
|
|
195
192
|
fi
|
|
@@ -208,7 +205,7 @@ read_notion_token() {
|
|
|
208
205
|
local via_lisa
|
|
209
206
|
via_lisa=$(node "$resolver" get NOTION_API_TOKEN 2>/dev/null) \
|
|
210
207
|
&& [ -n "$via_lisa" ] && { echo "$via_lisa"; return; }
|
|
211
|
-
|
|
208
|
+
# Empty/error means this substrate had no answer; try the next trusted one.
|
|
212
209
|
fi
|
|
213
210
|
done
|
|
214
211
|
# Legacy fallback: the OS keychain written by the guided flow below, for
|
|
@@ -64,13 +64,18 @@ The lock remains held through rollback and its deletion is verified before the
|
|
|
64
64
|
command reports success:
|
|
65
65
|
|
|
66
66
|
```bash
|
|
67
|
-
aws
|
|
68
|
-
--secret-id
|
|
67
|
+
aws secretsmanager get-secret-value \
|
|
68
|
+
--secret-id <selected-secret-name> \
|
|
69
69
|
--query SecretString \
|
|
70
70
|
--output text \
|
|
71
71
|
| node .claude/skills/lisa-secrets-access/scripts/publish-aws-bootstrap.mjs publish
|
|
72
72
|
```
|
|
73
73
|
|
|
74
|
+
Use the same secret name passed to `--secret-name`; the default is
|
|
75
|
+
`remote-agent-credentials`. Add `--profile <source-profile>` only when the
|
|
76
|
+
operator's ambient AWS identity cannot read the emission and the project names
|
|
77
|
+
a source profile. A named `shared` profile is not otherwise required.
|
|
78
|
+
|
|
74
79
|
Resolve the script from the installed runtime or `node_modules` when the
|
|
75
80
|
`.claude/skills` copy is not present. Never print or place the candidate in an
|
|
76
81
|
argument or temporary file. A CDK deployment followed later by a human copy is
|
|
@@ -97,9 +97,14 @@ A surface that **re-runs this script when a container resumes** — Codex Cloud
|
|
|
97
97
|
A surface that **skips this script whenever a filesystem cache exists** — Claude Code web — must not. Materializing here would write the values once and then never refresh them, so a credential rotated on Tuesday would still be serving Monday's value until the cache expired days later. Those surfaces materialize from a session-start hook instead, which runs every session including a resumed one:
|
|
98
98
|
|
|
99
99
|
```sh
|
|
100
|
-
bash scripts/lisa-remote-env/session-start.sh #
|
|
100
|
+
bash "$CLAUDE_PROJECT_DIR/scripts/lisa-remote-env/session-start.sh" # project-scoped absolute hook
|
|
101
101
|
```
|
|
102
102
|
|
|
103
|
+
The installer also registers a user-scoped hook using the checkout's resolved
|
|
104
|
+
absolute path. If invoking this asset by hand, either use that absolute path or
|
|
105
|
+
change to the repository root first; a bare checkout-relative command is not a
|
|
106
|
+
portable session-start configuration.
|
|
107
|
+
|
|
103
108
|
The selection comes from the surface's `materializeAt` capability in `lisa-secrets-access`, not from its name, so adding a surface does not mean editing a branch. The hook is committed to the repository, so it also fires on a developer's machine — it exits `0` immediately there rather than failing, because a correct local session must not look broken.
|
|
104
109
|
|
|
105
110
|
## Detect before you provision
|
|
@@ -46,8 +46,27 @@ here="$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd)"
|
|
|
46
46
|
# SessionStart hosts are fail-open, so they surface that result and still allow
|
|
47
47
|
# the agent session to continue.
|
|
48
48
|
bash "${here}/setup.sh" --phase=toolchain "$@"
|
|
49
|
+
|
|
50
|
+
# The toolchain child cannot export into this parent shell. Its durable output
|
|
51
|
+
# is linked into ~/.local/bin, so make that directory visible before the next
|
|
52
|
+
# child tries to execute the provider CLI it just installed.
|
|
53
|
+
case ":$PATH:" in
|
|
54
|
+
*":$HOME/.local/bin:"*) ;;
|
|
55
|
+
*) PATH="$HOME/.local/bin:$PATH"; export PATH ;;
|
|
56
|
+
esac
|
|
57
|
+
|
|
49
58
|
bash "${here}/setup.sh" --phase=secrets "$@"
|
|
50
59
|
|
|
60
|
+
# Materialization writes a Lisa-owned block into .profile that sources the
|
|
61
|
+
# generated environment and removes ambient AWS credential poison. The project
|
|
62
|
+
# hook is another non-login child, so load that block here and let the child
|
|
63
|
+
# inherit the exact environment materialization just produced.
|
|
64
|
+
if [ -r "$HOME/.profile" ]; then
|
|
65
|
+
# The materializer owns this runtime path.
|
|
66
|
+
# shellcheck disable=SC1090
|
|
67
|
+
. "$HOME/.profile"
|
|
68
|
+
fi
|
|
69
|
+
|
|
51
70
|
# A project hook is part of the remote toolchain contract too. It covers tools
|
|
52
71
|
# that cannot be expressed by the pinned manifest, so skipping it on a cached
|
|
53
72
|
# session can leave fresh credentials with no client capable of using them.
|
|
@@ -132,6 +132,7 @@ for candidate in \
|
|
|
132
132
|
".claude/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs" \
|
|
133
133
|
".agents/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs" \
|
|
134
134
|
".codex/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs" \
|
|
135
|
+
".opencode/skills/lisa/lisa-setup-remote-env/scripts/setup-remote-env.mjs" \
|
|
135
136
|
"plugins/lisa/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs" \
|
|
136
137
|
"node_modules/@codyswann/lisa/plugins/lisa/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs"; do
|
|
137
138
|
if [ -f "$candidate" ]; then
|
|
@@ -51,7 +51,10 @@ import { pathDirs } from "../../lisa-setup-workstation/scripts/catalogue.mjs";
|
|
|
51
51
|
|
|
52
52
|
import { assertPinned, extractVersion, planToolchain } from "./toolchain.mjs";
|
|
53
53
|
|
|
54
|
-
import {
|
|
54
|
+
import {
|
|
55
|
+
boundedChildOutput,
|
|
56
|
+
SETUP_OPERATION_BUDGET_MS,
|
|
57
|
+
} from "../../lisa-setup-workstation/scripts/bounded-child.mjs";
|
|
55
58
|
|
|
56
59
|
const HERE = dirname(fileURLToPath(import.meta.url));
|
|
57
60
|
|
|
@@ -173,12 +176,14 @@ function installReleaseZip(tool, binDir) {
|
|
|
173
176
|
const archive = join(temporary, "download.zip");
|
|
174
177
|
boundedChildOutput("curl", ["-fsSL", tool.url, "-o", archive], {
|
|
175
178
|
stdio: "inherit",
|
|
179
|
+
timeout: SETUP_OPERATION_BUDGET_MS,
|
|
176
180
|
});
|
|
177
181
|
// Verify before unpacking, not after. An unexpected archive must fail
|
|
178
182
|
// before any of its contents reach a directory that is on PATH.
|
|
179
183
|
verifyChecksum(archive, tool.sha256, tool.name);
|
|
180
184
|
boundedChildOutput("unzip", ["-q", "-o", archive, "-d", temporary], {
|
|
181
185
|
stdio: "inherit",
|
|
186
|
+
timeout: SETUP_OPERATION_BUDGET_MS,
|
|
182
187
|
});
|
|
183
188
|
const binary = join(temporary, tool.binary ?? tool.name);
|
|
184
189
|
boundedChildOutput(
|
|
@@ -186,6 +191,7 @@ function installReleaseZip(tool, binDir) {
|
|
|
186
191
|
["-m", "0755", binary, join(binDir, tool.name)],
|
|
187
192
|
{
|
|
188
193
|
stdio: "inherit",
|
|
194
|
+
timeout: SETUP_OPERATION_BUDGET_MS,
|
|
189
195
|
}
|
|
190
196
|
);
|
|
191
197
|
} finally {
|
|
@@ -210,10 +216,12 @@ function installReleaseTar(tool, binDir) {
|
|
|
210
216
|
const archive = join(temporary, "download.tar.gz");
|
|
211
217
|
boundedChildOutput("curl", ["-fsSL", tool.url, "-o", archive], {
|
|
212
218
|
stdio: "inherit",
|
|
219
|
+
timeout: SETUP_OPERATION_BUDGET_MS,
|
|
213
220
|
});
|
|
214
221
|
verifyChecksum(archive, tool.sha256, tool.name);
|
|
215
222
|
boundedChildOutput("tar", ["-xzf", archive, "-C", temporary], {
|
|
216
223
|
stdio: "inherit",
|
|
224
|
+
timeout: SETUP_OPERATION_BUDGET_MS,
|
|
217
225
|
});
|
|
218
226
|
// Release tarballs usually nest under a versioned directory, so `binary` is
|
|
219
227
|
// a path within the archive rather than a bare name.
|
|
@@ -223,6 +231,7 @@ function installReleaseTar(tool, binDir) {
|
|
|
223
231
|
["-m", "0755", binary, join(binDir, tool.name)],
|
|
224
232
|
{
|
|
225
233
|
stdio: "inherit",
|
|
234
|
+
timeout: SETUP_OPERATION_BUDGET_MS,
|
|
226
235
|
}
|
|
227
236
|
);
|
|
228
237
|
} finally {
|
|
@@ -272,6 +281,7 @@ function installReleaseTree(tool, binDir) {
|
|
|
272
281
|
const archive = join(temporary, "download.archive");
|
|
273
282
|
boundedChildOutput("curl", ["-fsSL", tool.url, "-o", archive], {
|
|
274
283
|
stdio: "inherit",
|
|
284
|
+
timeout: SETUP_OPERATION_BUDGET_MS,
|
|
275
285
|
});
|
|
276
286
|
// Verify before unpacking, as everywhere else here: an unexpected archive
|
|
277
287
|
// must fail before any of its contents reach the filesystem.
|
|
@@ -285,10 +295,12 @@ function installReleaseTree(tool, binDir) {
|
|
|
285
295
|
if (tool.url.endsWith(".zip")) {
|
|
286
296
|
boundedChildOutput("unzip", ["-q", "-o", archive, "-d", prefix], {
|
|
287
297
|
stdio: "inherit",
|
|
298
|
+
timeout: SETUP_OPERATION_BUDGET_MS,
|
|
288
299
|
});
|
|
289
300
|
} else {
|
|
290
301
|
boundedChildOutput("tar", ["-xzf", archive, "-C", prefix], {
|
|
291
302
|
stdio: "inherit",
|
|
303
|
+
timeout: SETUP_OPERATION_BUDGET_MS,
|
|
292
304
|
});
|
|
293
305
|
}
|
|
294
306
|
|
|
@@ -342,6 +354,7 @@ function installReleaseBinary(tool, binDir) {
|
|
|
342
354
|
const artifact = join(temporary, tool.name);
|
|
343
355
|
boundedChildOutput("curl", ["-fsSL", tool.url, "-o", artifact], {
|
|
344
356
|
stdio: "inherit",
|
|
357
|
+
timeout: SETUP_OPERATION_BUDGET_MS,
|
|
345
358
|
});
|
|
346
359
|
// Verify before it reaches a directory on PATH. For this kind that ordering
|
|
347
360
|
// matters more than for the archives: the downloaded file is directly
|
|
@@ -353,6 +366,7 @@ function installReleaseBinary(tool, binDir) {
|
|
|
353
366
|
["-m", "0755", artifact, join(binDir, tool.name)],
|
|
354
367
|
{
|
|
355
368
|
stdio: "inherit",
|
|
369
|
+
timeout: SETUP_OPERATION_BUDGET_MS,
|
|
356
370
|
}
|
|
357
371
|
);
|
|
358
372
|
} finally {
|
|
@@ -370,6 +384,7 @@ function installNpmGlobal(tool) {
|
|
|
370
384
|
["install", "--global", `${tool.package}@${tool.version}`],
|
|
371
385
|
{
|
|
372
386
|
stdio: "inherit",
|
|
387
|
+
timeout: SETUP_OPERATION_BUDGET_MS,
|
|
373
388
|
}
|
|
374
389
|
);
|
|
375
390
|
}
|
|
@@ -509,7 +524,10 @@ function runHook(hook, dryRun) {
|
|
|
509
524
|
console.log(`\nProject hook: ${hook}`);
|
|
510
525
|
if (dryRun) return;
|
|
511
526
|
chmodSync(path, 0o755);
|
|
512
|
-
boundedChildOutput("bash", [path], {
|
|
527
|
+
boundedChildOutput("bash", [path], {
|
|
528
|
+
stdio: "inherit",
|
|
529
|
+
timeout: SETUP_OPERATION_BUDGET_MS,
|
|
530
|
+
});
|
|
513
531
|
}
|
|
514
532
|
|
|
515
533
|
/** Phases this runner can execute, in the order they must happen. */
|
|
@@ -789,7 +807,10 @@ export function installUserSessionHook(repoRoot, options = {}) {
|
|
|
789
807
|
|
|
790
808
|
const dir = join(home, ".claude");
|
|
791
809
|
const settingsPath = join(dir, "settings.json");
|
|
792
|
-
|
|
810
|
+
// Settings stores shell source, so the absolute path still needs quoting.
|
|
811
|
+
// JSON string syntax is accepted by the shell for ordinary path text and
|
|
812
|
+
// safely escapes spaces, quotes, dollars and backticks.
|
|
813
|
+
const command = `bash ${JSON.stringify(script)}`;
|
|
793
814
|
|
|
794
815
|
let settings = {};
|
|
795
816
|
if (exists(settingsPath)) {
|
|
@@ -1506,7 +1527,7 @@ async function main() {
|
|
|
1506
1527
|
boundedChildOutput(
|
|
1507
1528
|
"node",
|
|
1508
1529
|
dryRun ? [materialize, "--dry-run"] : [materialize],
|
|
1509
|
-
{ stdio: "inherit" }
|
|
1530
|
+
{ stdio: "inherit", timeout: SETUP_OPERATION_BUDGET_MS }
|
|
1510
1531
|
);
|
|
1511
1532
|
} catch (err) {
|
|
1512
1533
|
if (!retried) throw err;
|
|
@@ -83,6 +83,15 @@ import { execFileSync, spawnSync } from "node:child_process";
|
|
|
83
83
|
*/
|
|
84
84
|
export const CHILD_BUDGET_MS = 30_000;
|
|
85
85
|
|
|
86
|
+
/**
|
|
87
|
+
* Deadline for setup operations that legitimately include downloads, package
|
|
88
|
+
* installation, secret-provider calls, or a project-declared hook.
|
|
89
|
+
*
|
|
90
|
+
* Kept separate from {@link CHILD_BUDGET_MS}: probes should still fail quickly,
|
|
91
|
+
* while a cold network install must not be killed by the probe budget.
|
|
92
|
+
*/
|
|
93
|
+
export const SETUP_OPERATION_BUDGET_MS = 10 * 60_000;
|
|
94
|
+
|
|
86
95
|
/**
|
|
87
96
|
* Whether this value is a child that was killed at its deadline.
|
|
88
97
|
*
|
|
@@ -36,7 +36,10 @@
|
|
|
36
36
|
import { existsSync, lstatSync, mkdirSync, rmSync, symlinkSync } from "node:fs";
|
|
37
37
|
import { join } from "node:path";
|
|
38
38
|
|
|
39
|
-
import {
|
|
39
|
+
import {
|
|
40
|
+
boundedChildOutput,
|
|
41
|
+
SETUP_OPERATION_BUDGET_MS,
|
|
42
|
+
} from "./bounded-child.mjs";
|
|
40
43
|
|
|
41
44
|
import {
|
|
42
45
|
AGENTS,
|
|
@@ -387,7 +390,9 @@ export function installEntry(entry, row, deps = {}) {
|
|
|
387
390
|
|
|
388
391
|
try {
|
|
389
392
|
if (entry.kind === "npm-global") {
|
|
390
|
-
run("npm", ["install", "-g", entry.package]
|
|
393
|
+
run("npm", ["install", "-g", entry.package], {
|
|
394
|
+
timeout: SETUP_OPERATION_BUDGET_MS,
|
|
395
|
+
});
|
|
391
396
|
} else if (entry.kind === "vendor-script") {
|
|
392
397
|
if (!entry.script) {
|
|
393
398
|
return {
|
|
@@ -410,12 +415,11 @@ export function installEntry(entry, row, deps = {}) {
|
|
|
410
415
|
// exit status is the SHELL's, not curl's, so a 404 feeds an empty script
|
|
411
416
|
// to bash, bash exits 0, and a tool that was never installed is reported
|
|
412
417
|
// as installed. That is exactly what `sonarsource.com/install` did.
|
|
413
|
-
run(
|
|
414
|
-
"
|
|
415
|
-
"pipefail",
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
]);
|
|
418
|
+
run(
|
|
419
|
+
"bash",
|
|
420
|
+
["-o", "pipefail", "-c", `curl -fsSL ${entry.script} | bash`],
|
|
421
|
+
{ timeout: SETUP_OPERATION_BUDGET_MS }
|
|
422
|
+
);
|
|
419
423
|
} else if (entry.kind === "aws-cli") {
|
|
420
424
|
// macOS ships a .pkg that wants an administrator, which a headless run
|
|
421
425
|
// has no business prompting for. Reported as manual with the one-line
|
|
@@ -436,20 +440,24 @@ export function installEntry(entry, row, deps = {}) {
|
|
|
436
440
|
const url = `https://awscli.amazonaws.com/awscli-exe-linux-${
|
|
437
441
|
process.arch === "arm64" ? "aarch64" : "x86_64"
|
|
438
442
|
}.zip`;
|
|
439
|
-
run(
|
|
440
|
-
"
|
|
441
|
-
"pipefail",
|
|
442
|
-
"-c",
|
|
443
|
+
run(
|
|
444
|
+
"bash",
|
|
443
445
|
[
|
|
444
|
-
"
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
446
|
+
"-o",
|
|
447
|
+
"pipefail",
|
|
448
|
+
"-c",
|
|
449
|
+
[
|
|
450
|
+
"set -e",
|
|
451
|
+
'tmp="$(mktemp -d)"',
|
|
452
|
+
`curl -fsSL "${url}" -o "$tmp/awscli.zip"`,
|
|
453
|
+
'unzip -q "$tmp/awscli.zip" -d "$tmp"',
|
|
454
|
+
`"$tmp/aws/install" --install-dir "${home}/.local/aws-cli" ` +
|
|
455
|
+
`--bin-dir "${home}/.local/bin" --update`,
|
|
456
|
+
'rm -rf "$tmp"',
|
|
457
|
+
].join("\n"),
|
|
458
|
+
],
|
|
459
|
+
{ timeout: SETUP_OPERATION_BUDGET_MS }
|
|
460
|
+
);
|
|
453
461
|
} else if (CHECKSUMMED.has(entry.kind)) {
|
|
454
462
|
// The pinned, checksummed path belongs to the remote-env installer. It is
|
|
455
463
|
// borrowed rather than reimplemented so the pins and checksums cannot
|
|
@@ -63,9 +63,9 @@ read_sonar_secret() {
|
|
|
63
63
|
local name="$1"
|
|
64
64
|
[ -n "${!name:-}" ] && { echo "${!name}"; return; }
|
|
65
65
|
#
|
|
66
|
-
# Ordered
|
|
67
|
-
#
|
|
68
|
-
#
|
|
66
|
+
# Ordered across trusted machine-managed substrates, ending at the installed
|
|
67
|
+
# package. Checkout-local paths are deliberately absent: a familiar generated
|
|
68
|
+
# destination is still repository-controlled executable code. The plugin
|
|
69
69
|
# rungs are the floor: `resolve-secret.mjs` ships beside this skill, so a rung
|
|
70
70
|
# pointing at it is reachable from anywhere the plugin itself is installed.
|
|
71
71
|
# Without one, a consumer repository that vendors none of the leading paths
|
|
@@ -74,12 +74,9 @@ read_sonar_secret() {
|
|
|
74
74
|
# lookups. This LADDER is identical in every skill that resolves a credential
|
|
75
75
|
# and `credential-resolver-ladder` fails if any copy diverges. Only what
|
|
76
76
|
# happens AFTER the ladder may differ between them.
|
|
77
|
-
local
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
.opencode/skills/lisa/lisa-secrets-access/scripts/resolve-secret.mjs
|
|
81
|
-
.codex/skills/lisa/lisa-secrets-access/scripts/resolve-secret.mjs
|
|
82
|
-
)
|
|
77
|
+
# Execute only machine-managed plugin/package resolvers. Checkout-local
|
|
78
|
+
# candidates are repository-controlled code, not trusted merely by path.
|
|
79
|
+
local candidates=()
|
|
83
80
|
if [ -n "${CLAUDE_PLUGIN_ROOT:-}" ]; then
|
|
84
81
|
candidates+=("$CLAUDE_PLUGIN_ROOT/skills/lisa-secrets-access/scripts/resolve-secret.mjs")
|
|
85
82
|
fi
|
|
@@ -98,7 +95,7 @@ read_sonar_secret() {
|
|
|
98
95
|
local via_lisa
|
|
99
96
|
via_lisa=$(node "$resolver" get "$name" 2>/dev/null) \
|
|
100
97
|
&& [ -n "$via_lisa" ] && { echo "$via_lisa"; return; }
|
|
101
|
-
|
|
98
|
+
# Empty/error means this substrate had no answer; try the next trusted one.
|
|
102
99
|
fi
|
|
103
100
|
done
|
|
104
101
|
# Name every path. A bare `return 1` sends the next reader hunting for a
|
|
@@ -58,7 +58,7 @@ The state machine (first match wins, evaluated over the **required** leaves only
|
|
|
58
58
|
| else any leaf has **started** (claimed or in review, or shipped while a sibling has not) | active / in-progress | `claimed` (or `review` where supported) |
|
|
59
59
|
| else (leaves exist, none started) | unchanged | — |
|
|
60
60
|
|
|
61
|
-
- **Blocked dominates** — one blocked leaf surfaces blocked on the parent even while others progress. It never says *which* child or *which kind* of hold
|
|
61
|
+
- **Blocked dominates** — one blocked leaf surfaces blocked on the parent even while others progress. It never says *which* child or *which kind* of hold. Resolve the shared classifier from `${CLAUDE_PLUGIN_ROOT:-${PLUGIN_ROOT:-plugins/lisa}}/scripts/rollup-blocker-classification.mjs` (the current-directory fallback supports a Lisa checkout), run it over the resolved child graph, and carry its per-class report — blocking leaf, path, and who must act — into the rollup note. A missing classifier or non-zero exit is a strict **no-write** result for every vendor: no lifecycle mutation and no rollup-comment mutation. Report the failure, never an all-clear. See `leaf-only-lifecycle` → **Classifying a hold**.
|
|
62
62
|
- **Least-advanced env wins** — a parent reaches an env only once all required leaves have reached at least that env (all `On Stg` → `On Stg`; mixed dev/staging → the dev value). Native terminal closure fires only at the production `done`, never at an intermediate env.
|
|
63
63
|
- **The parent never carries `ready`** — `ready` is a human "claim this leaf" signal; rollup only moves a parent between non-ready container states.
|
|
64
64
|
- **Rollup is recursive** — an Epic rolls up from its Stories, each of which rolls up from its own leaves. Evaluate bottom-up.
|
|
@@ -1064,8 +1064,38 @@ readonly AGENT_CREDENTIAL='(\.(claude|codex|cursor|copilot|gemini|antigravity)/[
|
|
|
1064
1064
|
# 15d. Dotenv files. `.env.example`, `.sample`, `.template`, `.dist` and
|
|
1065
1065
|
# `.schema` are checked-in documentation of which keys exist, never the values,
|
|
1066
1066
|
# so they are excluded — that collision is the one this rule most had to avoid.
|
|
1067
|
-
|
|
1068
|
-
|
|
1067
|
+
# Decide dotenv privacy per PATH, never by subtracting one command-wide match
|
|
1068
|
+
# from another. A command that names `.env.example` and `.env` contains both a
|
|
1069
|
+
# public path and a private one; seeing the former cannot authorize the latter.
|
|
1070
|
+
#
|
|
1071
|
+
# The one write-only shape this guard has always allowed remains explicit:
|
|
1072
|
+
# seeding a private dotenv destination from one public template. This is safe
|
|
1073
|
+
# because the private path is the destination, not a value being read back.
|
|
1074
|
+
has_private_dotenv_path() {
|
|
1075
|
+
dotenv_scan_status=0
|
|
1076
|
+
dotenv_candidates="$(printf '%s' "$normalized_command_str" \
|
|
1077
|
+
| grep -Eio -- '(^|[[:space:]='"$qc"'./])\.env(\.[[:alnum:]_-]+)?')" \
|
|
1078
|
+
|| dotenv_scan_status=$?
|
|
1079
|
+
if [ "$dotenv_scan_status" -gt 1 ]; then
|
|
1080
|
+
block "dotenv path classification failed; denying the credential-store read fail-closed."
|
|
1081
|
+
fi
|
|
1082
|
+
|
|
1083
|
+
while IFS= read -r candidate; do
|
|
1084
|
+
[ -n "$candidate" ] || continue
|
|
1085
|
+
candidate="$(printf '%s' "$candidate" \
|
|
1086
|
+
| tr '[:upper:]' '[:lower:]' \
|
|
1087
|
+
| grep -Eo -- '\.env(\.[[:alnum:]_-]+)?')"
|
|
1088
|
+
case "$candidate" in
|
|
1089
|
+
.env.example | .env.sample | .env.template | .env.dist | .env.schema | .env.defaults) ;;
|
|
1090
|
+
*) return 0 ;;
|
|
1091
|
+
esac
|
|
1092
|
+
done <<EOF
|
|
1093
|
+
$dotenv_candidates
|
|
1094
|
+
EOF
|
|
1095
|
+
return 1
|
|
1096
|
+
}
|
|
1097
|
+
|
|
1098
|
+
readonly SAFE_DOTENV_SEED='^[[:space:]]*(cp|mv)[[:space:]]+\.env\.(example|sample|template|dist|schema|defaults)[[:space:]]+\.env(\.[[:alnum:]_-]+)?[[:space:]]*$'
|
|
1069
1099
|
|
|
1070
1100
|
if matches "$SECRET_READ_VERB"; then
|
|
1071
1101
|
if matches "$SSH_PRIVATE_KEY"; then
|
|
@@ -1077,10 +1107,10 @@ if matches "$SECRET_READ_VERB"; then
|
|
|
1077
1107
|
if matches "$AGENT_CREDENTIAL"; then
|
|
1078
1108
|
block "reading, copying or transmitting a coding-agent or package-registry credential store. These tokens impersonate the operator to every service the agent can reach."
|
|
1079
1109
|
fi
|
|
1080
|
-
#
|
|
1081
|
-
#
|
|
1082
|
-
#
|
|
1083
|
-
if
|
|
1110
|
+
# A public path elsewhere in the command never exempts a private path. The
|
|
1111
|
+
# narrow public-template -> private-destination seed is write-only and remains
|
|
1112
|
+
# allowed; every other command containing a private dotenv path is refused.
|
|
1113
|
+
if has_private_dotenv_path && ! matches "$SAFE_DOTENV_SEED"; then
|
|
1084
1114
|
block "reading, copying or transmitting a dotenv file holding real values. \`.env.example\`, \`.env.sample\`, \`.env.template\` and \`.env.dist\` are readable, and WRITING a .env is unaffected — only reading one back is refused."
|
|
1085
1115
|
fi
|
|
1086
1116
|
# Fail-closed, narrowly. A read whose DIRECTORY is a known credential store
|
|
@@ -329,12 +329,16 @@ the complete bundle from the shared account. Do not extract or distribute its
|
|
|
329
329
|
individual access-key fields:
|
|
330
330
|
|
|
331
331
|
\`\`\`bash
|
|
332
|
-
aws
|
|
332
|
+
aws secretsmanager get-secret-value \\
|
|
333
333
|
--secret-id ${secretName} \\
|
|
334
334
|
--query SecretString \\
|
|
335
335
|
--output text
|
|
336
336
|
\`\`\`
|
|
337
337
|
|
|
338
|
+
This uses the ambient AWS identity. Add \`--profile <source-profile>\` only when
|
|
339
|
+
this project requires a named source profile to read the emission; \`shared\` is
|
|
340
|
+
not an implicit requirement.
|
|
341
|
+
|
|
338
342
|
Store that exact output as the masked secret \`LISA_AWS_BOOTSTRAP_JSON\` on each
|
|
339
343
|
remote-agent platform. Run the setup command and require its live
|
|
340
344
|
\`sts:GetCallerIdentity\` check to pass before considering the platform ready.
|
|
@@ -293,6 +293,8 @@ function collectHolds(children, context, path, seen, tally) {
|
|
|
293
293
|
* container?: { ref?: unknown, type?: unknown }
|
|
294
294
|
* readError?: unknown
|
|
295
295
|
* children?: unknown
|
|
296
|
+
* renderedState?: unknown
|
|
297
|
+
* childTally?: unknown
|
|
296
298
|
* blockedStates?: unknown
|
|
297
299
|
* markerNames?: { specDefect?: unknown, humanNeeded?: unknown }
|
|
298
300
|
* }} input
|
|
@@ -339,6 +341,10 @@ export function classifyRollupBlockers(input = {}) {
|
|
|
339
341
|
blockers.filter(blocker => blocker.class === name),
|
|
340
342
|
]).filter(([, group]) => group.length > 0)
|
|
341
343
|
);
|
|
344
|
+
const renderedState = trimmedString(input.renderedState);
|
|
345
|
+
const childTally =
|
|
346
|
+
trimmedString(input.childTally) ||
|
|
347
|
+
`examined=${tally.examined}, held=${blockers.length}, unreadable=${tally.unexaminable.length}`;
|
|
342
348
|
|
|
343
349
|
return {
|
|
344
350
|
ok: true,
|
|
@@ -348,6 +354,8 @@ export function classifyRollupBlockers(input = {}) {
|
|
|
348
354
|
blockers,
|
|
349
355
|
byClass,
|
|
350
356
|
unexaminable: tally.unexaminable,
|
|
357
|
+
renderedState,
|
|
358
|
+
childTally,
|
|
351
359
|
};
|
|
352
360
|
}
|
|
353
361
|
|
|
@@ -433,8 +441,8 @@ export function renderRollupBlockerReport(result) {
|
|
|
433
441
|
}
|
|
434
442
|
|
|
435
443
|
/**
|
|
436
|
-
* A stable identity for a rollup
|
|
437
|
-
* and its class, sorted.
|
|
444
|
+
* A stable identity for a rollup note: the rendered lifecycle state, child
|
|
445
|
+
* tally, container, and every held item plus its class, sorted.
|
|
438
446
|
*
|
|
439
447
|
* This is what lets a repeat cycle stay quiet. 32 identical hold comments over
|
|
440
448
|
* six weeks was the same verdict restated on a schedule; comparing this string
|
|
@@ -451,7 +459,14 @@ export function rollupBlockerFingerprint(result) {
|
|
|
451
459
|
.map(blocker => `${blocker.ref}:${blocker.class}`)
|
|
452
460
|
.sort((left, right) => left.localeCompare(right));
|
|
453
461
|
|
|
454
|
-
return
|
|
462
|
+
return [
|
|
463
|
+
`container=${result.container.ref}`,
|
|
464
|
+
`verdict=${result.verdict}`,
|
|
465
|
+
`rendered=${JSON.stringify(trimmedString(result.renderedState))}`,
|
|
466
|
+
`tally=${JSON.stringify(trimmedString(result.childTally))}`,
|
|
467
|
+
`examined=${result.examined}`,
|
|
468
|
+
`holds=${pairs.join(",")}`,
|
|
469
|
+
].join(";");
|
|
455
470
|
}
|
|
456
471
|
|
|
457
472
|
/**
|
|
@@ -57,9 +57,9 @@ read_atlassian_token() {
|
|
|
57
57
|
# OS keychain here — a second reader is how the same credential ends up living
|
|
58
58
|
# in two places and drifting.
|
|
59
59
|
#
|
|
60
|
-
# Ordered
|
|
61
|
-
#
|
|
62
|
-
#
|
|
60
|
+
# Ordered across trusted machine-managed substrates, ending at the installed
|
|
61
|
+
# package. Checkout-local paths are deliberately absent: a familiar generated
|
|
62
|
+
# destination is still repository-controlled executable code. The plugin
|
|
63
63
|
# rungs are the floor: `resolve-secret.mjs` ships beside this skill, so a rung
|
|
64
64
|
# pointing at it is reachable from anywhere the plugin itself is installed.
|
|
65
65
|
# Without one, a consumer repository that vendors none of the leading paths
|
|
@@ -68,12 +68,9 @@ read_atlassian_token() {
|
|
|
68
68
|
# lookups. This LADDER is identical in every skill that resolves a credential
|
|
69
69
|
# and `credential-resolver-ladder` fails if any copy diverges. Only what
|
|
70
70
|
# happens AFTER the ladder may differ between them.
|
|
71
|
-
local
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
.opencode/skills/lisa/lisa-secrets-access/scripts/resolve-secret.mjs
|
|
75
|
-
.codex/skills/lisa/lisa-secrets-access/scripts/resolve-secret.mjs
|
|
76
|
-
)
|
|
71
|
+
# Executable resolvers are a code boundary. Checkout-local copies are mutable
|
|
72
|
+
# repository content, so use only machine-managed plugin/package locations.
|
|
73
|
+
local candidates=()
|
|
77
74
|
if [ -n "${CLAUDE_PLUGIN_ROOT:-}" ]; then
|
|
78
75
|
candidates+=("$CLAUDE_PLUGIN_ROOT/skills/lisa-secrets-access/scripts/resolve-secret.mjs")
|
|
79
76
|
fi
|
|
@@ -92,7 +89,7 @@ read_atlassian_token() {
|
|
|
92
89
|
local via_lisa
|
|
93
90
|
via_lisa=$(node "$resolver" get ATLASSIAN_API_TOKEN 2>/dev/null) \
|
|
94
91
|
&& [ -n "$via_lisa" ] && { echo "$via_lisa"; return; }
|
|
95
|
-
|
|
92
|
+
# Empty/error means this substrate had no answer; try the next trusted one.
|
|
96
93
|
fi
|
|
97
94
|
done
|
|
98
95
|
# Legacy fallback: the OS keychain written by the guided /lisa:setup:atlassian
|
|
@@ -152,7 +149,7 @@ public static class LisaCred {
|
|
|
152
149
|
echo "Error: could not resolve ATLASSIAN_API_TOKEN through lisa-secrets-access or the legacy keychain." >&2
|
|
153
150
|
echo "Tried, in order (relative paths are from $PWD):" >&2
|
|
154
151
|
printf ' %s\n' "${tried[@]}" >&2
|
|
155
|
-
echo " <OS keychain> service=lisa-atlassian account
|
|
152
|
+
echo " <OS keychain> service=lisa-atlassian account=<configured>" >&2
|
|
156
153
|
return 1
|
|
157
154
|
}
|
|
158
155
|
TOKEN=$(read_atlassian_token "$EMAIL")
|
|
@@ -288,7 +285,7 @@ if [ -n "$site" ] && [ "$current_site" != "$site" ]; then
|
|
|
288
285
|
fi
|
|
289
286
|
|
|
290
287
|
if [ -n "$email" ] && [ -n "$current_email" ] && [ "$current_email" != "$email" ]; then
|
|
291
|
-
echo "Error: acli active account
|
|
288
|
+
echo "Error: acli active account does not match the configured Atlassian account. Run /lisa:setup:atlassian to add or repair the matching profile." >&2
|
|
292
289
|
exit 1
|
|
293
290
|
fi
|
|
294
291
|
```
|
|
@@ -310,7 +307,7 @@ if [ -z "$me_email" ]; then
|
|
|
310
307
|
exit 1
|
|
311
308
|
fi
|
|
312
309
|
if [ "$me_email" != "$email" ]; then
|
|
313
|
-
echo "Error: ATLASSIAN_API_TOKEN
|
|
310
|
+
echo "Error: ATLASSIAN_API_TOKEN identity does not match the configured Atlassian account. Multi-account misconfiguration; re-run /lisa:setup:atlassian." >&2
|
|
314
311
|
exit 1
|
|
315
312
|
fi
|
|
316
313
|
```
|
|
@@ -480,8 +480,8 @@ against both enforcing surfaces on paths a machine already takes:
|
|
|
480
480
|
| the shipped ruleset template a repository is provisioned from | `lisa doctor` (one operator-readable line) and `lisa doctor --json` → `declarationDrift.templates` | no |
|
|
481
481
|
| the live branch-protection ruleset | `lisa doctor --json` → `declarationDrift.live`, and the `github.declared-checks` check in `lisa health` | yes |
|
|
482
482
|
|
|
483
|
-
Both report one verdict per required context, and the vocabulary is
|
|
484
|
-
matched/unmatched, because
|
|
483
|
+
Both report one verdict per required context, and the vocabulary is seven values rather than
|
|
484
|
+
matched/unmatched, because the mismatches and an unreadable surface need different actions:
|
|
485
485
|
|
|
486
486
|
- `matched` — declared `required`, and the surface requires it.
|
|
487
487
|
- `declared-not-enforced` — the settings file says it must pass and nothing requires it. The
|
|
@@ -495,6 +495,8 @@ matched/unmatched, because four of the mismatches need four different actions:
|
|
|
495
495
|
- `enforced-not-lisa-owned` — protection requires it and no registry gate produces it. Third-party
|
|
496
496
|
checks are required by construction and declared by nobody; this bucket exists so they can be told
|
|
497
497
|
apart from a Lisa gate that fell out of the settings file, never so they can be removed.
|
|
498
|
+
- `unproven` — the surface could not be read, so no enforcement comparison was made. It is never a
|
|
499
|
+
match and never drift; the operator fixes access/availability and reruns the observation.
|
|
498
500
|
|
|
499
501
|
`enforced-declared-off` and `declared-not-enforced` fail the health check; the two gaps warn. No
|
|
500
502
|
remedy in that vocabulary removes a required context — the type has no such member, so the
|