@codyswann/lisa 2.297.4 → 2.297.6
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 +9 -0
- package/dist/cli/gate-commands.d.ts +22 -3
- package/dist/cli/gate-commands.d.ts.map +1 -1
- package/dist/cli/gate-commands.js +49 -1
- package/dist/cli/gate-commands.js.map +1 -1
- package/dist/cli/install-merge-driver-cmd.d.ts +21 -0
- package/dist/cli/install-merge-driver-cmd.d.ts.map +1 -0
- package/dist/cli/install-merge-driver-cmd.js +37 -0
- package/dist/cli/install-merge-driver-cmd.js.map +1 -0
- package/dist/cli/merge-learnings-cmd.d.ts +24 -0
- package/dist/cli/merge-learnings-cmd.d.ts.map +1 -0
- package/dist/cli/merge-learnings-cmd.js +82 -0
- package/dist/cli/merge-learnings-cmd.js.map +1 -0
- package/dist/core/learnings-budget-check.d.ts.map +1 -1
- package/dist/core/learnings-budget-check.js +18 -3
- package/dist/core/learnings-budget-check.js.map +1 -1
- package/dist/core/learnings-document.d.ts +46 -0
- package/dist/core/learnings-document.d.ts.map +1 -1
- package/dist/core/learnings-document.js +82 -4
- package/dist/core/learnings-document.js.map +1 -1
- package/dist/core/learnings-file-safety.d.ts.map +1 -1
- package/dist/core/learnings-file-safety.js +22 -0
- package/dist/core/learnings-file-safety.js.map +1 -1
- package/dist/core/learnings-merge-driver-config.d.ts +7 -0
- package/dist/core/learnings-merge-driver-config.d.ts.map +1 -0
- package/dist/core/learnings-merge-driver-config.js +58 -0
- package/dist/core/learnings-merge-driver-config.js.map +1 -0
- package/dist/core/learnings-merge-driver-install.d.ts +45 -0
- package/dist/core/learnings-merge-driver-install.d.ts.map +1 -0
- package/dist/core/learnings-merge-driver-install.js +161 -0
- package/dist/core/learnings-merge-driver-install.js.map +1 -0
- package/dist/core/learnings-merge-driver.d.ts +83 -0
- package/dist/core/learnings-merge-driver.d.ts.map +1 -0
- package/dist/core/learnings-merge-driver.js +100 -0
- package/dist/core/learnings-merge-driver.js.map +1 -0
- package/dist/core/learnings-merge.d.ts +23 -0
- package/dist/core/learnings-merge.d.ts.map +1 -0
- package/dist/core/learnings-merge.js +198 -0
- package/dist/core/learnings-merge.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 +32 -65
- package/dist/core/learnings-writer.js.map +1 -1
- package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
- package/dist/core/upstream-evidence-manifest.js +27 -4
- package/dist/core/upstream-evidence-manifest.js.map +1 -1
- package/dist/health/storage.d.ts.map +1 -1
- package/dist/health/storage.js +7 -20
- package/dist/health/storage.js.map +1 -1
- package/dist/migrations/ensure-learnings-gitattributes.d.ts +43 -0
- package/dist/migrations/ensure-learnings-gitattributes.d.ts.map +1 -0
- package/dist/migrations/ensure-learnings-gitattributes.js +93 -0
- package/dist/migrations/ensure-learnings-gitattributes.js.map +1 -0
- package/dist/migrations/ensure-learnings-merge-driver.d.ts +46 -0
- package/dist/migrations/ensure-learnings-merge-driver.d.ts.map +1 -0
- package/dist/migrations/ensure-learnings-merge-driver.js +70 -0
- package/dist/migrations/ensure-learnings-merge-driver.js.map +1 -0
- package/dist/migrations/index.d.ts +2 -0
- package/dist/migrations/index.d.ts.map +1 -1
- package/dist/migrations/index.js +6 -0
- package/dist/migrations/index.js.map +1 -1
- package/dist/standards/storage.d.ts.map +1 -1
- package/dist/standards/storage.js +7 -20
- package/dist/standards/storage.js.map +1 -1
- package/dist/utils/atomic-file-write.d.ts +30 -0
- package/dist/utils/atomic-file-write.d.ts.map +1 -0
- package/dist/utils/atomic-file-write.js +61 -0
- package/dist/utils/atomic-file-write.js.map +1 -0
- package/dist/utils/directory-sync.d.ts.map +1 -0
- package/dist/utils/directory-sync.js.map +1 -0
- 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-drive-pr-to-merge/SKILL.md +12 -0
- package/plugins/lisa/.codex-plugin/skills/lisa-persist-learning/SKILL.md +1 -0
- package/plugins/lisa/skills/lisa-drive-pr-to-merge/SKILL.md +12 -0
- package/plugins/lisa/skills/lisa-persist-learning/SKILL.md +1 -0
- package/plugins/lisa-agy/plugin.json +1 -1
- package/plugins/lisa-agy/skills/lisa-drive-pr-to-merge/SKILL.md +12 -0
- package/plugins/lisa-agy/skills/lisa-persist-learning/SKILL.md +1 -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/skills/lisa-drive-pr-to-merge/SKILL.md +12 -0
- package/plugins/lisa-copilot/skills/lisa-persist-learning/SKILL.md +1 -0
- package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cursor/skills/lisa-drive-pr-to-merge/SKILL.md +12 -0
- package/plugins/lisa-cursor/skills/lisa-persist-learning/SKILL.md +1 -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/skills/lisa-drive-pr-to-merge/SKILL.md +12 -0
- package/plugins/src/base/skills/lisa-persist-learning/SKILL.md +1 -0
- package/dist/health/directory-sync.d.ts.map +0 -1
- package/dist/health/directory-sync.js.map +0 -1
- /package/dist/{health → utils}/directory-sync.d.ts +0 -0
- /package/dist/{health → utils}/directory-sync.js +0 -0
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# BEGIN: AI GUARDRAILS
|
|
2
|
+
|
|
3
|
+
# The project learnings ledger is written by concurrent learner passes that
|
|
4
|
+
# each run on their own branch. Git's default line merge corrupts it with
|
|
5
|
+
# conflict markers; this driver unions entries by id instead. The driver
|
|
6
|
+
# command is machine-local — run `lisa install-merge-driver` to register it.
|
|
7
|
+
.lisa/PROJECT_LEARNINGS.md merge=lisa-learnings
|
|
8
|
+
|
|
9
|
+
# END: AI GUARDRAILS
|
|
@@ -1,13 +1,32 @@
|
|
|
1
1
|
/** Registrars for non-project gate commands shipped to host projects. */
|
|
2
2
|
import type { Command } from "commander";
|
|
3
3
|
import type { FileUpstreamOptions } from "./file-upstream-cmd.js";
|
|
4
|
-
/**
|
|
4
|
+
/**
|
|
5
|
+
* Gate runners kept structural to avoid importing the whole CLI dependency
|
|
6
|
+
* record.
|
|
7
|
+
*
|
|
8
|
+
* `merge-learnings` and `install-merge-driver` are deliberately NOT members.
|
|
9
|
+
* They are invoked by git and by an operator repairing a repository, never
|
|
10
|
+
* substituted by the root CLI, and both mutate real state — the merge driver
|
|
11
|
+
* overwrites the file git hands it, and the installer writes local git config.
|
|
12
|
+
* An optional, defaulted field would be the worst shape here: a caller that
|
|
13
|
+
* believed it had stubbed every gate command would silently run the real driver
|
|
14
|
+
* against real files. Leaving them off the record makes non-injectability
|
|
15
|
+
* explicit; they are covered directly by unit tests and by end-to-end tests
|
|
16
|
+
* that drive real `git merge`.
|
|
17
|
+
*/
|
|
5
18
|
export interface GateCommandDependencies {
|
|
6
19
|
runCheckLearningsBudget: (path: string | undefined) => Promise<number>;
|
|
7
20
|
runFileUpstream: (options: FileUpstreamOptions) => Promise<number>;
|
|
8
21
|
}
|
|
9
|
-
/**
|
|
10
|
-
|
|
22
|
+
/**
|
|
23
|
+
* Gate commands skip the root npm update check.
|
|
24
|
+
*
|
|
25
|
+
* `merge-learnings` especially: git runs it inline during every merge of the
|
|
26
|
+
* ledger, so a network update check would stall the merge and pollute the
|
|
27
|
+
* driver's output.
|
|
28
|
+
*/
|
|
29
|
+
export declare const GATE_COMMAND_NAMES: readonly ["check-learnings-budget", "file-upstream", "merge-learnings", "install-merge-driver"];
|
|
11
30
|
/**
|
|
12
31
|
* Register all non-project gate commands.
|
|
13
32
|
* @param program - Commander program
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gate-commands.d.ts","sourceRoot":"","sources":["../../src/cli/gate-commands.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"gate-commands.d.ts","sourceRoot":"","sources":["../../src/cli/gate-commands.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAOlE;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,uBAAuB;IACtC,uBAAuB,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACvE,eAAe,EAAE,CAAC,OAAO,EAAE,mBAAmB,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;CACpE;AAED;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB,iGAKrB,CAAC;AAuFX;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,OAAO,EAChB,YAAY,EAAE,uBAAuB,GACpC,IAAI,CAKN"}
|
|
@@ -1,7 +1,17 @@
|
|
|
1
|
-
|
|
1
|
+
import { runInstallMergeDriver } from "./install-merge-driver-cmd.js";
|
|
2
|
+
import { runMergeLearnings, } from "./merge-learnings-cmd.js";
|
|
3
|
+
/**
|
|
4
|
+
* Gate commands skip the root npm update check.
|
|
5
|
+
*
|
|
6
|
+
* `merge-learnings` especially: git runs it inline during every merge of the
|
|
7
|
+
* ledger, so a network update check would stall the merge and pollute the
|
|
8
|
+
* driver's output.
|
|
9
|
+
*/
|
|
2
10
|
export const GATE_COMMAND_NAMES = [
|
|
3
11
|
"check-learnings-budget",
|
|
4
12
|
"file-upstream",
|
|
13
|
+
"merge-learnings",
|
|
14
|
+
"install-merge-driver",
|
|
5
15
|
];
|
|
6
16
|
/**
|
|
7
17
|
* Register the bounded learnings-budget check.
|
|
@@ -35,6 +45,42 @@ function addFileUpstreamCommand(program, dependencies) {
|
|
|
35
45
|
process.exitCode = code;
|
|
36
46
|
});
|
|
37
47
|
}
|
|
48
|
+
/**
|
|
49
|
+
* Register the project-learnings union merge driver.
|
|
50
|
+
*
|
|
51
|
+
* Invoked by git, not by humans: the argument names map to git's `%O %A %B %P`
|
|
52
|
+
* placeholders and the exit code carries the merge verdict.
|
|
53
|
+
* @param program - Commander program
|
|
54
|
+
*/
|
|
55
|
+
function addMergeLearningsCommand(program) {
|
|
56
|
+
program
|
|
57
|
+
.command("merge-learnings")
|
|
58
|
+
.description("Git merge driver: union the project learnings ledger by entry id")
|
|
59
|
+
.option("--base <file>", "Merge-base version (git %O)")
|
|
60
|
+
.option("--ours <file>", "Our version; receives the result (git %A)")
|
|
61
|
+
.option("--theirs <file>", "Their version (git %B)")
|
|
62
|
+
.option("--path <path>", "Real pathname for diagnostics (git %P)")
|
|
63
|
+
.action(async (options) => {
|
|
64
|
+
const code = await runMergeLearnings(options);
|
|
65
|
+
if (code !== 0)
|
|
66
|
+
process.exitCode = code;
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Register the machine-local merge-driver installer.
|
|
71
|
+
* @param program - Commander program
|
|
72
|
+
*/
|
|
73
|
+
function addInstallMergeDriverCommand(program) {
|
|
74
|
+
program
|
|
75
|
+
.command("install-merge-driver")
|
|
76
|
+
.description("Register the project learnings union merge driver in local git config")
|
|
77
|
+
.argument("[path]", "Project directory (default: current directory)")
|
|
78
|
+
.action(async (targetPath) => {
|
|
79
|
+
const code = await runInstallMergeDriver(targetPath);
|
|
80
|
+
if (code !== 0)
|
|
81
|
+
process.exitCode = code;
|
|
82
|
+
});
|
|
83
|
+
}
|
|
38
84
|
/**
|
|
39
85
|
* Register all non-project gate commands.
|
|
40
86
|
* @param program - Commander program
|
|
@@ -43,5 +89,7 @@ function addFileUpstreamCommand(program, dependencies) {
|
|
|
43
89
|
export function addGateCommands(program, dependencies) {
|
|
44
90
|
addCheckLearningsBudgetCommand(program, dependencies);
|
|
45
91
|
addFileUpstreamCommand(program, dependencies);
|
|
92
|
+
addMergeLearningsCommand(program);
|
|
93
|
+
addInstallMergeDriverCommand(program);
|
|
46
94
|
}
|
|
47
95
|
//# sourceMappingURL=gate-commands.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gate-commands.js","sourceRoot":"","sources":["../../src/cli/gate-commands.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"gate-commands.js","sourceRoot":"","sources":["../../src/cli/gate-commands.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AACtE,OAAO,EACL,iBAAiB,GAElB,MAAM,0BAA0B,CAAC;AAqBlC;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,wBAAwB;IACxB,eAAe;IACf,iBAAiB;IACjB,sBAAsB;CACd,CAAC;AAEX;;;;GAIG;AACH,SAAS,8BAA8B,CACrC,OAAgB,EAChB,YAAqC;IAErC,OAAO;SACJ,OAAO,CAAC,wBAAwB,CAAC;SACjC,WAAW,CACV,kFAAkF,CACnF;SACA,QAAQ,CACP,QAAQ,EACR,oEAAoE,CACrE;SACA,MAAM,CAAC,KAAK,EAAE,UAA8B,EAAE,EAAE;QAC/C,MAAM,IAAI,GAAG,MAAM,YAAY,CAAC,uBAAuB,CAAC,UAAU,CAAC,CAAC;QACpE,IAAI,IAAI,KAAK,CAAC;YAAE,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;IAC1C,CAAC,CAAC,CAAC;AACP,CAAC;AAED;;;;GAIG;AACH,SAAS,sBAAsB,CAC7B,OAAgB,EAChB,YAAqC;IAErC,OAAO;SACJ,OAAO,CAAC,eAAe,CAAC;SACxB,WAAW,CACV,wEAAwE,CACzE;SACA,MAAM,CAAC,gBAAgB,EAAE,yCAAyC,CAAC;SACnE,MAAM,CAAC,KAAK,EAAE,OAA4B,EAAE,EAAE;QAC7C,MAAM,IAAI,GAAG,MAAM,YAAY,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;QACzD,IAAI,IAAI,KAAK,CAAC;YAAE,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;IAC1C,CAAC,CAAC,CAAC;AACP,CAAC;AAED;;;;;;GAMG;AACH,SAAS,wBAAwB,CAAC,OAAgB;IAChD,OAAO;SACJ,OAAO,CAAC,iBAAiB,CAAC;SAC1B,WAAW,CACV,kEAAkE,CACnE;SACA,MAAM,CAAC,eAAe,EAAE,6BAA6B,CAAC;SACtD,MAAM,CAAC,eAAe,EAAE,2CAA2C,CAAC;SACpE,MAAM,CAAC,iBAAiB,EAAE,wBAAwB,CAAC;SACnD,MAAM,CAAC,eAAe,EAAE,wCAAwC,CAAC;SACjE,MAAM,CAAC,KAAK,EAAE,OAA8B,EAAE,EAAE;QAC/C,MAAM,IAAI,GAAG,MAAM,iBAAiB,CAAC,OAAO,CAAC,CAAC;QAC9C,IAAI,IAAI,KAAK,CAAC;YAAE,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;IAC1C,CAAC,CAAC,CAAC;AACP,CAAC;AAED;;;GAGG;AACH,SAAS,4BAA4B,CAAC,OAAgB;IACpD,OAAO;SACJ,OAAO,CAAC,sBAAsB,CAAC;SAC/B,WAAW,CACV,uEAAuE,CACxE;SACA,QAAQ,CAAC,QAAQ,EAAE,gDAAgD,CAAC;SACpE,MAAM,CAAC,KAAK,EAAE,UAA8B,EAAE,EAAE;QAC/C,MAAM,IAAI,GAAG,MAAM,qBAAqB,CAAC,UAAU,CAAC,CAAC;QACrD,IAAI,IAAI,KAAK,CAAC;YAAE,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;IAC1C,CAAC,CAAC,CAAC;AACP,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAC7B,OAAgB,EAChB,YAAqC;IAErC,8BAA8B,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;IACtD,sBAAsB,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;IAC9C,wBAAwB,CAAC,OAAO,CAAC,CAAC;IAClC,4BAA4B,CAAC,OAAO,CAAC,CAAC;AACxC,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/** Injectable collaborators for {@link runInstallMergeDriver}. */
|
|
2
|
+
export interface InstallMergeDriverDependencies {
|
|
3
|
+
/** Working directory used to resolve a relative project path. */
|
|
4
|
+
readonly cwd?: string;
|
|
5
|
+
/** Sink for the outcome line (defaults to stdout). */
|
|
6
|
+
readonly log?: (message: string) => void;
|
|
7
|
+
/** Sink for a real registration failure (defaults to stderr). */
|
|
8
|
+
readonly error?: (message: string) => void;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Register the merge driver for one project.
|
|
12
|
+
* Exit code distinguishes a benign non-event from a real failure: a directory
|
|
13
|
+
* that is not a git repository passes (nothing to register), but a git-config
|
|
14
|
+
* write that failed exits non-zero. Reporting success there would tell an
|
|
15
|
+
* operator the ledger is protected when it is not.
|
|
16
|
+
* @param targetPath - Optional project directory (default: current directory)
|
|
17
|
+
* @param dependencies - Injectable collaborators for tests
|
|
18
|
+
* @returns Process exit code: 0 registered/unchanged/not-a-repo, 1 failed
|
|
19
|
+
*/
|
|
20
|
+
export declare function runInstallMergeDriver(targetPath: string | undefined, dependencies?: InstallMergeDriverDependencies): Promise<number>;
|
|
21
|
+
//# sourceMappingURL=install-merge-driver-cmd.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install-merge-driver-cmd.d.ts","sourceRoot":"","sources":["../../src/cli/install-merge-driver-cmd.ts"],"names":[],"mappings":"AAcA,kEAAkE;AAClE,MAAM,WAAW,8BAA8B;IAC7C,iEAAiE;IACjE,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,sDAAsD;IACtD,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,iEAAiE;IACjE,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CAC5C;AAED;;;;;;;;;GASG;AACH,wBAAsB,qBAAqB,CACzC,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,YAAY,GAAE,8BAAmC,GAChD,OAAO,CAAC,MAAM,CAAC,CAajB"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `lisa install-merge-driver` — register the project-learnings union merge
|
|
3
|
+
* driver in the current repository's local git config.
|
|
4
|
+
*
|
|
5
|
+
* `lisa apply` already does this through the `EnsureLearningsMergeDriver`
|
|
6
|
+
* migration, so this command exists for the cases apply does not cover: a fresh
|
|
7
|
+
* clone or worktree that has not been applied yet, and CI-like environments
|
|
8
|
+
* where the bootstrap guard suppresses apply. It is also the command the
|
|
9
|
+
* learnings budget gate names when it detects a conflict-corrupted ledger.
|
|
10
|
+
* @module cli/install-merge-driver-cmd
|
|
11
|
+
*/
|
|
12
|
+
import * as path from "node:path";
|
|
13
|
+
import { installLearningsMergeDriver } from "../core/learnings-merge-driver-install.js";
|
|
14
|
+
/**
|
|
15
|
+
* Register the merge driver for one project.
|
|
16
|
+
* Exit code distinguishes a benign non-event from a real failure: a directory
|
|
17
|
+
* that is not a git repository passes (nothing to register), but a git-config
|
|
18
|
+
* write that failed exits non-zero. Reporting success there would tell an
|
|
19
|
+
* operator the ledger is protected when it is not.
|
|
20
|
+
* @param targetPath - Optional project directory (default: current directory)
|
|
21
|
+
* @param dependencies - Injectable collaborators for tests
|
|
22
|
+
* @returns Process exit code: 0 registered/unchanged/not-a-repo, 1 failed
|
|
23
|
+
*/
|
|
24
|
+
export async function runInstallMergeDriver(targetPath, dependencies = {}) {
|
|
25
|
+
const cwd = dependencies.cwd ?? process.cwd();
|
|
26
|
+
const log = dependencies.log ?? ((message) => console.log(message));
|
|
27
|
+
const error = dependencies.error ?? ((message) => console.error(message));
|
|
28
|
+
const projectRoot = path.resolve(cwd, targetPath ?? ".");
|
|
29
|
+
const result = await installLearningsMergeDriver(projectRoot);
|
|
30
|
+
if (result.kind === "failed") {
|
|
31
|
+
error(`install-merge-driver: ${result.detail}`);
|
|
32
|
+
return 1;
|
|
33
|
+
}
|
|
34
|
+
log(`install-merge-driver: ${result.detail}`);
|
|
35
|
+
return 0;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=install-merge-driver-cmd.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install-merge-driver-cmd.js","sourceRoot":"","sources":["../../src/cli/install-merge-driver-cmd.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,2BAA2B,EAAE,MAAM,2CAA2C,CAAC;AAYxF;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,UAA8B,EAC9B,eAA+C,EAAE;IAEjD,MAAM,GAAG,GAAG,YAAY,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IAC9C,MAAM,GAAG,GAAG,YAAY,CAAC,GAAG,IAAI,CAAC,CAAC,OAAe,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;IAC5E,MAAM,KAAK,GACT,YAAY,CAAC,KAAK,IAAI,CAAC,CAAC,OAAe,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;IACtE,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,UAAU,IAAI,GAAG,CAAC,CAAC;IACzD,MAAM,MAAM,GAAG,MAAM,2BAA2B,CAAC,WAAW,CAAC,CAAC;IAC9D,IAAI,MAAM,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC7B,KAAK,CAAC,yBAAyB,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;QAChD,OAAO,CAAC,CAAC;IACX,CAAC;IACD,GAAG,CAAC,yBAAyB,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;IAC9C,OAAO,CAAC,CAAC;AACX,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/** Git-supplied merge sides, mapped from `%O %A %B %P`. */
|
|
2
|
+
export interface MergeLearningsOptions {
|
|
3
|
+
/** `%O` — merge-base version; an empty file when the ledger is new. */
|
|
4
|
+
readonly base?: string;
|
|
5
|
+
/** `%A` — our version, and the file the result must be written to. */
|
|
6
|
+
readonly ours?: string;
|
|
7
|
+
/** `%B` — their (incoming) version. */
|
|
8
|
+
readonly theirs?: string;
|
|
9
|
+
/** `%P` — the real pathname, used only in diagnostics. */
|
|
10
|
+
readonly path?: string;
|
|
11
|
+
}
|
|
12
|
+
/** Injectable collaborators for {@link runMergeLearnings}. */
|
|
13
|
+
export interface MergeLearningsDependencies {
|
|
14
|
+
/** Sink for the conflict diagnostic (defaults to stderr). */
|
|
15
|
+
readonly error?: (message: string) => void;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Run the union merge and publish the result.
|
|
19
|
+
* @param options - Git-supplied merge sides
|
|
20
|
+
* @param dependencies - Injectable collaborators for tests
|
|
21
|
+
* @returns Process exit code: 0 merged, 1 conflict
|
|
22
|
+
*/
|
|
23
|
+
export declare function runMergeLearnings(options: MergeLearningsOptions, dependencies?: MergeLearningsDependencies): Promise<number>;
|
|
24
|
+
//# sourceMappingURL=merge-learnings-cmd.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"merge-learnings-cmd.d.ts","sourceRoot":"","sources":["../../src/cli/merge-learnings-cmd.ts"],"names":[],"mappings":"AAsBA,2DAA2D;AAC3D,MAAM,WAAW,qBAAqB;IACpC,uEAAuE;IACvE,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,sEAAsE;IACtE,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,uCAAuC;IACvC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,0DAA0D;IAC1D,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,8DAA8D;AAC9D,MAAM,WAAW,0BAA0B;IACzC,6DAA6D;IAC7D,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CAC5C;AA2BD;;;;;GAKG;AACH,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,qBAAqB,EAC9B,YAAY,GAAE,0BAA+B,GAC5C,OAAO,CAAC,MAAM,CAAC,CA2CjB"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `lisa merge-learnings` — the git merge driver for the project-learnings
|
|
3
|
+
* ledger.
|
|
4
|
+
*
|
|
5
|
+
* Git invokes this with the three sides of a merge and expects the result to be
|
|
6
|
+
* written over the "ours" file, exiting zero for a clean merge and non-zero to
|
|
7
|
+
* record a conflict. The union itself lives in `core/learnings-merge.ts`; this
|
|
8
|
+
* module is only the process boundary — argument plumbing, file IO, and the
|
|
9
|
+
* exit-code contract.
|
|
10
|
+
*
|
|
11
|
+
* On conflict the "ours" file is deliberately left untouched rather than filled
|
|
12
|
+
* with conflict markers: git still records the conflict from the non-zero exit,
|
|
13
|
+
* and leaving a parseable ledger in the working tree means the recovering agent
|
|
14
|
+
* reads a real document plus a precise reason on stderr, instead of a corrupted
|
|
15
|
+
* one. The marker guard in `core/learnings-document.ts` remains the backstop for
|
|
16
|
+
* ledgers corrupted while this driver was NOT registered.
|
|
17
|
+
* @module cli/merge-learnings-cmd
|
|
18
|
+
*/
|
|
19
|
+
import { readFile } from "node:fs/promises";
|
|
20
|
+
import { mergeLearningsDocuments } from "../core/learnings-merge.js";
|
|
21
|
+
import { writeFileAtomically } from "../utils/atomic-file-write.js";
|
|
22
|
+
/**
|
|
23
|
+
* Read one merge side that was definitely supplied.
|
|
24
|
+
*
|
|
25
|
+
* Never conflates "unreadable" with "empty". Collapsing the two is what made
|
|
26
|
+
* this driver fail OPEN: an unreadable merge base silently became "no base",
|
|
27
|
+
* the union degraded to two-way, and a superseded entry was resurrected into a
|
|
28
|
+
* CLEAN, committed merge. Real triggers include ERR_STRING_TOO_LONG on an
|
|
29
|
+
* oversized base, EACCES, ENOMEM, and EMFILE/ENFILE exhaustion under exactly
|
|
30
|
+
* the parallel worktree merges this driver serves.
|
|
31
|
+
* @param file - Path supplied by git
|
|
32
|
+
* @returns The contents, or an explicit read failure
|
|
33
|
+
*/
|
|
34
|
+
async function readSide(file) {
|
|
35
|
+
try {
|
|
36
|
+
return { ok: true, content: await readFile(file, "utf8") };
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
return { ok: false };
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Run the union merge and publish the result.
|
|
44
|
+
* @param options - Git-supplied merge sides
|
|
45
|
+
* @param dependencies - Injectable collaborators for tests
|
|
46
|
+
* @returns Process exit code: 0 merged, 1 conflict
|
|
47
|
+
*/
|
|
48
|
+
export async function runMergeLearnings(options, dependencies = {}) {
|
|
49
|
+
const error = dependencies.error ?? ((message) => console.error(message));
|
|
50
|
+
const label = options.path ?? "project learnings";
|
|
51
|
+
if (options.ours === undefined || options.theirs === undefined) {
|
|
52
|
+
error("merge-learnings: --ours and --theirs are required (git supplies %A and %B)");
|
|
53
|
+
return 1;
|
|
54
|
+
}
|
|
55
|
+
const oursPath = options.ours;
|
|
56
|
+
const ours = await readSide(oursPath);
|
|
57
|
+
const theirs = await readSide(options.theirs);
|
|
58
|
+
if (!ours.ok || !theirs.ok) {
|
|
59
|
+
error(`merge-learnings: ${label}: could not read both merge sides`);
|
|
60
|
+
return 1;
|
|
61
|
+
}
|
|
62
|
+
// An OMITTED --base legitimately means "new on both sides". A base that was
|
|
63
|
+
// supplied and cannot be read is a different thing entirely, and must never
|
|
64
|
+
// be silently downgraded into the first case — exit 0 makes git record a
|
|
65
|
+
// clean merge, so failing open here publishes data loss with no marker, no
|
|
66
|
+
// diagnostic, and no second chance.
|
|
67
|
+
const base = options.base === undefined
|
|
68
|
+
? { ok: true, content: "" }
|
|
69
|
+
: await readSide(options.base);
|
|
70
|
+
if (!base.ok) {
|
|
71
|
+
error(`merge-learnings: ${label}: merge base could not be read — refusing to merge without it, because a two-way union silently resurrects superseded entries`);
|
|
72
|
+
return 1;
|
|
73
|
+
}
|
|
74
|
+
const result = mergeLearningsDocuments(base.content, ours.content, theirs.content);
|
|
75
|
+
if (result.kind === "conflict") {
|
|
76
|
+
error(`merge-learnings: ${label}: ${result.reason}`);
|
|
77
|
+
return 1;
|
|
78
|
+
}
|
|
79
|
+
await writeFileAtomically(oursPath, result.content);
|
|
80
|
+
return 0;
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=merge-learnings-cmd.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"merge-learnings-cmd.js","sourceRoot":"","sources":["../../src/cli/merge-learnings-cmd.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,uBAAuB,EAAE,MAAM,4BAA4B,CAAC;AACrE,OAAO,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AAyBpE;;;;;;;;;;;GAWG;AACH,KAAK,UAAU,QAAQ,CAAC,IAAY;IAClC,IAAI,CAAC;QACH,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,CAAC;IAC7D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC;IACvB,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,OAA8B,EAC9B,eAA2C,EAAE;IAE7C,MAAM,KAAK,GACT,YAAY,CAAC,KAAK,IAAI,CAAC,CAAC,OAAe,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;IACtE,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,IAAI,mBAAmB,CAAC;IAClD,IAAI,OAAO,CAAC,IAAI,KAAK,SAAS,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QAC/D,KAAK,CACH,4EAA4E,CAC7E,CAAC;QACF,OAAO,CAAC,CAAC;IACX,CAAC;IACD,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAC9B,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACtC,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAC9C,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;QAC3B,KAAK,CAAC,oBAAoB,KAAK,mCAAmC,CAAC,CAAC;QACpE,OAAO,CAAC,CAAC;IACX,CAAC;IACD,4EAA4E;IAC5E,4EAA4E;IAC5E,yEAAyE;IACzE,2EAA2E;IAC3E,oCAAoC;IACpC,MAAM,IAAI,GACR,OAAO,CAAC,IAAI,KAAK,SAAS;QACxB,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE;QAC3B,CAAC,CAAC,MAAM,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACnC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;QACb,KAAK,CACH,oBAAoB,KAAK,+HAA+H,CACzJ,CAAC;QACF,OAAO,CAAC,CAAC;IACX,CAAC;IACD,MAAM,MAAM,GAAG,uBAAuB,CACpC,IAAI,CAAC,OAAO,EACZ,IAAI,CAAC,OAAO,EACZ,MAAM,CAAC,OAAO,CACf,CAAC;IACF,IAAI,MAAM,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;QAC/B,KAAK,CAAC,oBAAoB,KAAK,KAAK,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;QACrD,OAAO,CAAC,CAAC;IACX,CAAC;IACD,MAAM,mBAAmB,CAAC,QAAQ,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;IACpD,OAAO,CAAC,CAAC;AACX,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"learnings-budget-check.d.ts","sourceRoot":"","sources":["../../src/core/learnings-budget-check.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"learnings-budget-check.d.ts","sourceRoot":"","sources":["../../src/core/learnings-budget-check.ts"],"names":[],"mappings":"AA+BA,yDAAyD;AACzD,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;IACpB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED,gFAAgF;AAChF,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,8EAA8E;AAC9E,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,8CAA8C;AAC9C,MAAM,MAAM,qBAAqB,GAC7B,iBAAiB,GACjB,sBAAsB,GACtB,wBAAwB,CAAC;AAE7B;;;;;;GAMG;AACH,wBAAsB,oBAAoB,CACxC,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,qBAAqB,CAAC,CAgChC;AAiDD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAYxD;AAoCD;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEzD"}
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
import { constants } from "node:fs";
|
|
18
18
|
import { open } from "node:fs/promises";
|
|
19
19
|
import { LEARNINGS_CONTRACT, estimateLearningTokens, } from "./learnings-contract.js";
|
|
20
|
-
import { parseLearningsFile, renderLearningsFile, } from "./learnings-document.js";
|
|
20
|
+
import { CONFLICT_MARKER_DIAGNOSIS, conflictMarkerError, findConflictMarkerInBytes, parseLearningsFile, renderLearningsFile, } from "./learnings-document.js";
|
|
21
21
|
import { validateLearningEntry } from "./learnings-entry.js";
|
|
22
22
|
/**
|
|
23
23
|
* Check one already-resolved absolute learnings path against the shared hard
|
|
@@ -70,6 +70,12 @@ function withRemediation(detail, file) {
|
|
|
70
70
|
return detail;
|
|
71
71
|
}
|
|
72
72
|
const target = formatDiagnosticPath(file);
|
|
73
|
+
// Checked before the budget clauses: a conflicted merge duplicates the JSONL
|
|
74
|
+
// block, so this failure often ALSO breaches a budget, and "shorten entries"
|
|
75
|
+
// is the wrong instruction for it.
|
|
76
|
+
if (detail.includes(CONFLICT_MARKER_DIAGNOSIS)) {
|
|
77
|
+
return `${detail} — recompact ${target} from both conflicting versions, then register the union merge driver (\`lisa install-merge-driver\`) so concurrent learning branches merge instead of conflicting`;
|
|
78
|
+
}
|
|
73
79
|
if (detail.includes("maxEntries")) {
|
|
74
80
|
return `${detail} — consolidate or remove entries in ${target} to fit the learnings budget`;
|
|
75
81
|
}
|
|
@@ -164,11 +170,20 @@ async function readBoundedRegularFile(file, maximumBytes) {
|
|
|
164
170
|
if (!before.isFile()) {
|
|
165
171
|
throw new Error("unsafe input: expected a regular file");
|
|
166
172
|
}
|
|
173
|
+
// Read the bounded prefix BEFORE judging size. A git-conflicted ledger is
|
|
174
|
+
// roughly double size, so the size guard used to win this race and report
|
|
175
|
+
// "shorten or remove entries" for a file whose problem is duplication —
|
|
176
|
+
// advice that has an operator deleting good learnings. The read is capped
|
|
177
|
+
// by the buffer either way, so an oversized file is still never slurped.
|
|
178
|
+
const buffer = Buffer.allocUnsafe(maximumBytes + 1);
|
|
179
|
+
const bytesRead = await fillBuffer(handle, buffer, 0);
|
|
180
|
+
const conflictLine = findConflictMarkerInBytes(buffer.subarray(0, bytesRead));
|
|
181
|
+
if (conflictLine !== undefined) {
|
|
182
|
+
throw conflictMarkerError(conflictLine);
|
|
183
|
+
}
|
|
167
184
|
if (before.size > BigInt(maximumBytes)) {
|
|
168
185
|
throw new Error(`maxTokens exceeded: measured ${before.size}, allowed ${maximumBytes}`);
|
|
169
186
|
}
|
|
170
|
-
const buffer = Buffer.allocUnsafe(maximumBytes + 1);
|
|
171
|
-
const bytesRead = await fillBuffer(handle, buffer, 0);
|
|
172
187
|
if (bytesRead > maximumBytes) {
|
|
173
188
|
throw new Error(`maxTokens exceeded: measured at least ${bytesRead}, allowed ${maximumBytes}`);
|
|
174
189
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"learnings-budget-check.js","sourceRoot":"","sources":["../../src/core/learnings-budget-check.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"learnings-budget-check.js","sourceRoot":"","sources":["../../src/core/learnings-budget-check.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
/** Pure parsing and rendering for the canonical project-learnings document. */
|
|
2
2
|
import { type LearningEntry } from "./learnings-contract.js";
|
|
3
|
+
/**
|
|
4
|
+
* Stable diagnosis prefix. Shared so the CI gate can recognize this specific
|
|
5
|
+
* failure and attach merge-driver remediation without re-implementing the scan.
|
|
6
|
+
*/
|
|
7
|
+
export declare const CONFLICT_MARKER_DIAGNOSIS = "Project learnings file contains a git conflict marker";
|
|
3
8
|
/**
|
|
4
9
|
* Render the complete file in one stable, machine-readable Markdown form.
|
|
5
10
|
* @param entries - Validated entries to serialize
|
|
@@ -19,4 +24,45 @@ export declare function parseLearningsFile(content: string): LearningEntry[];
|
|
|
19
24
|
* @param context - Error-message prefix
|
|
20
25
|
*/
|
|
21
26
|
export declare function assertDocumentBudget(content: string, entryCount: number, context: string): void;
|
|
27
|
+
/**
|
|
28
|
+
* Locate the first line git left a conflict marker on.
|
|
29
|
+
*
|
|
30
|
+
* The fs-level write lock cannot prevent this corruption: each learner pass
|
|
31
|
+
* runs on its own `learning/<fingerprint>` branch in its own worktree, so a
|
|
32
|
+
* path-scoped lock never sees the other writer and the collision surfaces at
|
|
33
|
+
* merge time.
|
|
34
|
+
*
|
|
35
|
+
* Detection is exact because of the render contract: entries are serialized one
|
|
36
|
+
* `JSON.stringify` object per line and that escapes every newline, so no stored
|
|
37
|
+
* field value can ever begin a line. Every line of a canonical document starts
|
|
38
|
+
* with `#`, `<!--`, a backtick fence, `{`, or is empty — so a line STARTING
|
|
39
|
+
* with a seven-character git marker is unambiguously foreign to the format and
|
|
40
|
+
* cannot be legitimate content.
|
|
41
|
+
* @param content - Untrusted learnings document
|
|
42
|
+
* @returns One-based line number of the first marker, or undefined when clean
|
|
43
|
+
*/
|
|
44
|
+
export declare function findConflictMarkerLine(content: string): number | undefined;
|
|
45
|
+
/**
|
|
46
|
+
* Build the one canonical conflict diagnosis every reader throws.
|
|
47
|
+
*
|
|
48
|
+
* Shared because the readers each apply a file-SIZE guard before handing bytes
|
|
49
|
+
* to the parser, and a real conflicted ledger is roughly double size — so the
|
|
50
|
+
* size guard would otherwise win the race and tell an operator to "shorten or
|
|
51
|
+
* remove entries" on a file whose actual problem is duplication. Each reader
|
|
52
|
+
* scans its bounded prefix and throws THIS error instead.
|
|
53
|
+
* @param line - One-based line number of the first marker
|
|
54
|
+
* @returns Error carrying the shared diagnosis and remediation
|
|
55
|
+
*/
|
|
56
|
+
export declare function conflictMarkerError(line: number): Error;
|
|
57
|
+
/**
|
|
58
|
+
* Scan a possibly-truncated UTF-8 prefix for a conflict marker.
|
|
59
|
+
*
|
|
60
|
+
* Decoded leniently on purpose: the buffer is cut at a fixed byte ceiling and
|
|
61
|
+
* may split a multi-byte character, which a strict decoder would reject. A
|
|
62
|
+
* replacement character cannot forge or hide a marker, since markers are ASCII
|
|
63
|
+
* anchored at line start.
|
|
64
|
+
* @param prefix - Bounded bytes read from the head of a candidate ledger
|
|
65
|
+
* @returns One-based line number of the first marker, or undefined when clean
|
|
66
|
+
*/
|
|
67
|
+
export declare function findConflictMarkerInBytes(prefix: Uint8Array): number | undefined;
|
|
22
68
|
//# sourceMappingURL=learnings-document.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"learnings-document.d.ts","sourceRoot":"","sources":["../../src/core/learnings-document.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,OAAO,EAGL,KAAK,aAAa,EACnB,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"learnings-document.d.ts","sourceRoot":"","sources":["../../src/core/learnings-document.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,OAAO,EAGL,KAAK,aAAa,EACnB,MAAM,yBAAyB,CAAC;AA+BjC;;;GAGG;AACH,eAAO,MAAM,yBAAyB,0DACmB,CAAC;AAE1D;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,SAAS,aAAa,EAAE,GAAG,MAAM,CAG7E;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,aAAa,EAAE,CA8BnE;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,GACd,IAAI,CAYN;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAK1E;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,KAAK,CAIvD;AAED;;;;;;;;;GASG;AACH,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,UAAU,GACjB,MAAM,GAAG,SAAS,CAEpB"}
|
|
@@ -8,7 +8,30 @@ const FILE_HEADER = `# Project Learnings
|
|
|
8
8
|
`;
|
|
9
9
|
const JSON_FENCE_START = "```jsonl\n";
|
|
10
10
|
const JSON_FENCE_END = "\n```\n";
|
|
11
|
-
|
|
11
|
+
/**
|
|
12
|
+
* Git's conflict markers, anchored to the start of a line.
|
|
13
|
+
*
|
|
14
|
+
* Seven characters is only the DEFAULT width. Git's `conflict-marker-size`
|
|
15
|
+
* attribute is real and widens every marker, and a `.gitattributes` setting it
|
|
16
|
+
* survives `lisa apply` because copy-contents preserves host lines outside the
|
|
17
|
+
* managed block — so a fixed `{7}` quantifier silently stops recognizing
|
|
18
|
+
* corruption in exactly the repositories that configured it. `{7,}` matches any
|
|
19
|
+
* legal width. The trailing class also admits `\r` so a CRLF checkout's
|
|
20
|
+
* `>>>>>>>\r` is still seen.
|
|
21
|
+
*
|
|
22
|
+
* Only the opener (`<<<<<<<`), the diff3 base separator (`|||||||`), and the
|
|
23
|
+
* closer (`>>>>>>>`) are matched. A bare `=======` is deliberately NOT a signal
|
|
24
|
+
* on its own: a row of equals signs is ordinary prose punctuation, so matching
|
|
25
|
+
* it would make a legitimate document undiagnosable. Every real git conflict
|
|
26
|
+
* emits an opener and a closer around it, so anchoring on those loses no
|
|
27
|
+
* detection power while removing the ambiguity.
|
|
28
|
+
*/
|
|
29
|
+
const CONFLICT_MARKER = /^(?:<{7,}|\|{7,}|>{7,})(?:[ \t\r]|$)/u;
|
|
30
|
+
/**
|
|
31
|
+
* Stable diagnosis prefix. Shared so the CI gate can recognize this specific
|
|
32
|
+
* failure and attach merge-driver remediation without re-implementing the scan.
|
|
33
|
+
*/
|
|
34
|
+
export const CONFLICT_MARKER_DIAGNOSIS = "Project learnings file contains a git conflict marker";
|
|
12
35
|
/**
|
|
13
36
|
* Render the complete file in one stable, machine-readable Markdown form.
|
|
14
37
|
* @param entries - Validated entries to serialize
|
|
@@ -24,12 +47,17 @@ export function renderLearningsFile(entries) {
|
|
|
24
47
|
* @returns Revalidated entries from the document
|
|
25
48
|
*/
|
|
26
49
|
export function parseLearningsFile(content) {
|
|
50
|
+
// Diagnose concurrent-write corruption BEFORE the byte budget. A conflicted
|
|
51
|
+
// merge duplicates the whole JSONL block, so a nearly-full ledger lands over
|
|
52
|
+
// budget and would otherwise report "exceeds maxTokens" — advice that sends
|
|
53
|
+
// an operator off deleting good learnings when the real fix is recompaction.
|
|
54
|
+
const conflictLine = findConflictMarkerLine(content);
|
|
55
|
+
if (conflictLine !== undefined) {
|
|
56
|
+
throw conflictMarkerError(conflictLine);
|
|
57
|
+
}
|
|
27
58
|
if (estimateLearningTokens(content) > LEARNINGS_CONTRACT.maxTokens) {
|
|
28
59
|
throw new Error(`Project learnings payload exceeds maxTokens ${LEARNINGS_CONTRACT.maxTokens}`);
|
|
29
60
|
}
|
|
30
|
-
if (CONFLICT_MARKER_PATTERN.test(content)) {
|
|
31
|
-
throw new Error("Project learnings ledger corrupted by concurrent write: embedded conflict markers found; restore or recompact the ledger before writing");
|
|
32
|
-
}
|
|
33
61
|
if (!content.startsWith(`${FILE_HEADER}${JSON_FENCE_START}`) ||
|
|
34
62
|
!content.endsWith(JSON_FENCE_END)) {
|
|
35
63
|
throw new Error("Invalid project learnings file format");
|
|
@@ -58,6 +86,56 @@ export function assertDocumentBudget(content, entryCount, context) {
|
|
|
58
86
|
throw new Error(`${context} exceeds maxTokens ${LEARNINGS_CONTRACT.maxTokens} (measured ${estimatedTokens})`);
|
|
59
87
|
}
|
|
60
88
|
}
|
|
89
|
+
/**
|
|
90
|
+
* Locate the first line git left a conflict marker on.
|
|
91
|
+
*
|
|
92
|
+
* The fs-level write lock cannot prevent this corruption: each learner pass
|
|
93
|
+
* runs on its own `learning/<fingerprint>` branch in its own worktree, so a
|
|
94
|
+
* path-scoped lock never sees the other writer and the collision surfaces at
|
|
95
|
+
* merge time.
|
|
96
|
+
*
|
|
97
|
+
* Detection is exact because of the render contract: entries are serialized one
|
|
98
|
+
* `JSON.stringify` object per line and that escapes every newline, so no stored
|
|
99
|
+
* field value can ever begin a line. Every line of a canonical document starts
|
|
100
|
+
* with `#`, `<!--`, a backtick fence, `{`, or is empty — so a line STARTING
|
|
101
|
+
* with a seven-character git marker is unambiguously foreign to the format and
|
|
102
|
+
* cannot be legitimate content.
|
|
103
|
+
* @param content - Untrusted learnings document
|
|
104
|
+
* @returns One-based line number of the first marker, or undefined when clean
|
|
105
|
+
*/
|
|
106
|
+
export function findConflictMarkerLine(content) {
|
|
107
|
+
const index = content
|
|
108
|
+
.split("\n")
|
|
109
|
+
.findIndex(line => CONFLICT_MARKER.test(line));
|
|
110
|
+
return index === -1 ? undefined : index + 1;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Build the one canonical conflict diagnosis every reader throws.
|
|
114
|
+
*
|
|
115
|
+
* Shared because the readers each apply a file-SIZE guard before handing bytes
|
|
116
|
+
* to the parser, and a real conflicted ledger is roughly double size — so the
|
|
117
|
+
* size guard would otherwise win the race and tell an operator to "shorten or
|
|
118
|
+
* remove entries" on a file whose actual problem is duplication. Each reader
|
|
119
|
+
* scans its bounded prefix and throws THIS error instead.
|
|
120
|
+
* @param line - One-based line number of the first marker
|
|
121
|
+
* @returns Error carrying the shared diagnosis and remediation
|
|
122
|
+
*/
|
|
123
|
+
export function conflictMarkerError(line) {
|
|
124
|
+
return new Error(`${CONFLICT_MARKER_DIAGNOSIS} on line ${line}: the ledger was corrupted by concurrent writers merging separate learning branches. Recompact it by keeping every distinct entry id from both sides, then re-run.`);
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Scan a possibly-truncated UTF-8 prefix for a conflict marker.
|
|
128
|
+
*
|
|
129
|
+
* Decoded leniently on purpose: the buffer is cut at a fixed byte ceiling and
|
|
130
|
+
* may split a multi-byte character, which a strict decoder would reject. A
|
|
131
|
+
* replacement character cannot forge or hide a marker, since markers are ASCII
|
|
132
|
+
* anchored at line start.
|
|
133
|
+
* @param prefix - Bounded bytes read from the head of a candidate ledger
|
|
134
|
+
* @returns One-based line number of the first marker, or undefined when clean
|
|
135
|
+
*/
|
|
136
|
+
export function findConflictMarkerInBytes(prefix) {
|
|
137
|
+
return findConflictMarkerLine(new TextDecoder("utf-8").decode(prefix));
|
|
138
|
+
}
|
|
61
139
|
/**
|
|
62
140
|
* Add a stable entry identifier to validation failures.
|
|
63
141
|
* @param candidate - Parsed JSONL value
|
|
@@ -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;
|
|
1
|
+
{"version":3,"file":"learnings-document.js","sourceRoot":"","sources":["../../src/core/learnings-document.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"learnings-file-safety.d.ts","sourceRoot":"","sources":["../../src/core/learnings-file-safety.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"learnings-file-safety.d.ts","sourceRoot":"","sources":["../../src/core/learnings-file-safety.ts"],"names":[],"mappings":"AAUA;;;;;GAKG;AACH,wBAAgB,yBAAyB,CACvC,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM,GACnB;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CASpD;AAED;;;;GAIG;AACH,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAyC7B;AAkBD;;;;GAIG;AACH,wBAAsB,yBAAyB,CAC7C,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,IAAI,CAAC,CAYf"}
|