@codyswann/lisa 2.285.1 → 2.286.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/core/upstream-evidence-manifest.d.ts.map +1 -1
- package/dist/core/upstream-evidence-manifest.js +14 -1
- package/dist/core/upstream-evidence-manifest.js.map +1 -1
- package/package.json +1 -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-task-decomposition/SKILL.md +38 -0
- package/plugins/lisa/rules/eager/dependency-internalization-kit.md +42 -0
- package/plugins/lisa/rules/reference/dependency-internalization-kit.md +197 -0
- package/plugins/lisa/skills/lisa-task-decomposition/SKILL.md +38 -0
- package/plugins/lisa-agy/plugin.json +1 -1
- package/plugins/lisa-agy/skills/lisa-task-decomposition/SKILL.md +38 -0
- package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk-agy/plugin.json +1 -1
- package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-copilot/rules/eager/dependency-internalization-kit.md +42 -0
- package/plugins/lisa-copilot/rules/reference/dependency-internalization-kit.md +197 -0
- package/plugins/lisa-copilot/skills/lisa-task-decomposition/SKILL.md +38 -0
- package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cursor/rules/dependency-internalization-kit-reference.mdc +202 -0
- package/plugins/lisa-cursor/rules/dependency-internalization-kit.mdc +47 -0
- package/plugins/lisa-cursor/skills/lisa-task-decomposition/SKILL.md +38 -0
- package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-expo-agy/plugin.json +1 -1
- package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-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/rules/eager/dependency-internalization-kit.md +42 -0
- package/plugins/src/base/rules/reference/dependency-internalization-kit.md +197 -0
- package/plugins/src/base/skills/lisa-task-decomposition/SKILL.md +38 -0
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
# Dependency Internalization Kit
|
|
2
|
+
|
|
3
|
+
Taking a dependency is a decision about trust: we believe someone else's code
|
|
4
|
+
works. Dropping one reverses that decision without reversing the obligation —
|
|
5
|
+
the capability still has to work, and now it is ours. The risk does not
|
|
6
|
+
disappear at the moment the package is uninstalled; it **changes shape**, from
|
|
7
|
+
"is upstream trustworthy?" to "did we actually rebuild what upstream did?"
|
|
8
|
+
|
|
9
|
+
The confidence-rebuild kit is the standing answer to that second question. It is
|
|
10
|
+
a reusable set of acceptance criteria that any removal, replacement, or
|
|
11
|
+
internalization work item inherits, so the evidence bar is decided once instead
|
|
12
|
+
of guessed at per ticket by whoever happens to write the tests.
|
|
13
|
+
|
|
14
|
+
The kit pairs with the other two dependency surfaces:
|
|
15
|
+
`.lisa/DEPENDENCY_DECISIONS.md` records *what we decided*, the
|
|
16
|
+
[dependency-trust-classes](dependency-trust-classes.md) rule says *what bar the
|
|
17
|
+
dependency had to clear to be there*, and this kit says *what proof we owe when
|
|
18
|
+
we take the capability back*.
|
|
19
|
+
|
|
20
|
+
## The seven required evidence types
|
|
21
|
+
|
|
22
|
+
Each is stated as the plain question it answers, because the person deciding
|
|
23
|
+
whether a removal is safe to ship is often not the person who wrote the code.
|
|
24
|
+
|
|
25
|
+
### 1. Real corpus — did we test it on real inputs, not toy examples?
|
|
26
|
+
|
|
27
|
+
The replacement must be exercised against **representative real inputs** drawn
|
|
28
|
+
from actual usage: production samples, recorded fixtures, historical files, real
|
|
29
|
+
config, the actual shapes the old dependency saw. Hand-written happy-path
|
|
30
|
+
examples are not a corpus. They are written by the same person who wrote the
|
|
31
|
+
implementation, from the same mental model, so they agree with the bug.
|
|
32
|
+
|
|
33
|
+
The acceptance criterion names where the corpus came from and roughly how big it
|
|
34
|
+
is. "We ran it on the 400 config files already in the repo" is a corpus. "We
|
|
35
|
+
tested it with `{a: 1}`" is not.
|
|
36
|
+
|
|
37
|
+
If real inputs cannot be obtained — because they are sensitive, or the capability
|
|
38
|
+
is new-shaped — say so explicitly and name what stands in for them. An unstated
|
|
39
|
+
absence reads as coverage that does not exist.
|
|
40
|
+
|
|
41
|
+
### 2. Conformance fixtures — does the new code do what the dependency did?
|
|
42
|
+
|
|
43
|
+
The replacement must be shown to **match the old dependency's behavior** on the
|
|
44
|
+
behavior we actually rely on. The strongest form is a differential test: run both
|
|
45
|
+
implementations over the corpus and assert the outputs agree, while the
|
|
46
|
+
dependency is still installed. That is why the kit belongs on the *removal*
|
|
47
|
+
ticket and not a follow-up — once the dependency is gone, the oracle is gone too.
|
|
48
|
+
|
|
49
|
+
Where a differential run is impossible, conformance fixtures are captured from
|
|
50
|
+
the old dependency's output *before* removal and asserted against afterwards.
|
|
51
|
+
|
|
52
|
+
Deliberate divergences are allowed and must be **written down** as divergences.
|
|
53
|
+
An intentional behavior change that nobody recorded is indistinguishable from a
|
|
54
|
+
regression six months later.
|
|
55
|
+
|
|
56
|
+
### 3. Negative fixtures — does it still reject what it should reject?
|
|
57
|
+
|
|
58
|
+
Most dependencies do half their work by **refusing** things: rejecting malformed
|
|
59
|
+
input, erroring on out-of-range values, failing closed on bad credentials.
|
|
60
|
+
Conformance fixtures over valid input never test that half, and a replacement
|
|
61
|
+
that accepts everything passes them all.
|
|
62
|
+
|
|
63
|
+
Negative fixtures assert the replacement still fails on what the dependency
|
|
64
|
+
failed on — and fails the same *way* where callers depend on the error type or
|
|
65
|
+
message. This is the criterion most often dropped, and its absence is how a
|
|
66
|
+
validation library gets internalized into a function that returns `true`.
|
|
67
|
+
|
|
68
|
+
### 4. Coverage as a gap detector — what behavior is still untested?
|
|
69
|
+
|
|
70
|
+
Coverage on internalization work is used to **find untested behavior**, not to
|
|
71
|
+
report a number. The criterion is a review of the uncovered lines and branches
|
|
72
|
+
with a stated disposition for each: tested, deliberately untested with a reason,
|
|
73
|
+
or a gap to close before shipping.
|
|
74
|
+
|
|
75
|
+
A coverage percentage on its own proves nothing here — new code written
|
|
76
|
+
alongside its own tests reaches a high number trivially while the branch that
|
|
77
|
+
matters is the one nobody thought of. The evidence is the *gap list*, and it is
|
|
78
|
+
acceptable for that list to end with "none".
|
|
79
|
+
|
|
80
|
+
### 5. Provenance and license review — where did this code come from, and are we allowed to use it?
|
|
81
|
+
|
|
82
|
+
Internalized code has a source: written from scratch against a spec, adapted
|
|
83
|
+
from the dependency's implementation, vendored wholesale, or copied from docs or
|
|
84
|
+
an answer online. The work item must **say which**, because that is what
|
|
85
|
+
determines our license obligation.
|
|
86
|
+
|
|
87
|
+
Adapting or vendoring carries the upstream license with it — attribution,
|
|
88
|
+
notice files, and copyleft terms follow the code even when the package does not.
|
|
89
|
+
A permissive license is not "no obligation"; it is usually an attribution
|
|
90
|
+
obligation.
|
|
91
|
+
|
|
92
|
+
The criterion states the origin, the license, and what we have to do about it. If
|
|
93
|
+
the answer is "written from scratch without reading their source," say that too —
|
|
94
|
+
it is the cleanest provenance available and worth recording.
|
|
95
|
+
|
|
96
|
+
### 6. Migration and update plan — how do existing call sites move, and how does the new code stay current?
|
|
97
|
+
|
|
98
|
+
Two halves, both required:
|
|
99
|
+
|
|
100
|
+
- **Migration**: every existing call site is enumerated and moved, in this change
|
|
101
|
+
or on a named schedule. A replacement nobody calls is not an internalization —
|
|
102
|
+
it is a second implementation, and the dependency is still installed.
|
|
103
|
+
- **Staying current**: the capability the dependency tracked usually keeps
|
|
104
|
+
moving — a spec revises, a format gains a version, a platform changes. Name
|
|
105
|
+
who watches for that and what triggers an update. "Upstream did this for us"
|
|
106
|
+
was a real service, and dropping the dependency dropped it.
|
|
107
|
+
|
|
108
|
+
### 7. Rollback or replacement criteria — what would make us go back, and to what?
|
|
109
|
+
|
|
110
|
+
Written **before** the removal ships, while it is still a technical judgment
|
|
111
|
+
rather than an argument during an incident. The criterion names:
|
|
112
|
+
|
|
113
|
+
- the observable conditions that mean the internalization failed — defect rate,
|
|
114
|
+
a class of input we cannot handle, maintenance cost we are not paying;
|
|
115
|
+
- what we do when they are met — reinstall the dependency, or pick a different
|
|
116
|
+
one, named;
|
|
117
|
+
- how long the rollback stays cheap, and what makes it expensive.
|
|
118
|
+
|
|
119
|
+
"We will fix forward" is a valid answer only if someone wrote it down on purpose.
|
|
120
|
+
|
|
121
|
+
## Applying the kit — and not over-applying it
|
|
122
|
+
|
|
123
|
+
The distinction the kit turns on is **whether ownership moves in-house**.
|
|
124
|
+
|
|
125
|
+
**Inherits the kit** — ownership moves:
|
|
126
|
+
|
|
127
|
+
- removing a material dependency and doing the work ourselves;
|
|
128
|
+
- replacing it with our own implementation;
|
|
129
|
+
- vendoring its source into the repo;
|
|
130
|
+
- forking it and maintaining the fork.
|
|
131
|
+
|
|
132
|
+
Each of those lands the capability in the
|
|
133
|
+
`thin wrapper suitable for in-house ownership` trust class or removes it from
|
|
134
|
+
the dependency set entirely, and either way we now own the behavior.
|
|
135
|
+
|
|
136
|
+
**Does not inherit the kit** — ownership does not move:
|
|
137
|
+
|
|
138
|
+
- a routine version bump of a trusted dependency **within its existing trust
|
|
139
|
+
class**, major or minor. The version-bump bar is the trust class's own
|
|
140
|
+
detection evidence and cadence, which already exist;
|
|
141
|
+
- swapping one third-party dependency for another third-party dependency, where
|
|
142
|
+
trust simply moves to a different upstream. That is a trust-class decision and
|
|
143
|
+
a decision-record update, not an internalization;
|
|
144
|
+
- adding a new dependency, which is covered by the trust-class rule.
|
|
145
|
+
|
|
146
|
+
Over-applying the kit is a real failure, not a harmless excess of caution. A
|
|
147
|
+
version bump forced to produce a corpus, conformance fixtures, and rollback
|
|
148
|
+
criteria costs days for evidence that proves nothing — nobody rebuilt anything —
|
|
149
|
+
and it teaches planners that the kit is boilerplate to be dispensed with, which
|
|
150
|
+
is exactly how it stops being applied when it matters.
|
|
151
|
+
|
|
152
|
+
The one exception: a version bump that **reclassifies** the dependency into
|
|
153
|
+
in-house ownership — a bump taken as a fork, or an upgrade we decline in favor of
|
|
154
|
+
owning the code — is an internalization wearing a bump's clothing, and it
|
|
155
|
+
inherits the kit.
|
|
156
|
+
|
|
157
|
+
## The non-material escape hatch
|
|
158
|
+
|
|
159
|
+
A work item that removes a dependency inherits the kit **unless it explicitly
|
|
160
|
+
justifies why the dependency is non-material**. A dependency is non-material when
|
|
161
|
+
its failure or disappearance would not break anything a user can see and would
|
|
162
|
+
not cost real time to replace — a one-line utility, a dev-only convenience, a
|
|
163
|
+
package nothing imports anymore.
|
|
164
|
+
|
|
165
|
+
The justification is written in the work item, in one sentence, and it is
|
|
166
|
+
reviewable. What is not acceptable is silence: a removal ticket with no kit and
|
|
167
|
+
no stated reason is not ready to build. That is the whole enforcement mechanism —
|
|
168
|
+
the planner must either carry the criteria or say on the record why they do not
|
|
169
|
+
apply.
|
|
170
|
+
|
|
171
|
+
## For the operator at the gate
|
|
172
|
+
|
|
173
|
+
The kit exists so that a removal ticket **explains how confidence will be rebuilt
|
|
174
|
+
before the dependency is dropped**, in language that does not require reading the
|
|
175
|
+
code. The seven questions are the readable form: did we test it on real inputs,
|
|
176
|
+
does it do what the old one did, does it still reject bad input, what is still
|
|
177
|
+
untested, where did the code come from and may we use it, how do callers move and
|
|
178
|
+
how does it stay current, and what would make us go back.
|
|
179
|
+
|
|
180
|
+
An operator who can read answers to those seven can judge the removal without
|
|
181
|
+
being an engineer. A removal ticket that cannot answer them is not a plan — it is
|
|
182
|
+
an intention.
|
|
183
|
+
|
|
184
|
+
## Agent parity
|
|
185
|
+
|
|
186
|
+
The kit is a governed markdown rule plus a decomposition-time expectation, not a
|
|
187
|
+
runtime behavior, so Claude Code, Codex, Cursor, OpenCode, Antigravity, and
|
|
188
|
+
Copilot all reach it identically through the shared rules mirror and the same
|
|
189
|
+
`lisa-task-decomposition` skill. Cursor receives the pair flattened into two
|
|
190
|
+
`.mdc` rules; Antigravity has no separate rules tree of its own and inherits the
|
|
191
|
+
same content through the shared mirror — no runtime is missing the kit.
|
|
192
|
+
|
|
193
|
+
The documented gap, uniform across all six runtimes: nothing enforces that a
|
|
194
|
+
removal ticket actually carries the kit. No hook or lint gate fails a build when
|
|
195
|
+
a dependency is deleted from a manifest with no corpus, no conformance fixtures,
|
|
196
|
+
and no rollback criteria. Inheritance is carried by this rule, the decomposition
|
|
197
|
+
skill, and review — the same posture as the trust-class rule it extends.
|
|
@@ -99,6 +99,43 @@ unit proposes adding one, the work unit must, before it is buildable:
|
|
|
99
99
|
If nobody can pick a class, that is the finding — resolve it before accepting
|
|
100
100
|
the work unit, not after the package is installed.
|
|
101
101
|
|
|
102
|
+
### 4.6. Inherit the Confidence-Rebuild Kit When Ownership Moves In-House
|
|
103
|
+
|
|
104
|
+
Step 4.5 covers dependencies a task proposes to **add**. This step covers
|
|
105
|
+
dependencies a task proposes to **remove, replace, or internalize** — vendor,
|
|
106
|
+
fork-and-maintain, or reimplement ourselves.
|
|
107
|
+
|
|
108
|
+
When ownership moves in-house, the risk stops being "do we trust upstream" and
|
|
109
|
+
becomes "did we prove we rebuilt the capability." A work unit that moves a
|
|
110
|
+
material dependency in-house **inherits all seven acceptance criteria** of the
|
|
111
|
+
`dependency-internalization-kit` rule, each written as an acceptance criterion
|
|
112
|
+
of the work unit:
|
|
113
|
+
|
|
114
|
+
1. **Real corpus** — did we test it on real inputs, not toy examples?
|
|
115
|
+
2. **Conformance fixtures** — does the new code do what the dependency did?
|
|
116
|
+
3. **Negative fixtures** — does it still reject what it should reject?
|
|
117
|
+
4. **Coverage as a gap detector** — what behavior is still untested?
|
|
118
|
+
5. **Provenance and license review** — where did this code come from, and are we
|
|
119
|
+
allowed to use it?
|
|
120
|
+
6. **Migration and update plan** — how do existing call sites move, and how does
|
|
121
|
+
the new code stay current?
|
|
122
|
+
7. **Rollback or replacement criteria** — what would make us go back, and to
|
|
123
|
+
what?
|
|
124
|
+
|
|
125
|
+
The only way out is an **explicit non-material justification** written into the
|
|
126
|
+
work unit — one reviewable sentence saying why this dependency's failure or
|
|
127
|
+
disappearance breaks nothing a user can see and costs no real time to replace.
|
|
128
|
+
Silence is not a justification.
|
|
129
|
+
|
|
130
|
+
**Do not over-apply the kit.** A routine version bump of a trusted dependency
|
|
131
|
+
**within its existing trust class** does not move ownership, so it does not
|
|
132
|
+
inherit the kit — its bar is that trust class's own detection evidence and
|
|
133
|
+
cadence. The same is true of swapping one third-party dependency for another,
|
|
134
|
+
which moves trust to a different upstream rather than in-house. Add the kit only
|
|
135
|
+
when ownership moves in-house; the exception is a bump taken *as* a fork or
|
|
136
|
+
declined *in favor of* owning the code, which is an internalization regardless of
|
|
137
|
+
how the ticket is titled.
|
|
138
|
+
|
|
102
139
|
### 5. Determine Execution Order
|
|
103
140
|
|
|
104
141
|
- Place foundational tasks first (types, schemas, interfaces, shared utilities)
|
|
@@ -147,6 +184,7 @@ Map each task to the skills needed to complete it. This enables delegation to sp
|
|
|
147
184
|
- Do not create tasks that cannot be verified -- if you cannot define how to prove it is done, the task is not well-scoped
|
|
148
185
|
- Every Task / Bug / Sub-task / Improvement is scoped to exactly one repo -- if the work spans repos, split into per-repo work units under a shared parent Story (see step 1.5)
|
|
149
186
|
- Any task proposing a new material dependency names its trust class, states that class's required evidence and whether human ratification is needed, and updates `.lisa/DEPENDENCY_DECISIONS.md` in the same change (see step 4.5) -- a proposed material dependency with no named class is not ready to build
|
|
187
|
+
- Any task removing, replacing, or internalizing a material dependency carries all seven confidence-rebuild kit criteria -- corpus, conformance, negative fixtures, coverage-as-gap-detector, provenance/license, migration/update plan, and rollback criteria (see step 4.6) -- unless it explicitly justifies why the dependency is non-material; a within-trust-class version bump does not carry the kit
|
|
150
188
|
- Keep tasks ordered so that no task references work that has not been completed by a prior task
|
|
151
189
|
- Flag any task that requires access, permissions, or external input not yet available
|
|
152
190
|
- Prefer more small tasks over fewer large tasks -- smaller tasks are easier to verify and less risky to fail
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Dependency Internalization Kit"
|
|
3
|
+
alwaysApply: false
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Dependency Internalization Kit
|
|
7
|
+
|
|
8
|
+
Taking a dependency is a decision about trust: we believe someone else's code
|
|
9
|
+
works. Dropping one reverses that decision without reversing the obligation —
|
|
10
|
+
the capability still has to work, and now it is ours. The risk does not
|
|
11
|
+
disappear at the moment the package is uninstalled; it **changes shape**, from
|
|
12
|
+
"is upstream trustworthy?" to "did we actually rebuild what upstream did?"
|
|
13
|
+
|
|
14
|
+
The confidence-rebuild kit is the standing answer to that second question. It is
|
|
15
|
+
a reusable set of acceptance criteria that any removal, replacement, or
|
|
16
|
+
internalization work item inherits, so the evidence bar is decided once instead
|
|
17
|
+
of guessed at per ticket by whoever happens to write the tests.
|
|
18
|
+
|
|
19
|
+
The kit pairs with the other two dependency surfaces:
|
|
20
|
+
`.lisa/DEPENDENCY_DECISIONS.md` records *what we decided*, the
|
|
21
|
+
[dependency-trust-classes](dependency-trust-classes.mdc) rule says *what bar the
|
|
22
|
+
dependency had to clear to be there*, and this kit says *what proof we owe when
|
|
23
|
+
we take the capability back*.
|
|
24
|
+
|
|
25
|
+
## The seven required evidence types
|
|
26
|
+
|
|
27
|
+
Each is stated as the plain question it answers, because the person deciding
|
|
28
|
+
whether a removal is safe to ship is often not the person who wrote the code.
|
|
29
|
+
|
|
30
|
+
### 1. Real corpus — did we test it on real inputs, not toy examples?
|
|
31
|
+
|
|
32
|
+
The replacement must be exercised against **representative real inputs** drawn
|
|
33
|
+
from actual usage: production samples, recorded fixtures, historical files, real
|
|
34
|
+
config, the actual shapes the old dependency saw. Hand-written happy-path
|
|
35
|
+
examples are not a corpus. They are written by the same person who wrote the
|
|
36
|
+
implementation, from the same mental model, so they agree with the bug.
|
|
37
|
+
|
|
38
|
+
The acceptance criterion names where the corpus came from and roughly how big it
|
|
39
|
+
is. "We ran it on the 400 config files already in the repo" is a corpus. "We
|
|
40
|
+
tested it with `{a: 1}`" is not.
|
|
41
|
+
|
|
42
|
+
If real inputs cannot be obtained — because they are sensitive, or the capability
|
|
43
|
+
is new-shaped — say so explicitly and name what stands in for them. An unstated
|
|
44
|
+
absence reads as coverage that does not exist.
|
|
45
|
+
|
|
46
|
+
### 2. Conformance fixtures — does the new code do what the dependency did?
|
|
47
|
+
|
|
48
|
+
The replacement must be shown to **match the old dependency's behavior** on the
|
|
49
|
+
behavior we actually rely on. The strongest form is a differential test: run both
|
|
50
|
+
implementations over the corpus and assert the outputs agree, while the
|
|
51
|
+
dependency is still installed. That is why the kit belongs on the *removal*
|
|
52
|
+
ticket and not a follow-up — once the dependency is gone, the oracle is gone too.
|
|
53
|
+
|
|
54
|
+
Where a differential run is impossible, conformance fixtures are captured from
|
|
55
|
+
the old dependency's output *before* removal and asserted against afterwards.
|
|
56
|
+
|
|
57
|
+
Deliberate divergences are allowed and must be **written down** as divergences.
|
|
58
|
+
An intentional behavior change that nobody recorded is indistinguishable from a
|
|
59
|
+
regression six months later.
|
|
60
|
+
|
|
61
|
+
### 3. Negative fixtures — does it still reject what it should reject?
|
|
62
|
+
|
|
63
|
+
Most dependencies do half their work by **refusing** things: rejecting malformed
|
|
64
|
+
input, erroring on out-of-range values, failing closed on bad credentials.
|
|
65
|
+
Conformance fixtures over valid input never test that half, and a replacement
|
|
66
|
+
that accepts everything passes them all.
|
|
67
|
+
|
|
68
|
+
Negative fixtures assert the replacement still fails on what the dependency
|
|
69
|
+
failed on — and fails the same *way* where callers depend on the error type or
|
|
70
|
+
message. This is the criterion most often dropped, and its absence is how a
|
|
71
|
+
validation library gets internalized into a function that returns `true`.
|
|
72
|
+
|
|
73
|
+
### 4. Coverage as a gap detector — what behavior is still untested?
|
|
74
|
+
|
|
75
|
+
Coverage on internalization work is used to **find untested behavior**, not to
|
|
76
|
+
report a number. The criterion is a review of the uncovered lines and branches
|
|
77
|
+
with a stated disposition for each: tested, deliberately untested with a reason,
|
|
78
|
+
or a gap to close before shipping.
|
|
79
|
+
|
|
80
|
+
A coverage percentage on its own proves nothing here — new code written
|
|
81
|
+
alongside its own tests reaches a high number trivially while the branch that
|
|
82
|
+
matters is the one nobody thought of. The evidence is the *gap list*, and it is
|
|
83
|
+
acceptable for that list to end with "none".
|
|
84
|
+
|
|
85
|
+
### 5. Provenance and license review — where did this code come from, and are we allowed to use it?
|
|
86
|
+
|
|
87
|
+
Internalized code has a source: written from scratch against a spec, adapted
|
|
88
|
+
from the dependency's implementation, vendored wholesale, or copied from docs or
|
|
89
|
+
an answer online. The work item must **say which**, because that is what
|
|
90
|
+
determines our license obligation.
|
|
91
|
+
|
|
92
|
+
Adapting or vendoring carries the upstream license with it — attribution,
|
|
93
|
+
notice files, and copyleft terms follow the code even when the package does not.
|
|
94
|
+
A permissive license is not "no obligation"; it is usually an attribution
|
|
95
|
+
obligation.
|
|
96
|
+
|
|
97
|
+
The criterion states the origin, the license, and what we have to do about it. If
|
|
98
|
+
the answer is "written from scratch without reading their source," say that too —
|
|
99
|
+
it is the cleanest provenance available and worth recording.
|
|
100
|
+
|
|
101
|
+
### 6. Migration and update plan — how do existing call sites move, and how does the new code stay current?
|
|
102
|
+
|
|
103
|
+
Two halves, both required:
|
|
104
|
+
|
|
105
|
+
- **Migration**: every existing call site is enumerated and moved, in this change
|
|
106
|
+
or on a named schedule. A replacement nobody calls is not an internalization —
|
|
107
|
+
it is a second implementation, and the dependency is still installed.
|
|
108
|
+
- **Staying current**: the capability the dependency tracked usually keeps
|
|
109
|
+
moving — a spec revises, a format gains a version, a platform changes. Name
|
|
110
|
+
who watches for that and what triggers an update. "Upstream did this for us"
|
|
111
|
+
was a real service, and dropping the dependency dropped it.
|
|
112
|
+
|
|
113
|
+
### 7. Rollback or replacement criteria — what would make us go back, and to what?
|
|
114
|
+
|
|
115
|
+
Written **before** the removal ships, while it is still a technical judgment
|
|
116
|
+
rather than an argument during an incident. The criterion names:
|
|
117
|
+
|
|
118
|
+
- the observable conditions that mean the internalization failed — defect rate,
|
|
119
|
+
a class of input we cannot handle, maintenance cost we are not paying;
|
|
120
|
+
- what we do when they are met — reinstall the dependency, or pick a different
|
|
121
|
+
one, named;
|
|
122
|
+
- how long the rollback stays cheap, and what makes it expensive.
|
|
123
|
+
|
|
124
|
+
"We will fix forward" is a valid answer only if someone wrote it down on purpose.
|
|
125
|
+
|
|
126
|
+
## Applying the kit — and not over-applying it
|
|
127
|
+
|
|
128
|
+
The distinction the kit turns on is **whether ownership moves in-house**.
|
|
129
|
+
|
|
130
|
+
**Inherits the kit** — ownership moves:
|
|
131
|
+
|
|
132
|
+
- removing a material dependency and doing the work ourselves;
|
|
133
|
+
- replacing it with our own implementation;
|
|
134
|
+
- vendoring its source into the repo;
|
|
135
|
+
- forking it and maintaining the fork.
|
|
136
|
+
|
|
137
|
+
Each of those lands the capability in the
|
|
138
|
+
`thin wrapper suitable for in-house ownership` trust class or removes it from
|
|
139
|
+
the dependency set entirely, and either way we now own the behavior.
|
|
140
|
+
|
|
141
|
+
**Does not inherit the kit** — ownership does not move:
|
|
142
|
+
|
|
143
|
+
- a routine version bump of a trusted dependency **within its existing trust
|
|
144
|
+
class**, major or minor. The version-bump bar is the trust class's own
|
|
145
|
+
detection evidence and cadence, which already exist;
|
|
146
|
+
- swapping one third-party dependency for another third-party dependency, where
|
|
147
|
+
trust simply moves to a different upstream. That is a trust-class decision and
|
|
148
|
+
a decision-record update, not an internalization;
|
|
149
|
+
- adding a new dependency, which is covered by the trust-class rule.
|
|
150
|
+
|
|
151
|
+
Over-applying the kit is a real failure, not a harmless excess of caution. A
|
|
152
|
+
version bump forced to produce a corpus, conformance fixtures, and rollback
|
|
153
|
+
criteria costs days for evidence that proves nothing — nobody rebuilt anything —
|
|
154
|
+
and it teaches planners that the kit is boilerplate to be dispensed with, which
|
|
155
|
+
is exactly how it stops being applied when it matters.
|
|
156
|
+
|
|
157
|
+
The one exception: a version bump that **reclassifies** the dependency into
|
|
158
|
+
in-house ownership — a bump taken as a fork, or an upgrade we decline in favor of
|
|
159
|
+
owning the code — is an internalization wearing a bump's clothing, and it
|
|
160
|
+
inherits the kit.
|
|
161
|
+
|
|
162
|
+
## The non-material escape hatch
|
|
163
|
+
|
|
164
|
+
A work item that removes a dependency inherits the kit **unless it explicitly
|
|
165
|
+
justifies why the dependency is non-material**. A dependency is non-material when
|
|
166
|
+
its failure or disappearance would not break anything a user can see and would
|
|
167
|
+
not cost real time to replace — a one-line utility, a dev-only convenience, a
|
|
168
|
+
package nothing imports anymore.
|
|
169
|
+
|
|
170
|
+
The justification is written in the work item, in one sentence, and it is
|
|
171
|
+
reviewable. What is not acceptable is silence: a removal ticket with no kit and
|
|
172
|
+
no stated reason is not ready to build. That is the whole enforcement mechanism —
|
|
173
|
+
the planner must either carry the criteria or say on the record why they do not
|
|
174
|
+
apply.
|
|
175
|
+
|
|
176
|
+
## For the operator at the gate
|
|
177
|
+
|
|
178
|
+
The kit exists so that a removal ticket **explains how confidence will be rebuilt
|
|
179
|
+
before the dependency is dropped**, in language that does not require reading the
|
|
180
|
+
code. The seven questions are the readable form: did we test it on real inputs,
|
|
181
|
+
does it do what the old one did, does it still reject bad input, what is still
|
|
182
|
+
untested, where did the code come from and may we use it, how do callers move and
|
|
183
|
+
how does it stay current, and what would make us go back.
|
|
184
|
+
|
|
185
|
+
An operator who can read answers to those seven can judge the removal without
|
|
186
|
+
being an engineer. A removal ticket that cannot answer them is not a plan — it is
|
|
187
|
+
an intention.
|
|
188
|
+
|
|
189
|
+
## Agent parity
|
|
190
|
+
|
|
191
|
+
The kit is a governed markdown rule plus a decomposition-time expectation, not a
|
|
192
|
+
runtime behavior, so Claude Code, Codex, Cursor, OpenCode, Antigravity, and
|
|
193
|
+
Copilot all reach it identically through the shared rules mirror and the same
|
|
194
|
+
`lisa-task-decomposition` skill. Cursor receives the pair flattened into two
|
|
195
|
+
`.mdc` rules; Antigravity has no separate rules tree of its own and inherits the
|
|
196
|
+
same content through the shared mirror — no runtime is missing the kit.
|
|
197
|
+
|
|
198
|
+
The documented gap, uniform across all six runtimes: nothing enforces that a
|
|
199
|
+
removal ticket actually carries the kit. No hook or lint gate fails a build when
|
|
200
|
+
a dependency is deleted from a manifest with no corpus, no conformance fixtures,
|
|
201
|
+
and no rollback criteria. Inheritance is carried by this rule, the decomposition
|
|
202
|
+
skill, and review — the same posture as the trust-class rule it extends.
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Dependency Internalization Kit (load-bearing)"
|
|
3
|
+
alwaysApply: true
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Dependency Internalization Kit (load-bearing)
|
|
7
|
+
|
|
8
|
+
When a work item **removes, replaces, or internalizes** a material dependency,
|
|
9
|
+
ownership of that capability moves in-house. The risk moves with it: we stop
|
|
10
|
+
trusting an upstream project and start having to **prove we rebuilt the
|
|
11
|
+
capability correctly**. The confidence-rebuild kit is the standing acceptance
|
|
12
|
+
bar for that proof, so internalization work never has to guess at its own tests.
|
|
13
|
+
|
|
14
|
+
The kit is seven required evidence types. Each leads with the plain question it
|
|
15
|
+
answers:
|
|
16
|
+
|
|
17
|
+
1. **Real corpus** — did we test it on real inputs, not toy examples?
|
|
18
|
+
2. **Conformance fixtures** — does the new code do what the dependency did?
|
|
19
|
+
3. **Negative fixtures** — does it still reject what it should reject?
|
|
20
|
+
4. **Coverage as a gap detector** — what behavior is still untested?
|
|
21
|
+
5. **Provenance and license review** — where did this code come from, and are we
|
|
22
|
+
allowed to use it?
|
|
23
|
+
6. **Migration and update plan** — how do existing call sites move, and how does
|
|
24
|
+
the new code stay current?
|
|
25
|
+
7. **Rollback or replacement criteria** — what would make us go back, and to
|
|
26
|
+
what?
|
|
27
|
+
|
|
28
|
+
All seven are required. A partial kit is the finding: dropping the corpus leaves
|
|
29
|
+
a toy-example pass, dropping negative fixtures leaves code that accepts garbage,
|
|
30
|
+
and dropping rollback criteria leaves nobody able to say the internalization
|
|
31
|
+
failed.
|
|
32
|
+
|
|
33
|
+
**When the kit applies:** ownership moves in-house — the dependency is removed,
|
|
34
|
+
replaced with our own code, vendored, or forked and maintained by us. That is
|
|
35
|
+
usually a move into the `thin wrapper suitable for in-house ownership` trust
|
|
36
|
+
class, or out of the dependency set entirely.
|
|
37
|
+
|
|
38
|
+
**When the kit does NOT apply:** a routine version bump of a trusted dependency
|
|
39
|
+
**within its existing trust class**. Ownership does not move, so there is no
|
|
40
|
+
rebuilt capability to prove. Applying the kit there is over-application — it
|
|
41
|
+
buys no confidence and makes ordinary upkeep expensive.
|
|
42
|
+
|
|
43
|
+
A work item that removes, replaces, or internalizes a material dependency
|
|
44
|
+
inherits all seven criteria unless it explicitly justifies why the dependency is
|
|
45
|
+
**non-material**. Silence is not a justification.
|
|
46
|
+
|
|
47
|
+
Full prose: [reference/dependency-internalization-kit.md](dependency-internalization-kit-reference.mdc).
|
|
@@ -99,6 +99,43 @@ unit proposes adding one, the work unit must, before it is buildable:
|
|
|
99
99
|
If nobody can pick a class, that is the finding — resolve it before accepting
|
|
100
100
|
the work unit, not after the package is installed.
|
|
101
101
|
|
|
102
|
+
### 4.6. Inherit the Confidence-Rebuild Kit When Ownership Moves In-House
|
|
103
|
+
|
|
104
|
+
Step 4.5 covers dependencies a task proposes to **add**. This step covers
|
|
105
|
+
dependencies a task proposes to **remove, replace, or internalize** — vendor,
|
|
106
|
+
fork-and-maintain, or reimplement ourselves.
|
|
107
|
+
|
|
108
|
+
When ownership moves in-house, the risk stops being "do we trust upstream" and
|
|
109
|
+
becomes "did we prove we rebuilt the capability." A work unit that moves a
|
|
110
|
+
material dependency in-house **inherits all seven acceptance criteria** of the
|
|
111
|
+
`dependency-internalization-kit` rule, each written as an acceptance criterion
|
|
112
|
+
of the work unit:
|
|
113
|
+
|
|
114
|
+
1. **Real corpus** — did we test it on real inputs, not toy examples?
|
|
115
|
+
2. **Conformance fixtures** — does the new code do what the dependency did?
|
|
116
|
+
3. **Negative fixtures** — does it still reject what it should reject?
|
|
117
|
+
4. **Coverage as a gap detector** — what behavior is still untested?
|
|
118
|
+
5. **Provenance and license review** — where did this code come from, and are we
|
|
119
|
+
allowed to use it?
|
|
120
|
+
6. **Migration and update plan** — how do existing call sites move, and how does
|
|
121
|
+
the new code stay current?
|
|
122
|
+
7. **Rollback or replacement criteria** — what would make us go back, and to
|
|
123
|
+
what?
|
|
124
|
+
|
|
125
|
+
The only way out is an **explicit non-material justification** written into the
|
|
126
|
+
work unit — one reviewable sentence saying why this dependency's failure or
|
|
127
|
+
disappearance breaks nothing a user can see and costs no real time to replace.
|
|
128
|
+
Silence is not a justification.
|
|
129
|
+
|
|
130
|
+
**Do not over-apply the kit.** A routine version bump of a trusted dependency
|
|
131
|
+
**within its existing trust class** does not move ownership, so it does not
|
|
132
|
+
inherit the kit — its bar is that trust class's own detection evidence and
|
|
133
|
+
cadence. The same is true of swapping one third-party dependency for another,
|
|
134
|
+
which moves trust to a different upstream rather than in-house. Add the kit only
|
|
135
|
+
when ownership moves in-house; the exception is a bump taken *as* a fork or
|
|
136
|
+
declined *in favor of* owning the code, which is an internalization regardless of
|
|
137
|
+
how the ticket is titled.
|
|
138
|
+
|
|
102
139
|
### 5. Determine Execution Order
|
|
103
140
|
|
|
104
141
|
- Place foundational tasks first (types, schemas, interfaces, shared utilities)
|
|
@@ -147,6 +184,7 @@ Map each task to the skills needed to complete it. This enables delegation to sp
|
|
|
147
184
|
- Do not create tasks that cannot be verified -- if you cannot define how to prove it is done, the task is not well-scoped
|
|
148
185
|
- Every Task / Bug / Sub-task / Improvement is scoped to exactly one repo -- if the work spans repos, split into per-repo work units under a shared parent Story (see step 1.5)
|
|
149
186
|
- Any task proposing a new material dependency names its trust class, states that class's required evidence and whether human ratification is needed, and updates `.lisa/DEPENDENCY_DECISIONS.md` in the same change (see step 4.5) -- a proposed material dependency with no named class is not ready to build
|
|
187
|
+
- Any task removing, replacing, or internalizing a material dependency carries all seven confidence-rebuild kit criteria -- corpus, conformance, negative fixtures, coverage-as-gap-detector, provenance/license, migration/update plan, and rollback criteria (see step 4.6) -- unless it explicitly justifies why the dependency is non-material; a within-trust-class version bump does not carry the kit
|
|
150
188
|
- Keep tasks ordered so that no task references work that has not been completed by a prior task
|
|
151
189
|
- Flag any task that requires access, permissions, or external input not yet available
|
|
152
190
|
- Prefer more small tasks over fewer large tasks -- smaller tasks are easier to verify and less risky to fail
|