@codyswann/lisa 2.298.1 → 2.299.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/all/copy-contents/.gitattributes +6 -0
- 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
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"learnings-document.js","sourceRoot":"","sources":["../../src/core/learnings-document.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,OAAO,EACL,kBAAkB,EAClB,sBAAsB,GAEvB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAE7D,MAAM,WAAW,GAAG;;gCAEY,kBAAkB,CAAC,OAAO;;CAEzD,CAAC;AACF,MAAM,gBAAgB,GAAG,YAAY,CAAC;AACtC,MAAM,cAAc,GAAG,SAAS,CAAC;AAEjC;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,eAAe,GAAG,uCAAuC,CAAC;AAEhE;;;GAGG;AACH,MAAM,CAAC,MAAM,yBAAyB,GACpC,uDAAuD,CAAC;AAE1D;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAAC,OAAiC;IACnE,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACrE,OAAO,GAAG,WAAW,GAAG,gBAAgB,GAAG,KAAK,GAAG,cAAc,EAAE,CAAC;AACtE,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAAC,OAAe;IAChD,4EAA4E;IAC5E,6EAA6E;IAC7E,4EAA4E;IAC5E,6EAA6E;IAC7E,MAAM,YAAY,GAAG,sBAAsB,CAAC,OAAO,CAAC,CAAC;IACrD,IAAI,YAAY,KAAK,SAAS,EAAE,CAAC;QAC/B,MAAM,mBAAmB,CAAC,YAAY,CAAC,CAAC;IAC1C,CAAC;IACD,IAAI,sBAAsB,CAAC,OAAO,CAAC,GAAG,kBAAkB,CAAC,SAAS,EAAE,CAAC;QACnE,MAAM,IAAI,KAAK,CACb,+CAA+C,kBAAkB,CAAC,SAAS,EAAE,CAC9E,CAAC;IACJ,CAAC;IACD,IACE,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,WAAW,GAAG,gBAAgB,EAAE,CAAC;QACxD,CAAC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC,EACjC,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;IAC3D,CAAC;IACD,MAAM,SAAS,GAAG,WAAW,CAAC,MAAM,GAAG,gBAAgB,CAAC,MAAM,CAAC;IAC/D,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,GAAG,cAAc,CAAC,MAAM,CAAC;IACvD,MAAM,OAAO,GAAG,cAAc,CAAC,OAAO,CAAC,KAAK,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,CACnE,2BAA2B,CAC5B,CAAC;IACF,IAAI,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC;QACpE,MAAM,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAC;IACtE,CAAC;IACD,oBAAoB,CAAC,OAAO,EAAE,OAAO,CAAC,MAAM,EAAE,2BAA2B,CAAC,CAAC;IAC3E,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB,CAClC,OAAe,EACf,UAAkB,EAClB,OAAe;IAEf,IAAI,UAAU,GAAG,kBAAkB,CAAC,UAAU,EAAE,CAAC;QAC/C,MAAM,IAAI,
|
|
1
|
+
{"version":3,"file":"learnings-document.js","sourceRoot":"","sources":["../../src/core/learnings-document.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,OAAO,EACL,kBAAkB,EAClB,sBAAsB,GAEvB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAE7D,MAAM,WAAW,GAAG;;gCAEY,kBAAkB,CAAC,OAAO;;CAEzD,CAAC;AACF,MAAM,gBAAgB,GAAG,YAAY,CAAC;AACtC,MAAM,cAAc,GAAG,SAAS,CAAC;AAEjC;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,eAAe,GAAG,uCAAuC,CAAC;AAEhE;;;GAGG;AACH,MAAM,CAAC,MAAM,yBAAyB,GACpC,uDAAuD,CAAC;AAE1D;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAAC,OAAiC;IACnE,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACrE,OAAO,GAAG,WAAW,GAAG,gBAAgB,GAAG,KAAK,GAAG,cAAc,EAAE,CAAC;AACtE,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAAC,OAAe;IAChD,4EAA4E;IAC5E,6EAA6E;IAC7E,4EAA4E;IAC5E,6EAA6E;IAC7E,MAAM,YAAY,GAAG,sBAAsB,CAAC,OAAO,CAAC,CAAC;IACrD,IAAI,YAAY,KAAK,SAAS,EAAE,CAAC;QAC/B,MAAM,mBAAmB,CAAC,YAAY,CAAC,CAAC;IAC1C,CAAC;IACD,IAAI,sBAAsB,CAAC,OAAO,CAAC,GAAG,kBAAkB,CAAC,SAAS,EAAE,CAAC;QACnE,MAAM,IAAI,KAAK,CACb,+CAA+C,kBAAkB,CAAC,SAAS,EAAE,CAC9E,CAAC;IACJ,CAAC;IACD,IACE,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,WAAW,GAAG,gBAAgB,EAAE,CAAC;QACxD,CAAC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC,EACjC,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;IAC3D,CAAC;IACD,MAAM,SAAS,GAAG,WAAW,CAAC,MAAM,GAAG,gBAAgB,CAAC,MAAM,CAAC;IAC/D,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,GAAG,cAAc,CAAC,MAAM,CAAC;IACvD,MAAM,OAAO,GAAG,cAAc,CAAC,OAAO,CAAC,KAAK,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,CACnE,2BAA2B,CAC5B,CAAC;IACF,IAAI,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC;QACpE,MAAM,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAC;IACtE,CAAC;IACD,oBAAoB,CAAC,OAAO,EAAE,OAAO,CAAC,MAAM,EAAE,2BAA2B,CAAC,CAAC;IAC3E,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,OAAO,oBAAqB,SAAQ,KAAK;IAC7C;;;OAGG;IACH,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAC;IACrC,CAAC;CACF;AAED;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB,CAClC,OAAe,EACf,UAAkB,EAClB,OAAe;IAEf,IAAI,UAAU,GAAG,kBAAkB,CAAC,UAAU,EAAE,CAAC;QAC/C,MAAM,IAAI,oBAAoB,CAC5B,GAAG,OAAO,iCAAiC,UAAU,aAAa,kBAAkB,CAAC,UAAU,EAAE,CAClG,CAAC;IACJ,CAAC;IACD,MAAM,eAAe,GAAG,sBAAsB,CAAC,OAAO,CAAC,CAAC;IACxD,IAAI,eAAe,GAAG,kBAAkB,CAAC,SAAS,EAAE,CAAC;QACnD,MAAM,IAAI,oBAAoB,CAC5B,GAAG,OAAO,sBAAsB,kBAAkB,CAAC,SAAS,cAAc,eAAe,GAAG,CAC7F,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,sBAAsB,CAAC,OAAe;IACpD,MAAM,KAAK,GAAG,OAAO;SAClB,KAAK,CAAC,IAAI,CAAC;SACX,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IACjD,OAAO,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC;AAC9C,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAAY;IAC9C,OAAO,IAAI,KAAK,CACd,GAAG,yBAAyB,YAAY,IAAI,oKAAoK,CACjN,CAAC;AACJ,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,yBAAyB,CACvC,MAAkB;IAElB,OAAO,sBAAsB,CAAC,IAAI,WAAW,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;AACzE,CAAC;AAED;;;;;GAKG;AACH,SAAS,2BAA2B,CAClC,SAAkB,EAClB,KAAa;IAEb,IAAI,CAAC;QACH,OAAO,qBAAqB,CAAC,SAAS,CAAC,CAAC;IAC1C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,EAAE,GAAG,qBAAqB,CAAC,SAAS,CAAC,CAAC;QAC5C,0EAA0E;QAC1E,wEAAwE;QACxE,yEAAyE;QACzE,yEAAyE;QACzE,4BAA4B;QAC5B,MAAM,KAAK,GAAG,EAAE,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,KAAK,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,EAAE,GAAG,CAAC;QACxE,MAAM,MAAM,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACtE,MAAM,IAAI,KAAK,CAAC,oBAAoB,KAAK,KAAK,MAAM,EAAE,CAAC,CAAC;IAC1D,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,SAAS,qBAAqB,CAAC,SAAkB;IAC/C,IAAI,SAAS,KAAK,IAAI,IAAI,OAAO,SAAS,KAAK,QAAQ,EAAE,CAAC;QACxD,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,MAAM,UAAU,GAAG,MAAM,CAAC,wBAAwB,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IACpE,OAAO,UAAU,KAAK,SAAS;QAC7B,OAAO,IAAI,UAAU;QACrB,OAAO,UAAU,CAAC,KAAK,KAAK,QAAQ;QACpC,CAAC,CAAC,UAAU,CAAC,KAAK;QAClB,CAAC,CAAC,SAAS,CAAC;AAChB,CAAC;AAED;;;;GAIG;AACH,SAAS,cAAc,CAAC,OAAe;IACrC,IAAI,OAAO,KAAK,EAAE,EAAE,CAAC;QACnB,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,IAAI,CAAC;QACH,OAAO,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAY,CAAC,CAAC;IACtE,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAC;IAC7D,CAAC;AACH,CAAC"}
|
|
@@ -1,36 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Registration contract for the project-learnings union merge driver.
|
|
3
|
-
*
|
|
4
|
-
* A git merge driver has two halves that live in different places:
|
|
5
|
-
*
|
|
6
|
-
* 1. **The attribute** (`.gitattributes`) says WHICH driver a path uses. It is
|
|
7
|
-
* a committed file, so Lisa ships it to the repository and to every host
|
|
8
|
-
* project through the template pipeline.
|
|
9
|
-
* 2. **The driver command** (`merge.<name>.driver`) says HOW to run it. Git
|
|
10
|
-
* deliberately keeps this in machine-local config and never reads it from
|
|
11
|
-
* the repository, because a committed driver command would let a cloned
|
|
12
|
-
* repository execute arbitrary code on `git merge`.
|
|
13
|
-
*
|
|
14
|
-
* So the attribute alone is inert. Until the command is registered, git falls
|
|
15
|
-
* back to its built-in text merge — which is exactly today's behavior, so an
|
|
16
|
-
* unregistered checkout is degraded, never broken. That fallback is asserted in
|
|
17
|
-
* `tests/unit/core/learnings-merge-driver.test.ts`.
|
|
18
|
-
*
|
|
19
|
-
* Registration is AUTOMATIC, not operator-initiated. `EnsureLearningsMergeDriver`
|
|
20
|
-
* runs on every `lisa apply`, and the TypeScript stack's `package.lisa.json`
|
|
21
|
-
* wires `lisa apply` into `postinstall` — so an ordinary `npm install` in a host
|
|
22
|
-
* project writes `merge.lisa-learnings.driver` into `.git/config` with no
|
|
23
|
-
* separate human step, and against Lisa's own repository too.
|
|
24
|
-
*
|
|
25
|
-
* That is worth stating plainly because of what it implies: the registration
|
|
26
|
-
* persists an executable hook in local git config that fires on ordinary git
|
|
27
|
-
* operations, outside npm's lifecycle. It is not an escalation over `npm
|
|
28
|
-
* install` itself (which already runs arbitrary code), but it does outlive it.
|
|
29
|
-
* Hosts that would rather not carry that hook set `learnings.mergeDriver: false`
|
|
30
|
-
* in `.lisa.config.json`; `lisa install-merge-driver` remains available to
|
|
31
|
-
* register it by hand in a clone that apply has not touched.
|
|
32
|
-
* @module core/learnings-merge-driver
|
|
33
|
-
*/
|
|
34
1
|
/** Git merge-driver name shared by `.gitattributes` and the local git config. */
|
|
35
2
|
export declare const LEARNINGS_MERGE_DRIVER_NAME = "lisa-learnings";
|
|
36
3
|
/** Human-readable driver name recorded alongside the command. */
|
|
@@ -76,6 +43,14 @@ export declare function buildLearningsAttributeLine(ledgerPath: string): string;
|
|
|
76
43
|
* Wrapped in the same guardrail markers the `.gitignore` template uses, so the
|
|
77
44
|
* `copy-contents` strategy replaces exactly this block on re-apply and leaves
|
|
78
45
|
* every host-authored rule outside it untouched.
|
|
46
|
+
*
|
|
47
|
+
* Both halves of the learnings surface are bound. The overflow file
|
|
48
|
+
* (CodySwannGT/lisa#1996) is written by the same concurrent learner passes, on
|
|
49
|
+
* the same per-fingerprint branches, in the same canonical document format — so
|
|
50
|
+
* it has the ledger's exact merge problem and the exact same union-by-id
|
|
51
|
+
* resolution. Binding only the ledger would leave the overflow on git's default
|
|
52
|
+
* text merge, silently re-introducing the corruption this driver exists to
|
|
53
|
+
* remove, on the one file whose whole job is not losing content.
|
|
79
54
|
* @param ledgerPath - Project-relative learnings file path
|
|
80
55
|
* @returns Managed block, newline-terminated
|
|
81
56
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"learnings-merge-driver.d.ts","sourceRoot":"","sources":["../../src/core/learnings-merge-driver.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"learnings-merge-driver.d.ts","sourceRoot":"","sources":["../../src/core/learnings-merge-driver.ts"],"names":[],"mappings":"AAmCA,iFAAiF;AACjF,eAAO,MAAM,2BAA2B,mBAAmB,CAAC;AAE5D,iEAAiE;AACjE,eAAO,MAAM,kCAAkC,wCACR,CAAC;AAExC,wEAAwE;AACxE,eAAO,MAAM,0BAA0B,2BAA2B,CAAC;AAEnE,wEAAwE;AACxE,eAAO,MAAM,wBAAwB,yBAAyB,CAAC;AAE/D;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,gCAAgC,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAE3E;AAED;;;;GAIG;AACH,wBAAgB,2BAA2B,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAEtE;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,iCAAiC,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAmB5E"}
|
|
@@ -31,6 +31,7 @@
|
|
|
31
31
|
* register it by hand in a clone that apply has not touched.
|
|
32
32
|
* @module core/learnings-merge-driver
|
|
33
33
|
*/
|
|
34
|
+
import { resolveLearningsOverflowFile } from "./learnings-overflow.js";
|
|
34
35
|
/** Git merge-driver name shared by `.gitattributes` and the local git config. */
|
|
35
36
|
export const LEARNINGS_MERGE_DRIVER_NAME = "lisa-learnings";
|
|
36
37
|
/** Human-readable driver name recorded alongside the command. */
|
|
@@ -80,6 +81,14 @@ export function buildLearningsAttributeLine(ledgerPath) {
|
|
|
80
81
|
* Wrapped in the same guardrail markers the `.gitignore` template uses, so the
|
|
81
82
|
* `copy-contents` strategy replaces exactly this block on re-apply and leaves
|
|
82
83
|
* every host-authored rule outside it untouched.
|
|
84
|
+
*
|
|
85
|
+
* Both halves of the learnings surface are bound. The overflow file
|
|
86
|
+
* (CodySwannGT/lisa#1996) is written by the same concurrent learner passes, on
|
|
87
|
+
* the same per-fingerprint branches, in the same canonical document format — so
|
|
88
|
+
* it has the ledger's exact merge problem and the exact same union-by-id
|
|
89
|
+
* resolution. Binding only the ledger would leave the overflow on git's default
|
|
90
|
+
* text merge, silently re-introducing the corruption this driver exists to
|
|
91
|
+
* remove, on the one file whose whole job is not losing content.
|
|
83
92
|
* @param ledgerPath - Project-relative learnings file path
|
|
84
93
|
* @returns Managed block, newline-terminated
|
|
85
94
|
*/
|
|
@@ -93,6 +102,12 @@ export function renderLearningsGitattributesBlock(ledgerPath) {
|
|
|
93
102
|
"# command is machine-local — run `lisa install-merge-driver` to register it.",
|
|
94
103
|
buildLearningsAttributeLine(ledgerPath),
|
|
95
104
|
"",
|
|
105
|
+
"# The overflow buffer holds captures the ledger had no budget for, until",
|
|
106
|
+
"# the gardener drains them. Same writers, same branches, same format — so",
|
|
107
|
+
"# it needs the same union merge, or a merge could destroy the very content",
|
|
108
|
+
"# it exists to preserve.",
|
|
109
|
+
buildLearningsAttributeLine(resolveLearningsOverflowFile(ledgerPath)),
|
|
110
|
+
"",
|
|
96
111
|
GITATTRIBUTES_END_MARKER,
|
|
97
112
|
"",
|
|
98
113
|
].join("\n");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"learnings-merge-driver.js","sourceRoot":"","sources":["../../src/core/learnings-merge-driver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;
|
|
1
|
+
{"version":3,"file":"learnings-merge-driver.js","sourceRoot":"","sources":["../../src/core/learnings-merge-driver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,OAAO,EAAE,4BAA4B,EAAE,MAAM,yBAAyB,CAAC;AAEvE,iFAAiF;AACjF,MAAM,CAAC,MAAM,2BAA2B,GAAG,gBAAgB,CAAC;AAE5D,iEAAiE;AACjE,MAAM,CAAC,MAAM,kCAAkC,GAC7C,qCAAqC,CAAC;AAExC,wEAAwE;AACxE,MAAM,CAAC,MAAM,0BAA0B,GAAG,wBAAwB,CAAC;AAEnE,wEAAwE;AACxE,MAAM,CAAC,MAAM,wBAAwB,GAAG,sBAAsB,CAAC;AAE/D;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,UAAU,gCAAgC,CAAC,UAAkB;IACjE,OAAO,GAAG,UAAU,4DAA4D,CAAC;AACnF,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,2BAA2B,CAAC,UAAkB;IAC5D,OAAO,GAAG,UAAU,UAAU,2BAA2B,EAAE,CAAC;AAC9D,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,iCAAiC,CAAC,UAAkB;IAClE,OAAO;QACL,0BAA0B;QAC1B,EAAE;QACF,6EAA6E;QAC7E,2EAA2E;QAC3E,0EAA0E;QAC1E,8EAA8E;QAC9E,2BAA2B,CAAC,UAAU,CAAC;QACvC,EAAE;QACF,0EAA0E;QAC1E,2EAA2E;QAC3E,4EAA4E;QAC5E,0BAA0B;QAC1B,2BAA2B,CAAC,4BAA4B,CAAC,UAAU,CAAC,CAAC;QACrE,EAAE;QACF,wBAAwB;QACxB,EAAE;KACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { type LearningEntry } from "./learnings-contract.js";
|
|
2
|
+
import { LearningsBudgetError } from "./learnings-document.js";
|
|
3
|
+
/**
|
|
4
|
+
* Derive the overflow path from a project's configured ledger path.
|
|
5
|
+
*
|
|
6
|
+
* Derived rather than separately configurable so a project that relocates its
|
|
7
|
+
* ledger through `learnings.file` cannot end up with the two halves of one
|
|
8
|
+
* mechanism in different directories — and so there is no second config key to
|
|
9
|
+
* validate, contain, and keep in sync.
|
|
10
|
+
* @param learningsFile - Project-relative ledger path
|
|
11
|
+
* @returns Project-relative overflow path
|
|
12
|
+
*/
|
|
13
|
+
export declare function resolveLearningsOverflowFile(learningsFile: string): string;
|
|
14
|
+
/** Entries currently awaiting drain, and where they live. */
|
|
15
|
+
export interface LearningsOverflowContents {
|
|
16
|
+
/** Absolute overflow path, whether or not the file exists yet. */
|
|
17
|
+
readonly file: string;
|
|
18
|
+
/** Validated entries awaiting drain. */
|
|
19
|
+
readonly entries: readonly LearningEntry[];
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Read the overflow without modifying it.
|
|
23
|
+
*
|
|
24
|
+
* An absent file is the common, expected case and reads as empty — a project
|
|
25
|
+
* that has never dropped a capture must not have to special-case its absence.
|
|
26
|
+
* @param projectRoot - Absolute path to the host project root
|
|
27
|
+
* @returns Overflow path and the entries awaiting drain
|
|
28
|
+
*/
|
|
29
|
+
export declare function readLearningsOverflow(projectRoot: string): Promise<LearningsOverflowContents>;
|
|
30
|
+
/** Outcome of draining entries the gardener has finished with. */
|
|
31
|
+
export interface LearningsOverflowDrain {
|
|
32
|
+
/** Absolute overflow path. */
|
|
33
|
+
readonly file: string;
|
|
34
|
+
/** Ids that were present and have now been removed. */
|
|
35
|
+
readonly drained: readonly string[];
|
|
36
|
+
/** Requested ids that were not in the overflow — reported, never fatal. */
|
|
37
|
+
readonly absent: readonly string[];
|
|
38
|
+
/** How many entries still await drain. */
|
|
39
|
+
readonly remaining: number;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Remove entries the gardener has durably captured elsewhere.
|
|
43
|
+
*
|
|
44
|
+
* Drain is BY ID and never "empty the file", because the gardener's real
|
|
45
|
+
* sequence is read → file a ticket per entry → drain. Clearing everything up
|
|
46
|
+
* front would lose any entry whose ticket failed to file; removing only the ids
|
|
47
|
+
* that already have a durable home makes a partial run safely resumable.
|
|
48
|
+
*
|
|
49
|
+
* An unknown id is reported rather than thrown, for the same reason an absent
|
|
50
|
+
* supersede target is tolerated: on a re-run, an id another pass already drained
|
|
51
|
+
* is indistinguishable from a bogus one, and failing the drain would strand
|
|
52
|
+
* every other entry in the batch.
|
|
53
|
+
* @param projectRoot - Absolute path to the host project root
|
|
54
|
+
* @param ids - Entry ids to remove
|
|
55
|
+
* @returns Which ids were drained, which were absent, and what remains
|
|
56
|
+
*/
|
|
57
|
+
export declare function drainLearningsOverflow(projectRoot: string, ids: readonly string[]): Promise<LearningsOverflowDrain>;
|
|
58
|
+
/**
|
|
59
|
+
* Preserve a capture the ledger had no budget for, then re-raise the breach.
|
|
60
|
+
*
|
|
61
|
+
* Never returns normally: the capture genuinely did not land in the ledger, and
|
|
62
|
+
* a caller that treated preservation as success would report a learning as
|
|
63
|
+
* persisted when the projection will never serve it. The re-raised error names
|
|
64
|
+
* the overflow file so the drop is actionable rather than merely fatal.
|
|
65
|
+
*
|
|
66
|
+
* If the overflow is itself full, the original ledger breach is re-raised with
|
|
67
|
+
* both surfaces named. Nothing is evicted to make room — silently discarding an
|
|
68
|
+
* older dropped learning to store a newer one is the exact data loss this whole
|
|
69
|
+
* mechanism exists to prevent.
|
|
70
|
+
* @param projectRoot - Absolute path to the host project root
|
|
71
|
+
* @param entry - The validated entry the ledger rejected
|
|
72
|
+
* @param breach - The budget breach the ledger write raised
|
|
73
|
+
* @returns Never — always throws
|
|
74
|
+
*/
|
|
75
|
+
export declare function preserveDroppedLearning(projectRoot: string, entry: LearningEntry, breach: LearningsBudgetError): Promise<never>;
|
|
76
|
+
//# sourceMappingURL=learnings-overflow.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"learnings-overflow.d.ts","sourceRoot":"","sources":["../../src/core/learnings-overflow.ts"],"names":[],"mappings":"AAkDA,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EACL,oBAAoB,EAIrB,MAAM,yBAAyB,CAAC;AAejC;;;;;;;;;GASG;AACH,wBAAgB,4BAA4B,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,CAI1E;AAmCD,6DAA6D;AAC7D,MAAM,WAAW,yBAAyB;IACxC,kEAAkE;IAClE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,wCAAwC;IACxC,QAAQ,CAAC,OAAO,EAAE,SAAS,aAAa,EAAE,CAAC;CAC5C;AAED;;;;;;;GAOG;AACH,wBAAsB,qBAAqB,CACzC,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,yBAAyB,CAAC,CAGpC;AAED,kEAAkE;AAClE,MAAM,WAAW,sBAAsB;IACrC,8BAA8B;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,uDAAuD;IACvD,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,2EAA2E;IAC3E,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,0CAA0C;IAC1C,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,sBAAsB,CAC1C,WAAW,EAAE,MAAM,EACnB,GAAG,EAAE,SAAS,MAAM,EAAE,GACrB,OAAO,CAAC,sBAAsB,CAAC,CAwBjC;AAqBD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,uBAAuB,CAC3C,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,aAAa,EACpB,MAAM,EAAE,oBAAoB,GAC3B,OAAO,CAAC,KAAK,CAAC,CAyBhB"}
|
|
@@ -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"}
|