@codyswann/lisa 2.259.4 → 2.260.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/dist/cli/file-upstream-cmd.d.ts +28 -0
- package/dist/cli/file-upstream-cmd.d.ts.map +1 -0
- package/dist/cli/file-upstream-cmd.js +231 -0
- package/dist/cli/file-upstream-cmd.js.map +1 -0
- package/dist/cli/gate-commands.d.ts +17 -0
- package/dist/cli/gate-commands.d.ts.map +1 -0
- package/dist/cli/gate-commands.js +47 -0
- package/dist/cli/gate-commands.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +6 -27
- package/dist/cli/index.js.map +1 -1
- package/dist/core/upstream-attribution-body.d.ts +38 -25
- package/dist/core/upstream-attribution-body.d.ts.map +1 -1
- package/dist/core/upstream-attribution-body.js +515 -155
- package/dist/core/upstream-attribution-body.js.map +1 -1
- package/dist/core/upstream-evidence-manifest.d.ts +7 -0
- package/dist/core/upstream-evidence-manifest.d.ts.map +1 -0
- package/dist/core/upstream-evidence-manifest.js +11623 -0
- package/dist/core/upstream-evidence-manifest.js.map +1 -0
- package/package.json +4 -1
- 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-persist-learning/SKILL.md +32 -8
- package/plugins/lisa/skills/lisa-persist-learning/SKILL.md +32 -8
- package/plugins/lisa-agy/plugin.json +1 -1
- package/plugins/lisa-agy/skills/lisa-persist-learning/SKILL.md +32 -8
- 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/skills/lisa-persist-learning/SKILL.md +32 -8
- package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cursor/skills/lisa-persist-learning/SKILL.md +32 -8
- 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/skills/lisa-persist-learning/SKILL.md +32 -8
- package/scripts/generate-upstream-evidence-manifest.mjs +157 -0
package/package.json
CHANGED
|
@@ -32,6 +32,9 @@
|
|
|
32
32
|
"prepublishOnly": "$npm_execpath run build",
|
|
33
33
|
"check:plugins": "bash scripts/check-plugins-sync.sh",
|
|
34
34
|
"check:learnings-budget": "bun scripts/check-learnings-budget.ts",
|
|
35
|
+
"build:upstream-evidence-manifest": "node scripts/generate-upstream-evidence-manifest.mjs",
|
|
36
|
+
"check:upstream-evidence-manifest": "node scripts/generate-upstream-evidence-manifest.mjs --check",
|
|
37
|
+
"refresh:upstream-public-commits": "node scripts/generate-upstream-evidence-manifest.mjs --refresh-public-commits",
|
|
35
38
|
"check:rules-pairing": "bash scripts/check-rules-pairing.sh",
|
|
36
39
|
"check:workflow-inputs": "node scripts/detect-stale-workflow-inputs.mjs --project . --project typescript/create-only --project rails/create-only --json"
|
|
37
40
|
},
|
|
@@ -102,7 +105,7 @@
|
|
|
102
105
|
"form-data": ">=4.0.6"
|
|
103
106
|
},
|
|
104
107
|
"name": "@codyswann/lisa",
|
|
105
|
-
"version": "2.
|
|
108
|
+
"version": "2.260.0",
|
|
106
109
|
"description": "Claude Code governance framework that applies guardrails, guidance, and automated enforcement to projects",
|
|
107
110
|
"main": "dist/index.js",
|
|
108
111
|
"exports": {
|
|
@@ -90,19 +90,19 @@ This disposition completes the SLL-5 loop (#1583): on a Lisa-attributed failure
|
|
|
90
90
|
root-cause-key = <lisa-surface>#<failure-class>
|
|
91
91
|
```
|
|
92
92
|
|
|
93
|
-
- `<lisa-surface>` — the Lisa-relative path of the surface at fault (e.g. `plugins/src/base/skills/lisa-doctor/SKILL.md`, `typescript/copy-overwrite/.github/workflows/quality.yml`)
|
|
94
|
-
- `<failure-class>` —
|
|
93
|
+
- `<lisa-surface>` — the exact public Lisa-relative path of the surface at fault (e.g. `plugins/src/base/skills/lisa-doctor/SKILL.md`, `typescript/copy-overwrite/.github/workflows/quality.yml`). Canonical names, aliases, host paths, and unmanifested paths are prohibited.
|
|
94
|
+
- `<failure-class>` — exactly one exported closed value: `access-control-failure`, `agent-parity-regression`, `configuration-regression`, `data-integrity-failure`, `dependency-regression`, `generated-artifact-regression`, `installation-regression`, `observability-gap`, `pagination-truncation`, `performance-regression`, `public-data-exposure`, `release-regression`, `runtime-regression`, `stale-artifact-overwrite`, `test-coverage-gap`, `validation-gap`, or `workflow-contract-violation`.
|
|
95
95
|
- Normalize: lowercase, trim, collapse every whitespace run to a single `-`. The key must contain no host-project name, no local issue number, and no fingerprint — those vary per project and would defeat fleet-wide dedupe.
|
|
96
96
|
|
|
97
97
|
4. **Enforce the per-run cap.** Resolve `hardening.maxUpstreamFilingsPerRun` from `.lisa.config.json` (default `5` — a conservative bound modeled on `lisa-repair-intake`'s `max_candidates` precedent). Count every upstream create **and** update this run performs; once the cap is reached, drop the remaining candidates and **note each dropped candidate visibly** (in the run summary, naming its root-cause key) — never queue a spam burst and never drop silently. A later run picks the dropped candidates up idempotently.
|
|
98
98
|
|
|
99
|
-
5. **Evidence redaction (binding).** The upstream repo is PUBLIC by default (`hardening.upstreamRepo` → `CodySwannGT/lisa`) and this filing runs headless on crons — treat every drafted upstream body and comment as world-readable:
|
|
99
|
+
5. **Evidence redaction (binding).** The upstream repo is PUBLIC by default (`hardening.upstreamRepo` → `CodySwannGT/lisa`) and this filing runs headless on crons — treat every drafted upstream body and comment as world-readable. The PRIMARY control is the **allowlist projection** in step 6: `bunx @codyswann/lisa file-upstream` calls the sole `buildUpstreamAttributionIssueBody` export from `@codyswann/lisa/learnings`, so content outside its enumerated fields is structurally incapable of reaching the public document. The rules below bind the FIELDS supplied to that command; the closing scan is a defense-in-depth backstop, never the primary control:
|
|
100
100
|
|
|
101
101
|
- Quote ONLY Lisa-owned surface text: template/rule/skill/hook excerpts and upstream commit references. The reproduction must be REDACTED — generic placeholders, never the host project's real values.
|
|
102
102
|
- Never paste host environment values, tokens/credentials, connection strings, API keys, PII (names, emails, customer data), or proprietary host code/payloads.
|
|
103
|
-
- The evidence chain names the Lisa surface and the failure class — never project payloads.
|
|
104
|
-
-
|
|
105
|
-
-
|
|
103
|
+
- The evidence chain names the Lisa surface and the failure class — never project payloads. Keep any host-project issue link only in the private local trace; it is never supplied to or emitted by the public builder.
|
|
104
|
+
- Use only these exact generic placeholders: `<host-project>`, `<env-value>`, `<credential>`, `<connection-string>`, `<pii>`, `<host-payload>`, `<path>`, `<identifier>`. A project-specific placeholder is host prose and must be rejected.
|
|
105
|
+
- **Backstop (defense in depth, never the primary control).** Before filing or commenting, scan the projected document for common secret shapes — `key=value` pairs with high-entropy values, token prefixes (`AKIA`, `ghp_`, `xox`), email addresses — and reject on a match. To strip on match, remove the offending INPUT field and re-run `file-upstream`; never strip or edit the generated output itself. Non-allowlisted fields must reject before filing rather than be silently dropped. When in doubt, leave it out: a thinner upstream document is recoverable; a leaked secret is not.
|
|
106
106
|
|
|
107
107
|
6. **Dedupe by marker, then file or update.** The upstream marker is:
|
|
108
108
|
|
|
@@ -112,8 +112,32 @@ This disposition completes the SLL-5 loop (#1583): on a Lisa-attributed failure
|
|
|
112
112
|
|
|
113
113
|
Resolve the upstream repo from `.lisa.config.json` `hardening.upstreamRepo` (default `CodySwannGT/lisa`). Search **all issue states** for an existing issue carrying the marker — a closed marker-bearing ticket still owns this root cause, and searching only open issues would mint a duplicate the moment the original closes. Match on the **MARKER, never the title** — with the same eventual-consistency guard as above (`gh issue list -R <upstream> --state all --search '"<marker>" in:body' --json number,state,url`, and when the search index returns nothing, also `gh issue list -R <upstream> --state all --json number,state,body` and grep the bodies for the marker before concluding no ticket exists).
|
|
114
114
|
|
|
115
|
-
- **No existing ticket** →
|
|
116
|
-
|
|
115
|
+
- **No existing ticket** → compose the body EXCLUSIVELY through the executable builder, then file its stdout verbatim via `lisa-github-write-issue` targeting the upstream repo with the `self-hardening` label:
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
bunx @codyswann/lisa file-upstream --input filing-event.json # or pipe the JSON on stdin
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
**Never assemble the public body as free-form prose.** Public composition happens through the builder, never by free-form prose assembly. The builder owns the three-audience description and the redacted evidence chain (Lisa-owned text only). Do not hand-write either section, name an affected project in prose, or edit the builder's output after generation. Supply only this JSON shape; host-project issue URLs remain private local-trace data and are never accepted by the public builder:
|
|
122
|
+
|
|
123
|
+
```json
|
|
124
|
+
{
|
|
125
|
+
"documentKind": "issue",
|
|
126
|
+
"lisaSurface": "plugins/src/base/skills/lisa-doctor/SKILL.md",
|
|
127
|
+
"failureClass": "stale-artifact-overwrite",
|
|
128
|
+
"lisaOwnedExcerpts": [
|
|
129
|
+
{
|
|
130
|
+
"file": "plugins/src/base/skills/lisa-doctor/SKILL.md",
|
|
131
|
+
"text": "<verbatim Lisa-owned text>"
|
|
132
|
+
}
|
|
133
|
+
],
|
|
134
|
+
"upstreamCommitRefs": ["<full 40-character public-origin SHA>"],
|
|
135
|
+
"redactedPlaceholders": ["<host-project>", "<env-value>"]
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Every excerpt is verified against the installed package's Lisa-owned source and every commit against the public origin. Callers cannot supply a verifier or Lisa root. Anything outside the allowlist is REJECTED by field name with empty stdout and a non-zero exit; fix or remove the offending input field and re-run the command, never route around it. The builder emits **exactly one** dedupe marker; **never write a markerless body** — it permanently breaks all future dedupe.
|
|
140
|
+
- **Existing ticket (open or closed)** → this is a repeat encounter: comment the new occurrence on the existing issue with this project's evidence. The comment is projected through the same builder: run `bunx @codyswann/lisa file-upstream` with the same allowlisted fields plus exactly `"documentKind": "occurrence"` and `"occurrenceFingerprint": "<fingerprint>"`. The supplied fingerprint is only a validated seed: the builder hashes it and emits a different deterministic `sll4-<12 lowercase hex>` marker. Use the marker in the builder's stdout — never the supplied literal — to search existing issue comments for a duplicate, then post stdout verbatim only when that emitted marker is absent. Free-form occurrence prose is prohibited, and post-generation edits are prohibited. Never open a second issue, and never match on the title — evidence compounds on one ticket. When the match is **CLOSED**, still comment the occurrence there and reference it in the local trace instead of filing a duplicate; do not reopen it yourself — recurrence evidence on a closed ticket signals the shipped fix may not cover this case, and reopening is the upstream maintainer's call.
|
|
117
141
|
|
|
118
142
|
7. **Leave the local trace — a note, never a rule.** Post one follow-up comment on the triggering issue linking the upstream ticket:
|
|
119
143
|
|
|
@@ -90,19 +90,19 @@ This disposition completes the SLL-5 loop (#1583): on a Lisa-attributed failure
|
|
|
90
90
|
root-cause-key = <lisa-surface>#<failure-class>
|
|
91
91
|
```
|
|
92
92
|
|
|
93
|
-
- `<lisa-surface>` — the Lisa-relative path of the surface at fault (e.g. `plugins/src/base/skills/lisa-doctor/SKILL.md`, `typescript/copy-overwrite/.github/workflows/quality.yml`)
|
|
94
|
-
- `<failure-class>` —
|
|
93
|
+
- `<lisa-surface>` — the exact public Lisa-relative path of the surface at fault (e.g. `plugins/src/base/skills/lisa-doctor/SKILL.md`, `typescript/copy-overwrite/.github/workflows/quality.yml`). Canonical names, aliases, host paths, and unmanifested paths are prohibited.
|
|
94
|
+
- `<failure-class>` — exactly one exported closed value: `access-control-failure`, `agent-parity-regression`, `configuration-regression`, `data-integrity-failure`, `dependency-regression`, `generated-artifact-regression`, `installation-regression`, `observability-gap`, `pagination-truncation`, `performance-regression`, `public-data-exposure`, `release-regression`, `runtime-regression`, `stale-artifact-overwrite`, `test-coverage-gap`, `validation-gap`, or `workflow-contract-violation`.
|
|
95
95
|
- Normalize: lowercase, trim, collapse every whitespace run to a single `-`. The key must contain no host-project name, no local issue number, and no fingerprint — those vary per project and would defeat fleet-wide dedupe.
|
|
96
96
|
|
|
97
97
|
4. **Enforce the per-run cap.** Resolve `hardening.maxUpstreamFilingsPerRun` from `.lisa.config.json` (default `5` — a conservative bound modeled on `lisa-repair-intake`'s `max_candidates` precedent). Count every upstream create **and** update this run performs; once the cap is reached, drop the remaining candidates and **note each dropped candidate visibly** (in the run summary, naming its root-cause key) — never queue a spam burst and never drop silently. A later run picks the dropped candidates up idempotently.
|
|
98
98
|
|
|
99
|
-
5. **Evidence redaction (binding).** The upstream repo is PUBLIC by default (`hardening.upstreamRepo` → `CodySwannGT/lisa`) and this filing runs headless on crons — treat every drafted upstream body and comment as world-readable:
|
|
99
|
+
5. **Evidence redaction (binding).** The upstream repo is PUBLIC by default (`hardening.upstreamRepo` → `CodySwannGT/lisa`) and this filing runs headless on crons — treat every drafted upstream body and comment as world-readable. The PRIMARY control is the **allowlist projection** in step 6: `bunx @codyswann/lisa file-upstream` calls the sole `buildUpstreamAttributionIssueBody` export from `@codyswann/lisa/learnings`, so content outside its enumerated fields is structurally incapable of reaching the public document. The rules below bind the FIELDS supplied to that command; the closing scan is a defense-in-depth backstop, never the primary control:
|
|
100
100
|
|
|
101
101
|
- Quote ONLY Lisa-owned surface text: template/rule/skill/hook excerpts and upstream commit references. The reproduction must be REDACTED — generic placeholders, never the host project's real values.
|
|
102
102
|
- Never paste host environment values, tokens/credentials, connection strings, API keys, PII (names, emails, customer data), or proprietary host code/payloads.
|
|
103
|
-
- The evidence chain names the Lisa surface and the failure class — never project payloads.
|
|
104
|
-
-
|
|
105
|
-
-
|
|
103
|
+
- The evidence chain names the Lisa surface and the failure class — never project payloads. Keep any host-project issue link only in the private local trace; it is never supplied to or emitted by the public builder.
|
|
104
|
+
- Use only these exact generic placeholders: `<host-project>`, `<env-value>`, `<credential>`, `<connection-string>`, `<pii>`, `<host-payload>`, `<path>`, `<identifier>`. A project-specific placeholder is host prose and must be rejected.
|
|
105
|
+
- **Backstop (defense in depth, never the primary control).** Before filing or commenting, scan the projected document for common secret shapes — `key=value` pairs with high-entropy values, token prefixes (`AKIA`, `ghp_`, `xox`), email addresses — and reject on a match. To strip on match, remove the offending INPUT field and re-run `file-upstream`; never strip or edit the generated output itself. Non-allowlisted fields must reject before filing rather than be silently dropped. When in doubt, leave it out: a thinner upstream document is recoverable; a leaked secret is not.
|
|
106
106
|
|
|
107
107
|
6. **Dedupe by marker, then file or update.** The upstream marker is:
|
|
108
108
|
|
|
@@ -112,8 +112,32 @@ This disposition completes the SLL-5 loop (#1583): on a Lisa-attributed failure
|
|
|
112
112
|
|
|
113
113
|
Resolve the upstream repo from `.lisa.config.json` `hardening.upstreamRepo` (default `CodySwannGT/lisa`). Search **all issue states** for an existing issue carrying the marker — a closed marker-bearing ticket still owns this root cause, and searching only open issues would mint a duplicate the moment the original closes. Match on the **MARKER, never the title** — with the same eventual-consistency guard as above (`gh issue list -R <upstream> --state all --search '"<marker>" in:body' --json number,state,url`, and when the search index returns nothing, also `gh issue list -R <upstream> --state all --json number,state,body` and grep the bodies for the marker before concluding no ticket exists).
|
|
114
114
|
|
|
115
|
-
- **No existing ticket** →
|
|
116
|
-
|
|
115
|
+
- **No existing ticket** → compose the body EXCLUSIVELY through the executable builder, then file its stdout verbatim via `lisa-github-write-issue` targeting the upstream repo with the `self-hardening` label:
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
bunx @codyswann/lisa file-upstream --input filing-event.json # or pipe the JSON on stdin
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
**Never assemble the public body as free-form prose.** Public composition happens through the builder, never by free-form prose assembly. The builder owns the three-audience description and the redacted evidence chain (Lisa-owned text only). Do not hand-write either section, name an affected project in prose, or edit the builder's output after generation. Supply only this JSON shape; host-project issue URLs remain private local-trace data and are never accepted by the public builder:
|
|
122
|
+
|
|
123
|
+
```json
|
|
124
|
+
{
|
|
125
|
+
"documentKind": "issue",
|
|
126
|
+
"lisaSurface": "plugins/src/base/skills/lisa-doctor/SKILL.md",
|
|
127
|
+
"failureClass": "stale-artifact-overwrite",
|
|
128
|
+
"lisaOwnedExcerpts": [
|
|
129
|
+
{
|
|
130
|
+
"file": "plugins/src/base/skills/lisa-doctor/SKILL.md",
|
|
131
|
+
"text": "<verbatim Lisa-owned text>"
|
|
132
|
+
}
|
|
133
|
+
],
|
|
134
|
+
"upstreamCommitRefs": ["<full 40-character public-origin SHA>"],
|
|
135
|
+
"redactedPlaceholders": ["<host-project>", "<env-value>"]
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Every excerpt is verified against the installed package's Lisa-owned source and every commit against the public origin. Callers cannot supply a verifier or Lisa root. Anything outside the allowlist is REJECTED by field name with empty stdout and a non-zero exit; fix or remove the offending input field and re-run the command, never route around it. The builder emits **exactly one** dedupe marker; **never write a markerless body** — it permanently breaks all future dedupe.
|
|
140
|
+
- **Existing ticket (open or closed)** → this is a repeat encounter: comment the new occurrence on the existing issue with this project's evidence. The comment is projected through the same builder: run `bunx @codyswann/lisa file-upstream` with the same allowlisted fields plus exactly `"documentKind": "occurrence"` and `"occurrenceFingerprint": "<fingerprint>"`. The supplied fingerprint is only a validated seed: the builder hashes it and emits a different deterministic `sll4-<12 lowercase hex>` marker. Use the marker in the builder's stdout — never the supplied literal — to search existing issue comments for a duplicate, then post stdout verbatim only when that emitted marker is absent. Free-form occurrence prose is prohibited, and post-generation edits are prohibited. Never open a second issue, and never match on the title — evidence compounds on one ticket. When the match is **CLOSED**, still comment the occurrence there and reference it in the local trace instead of filing a duplicate; do not reopen it yourself — recurrence evidence on a closed ticket signals the shipped fix may not cover this case, and reopening is the upstream maintainer's call.
|
|
117
141
|
|
|
118
142
|
7. **Leave the local trace — a note, never a rule.** Post one follow-up comment on the triggering issue linking the upstream ticket:
|
|
119
143
|
|
|
@@ -90,19 +90,19 @@ This disposition completes the SLL-5 loop (#1583): on a Lisa-attributed failure
|
|
|
90
90
|
root-cause-key = <lisa-surface>#<failure-class>
|
|
91
91
|
```
|
|
92
92
|
|
|
93
|
-
- `<lisa-surface>` — the Lisa-relative path of the surface at fault (e.g. `plugins/src/base/skills/lisa-doctor/SKILL.md`, `typescript/copy-overwrite/.github/workflows/quality.yml`)
|
|
94
|
-
- `<failure-class>` —
|
|
93
|
+
- `<lisa-surface>` — the exact public Lisa-relative path of the surface at fault (e.g. `plugins/src/base/skills/lisa-doctor/SKILL.md`, `typescript/copy-overwrite/.github/workflows/quality.yml`). Canonical names, aliases, host paths, and unmanifested paths are prohibited.
|
|
94
|
+
- `<failure-class>` — exactly one exported closed value: `access-control-failure`, `agent-parity-regression`, `configuration-regression`, `data-integrity-failure`, `dependency-regression`, `generated-artifact-regression`, `installation-regression`, `observability-gap`, `pagination-truncation`, `performance-regression`, `public-data-exposure`, `release-regression`, `runtime-regression`, `stale-artifact-overwrite`, `test-coverage-gap`, `validation-gap`, or `workflow-contract-violation`.
|
|
95
95
|
- Normalize: lowercase, trim, collapse every whitespace run to a single `-`. The key must contain no host-project name, no local issue number, and no fingerprint — those vary per project and would defeat fleet-wide dedupe.
|
|
96
96
|
|
|
97
97
|
4. **Enforce the per-run cap.** Resolve `hardening.maxUpstreamFilingsPerRun` from `.lisa.config.json` (default `5` — a conservative bound modeled on `lisa-repair-intake`'s `max_candidates` precedent). Count every upstream create **and** update this run performs; once the cap is reached, drop the remaining candidates and **note each dropped candidate visibly** (in the run summary, naming its root-cause key) — never queue a spam burst and never drop silently. A later run picks the dropped candidates up idempotently.
|
|
98
98
|
|
|
99
|
-
5. **Evidence redaction (binding).** The upstream repo is PUBLIC by default (`hardening.upstreamRepo` → `CodySwannGT/lisa`) and this filing runs headless on crons — treat every drafted upstream body and comment as world-readable:
|
|
99
|
+
5. **Evidence redaction (binding).** The upstream repo is PUBLIC by default (`hardening.upstreamRepo` → `CodySwannGT/lisa`) and this filing runs headless on crons — treat every drafted upstream body and comment as world-readable. The PRIMARY control is the **allowlist projection** in step 6: `bunx @codyswann/lisa file-upstream` calls the sole `buildUpstreamAttributionIssueBody` export from `@codyswann/lisa/learnings`, so content outside its enumerated fields is structurally incapable of reaching the public document. The rules below bind the FIELDS supplied to that command; the closing scan is a defense-in-depth backstop, never the primary control:
|
|
100
100
|
|
|
101
101
|
- Quote ONLY Lisa-owned surface text: template/rule/skill/hook excerpts and upstream commit references. The reproduction must be REDACTED — generic placeholders, never the host project's real values.
|
|
102
102
|
- Never paste host environment values, tokens/credentials, connection strings, API keys, PII (names, emails, customer data), or proprietary host code/payloads.
|
|
103
|
-
- The evidence chain names the Lisa surface and the failure class — never project payloads.
|
|
104
|
-
-
|
|
105
|
-
-
|
|
103
|
+
- The evidence chain names the Lisa surface and the failure class — never project payloads. Keep any host-project issue link only in the private local trace; it is never supplied to or emitted by the public builder.
|
|
104
|
+
- Use only these exact generic placeholders: `<host-project>`, `<env-value>`, `<credential>`, `<connection-string>`, `<pii>`, `<host-payload>`, `<path>`, `<identifier>`. A project-specific placeholder is host prose and must be rejected.
|
|
105
|
+
- **Backstop (defense in depth, never the primary control).** Before filing or commenting, scan the projected document for common secret shapes — `key=value` pairs with high-entropy values, token prefixes (`AKIA`, `ghp_`, `xox`), email addresses — and reject on a match. To strip on match, remove the offending INPUT field and re-run `file-upstream`; never strip or edit the generated output itself. Non-allowlisted fields must reject before filing rather than be silently dropped. When in doubt, leave it out: a thinner upstream document is recoverable; a leaked secret is not.
|
|
106
106
|
|
|
107
107
|
6. **Dedupe by marker, then file or update.** The upstream marker is:
|
|
108
108
|
|
|
@@ -112,8 +112,32 @@ This disposition completes the SLL-5 loop (#1583): on a Lisa-attributed failure
|
|
|
112
112
|
|
|
113
113
|
Resolve the upstream repo from `.lisa.config.json` `hardening.upstreamRepo` (default `CodySwannGT/lisa`). Search **all issue states** for an existing issue carrying the marker — a closed marker-bearing ticket still owns this root cause, and searching only open issues would mint a duplicate the moment the original closes. Match on the **MARKER, never the title** — with the same eventual-consistency guard as above (`gh issue list -R <upstream> --state all --search '"<marker>" in:body' --json number,state,url`, and when the search index returns nothing, also `gh issue list -R <upstream> --state all --json number,state,body` and grep the bodies for the marker before concluding no ticket exists).
|
|
114
114
|
|
|
115
|
-
- **No existing ticket** →
|
|
116
|
-
|
|
115
|
+
- **No existing ticket** → compose the body EXCLUSIVELY through the executable builder, then file its stdout verbatim via `lisa-github-write-issue` targeting the upstream repo with the `self-hardening` label:
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
bunx @codyswann/lisa file-upstream --input filing-event.json # or pipe the JSON on stdin
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
**Never assemble the public body as free-form prose.** Public composition happens through the builder, never by free-form prose assembly. The builder owns the three-audience description and the redacted evidence chain (Lisa-owned text only). Do not hand-write either section, name an affected project in prose, or edit the builder's output after generation. Supply only this JSON shape; host-project issue URLs remain private local-trace data and are never accepted by the public builder:
|
|
122
|
+
|
|
123
|
+
```json
|
|
124
|
+
{
|
|
125
|
+
"documentKind": "issue",
|
|
126
|
+
"lisaSurface": "plugins/src/base/skills/lisa-doctor/SKILL.md",
|
|
127
|
+
"failureClass": "stale-artifact-overwrite",
|
|
128
|
+
"lisaOwnedExcerpts": [
|
|
129
|
+
{
|
|
130
|
+
"file": "plugins/src/base/skills/lisa-doctor/SKILL.md",
|
|
131
|
+
"text": "<verbatim Lisa-owned text>"
|
|
132
|
+
}
|
|
133
|
+
],
|
|
134
|
+
"upstreamCommitRefs": ["<full 40-character public-origin SHA>"],
|
|
135
|
+
"redactedPlaceholders": ["<host-project>", "<env-value>"]
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Every excerpt is verified against the installed package's Lisa-owned source and every commit against the public origin. Callers cannot supply a verifier or Lisa root. Anything outside the allowlist is REJECTED by field name with empty stdout and a non-zero exit; fix or remove the offending input field and re-run the command, never route around it. The builder emits **exactly one** dedupe marker; **never write a markerless body** — it permanently breaks all future dedupe.
|
|
140
|
+
- **Existing ticket (open or closed)** → this is a repeat encounter: comment the new occurrence on the existing issue with this project's evidence. The comment is projected through the same builder: run `bunx @codyswann/lisa file-upstream` with the same allowlisted fields plus exactly `"documentKind": "occurrence"` and `"occurrenceFingerprint": "<fingerprint>"`. The supplied fingerprint is only a validated seed: the builder hashes it and emits a different deterministic `sll4-<12 lowercase hex>` marker. Use the marker in the builder's stdout — never the supplied literal — to search existing issue comments for a duplicate, then post stdout verbatim only when that emitted marker is absent. Free-form occurrence prose is prohibited, and post-generation edits are prohibited. Never open a second issue, and never match on the title — evidence compounds on one ticket. When the match is **CLOSED**, still comment the occurrence there and reference it in the local trace instead of filing a duplicate; do not reopen it yourself — recurrence evidence on a closed ticket signals the shipped fix may not cover this case, and reopening is the upstream maintainer's call.
|
|
117
141
|
|
|
118
142
|
7. **Leave the local trace — a note, never a rule.** Post one follow-up comment on the triggering issue linking the upstream ticket:
|
|
119
143
|
|
|
@@ -90,19 +90,19 @@ This disposition completes the SLL-5 loop (#1583): on a Lisa-attributed failure
|
|
|
90
90
|
root-cause-key = <lisa-surface>#<failure-class>
|
|
91
91
|
```
|
|
92
92
|
|
|
93
|
-
- `<lisa-surface>` — the Lisa-relative path of the surface at fault (e.g. `plugins/src/base/skills/lisa-doctor/SKILL.md`, `typescript/copy-overwrite/.github/workflows/quality.yml`)
|
|
94
|
-
- `<failure-class>` —
|
|
93
|
+
- `<lisa-surface>` — the exact public Lisa-relative path of the surface at fault (e.g. `plugins/src/base/skills/lisa-doctor/SKILL.md`, `typescript/copy-overwrite/.github/workflows/quality.yml`). Canonical names, aliases, host paths, and unmanifested paths are prohibited.
|
|
94
|
+
- `<failure-class>` — exactly one exported closed value: `access-control-failure`, `agent-parity-regression`, `configuration-regression`, `data-integrity-failure`, `dependency-regression`, `generated-artifact-regression`, `installation-regression`, `observability-gap`, `pagination-truncation`, `performance-regression`, `public-data-exposure`, `release-regression`, `runtime-regression`, `stale-artifact-overwrite`, `test-coverage-gap`, `validation-gap`, or `workflow-contract-violation`.
|
|
95
95
|
- Normalize: lowercase, trim, collapse every whitespace run to a single `-`. The key must contain no host-project name, no local issue number, and no fingerprint — those vary per project and would defeat fleet-wide dedupe.
|
|
96
96
|
|
|
97
97
|
4. **Enforce the per-run cap.** Resolve `hardening.maxUpstreamFilingsPerRun` from `.lisa.config.json` (default `5` — a conservative bound modeled on `lisa-repair-intake`'s `max_candidates` precedent). Count every upstream create **and** update this run performs; once the cap is reached, drop the remaining candidates and **note each dropped candidate visibly** (in the run summary, naming its root-cause key) — never queue a spam burst and never drop silently. A later run picks the dropped candidates up idempotently.
|
|
98
98
|
|
|
99
|
-
5. **Evidence redaction (binding).** The upstream repo is PUBLIC by default (`hardening.upstreamRepo` → `CodySwannGT/lisa`) and this filing runs headless on crons — treat every drafted upstream body and comment as world-readable:
|
|
99
|
+
5. **Evidence redaction (binding).** The upstream repo is PUBLIC by default (`hardening.upstreamRepo` → `CodySwannGT/lisa`) and this filing runs headless on crons — treat every drafted upstream body and comment as world-readable. The PRIMARY control is the **allowlist projection** in step 6: `bunx @codyswann/lisa file-upstream` calls the sole `buildUpstreamAttributionIssueBody` export from `@codyswann/lisa/learnings`, so content outside its enumerated fields is structurally incapable of reaching the public document. The rules below bind the FIELDS supplied to that command; the closing scan is a defense-in-depth backstop, never the primary control:
|
|
100
100
|
|
|
101
101
|
- Quote ONLY Lisa-owned surface text: template/rule/skill/hook excerpts and upstream commit references. The reproduction must be REDACTED — generic placeholders, never the host project's real values.
|
|
102
102
|
- Never paste host environment values, tokens/credentials, connection strings, API keys, PII (names, emails, customer data), or proprietary host code/payloads.
|
|
103
|
-
- The evidence chain names the Lisa surface and the failure class — never project payloads.
|
|
104
|
-
-
|
|
105
|
-
-
|
|
103
|
+
- The evidence chain names the Lisa surface and the failure class — never project payloads. Keep any host-project issue link only in the private local trace; it is never supplied to or emitted by the public builder.
|
|
104
|
+
- Use only these exact generic placeholders: `<host-project>`, `<env-value>`, `<credential>`, `<connection-string>`, `<pii>`, `<host-payload>`, `<path>`, `<identifier>`. A project-specific placeholder is host prose and must be rejected.
|
|
105
|
+
- **Backstop (defense in depth, never the primary control).** Before filing or commenting, scan the projected document for common secret shapes — `key=value` pairs with high-entropy values, token prefixes (`AKIA`, `ghp_`, `xox`), email addresses — and reject on a match. To strip on match, remove the offending INPUT field and re-run `file-upstream`; never strip or edit the generated output itself. Non-allowlisted fields must reject before filing rather than be silently dropped. When in doubt, leave it out: a thinner upstream document is recoverable; a leaked secret is not.
|
|
106
106
|
|
|
107
107
|
6. **Dedupe by marker, then file or update.** The upstream marker is:
|
|
108
108
|
|
|
@@ -112,8 +112,32 @@ This disposition completes the SLL-5 loop (#1583): on a Lisa-attributed failure
|
|
|
112
112
|
|
|
113
113
|
Resolve the upstream repo from `.lisa.config.json` `hardening.upstreamRepo` (default `CodySwannGT/lisa`). Search **all issue states** for an existing issue carrying the marker — a closed marker-bearing ticket still owns this root cause, and searching only open issues would mint a duplicate the moment the original closes. Match on the **MARKER, never the title** — with the same eventual-consistency guard as above (`gh issue list -R <upstream> --state all --search '"<marker>" in:body' --json number,state,url`, and when the search index returns nothing, also `gh issue list -R <upstream> --state all --json number,state,body` and grep the bodies for the marker before concluding no ticket exists).
|
|
114
114
|
|
|
115
|
-
- **No existing ticket** →
|
|
116
|
-
|
|
115
|
+
- **No existing ticket** → compose the body EXCLUSIVELY through the executable builder, then file its stdout verbatim via `lisa-github-write-issue` targeting the upstream repo with the `self-hardening` label:
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
bunx @codyswann/lisa file-upstream --input filing-event.json # or pipe the JSON on stdin
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
**Never assemble the public body as free-form prose.** Public composition happens through the builder, never by free-form prose assembly. The builder owns the three-audience description and the redacted evidence chain (Lisa-owned text only). Do not hand-write either section, name an affected project in prose, or edit the builder's output after generation. Supply only this JSON shape; host-project issue URLs remain private local-trace data and are never accepted by the public builder:
|
|
122
|
+
|
|
123
|
+
```json
|
|
124
|
+
{
|
|
125
|
+
"documentKind": "issue",
|
|
126
|
+
"lisaSurface": "plugins/src/base/skills/lisa-doctor/SKILL.md",
|
|
127
|
+
"failureClass": "stale-artifact-overwrite",
|
|
128
|
+
"lisaOwnedExcerpts": [
|
|
129
|
+
{
|
|
130
|
+
"file": "plugins/src/base/skills/lisa-doctor/SKILL.md",
|
|
131
|
+
"text": "<verbatim Lisa-owned text>"
|
|
132
|
+
}
|
|
133
|
+
],
|
|
134
|
+
"upstreamCommitRefs": ["<full 40-character public-origin SHA>"],
|
|
135
|
+
"redactedPlaceholders": ["<host-project>", "<env-value>"]
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Every excerpt is verified against the installed package's Lisa-owned source and every commit against the public origin. Callers cannot supply a verifier or Lisa root. Anything outside the allowlist is REJECTED by field name with empty stdout and a non-zero exit; fix or remove the offending input field and re-run the command, never route around it. The builder emits **exactly one** dedupe marker; **never write a markerless body** — it permanently breaks all future dedupe.
|
|
140
|
+
- **Existing ticket (open or closed)** → this is a repeat encounter: comment the new occurrence on the existing issue with this project's evidence. The comment is projected through the same builder: run `bunx @codyswann/lisa file-upstream` with the same allowlisted fields plus exactly `"documentKind": "occurrence"` and `"occurrenceFingerprint": "<fingerprint>"`. The supplied fingerprint is only a validated seed: the builder hashes it and emits a different deterministic `sll4-<12 lowercase hex>` marker. Use the marker in the builder's stdout — never the supplied literal — to search existing issue comments for a duplicate, then post stdout verbatim only when that emitted marker is absent. Free-form occurrence prose is prohibited, and post-generation edits are prohibited. Never open a second issue, and never match on the title — evidence compounds on one ticket. When the match is **CLOSED**, still comment the occurrence there and reference it in the local trace instead of filing a duplicate; do not reopen it yourself — recurrence evidence on a closed ticket signals the shipped fix may not cover this case, and reopening is the upstream maintainer's call.
|
|
117
141
|
|
|
118
142
|
7. **Leave the local trace — a note, never a rule.** Post one follow-up comment on the triggering issue linking the upstream ticket:
|
|
119
143
|
|
|
@@ -90,19 +90,19 @@ This disposition completes the SLL-5 loop (#1583): on a Lisa-attributed failure
|
|
|
90
90
|
root-cause-key = <lisa-surface>#<failure-class>
|
|
91
91
|
```
|
|
92
92
|
|
|
93
|
-
- `<lisa-surface>` — the Lisa-relative path of the surface at fault (e.g. `plugins/src/base/skills/lisa-doctor/SKILL.md`, `typescript/copy-overwrite/.github/workflows/quality.yml`)
|
|
94
|
-
- `<failure-class>` —
|
|
93
|
+
- `<lisa-surface>` — the exact public Lisa-relative path of the surface at fault (e.g. `plugins/src/base/skills/lisa-doctor/SKILL.md`, `typescript/copy-overwrite/.github/workflows/quality.yml`). Canonical names, aliases, host paths, and unmanifested paths are prohibited.
|
|
94
|
+
- `<failure-class>` — exactly one exported closed value: `access-control-failure`, `agent-parity-regression`, `configuration-regression`, `data-integrity-failure`, `dependency-regression`, `generated-artifact-regression`, `installation-regression`, `observability-gap`, `pagination-truncation`, `performance-regression`, `public-data-exposure`, `release-regression`, `runtime-regression`, `stale-artifact-overwrite`, `test-coverage-gap`, `validation-gap`, or `workflow-contract-violation`.
|
|
95
95
|
- Normalize: lowercase, trim, collapse every whitespace run to a single `-`. The key must contain no host-project name, no local issue number, and no fingerprint — those vary per project and would defeat fleet-wide dedupe.
|
|
96
96
|
|
|
97
97
|
4. **Enforce the per-run cap.** Resolve `hardening.maxUpstreamFilingsPerRun` from `.lisa.config.json` (default `5` — a conservative bound modeled on `lisa-repair-intake`'s `max_candidates` precedent). Count every upstream create **and** update this run performs; once the cap is reached, drop the remaining candidates and **note each dropped candidate visibly** (in the run summary, naming its root-cause key) — never queue a spam burst and never drop silently. A later run picks the dropped candidates up idempotently.
|
|
98
98
|
|
|
99
|
-
5. **Evidence redaction (binding).** The upstream repo is PUBLIC by default (`hardening.upstreamRepo` → `CodySwannGT/lisa`) and this filing runs headless on crons — treat every drafted upstream body and comment as world-readable:
|
|
99
|
+
5. **Evidence redaction (binding).** The upstream repo is PUBLIC by default (`hardening.upstreamRepo` → `CodySwannGT/lisa`) and this filing runs headless on crons — treat every drafted upstream body and comment as world-readable. The PRIMARY control is the **allowlist projection** in step 6: `bunx @codyswann/lisa file-upstream` calls the sole `buildUpstreamAttributionIssueBody` export from `@codyswann/lisa/learnings`, so content outside its enumerated fields is structurally incapable of reaching the public document. The rules below bind the FIELDS supplied to that command; the closing scan is a defense-in-depth backstop, never the primary control:
|
|
100
100
|
|
|
101
101
|
- Quote ONLY Lisa-owned surface text: template/rule/skill/hook excerpts and upstream commit references. The reproduction must be REDACTED — generic placeholders, never the host project's real values.
|
|
102
102
|
- Never paste host environment values, tokens/credentials, connection strings, API keys, PII (names, emails, customer data), or proprietary host code/payloads.
|
|
103
|
-
- The evidence chain names the Lisa surface and the failure class — never project payloads.
|
|
104
|
-
-
|
|
105
|
-
-
|
|
103
|
+
- The evidence chain names the Lisa surface and the failure class — never project payloads. Keep any host-project issue link only in the private local trace; it is never supplied to or emitted by the public builder.
|
|
104
|
+
- Use only these exact generic placeholders: `<host-project>`, `<env-value>`, `<credential>`, `<connection-string>`, `<pii>`, `<host-payload>`, `<path>`, `<identifier>`. A project-specific placeholder is host prose and must be rejected.
|
|
105
|
+
- **Backstop (defense in depth, never the primary control).** Before filing or commenting, scan the projected document for common secret shapes — `key=value` pairs with high-entropy values, token prefixes (`AKIA`, `ghp_`, `xox`), email addresses — and reject on a match. To strip on match, remove the offending INPUT field and re-run `file-upstream`; never strip or edit the generated output itself. Non-allowlisted fields must reject before filing rather than be silently dropped. When in doubt, leave it out: a thinner upstream document is recoverable; a leaked secret is not.
|
|
106
106
|
|
|
107
107
|
6. **Dedupe by marker, then file or update.** The upstream marker is:
|
|
108
108
|
|
|
@@ -112,8 +112,32 @@ This disposition completes the SLL-5 loop (#1583): on a Lisa-attributed failure
|
|
|
112
112
|
|
|
113
113
|
Resolve the upstream repo from `.lisa.config.json` `hardening.upstreamRepo` (default `CodySwannGT/lisa`). Search **all issue states** for an existing issue carrying the marker — a closed marker-bearing ticket still owns this root cause, and searching only open issues would mint a duplicate the moment the original closes. Match on the **MARKER, never the title** — with the same eventual-consistency guard as above (`gh issue list -R <upstream> --state all --search '"<marker>" in:body' --json number,state,url`, and when the search index returns nothing, also `gh issue list -R <upstream> --state all --json number,state,body` and grep the bodies for the marker before concluding no ticket exists).
|
|
114
114
|
|
|
115
|
-
- **No existing ticket** →
|
|
116
|
-
|
|
115
|
+
- **No existing ticket** → compose the body EXCLUSIVELY through the executable builder, then file its stdout verbatim via `lisa-github-write-issue` targeting the upstream repo with the `self-hardening` label:
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
bunx @codyswann/lisa file-upstream --input filing-event.json # or pipe the JSON on stdin
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
**Never assemble the public body as free-form prose.** Public composition happens through the builder, never by free-form prose assembly. The builder owns the three-audience description and the redacted evidence chain (Lisa-owned text only). Do not hand-write either section, name an affected project in prose, or edit the builder's output after generation. Supply only this JSON shape; host-project issue URLs remain private local-trace data and are never accepted by the public builder:
|
|
122
|
+
|
|
123
|
+
```json
|
|
124
|
+
{
|
|
125
|
+
"documentKind": "issue",
|
|
126
|
+
"lisaSurface": "plugins/src/base/skills/lisa-doctor/SKILL.md",
|
|
127
|
+
"failureClass": "stale-artifact-overwrite",
|
|
128
|
+
"lisaOwnedExcerpts": [
|
|
129
|
+
{
|
|
130
|
+
"file": "plugins/src/base/skills/lisa-doctor/SKILL.md",
|
|
131
|
+
"text": "<verbatim Lisa-owned text>"
|
|
132
|
+
}
|
|
133
|
+
],
|
|
134
|
+
"upstreamCommitRefs": ["<full 40-character public-origin SHA>"],
|
|
135
|
+
"redactedPlaceholders": ["<host-project>", "<env-value>"]
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Every excerpt is verified against the installed package's Lisa-owned source and every commit against the public origin. Callers cannot supply a verifier or Lisa root. Anything outside the allowlist is REJECTED by field name with empty stdout and a non-zero exit; fix or remove the offending input field and re-run the command, never route around it. The builder emits **exactly one** dedupe marker; **never write a markerless body** — it permanently breaks all future dedupe.
|
|
140
|
+
- **Existing ticket (open or closed)** → this is a repeat encounter: comment the new occurrence on the existing issue with this project's evidence. The comment is projected through the same builder: run `bunx @codyswann/lisa file-upstream` with the same allowlisted fields plus exactly `"documentKind": "occurrence"` and `"occurrenceFingerprint": "<fingerprint>"`. The supplied fingerprint is only a validated seed: the builder hashes it and emits a different deterministic `sll4-<12 lowercase hex>` marker. Use the marker in the builder's stdout — never the supplied literal — to search existing issue comments for a duplicate, then post stdout verbatim only when that emitted marker is absent. Free-form occurrence prose is prohibited, and post-generation edits are prohibited. Never open a second issue, and never match on the title — evidence compounds on one ticket. When the match is **CLOSED**, still comment the occurrence there and reference it in the local trace instead of filing a duplicate; do not reopen it yourself — recurrence evidence on a closed ticket signals the shipped fix may not cover this case, and reopening is the upstream maintainer's call.
|
|
117
141
|
|
|
118
142
|
7. **Leave the local trace — a note, never a rule.** Post one follow-up comment on the triggering issue linking the upstream ticket:
|
|
119
143
|
|