@codyswann/lisa 2.298.1 → 2.299.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/all/copy-contents/.gitattributes +6 -0
- package/dist/cli/doctor-readiness-domain.d.ts.map +1 -1
- package/dist/cli/doctor-readiness-domain.js +10 -0
- package/dist/cli/doctor-readiness-domain.js.map +1 -1
- package/dist/cli/doctor-readiness-guardrails.d.ts.map +1 -1
- package/dist/cli/doctor-readiness-guardrails.js +10 -4
- package/dist/cli/doctor-readiness-guardrails.js.map +1 -1
- package/dist/cli/gate-commands.d.ts +8 -6
- package/dist/cli/gate-commands.d.ts.map +1 -1
- package/dist/cli/gate-commands.js +21 -0
- package/dist/cli/gate-commands.js.map +1 -1
- package/dist/cli/learnings-overflow-cmd.d.ts +27 -0
- package/dist/cli/learnings-overflow-cmd.d.ts.map +1 -0
- package/dist/cli/learnings-overflow-cmd.js +57 -0
- package/dist/cli/learnings-overflow-cmd.js.map +1 -0
- package/dist/core/learnings-alias.d.ts +156 -0
- package/dist/core/learnings-alias.d.ts.map +1 -0
- package/dist/core/learnings-alias.js +199 -0
- package/dist/core/learnings-alias.js.map +1 -0
- package/dist/core/learnings-document.d.ts +18 -0
- package/dist/core/learnings-document.d.ts.map +1 -1
- package/dist/core/learnings-document.js +23 -2
- package/dist/core/learnings-document.js.map +1 -1
- package/dist/core/learnings-merge-driver.d.ts +8 -33
- package/dist/core/learnings-merge-driver.d.ts.map +1 -1
- package/dist/core/learnings-merge-driver.js +15 -0
- package/dist/core/learnings-merge-driver.js.map +1 -1
- package/dist/core/learnings-overflow.d.ts +76 -0
- package/dist/core/learnings-overflow.d.ts.map +1 -0
- package/dist/core/learnings-overflow.js +212 -0
- package/dist/core/learnings-overflow.js.map +1 -0
- package/dist/core/learnings-writer.d.ts +6 -0
- package/dist/core/learnings-writer.d.ts.map +1 -1
- package/dist/core/learnings-writer.js +57 -8
- package/dist/core/learnings-writer.js.map +1 -1
- package/dist/core/learnings.d.ts +2 -0
- package/dist/core/learnings.d.ts.map +1 -1
- package/dist/core/learnings.js +2 -0
- package/dist/core/learnings.js.map +1 -1
- package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
- package/dist/core/upstream-evidence-manifest.js +11 -3
- 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-learnings-audit/SKILL.md +42 -6
- package/plugins/lisa/.codex-plugin/skills/lisa-persist-learning/SKILL.md +7 -2
- package/plugins/lisa/skills/lisa-learnings-audit/SKILL.md +42 -6
- package/plugins/lisa/skills/lisa-persist-learning/SKILL.md +7 -2
- package/plugins/lisa-agy/plugin.json +1 -1
- package/plugins/lisa-agy/skills/lisa-learnings-audit/SKILL.md +42 -6
- package/plugins/lisa-agy/skills/lisa-persist-learning/SKILL.md +7 -2
- 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-learnings-audit/SKILL.md +42 -6
- package/plugins/lisa-copilot/skills/lisa-persist-learning/SKILL.md +7 -2
- package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cursor/skills/lisa-learnings-audit/SKILL.md +42 -6
- package/plugins/lisa-cursor/skills/lisa-persist-learning/SKILL.md +7 -2
- 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-learnings-audit/SKILL.md +42 -6
- package/plugins/src/base/skills/lisa-persist-learning/SKILL.md +7 -2
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Durable holding area for learnings the ledger had no budget to accept.
|
|
3
|
+
*
|
|
4
|
+
* ## Why this exists
|
|
5
|
+
*
|
|
6
|
+
* When a judged-durable capture cannot fit the ledger's hard caps, the writer
|
|
7
|
+
* drops it. Before this module the dropped CONTENT survived only in the capture
|
|
8
|
+
* report's text, so once that scrolled away a genuinely valuable learning was
|
|
9
|
+
* gone and the gardener had nothing to drain (CodySwannGT/lisa#1996).
|
|
10
|
+
* CodySwannGT/lisa#1959 raised the byte budget and added the
|
|
11
|
+
* `[lisa-ledger-saturated]` tracker signal — the signal says "saturated"; this
|
|
12
|
+
* file says "and here is exactly what was dropped".
|
|
13
|
+
*
|
|
14
|
+
* ## Why it is git-tracked, in the ledger's own format
|
|
15
|
+
*
|
|
16
|
+
* A learner pass runs on its own `learning/<fingerprint>` branch in its own
|
|
17
|
+
* worktree, and those worktrees are disposable. An untracked, machine-local
|
|
18
|
+
* overflow would be deleted by ordinary worktree cleanup before any gardener
|
|
19
|
+
* saw it — durable in name only, and invisible to a gardener running anywhere
|
|
20
|
+
* else. So the overflow ships to `main` on the same pull request as the capture
|
|
21
|
+
* that produced it.
|
|
22
|
+
*
|
|
23
|
+
* Being tracked means it has the very concurrent-writer problem the ledger just
|
|
24
|
+
* had (CodySwannGT/lisa#1995), which is exactly why it reuses the ledger's
|
|
25
|
+
* canonical document format verbatim: one `.gitattributes` line binds it to the
|
|
26
|
+
* SAME union-by-id merge driver, `parseLearningsFile` gives it the SAME
|
|
27
|
+
* conflict-marker guard, and `checkLearningsBudget` can gate it in CI unchanged.
|
|
28
|
+
* A bespoke format would have needed all of that written a second time.
|
|
29
|
+
*
|
|
30
|
+
* ## Why it carries the same budget
|
|
31
|
+
*
|
|
32
|
+
* The overflow is a hand-off buffer the gardener drains, not an archive. Letting
|
|
33
|
+
* it grow without bound would relocate the very context-bloat problem the
|
|
34
|
+
* contract exists to prevent, and a repository file that only ever grows is its
|
|
35
|
+
* own incident. So it is capped exactly like the ledger, nothing is ever
|
|
36
|
+
* silently evicted from it, and an overflow that is itself full surfaces as a
|
|
37
|
+
* loud failure naming both surfaces.
|
|
38
|
+
*
|
|
39
|
+
* ## Lock discipline
|
|
40
|
+
*
|
|
41
|
+
* The ledger lock and the overflow lock are NEVER held at the same time. The
|
|
42
|
+
* writer's ledger transaction fails and fully releases its lock before
|
|
43
|
+
* {@link preserveDroppedLearning} takes the overflow lock, so the two paths are
|
|
44
|
+
* strictly sequential and the pair cannot deadlock regardless of acquisition
|
|
45
|
+
* order between processes.
|
|
46
|
+
* @module core/learnings-overflow
|
|
47
|
+
*/
|
|
48
|
+
import * as fse from "fs-extra";
|
|
49
|
+
import * as path from "node:path";
|
|
50
|
+
import { writeFileAtomically } from "../utils/atomic-file-write.js";
|
|
51
|
+
import { LearningsBudgetError, assertDocumentBudget, parseLearningsFile, renderLearningsFile, } from "./learnings-document.js";
|
|
52
|
+
import { assertSafeLearningParents, readExistingLearnings, resolveSafeLearningTarget, } from "./learnings-file-safety.js";
|
|
53
|
+
import { withFileTargetLock } from "./learnings-lock.js";
|
|
54
|
+
import { readProjectConfig, resolveProjectLearningsFile, } from "./project-config.js";
|
|
55
|
+
/** Suffix distinguishing the overflow from the ledger it belongs to. */
|
|
56
|
+
const OVERFLOW_SUFFIX = ".overflow";
|
|
57
|
+
/**
|
|
58
|
+
* Derive the overflow path from a project's configured ledger path.
|
|
59
|
+
*
|
|
60
|
+
* Derived rather than separately configurable so a project that relocates its
|
|
61
|
+
* ledger through `learnings.file` cannot end up with the two halves of one
|
|
62
|
+
* mechanism in different directories — and so there is no second config key to
|
|
63
|
+
* validate, contain, and keep in sync.
|
|
64
|
+
* @param learningsFile - Project-relative ledger path
|
|
65
|
+
* @returns Project-relative overflow path
|
|
66
|
+
*/
|
|
67
|
+
export function resolveLearningsOverflowFile(learningsFile) {
|
|
68
|
+
const extension = path.posix.extname(learningsFile);
|
|
69
|
+
const base = learningsFile.slice(0, learningsFile.length - extension.length);
|
|
70
|
+
return `${base}${OVERFLOW_SUFFIX}${extension}`;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Resolve and contain the overflow target for one project.
|
|
74
|
+
* @param projectRoot - Absolute path to the host project root
|
|
75
|
+
* @returns Resolved project root and absolute overflow path
|
|
76
|
+
*/
|
|
77
|
+
async function resolveOverflowTarget(projectRoot) {
|
|
78
|
+
const config = await readProjectConfig(projectRoot);
|
|
79
|
+
const relative = resolveLearningsOverflowFile(resolveProjectLearningsFile(config));
|
|
80
|
+
return resolveSafeLearningTarget(projectRoot, relative);
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Read the entries currently held in the overflow.
|
|
84
|
+
* @param target - Absolute overflow path
|
|
85
|
+
* @returns Validated entries, empty when the file does not exist
|
|
86
|
+
*/
|
|
87
|
+
async function readOverflowEntries(target) {
|
|
88
|
+
const existing = await readExistingLearnings(target);
|
|
89
|
+
return existing === undefined ? [] : parseLearningsFile(existing);
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Read the overflow without modifying it.
|
|
93
|
+
*
|
|
94
|
+
* An absent file is the common, expected case and reads as empty — a project
|
|
95
|
+
* that has never dropped a capture must not have to special-case its absence.
|
|
96
|
+
* @param projectRoot - Absolute path to the host project root
|
|
97
|
+
* @returns Overflow path and the entries awaiting drain
|
|
98
|
+
*/
|
|
99
|
+
export async function readLearningsOverflow(projectRoot) {
|
|
100
|
+
const { target } = await resolveOverflowTarget(projectRoot);
|
|
101
|
+
return { file: target, entries: await readOverflowEntries(target) };
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Remove entries the gardener has durably captured elsewhere.
|
|
105
|
+
*
|
|
106
|
+
* Drain is BY ID and never "empty the file", because the gardener's real
|
|
107
|
+
* sequence is read → file a ticket per entry → drain. Clearing everything up
|
|
108
|
+
* front would lose any entry whose ticket failed to file; removing only the ids
|
|
109
|
+
* that already have a durable home makes a partial run safely resumable.
|
|
110
|
+
*
|
|
111
|
+
* An unknown id is reported rather than thrown, for the same reason an absent
|
|
112
|
+
* supersede target is tolerated: on a re-run, an id another pass already drained
|
|
113
|
+
* is indistinguishable from a bogus one, and failing the drain would strand
|
|
114
|
+
* every other entry in the batch.
|
|
115
|
+
* @param projectRoot - Absolute path to the host project root
|
|
116
|
+
* @param ids - Entry ids to remove
|
|
117
|
+
* @returns Which ids were drained, which were absent, and what remains
|
|
118
|
+
*/
|
|
119
|
+
export async function drainLearningsOverflow(projectRoot, ids) {
|
|
120
|
+
const requested = new Set(validateOverflowIds(ids));
|
|
121
|
+
const { root, target } = await resolveOverflowTarget(projectRoot);
|
|
122
|
+
await assertSafeLearningParents(root, path.dirname(target));
|
|
123
|
+
return withFileTargetLock(target, async () => {
|
|
124
|
+
// The pre-lock check can go stale while waiting on the lock, so the
|
|
125
|
+
// containment guarantee has to be re-established once the read is
|
|
126
|
+
// actually about to happen. Same discipline as the ledger writer.
|
|
127
|
+
await assertSafeLearningParents(root, path.dirname(target));
|
|
128
|
+
const entries = await readOverflowEntries(target);
|
|
129
|
+
const drained = entries
|
|
130
|
+
.filter(entry => requested.has(entry.id))
|
|
131
|
+
.map(entry => entry.id);
|
|
132
|
+
const retained = entries.filter(entry => !requested.has(entry.id));
|
|
133
|
+
if (drained.length > 0) {
|
|
134
|
+
await publishOverflow(root, target, retained);
|
|
135
|
+
}
|
|
136
|
+
return {
|
|
137
|
+
file: target,
|
|
138
|
+
drained,
|
|
139
|
+
absent: [...requested].filter(id => !drained.includes(id)),
|
|
140
|
+
remaining: retained.length,
|
|
141
|
+
};
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Render, budget-check, and atomically publish the overflow document.
|
|
146
|
+
* @param root - Resolved project root
|
|
147
|
+
* @param target - Absolute overflow path
|
|
148
|
+
* @param entries - Entries the overflow should now hold
|
|
149
|
+
*/
|
|
150
|
+
async function publishOverflow(root, target, entries) {
|
|
151
|
+
const rendered = renderLearningsFile(entries);
|
|
152
|
+
assertDocumentBudget(rendered, entries.length, "Learnings overflow");
|
|
153
|
+
await fse.ensureDir(path.dirname(target));
|
|
154
|
+
await writeFileAtomically(target, rendered, {
|
|
155
|
+
beforeRename: () => assertSafeLearningParents(root, path.dirname(target)),
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Preserve a capture the ledger had no budget for, then re-raise the breach.
|
|
160
|
+
*
|
|
161
|
+
* Never returns normally: the capture genuinely did not land in the ledger, and
|
|
162
|
+
* a caller that treated preservation as success would report a learning as
|
|
163
|
+
* persisted when the projection will never serve it. The re-raised error names
|
|
164
|
+
* the overflow file so the drop is actionable rather than merely fatal.
|
|
165
|
+
*
|
|
166
|
+
* If the overflow is itself full, the original ledger breach is re-raised with
|
|
167
|
+
* both surfaces named. Nothing is evicted to make room — silently discarding an
|
|
168
|
+
* older dropped learning to store a newer one is the exact data loss this whole
|
|
169
|
+
* mechanism exists to prevent.
|
|
170
|
+
* @param projectRoot - Absolute path to the host project root
|
|
171
|
+
* @param entry - The validated entry the ledger rejected
|
|
172
|
+
* @param breach - The budget breach the ledger write raised
|
|
173
|
+
* @returns Never — always throws
|
|
174
|
+
*/
|
|
175
|
+
export async function preserveDroppedLearning(projectRoot, entry, breach) {
|
|
176
|
+
const { root, target } = await resolveOverflowTarget(projectRoot);
|
|
177
|
+
await assertSafeLearningParents(root, path.dirname(target));
|
|
178
|
+
const preserved = await withFileTargetLock(target, async () => {
|
|
179
|
+
// Re-establish containment after the lock wait; see drainLearningsOverflow.
|
|
180
|
+
await assertSafeLearningParents(root, path.dirname(target));
|
|
181
|
+
const entries = await readOverflowEntries(target);
|
|
182
|
+
if (entries.some(current => current.id === entry.id)) {
|
|
183
|
+
return true;
|
|
184
|
+
}
|
|
185
|
+
try {
|
|
186
|
+
await publishOverflow(root, target, [...entries, entry]);
|
|
187
|
+
return true;
|
|
188
|
+
}
|
|
189
|
+
catch (error) {
|
|
190
|
+
if (error instanceof LearningsBudgetError) {
|
|
191
|
+
return false;
|
|
192
|
+
}
|
|
193
|
+
throw error;
|
|
194
|
+
}
|
|
195
|
+
});
|
|
196
|
+
throw new LearningsBudgetError(preserved
|
|
197
|
+
? `${breach.message} — the capture was preserved in ${target}; drain it with \`lisa learnings-overflow\` (the gardener does this automatically)`
|
|
198
|
+
: `${breach.message} — the overflow at ${target} is full too, so the capture could not be preserved; drain the overflow, then promote or retire a learning`);
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Reject malformed drain directives before any filesystem work.
|
|
202
|
+
* @param ids - Caller-supplied (possibly untrusted) entry ids
|
|
203
|
+
* @returns Deduplicated list of validated ids
|
|
204
|
+
*/
|
|
205
|
+
function validateOverflowIds(ids) {
|
|
206
|
+
if (!Array.isArray(ids) ||
|
|
207
|
+
ids.some(id => typeof id !== "string" || id.trim() === "")) {
|
|
208
|
+
throw new Error("Invalid overflow drain ids: expected non-empty learning id strings");
|
|
209
|
+
}
|
|
210
|
+
return [...new Set(ids)];
|
|
211
|
+
}
|
|
212
|
+
//# sourceMappingURL=learnings-overflow.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"learnings-overflow.js","sourceRoot":"","sources":["../../src/core/learnings-overflow.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,6 +8,12 @@ export interface ConsolidatedLearningOptions {
|
|
|
8
8
|
* succeeds; this is a diagnostic, not a failure hook.
|
|
9
9
|
*/
|
|
10
10
|
readonly onAbsentSupersede?: (ids: readonly string[]) => void;
|
|
11
|
+
/**
|
|
12
|
+
* Called when a `supersedes:` alias reference did not fit inside the entry's
|
|
13
|
+
* provenance cap and was dropped. A reference that is about to stop resolving
|
|
14
|
+
* must never disappear silently; the write still succeeds.
|
|
15
|
+
*/
|
|
16
|
+
readonly onAliasesDropped?: (references: readonly string[]) => void;
|
|
11
17
|
}
|
|
12
18
|
/**
|
|
13
19
|
* Persist one already-selected learning without generating or truncating it.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"learnings-writer.d.ts","sourceRoot":"","sources":["../../src/core/learnings-writer.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"learnings-writer.d.ts","sourceRoot":"","sources":["../../src/core/learnings-writer.ts"],"names":[],"mappings":"AA4BA,gFAAgF;AAChF,MAAM,WAAW,2BAA2B;IAC1C,gEAAgE;IAChE,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACvC;;;;OAIG;IACH,QAAQ,CAAC,iBAAiB,CAAC,EAAE,CAAC,GAAG,EAAE,SAAS,MAAM,EAAE,KAAK,IAAI,CAAC;IAC9D;;;;OAIG;IACH,QAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,KAAK,IAAI,CAAC;CACrE;AAED;;;;;;;;GAQG;AACH,wBAAsB,oBAAoB,CACxC,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,OAAO,GACjB,OAAO,CAAC,MAAM,CAAC,CAEjB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,2BAA2B,CAC/C,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,OAAO,EAClB,OAAO,GAAE,2BAAgC,GACxC,OAAO,CAAC,MAAM,CAAC,CA8BjB;AAsED,2DAA2D;AAC3D,MAAM,MAAM,qBAAqB,GAAG,WAAW,GAAG,WAAW,GAAG,WAAW,CAAC;AAE5E,uEAAuE;AACvE,MAAM,WAAW,qBAAqB;IACpC,8EAA8E;IAC9E,QAAQ,CAAC,MAAM,EAAE,qBAAqB,CAAC;IACvC,gDAAgD;IAChD,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB;;;;OAIG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,mEAAmE;IACnE,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,oBAAoB,CACxC,WAAW,EAAE,MAAM,EACnB,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,qBAAqB,CAAC,CA2ChC;AAED,OAAO,EACL,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC"}
|
|
@@ -2,10 +2,12 @@
|
|
|
2
2
|
import * as fse from "fs-extra";
|
|
3
3
|
import * as path from "node:path";
|
|
4
4
|
import { writeFileAtomically } from "../utils/atomic-file-write.js";
|
|
5
|
-
import {
|
|
5
|
+
import { applySupersedeAliases, findCallerMintedAliasError, } from "./learnings-alias.js";
|
|
6
|
+
import { LearningsBudgetError, assertDocumentBudget, parseLearningsFile, renderLearningsFile, } from "./learnings-document.js";
|
|
6
7
|
import { requireIsoDate, validateLearningEntry } from "./learnings-entry.js";
|
|
7
8
|
import { assertSafeLearningParents, readExistingLearnings, resolveSafeLearningTarget, } from "./learnings-file-safety.js";
|
|
8
9
|
import { withLearningTargetLock } from "./learnings-lock.js";
|
|
10
|
+
import { preserveDroppedLearning } from "./learnings-overflow.js";
|
|
9
11
|
import { readProjectConfig, resolveProjectLearningsFile, } from "./project-config.js";
|
|
10
12
|
/**
|
|
11
13
|
* Persist one already-selected learning without generating or truncating it.
|
|
@@ -34,6 +36,10 @@ export async function persistLearningEntry(projectRoot, candidate) {
|
|
|
34
36
|
*/
|
|
35
37
|
export async function persistConsolidatedLearning(projectRoot, candidate, options = {}) {
|
|
36
38
|
const entry = validateLearningEntry(candidate);
|
|
39
|
+
const mintedAlias = findCallerMintedAliasError(entry);
|
|
40
|
+
if (mintedAlias !== undefined) {
|
|
41
|
+
throw mintedAlias;
|
|
42
|
+
}
|
|
37
43
|
const supersede = validateSupersedeIds(options.supersede);
|
|
38
44
|
const config = await readProjectConfig(projectRoot);
|
|
39
45
|
const relativeFile = resolveProjectLearningsFile(config);
|
|
@@ -42,32 +48,75 @@ export async function persistConsolidatedLearning(projectRoot, candidate, option
|
|
|
42
48
|
buildNextDocument([], entry, []);
|
|
43
49
|
await assertSafeLearningParents(root, path.dirname(target));
|
|
44
50
|
await fse.ensureDir(path.dirname(target));
|
|
45
|
-
|
|
51
|
+
try {
|
|
52
|
+
return await writeLearningEntriesWithLock({ root, target }, entry, supersede, options);
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
if (!(error instanceof LearningsBudgetError)) {
|
|
56
|
+
throw error;
|
|
57
|
+
}
|
|
58
|
+
// The ledger lock is fully released by now — `withLearningTargetLock`
|
|
59
|
+
// releases in a `finally` — so the overflow lock below is taken with no
|
|
60
|
+
// other learnings lock held. The two are never nested.
|
|
61
|
+
return preserveDroppedLearning(projectRoot, entry, error);
|
|
62
|
+
}
|
|
46
63
|
}
|
|
47
64
|
/**
|
|
48
65
|
* Perform the locked read-validate-write transaction for a learnings update.
|
|
49
|
-
* @param
|
|
50
|
-
* @param
|
|
66
|
+
* @param location - Resolved project root and absolute learnings file path
|
|
67
|
+
* @param location.root - Resolved project root
|
|
68
|
+
* @param location.target - Absolute learnings file path
|
|
51
69
|
* @param entry - New validated entry
|
|
52
70
|
* @param supersede - Ids of existing entries the new entry replaces
|
|
53
|
-
* @param
|
|
71
|
+
* @param options - Caller diagnostics for absent targets and dropped aliases
|
|
54
72
|
* @returns Absolute path to the persisted learnings file
|
|
55
73
|
*/
|
|
56
|
-
function writeLearningEntriesWithLock(root, target, entry, supersede,
|
|
74
|
+
function writeLearningEntriesWithLock({ root, target }, entry, supersede, options) {
|
|
57
75
|
return withLearningTargetLock(target, async () => {
|
|
58
76
|
await assertSafeLearningParents(root, path.dirname(target));
|
|
59
77
|
const existing = await readExistingLearnings(target);
|
|
60
78
|
const entries = existing === undefined ? [] : parseLearningsFile(existing);
|
|
61
79
|
const absent = supersede.filter(id => !entries.some(current => current.id === id));
|
|
62
80
|
if (absent.length > 0)
|
|
63
|
-
onAbsentSupersede?.(absent);
|
|
64
|
-
const
|
|
81
|
+
options.onAbsentSupersede?.(absent);
|
|
82
|
+
const aliased = aliasSupersededEntries(entries, entry, supersede, options);
|
|
83
|
+
const rendered = buildNextDocument(entries, aliased, supersede);
|
|
65
84
|
await writeFileAtomically(target, rendered, {
|
|
66
85
|
beforeRename: () => assertSafeLearningParents(root, path.dirname(target)),
|
|
67
86
|
});
|
|
68
87
|
return target;
|
|
69
88
|
});
|
|
70
89
|
}
|
|
90
|
+
/**
|
|
91
|
+
* Record, in the new entry's provenance, which entries this write replaced.
|
|
92
|
+
*
|
|
93
|
+
* Only targets that are genuinely PRESENT contribute an alias. A supersede
|
|
94
|
+
* naming an already-consolidated id removed nothing, so claiming its reference
|
|
95
|
+
* would hijack a pointer the earlier writer legitimately owns — see
|
|
96
|
+
* `learnings-alias.ts` for why that distinction is what keeps the #1995
|
|
97
|
+
* losing-writer guarantee intact.
|
|
98
|
+
*
|
|
99
|
+
* The rewritten entry is pushed back through `validateLearningEntry` rather than
|
|
100
|
+
* spread-and-trusted, so the added references are held to the same schema as any
|
|
101
|
+
* caller-supplied one and the persisted object stays a frozen, exactly-seven-field
|
|
102
|
+
* entry.
|
|
103
|
+
* @param entries - Entries currently in the document
|
|
104
|
+
* @param entry - New validated entry as the caller composed it
|
|
105
|
+
* @param supersede - Validated supersede ids
|
|
106
|
+
* @param options - Caller diagnostics
|
|
107
|
+
* @returns The entry to persist, carrying its supersede aliases
|
|
108
|
+
*/
|
|
109
|
+
function aliasSupersededEntries(entries, entry, supersede, options) {
|
|
110
|
+
const superseded = new Set(supersede);
|
|
111
|
+
const removed = entries.filter(current => superseded.has(current.id));
|
|
112
|
+
if (removed.length === 0) {
|
|
113
|
+
return entry;
|
|
114
|
+
}
|
|
115
|
+
const aliased = applySupersedeAliases(entry, removed);
|
|
116
|
+
if (aliased.dropped.length > 0)
|
|
117
|
+
options.onAliasesDropped?.(aliased.dropped);
|
|
118
|
+
return validateLearningEntry({ ...entry, provenance: aliased.provenance });
|
|
119
|
+
}
|
|
71
120
|
/**
|
|
72
121
|
* Surgically advance ONLY one entry's `last_confirmed` timestamp — the
|
|
73
122
|
* claim-time "this rule demonstrably applied" confirmation (#1579). Uses the
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"learnings-writer.js","sourceRoot":"","sources":["../../src/core/learnings-writer.ts"],"names":[],"mappings":"AAAA,6DAA6D;AAC7D,OAAO,KAAK,GAAG,MAAM,UAAU,CAAC;AAChC,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"learnings-writer.js","sourceRoot":"","sources":["../../src/core/learnings-writer.ts"],"names":[],"mappings":"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"}
|
package/dist/core/learnings.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"learnings.d.ts","sourceRoot":"","sources":["../../src/core/learnings.ts"],"names":[],"mappings":"AAAA,cAAc,yBAAyB,CAAC;AACxC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,uBAAuB,CAAC;AACtC,cAAc,gCAAgC,CAAC;AAC/C,OAAO,EACL,8BAA8B,EAC9B,0BAA0B,EAC1B,0BAA0B,EAC1B,iBAAiB,EACjB,iCAAiC,EACjC,2BAA2B,EAC3B,uBAAuB,EACvB,KAAK,eAAe,EACpB,KAAK,aAAa,GACnB,MAAM,qBAAqB,CAAC"}
|
|
1
|
+
{"version":3,"file":"learnings.d.ts","sourceRoot":"","sources":["../../src/core/learnings.ts"],"names":[],"mappings":"AAAA,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC;AACxC,cAAc,yBAAyB,CAAC;AACxC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,uBAAuB,CAAC;AACtC,cAAc,gCAAgC,CAAC;AAC/C,OAAO,EACL,8BAA8B,EAC9B,0BAA0B,EAC1B,0BAA0B,EAC1B,iBAAiB,EACjB,iCAAiC,EACjC,2BAA2B,EAC3B,uBAAuB,EACvB,KAAK,eAAe,EACpB,KAAK,aAAa,GACnB,MAAM,qBAAqB,CAAC"}
|
package/dist/core/learnings.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"learnings.js","sourceRoot":"","sources":["../../src/core/learnings.ts"],"names":[],"mappings":"AAAA,cAAc,yBAAyB,CAAC;AACxC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,uBAAuB,CAAC;AACtC,cAAc,gCAAgC,CAAC;AAC/C,OAAO,EACL,8BAA8B,EAC9B,0BAA0B,EAC1B,0BAA0B,EAC1B,iBAAiB,EACjB,iCAAiC,EACjC,2BAA2B,EAC3B,uBAAuB,GAGxB,MAAM,qBAAqB,CAAC"}
|
|
1
|
+
{"version":3,"file":"learnings.js","sourceRoot":"","sources":["../../src/core/learnings.ts"],"names":[],"mappings":"AAAA,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC;AACxC,cAAc,yBAAyB,CAAC;AACxC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,uBAAuB,CAAC;AACtC,cAAc,gCAAgC,CAAC;AAC/C,OAAO,EACL,8BAA8B,EAC9B,0BAA0B,EAC1B,0BAA0B,EAC1B,iBAAiB,EACjB,iCAAiC,EACjC,2BAA2B,EAC3B,uBAAuB,GAGxB,MAAM,qBAAqB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"upstream-evidence-manifest.d.ts","sourceRoot":"","sources":["../../src/core/upstream-evidence-manifest.ts"],"names":[],"mappings":"AACA,iFAAiF;AACjF,eAAO,MAAM,0BAA0B,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAkiEpE,CAAC;AAEL,4EAA4E;AAC5E,eAAO,MAAM,yBAAyB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"upstream-evidence-manifest.d.ts","sourceRoot":"","sources":["../../src/core/upstream-evidence-manifest.ts"],"names":[],"mappings":"AACA,iFAAiF;AACjF,eAAO,MAAM,0BAA0B,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAkiEpE,CAAC;AAEL,4EAA4E;AAC5E,eAAO,MAAM,yBAAyB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CA0yMjE,CAAC;AAEL,sFAAsF;AACtF,eAAO,MAAM,uBAAuB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAk6I/D,CAAC"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/* eslint-disable max-lines -- generated exact public-evidence allowlist */
|
|
2
2
|
/** Generated by scripts/generate-upstream-evidence-manifest.mjs. Do not edit. */
|
|
3
3
|
export const UPSTREAM_EVIDENCE_MANIFEST = Object.freeze({
|
|
4
|
-
"all/copy-contents/.gitattributes": "
|
|
4
|
+
"all/copy-contents/.gitattributes": "9d3831007e681186a3673e1037ef3fc82980cab2fc04e27c0868e562912c9e9f",
|
|
5
5
|
"all/copy-contents/gitignore": "06b56376465d5421db55d0b04958bbc79fdbf33b42f0559fe5ef6875ced1160f",
|
|
6
6
|
"all/copy-overwrite/scripts/lisa-work-item.mjs": "5eb31c284e820a51312d4484f0669128007326af55ee515923fec33700d003a1",
|
|
7
7
|
"all/create-only/.claude/rules/PROJECT_RULES.md": "6e1c7923ad2a15356babc60c97e7f97be728d790af285b6a7cd7d1b4d39cd97f",
|
|
@@ -455,7 +455,7 @@ export const UPSTREAM_EVIDENCE_MANIFEST = Object.freeze({
|
|
|
455
455
|
"plugins/src/base/skills/lisa-jira-write-ticket/SKILL.md": "7328f4d8df5b20002ddcf0af6eb59d32a3e1cd6ec3c10521a3e828e6c09f6722",
|
|
456
456
|
"plugins/src/base/skills/lisa-jsdoc-best-practices/SKILL.md": "7cf0729966ac0afcab6e2c043f192772a9e9e7c72fae61e55b300e97308f970e",
|
|
457
457
|
"plugins/src/base/skills/lisa-kane-browser/SKILL.md": "e082517cb42f437eeb22b3935aa0fef09299874736e55184e88d2b64f7860a7d",
|
|
458
|
-
"plugins/src/base/skills/lisa-learnings-audit/SKILL.md": "
|
|
458
|
+
"plugins/src/base/skills/lisa-learnings-audit/SKILL.md": "0f56daf610cab90a2127cebf83a5bbe05cdcba0f692ebfae8fcf3da153826316",
|
|
459
459
|
"plugins/src/base/skills/lisa-linear-access/SKILL.md": "f6034d41014561aad0caf42a76bbc82329423ba1ee90d9eb832b7800a7c6d3bc",
|
|
460
460
|
"plugins/src/base/skills/lisa-linear-add-journey/SKILL.md": "0a9f2bd0e19fbaa4794537e436c22748c7621644253a91923d84bc77ca43f793",
|
|
461
461
|
"plugins/src/base/skills/lisa-linear-build-intake/SKILL.md": "e1924eb8d968151127ac29d2242ba5bb220fe86c69f7f92e651867b97819581b",
|
|
@@ -487,7 +487,7 @@ export const UPSTREAM_EVIDENCE_MANIFEST = Object.freeze({
|
|
|
487
487
|
"plugins/src/base/skills/lisa-parity-sentry-seer/SKILL.md": "f44216fa7c8f0c3c3371c65ff73bbeadd1717579502a5603f16b3b33291cab7a",
|
|
488
488
|
"plugins/src/base/skills/lisa-parity-skill-creator/SKILL.md": "616e0493f75fe92c18137548d7c86a91a9b04d9844ca76fa3f14156e3e7814e5",
|
|
489
489
|
"plugins/src/base/skills/lisa-performance-review/SKILL.md": "351542c256e54940e6d672a70606b8414425c6435ae6f026841bcc02f9fce9c4",
|
|
490
|
-
"plugins/src/base/skills/lisa-persist-learning/SKILL.md": "
|
|
490
|
+
"plugins/src/base/skills/lisa-persist-learning/SKILL.md": "41ffd8a415c6b1b98952061760e54837f3d6e6ea046e4d1c122dd53878af84de",
|
|
491
491
|
"plugins/src/base/skills/lisa-plan/SKILL.md": "9c372e106afd53ff988046119cf36b0f6519c4426775dd8ad3c9d9baeee5d3e2",
|
|
492
492
|
"plugins/src/base/skills/lisa-plugin-sync-explain/SKILL.md": "b41619f3d0d342af2438afd54cb97db7d2445e54e3fc7bb012292079acbc6a4f",
|
|
493
493
|
"plugins/src/base/skills/lisa-posthog-access/SKILL.md": "977aef803160b04312c0408136882ac106d8357caf5063a523e72f265bf20cb1",
|
|
@@ -6359,6 +6359,7 @@ export const UPSTREAM_SURFACE_MANIFEST = Object.freeze({
|
|
|
6359
6359
|
"src/cli/index.ts": true,
|
|
6360
6360
|
"src/cli/install-merge-driver-cmd.ts": true,
|
|
6361
6361
|
"src/cli/kane-cmd.ts": true,
|
|
6362
|
+
"src/cli/learnings-overflow-cmd.ts": true,
|
|
6362
6363
|
"src/cli/merge-learnings-cmd.ts": true,
|
|
6363
6364
|
"src/cli/print-update-warning.ts": true,
|
|
6364
6365
|
"src/cli/prompts.ts": true,
|
|
@@ -6466,6 +6467,7 @@ export const UPSTREAM_SURFACE_MANIFEST = Object.freeze({
|
|
|
6466
6467
|
"src/core/kane-pilot-report.ts": true,
|
|
6467
6468
|
"src/core/kane-pilot-types.ts": true,
|
|
6468
6469
|
"src/core/kane-pilot.ts": true,
|
|
6470
|
+
"src/core/learnings-alias.ts": true,
|
|
6469
6471
|
"src/core/learnings-budget-check.ts": true,
|
|
6470
6472
|
"src/core/learnings-contract.ts": true,
|
|
6471
6473
|
"src/core/learnings-document.ts": true,
|
|
@@ -6476,6 +6478,7 @@ export const UPSTREAM_SURFACE_MANIFEST = Object.freeze({
|
|
|
6476
6478
|
"src/core/learnings-merge-driver-install.ts": true,
|
|
6477
6479
|
"src/core/learnings-merge-driver.ts": true,
|
|
6478
6480
|
"src/core/learnings-merge.ts": true,
|
|
6481
|
+
"src/core/learnings-overflow.ts": true,
|
|
6479
6482
|
"src/core/learnings-projection.ts": true,
|
|
6480
6483
|
"src/core/learnings-writer.ts": true,
|
|
6481
6484
|
"src/core/learnings.ts": true,
|
|
@@ -6740,6 +6743,7 @@ export const UPSTREAM_SURFACE_MANIFEST = Object.freeze({
|
|
|
6740
6743
|
"tests/unit/cli/index.test.ts": true,
|
|
6741
6744
|
"tests/unit/cli/kane-cmd.test.ts": true,
|
|
6742
6745
|
"tests/unit/cli/kane-index.test.ts": true,
|
|
6746
|
+
"tests/unit/cli/learnings-overflow-cmd.test.ts": true,
|
|
6743
6747
|
"tests/unit/cli/merge-learnings-cmd.test.ts": true,
|
|
6744
6748
|
"tests/unit/cli/prompts.test.ts": true,
|
|
6745
6749
|
"tests/unit/cli/setup-project.test.ts": true,
|
|
@@ -6838,6 +6842,7 @@ export const UPSTREAM_SURFACE_MANIFEST = Object.freeze({
|
|
|
6838
6842
|
"tests/unit/core/kane-cli.test.ts": true,
|
|
6839
6843
|
"tests/unit/core/kane-pilot.test.ts": true,
|
|
6840
6844
|
"tests/unit/core/kane-readiness.test.ts": true,
|
|
6845
|
+
"tests/unit/core/learnings-alias-provenance.test.ts": true,
|
|
6841
6846
|
"tests/unit/core/learnings-barrel.test.ts": true,
|
|
6842
6847
|
"tests/unit/core/learnings-budget-check.test.ts": true,
|
|
6843
6848
|
"tests/unit/core/learnings-concurrency.test.ts": true,
|
|
@@ -6850,7 +6855,9 @@ export const UPSTREAM_SURFACE_MANIFEST = Object.freeze({
|
|
|
6850
6855
|
"tests/unit/core/learnings-merge-driver-install.test.ts": true,
|
|
6851
6856
|
"tests/unit/core/learnings-merge-driver.test.ts": true,
|
|
6852
6857
|
"tests/unit/core/learnings-merge.test.ts": true,
|
|
6858
|
+
"tests/unit/core/learnings-overflow.test.ts": true,
|
|
6853
6859
|
"tests/unit/core/learnings-projection.test.ts": true,
|
|
6860
|
+
"tests/unit/core/learnings-stable-ids.test.ts": true,
|
|
6854
6861
|
"tests/unit/core/learnings-supersede-race.test.ts": true,
|
|
6855
6862
|
"tests/unit/core/learnings-unlocked-read.test.ts": true,
|
|
6856
6863
|
"tests/unit/core/learnings-writer.test.ts": true,
|
|
@@ -7069,6 +7076,7 @@ export const UPSTREAM_SURFACE_MANIFEST = Object.freeze({
|
|
|
7069
7076
|
"tests/unit/strategies/learner-capture-contract.test.ts": true,
|
|
7070
7077
|
"tests/unit/strategies/learnings-audit-contract.test.ts": true,
|
|
7071
7078
|
"tests/unit/strategies/learnings-confirmation-contract.test.ts": true,
|
|
7079
|
+
"tests/unit/strategies/learnings-overflow-contract.test.ts": true,
|
|
7072
7080
|
"tests/unit/strategies/linear-access-history.test.ts": true,
|
|
7073
7081
|
"tests/unit/strategies/merge.test.ts": true,
|
|
7074
7082
|
"tests/unit/strategies/mld-telemetry-contract.test.ts": true,
|