@codyswann/lisa 4.20.0 → 4.21.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 +2 -1
- package/all/create-only/.lisa/PROJECT_LEARNINGS.md +1 -1
- package/dist/core/learnings-alias.d.ts +26 -45
- package/dist/core/learnings-alias.d.ts.map +1 -1
- package/dist/core/learnings-alias.js +29 -48
- package/dist/core/learnings-alias.js.map +1 -1
- package/dist/core/learnings-budget-check.d.ts +2 -1
- package/dist/core/learnings-budget-check.d.ts.map +1 -1
- package/dist/core/learnings-budget-check.js +13 -11
- package/dist/core/learnings-budget-check.js.map +1 -1
- package/dist/core/learnings-contract.d.ts +27 -10
- package/dist/core/learnings-contract.d.ts.map +1 -1
- package/dist/core/learnings-contract.js +37 -9
- package/dist/core/learnings-contract.js.map +1 -1
- package/dist/core/learnings-document.d.ts +20 -1
- package/dist/core/learnings-document.d.ts.map +1 -1
- package/dist/core/learnings-document.js +81 -14
- package/dist/core/learnings-document.js.map +1 -1
- package/dist/core/learnings-entry.d.ts +11 -1
- package/dist/core/learnings-entry.d.ts.map +1 -1
- package/dist/core/learnings-entry.js +98 -24
- package/dist/core/learnings-entry.js.map +1 -1
- package/dist/core/learnings-merge-driver.d.ts +4 -2
- package/dist/core/learnings-merge-driver.d.ts.map +1 -1
- package/dist/core/learnings-merge-driver.js +6 -3
- package/dist/core/learnings-merge-driver.js.map +1 -1
- package/dist/core/learnings-merge.d.ts.map +1 -1
- package/dist/core/learnings-merge.js +96 -10
- package/dist/core/learnings-merge.js.map +1 -1
- package/dist/core/learnings-overflow.d.ts.map +1 -1
- package/dist/core/learnings-overflow.js +72 -3
- package/dist/core/learnings-overflow.js.map +1 -1
- package/dist/core/learnings-supersede.d.ts +56 -0
- package/dist/core/learnings-supersede.d.ts.map +1 -0
- package/dist/core/learnings-supersede.js +199 -0
- package/dist/core/learnings-supersede.js.map +1 -0
- package/dist/core/learnings-writer.d.ts +9 -7
- package/dist/core/learnings-writer.d.ts.map +1 -1
- package/dist/core/learnings-writer.js +31 -58
- package/dist/core/learnings-writer.js.map +1 -1
- package/dist/core/learnings.d.ts +3 -0
- package/dist/core/learnings.d.ts.map +1 -1
- package/dist/core/learnings.js +3 -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 +15 -6
- package/dist/core/upstream-evidence-manifest.js.map +1 -1
- package/package.json +3 -2
- 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-debrief-apply/SKILL.md +5 -4
- package/plugins/lisa/.codex-plugin/skills/lisa-persist-learning/SKILL.md +2 -2
- package/plugins/lisa/agents/learner.md +7 -6
- package/plugins/lisa/rules/reference/project-learnings.md +34 -1
- package/plugins/lisa/skills/lisa-debrief-apply/SKILL.md +5 -4
- package/plugins/lisa/skills/lisa-persist-learning/SKILL.md +2 -2
- package/plugins/lisa-agy/agents/learner.md +7 -6
- package/plugins/lisa-agy/plugin.json +1 -1
- package/plugins/lisa-agy/skills/lisa-debrief-apply/SKILL.md +5 -4
- package/plugins/lisa-agy/skills/lisa-persist-learning/SKILL.md +2 -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/agents/learner.agent.md +7 -6
- package/plugins/lisa-copilot/rules/reference/project-learnings.md +34 -1
- package/plugins/lisa-copilot/skills/lisa-debrief-apply/SKILL.md +5 -4
- package/plugins/lisa-copilot/skills/lisa-persist-learning/SKILL.md +2 -2
- package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cursor/agents/learner.md +7 -6
- package/plugins/lisa-cursor/rules/project-learnings-reference.mdc +34 -1
- package/plugins/lisa-cursor/skills/lisa-debrief-apply/SKILL.md +5 -4
- package/plugins/lisa-cursor/skills/lisa-persist-learning/SKILL.md +2 -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/agents/learner.md +7 -6
- package/plugins/src/base/rules/reference/project-learnings.md +34 -1
- package/plugins/src/base/skills/lisa-debrief-apply/SKILL.md +5 -4
- package/plugins/src/base/skills/lisa-persist-learning/SKILL.md +2 -2
- package/scripts/verify-learner-frontmatter-built.mjs +1 -1
- package/scripts/verify-packed-learnings-contract.mjs +268 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: learner
|
|
3
|
-
description: "Post-implementation learning agent. Capture-only — collects task learnings, builds
|
|
3
|
+
description: "Post-implementation learning agent. Capture-only — collects task learnings, builds eight-field entries, and persists them to the machine-managed ledger through the executable contract with provenance. Never promotes: it creates no skills, appends no rules, files no upstream issues; promotion is exclusively the gardener's ticket-gated job."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Learner Agent
|
|
@@ -22,11 +22,12 @@ Why this shape: promotion without a human gate lets agents unilaterally rewrite
|
|
|
22
22
|
|
|
23
23
|
If no learnings exist, report "No learnings to process" and complete.
|
|
24
24
|
|
|
25
|
-
### Step 2: Build the
|
|
25
|
+
### Step 2: Build the Eight-Field Entry
|
|
26
26
|
|
|
27
27
|
For each `mistake`/`learning` candidate, build the ledger entry the executable contract validates. The `LEARNINGS_CONTRACT` caps apply — an over-cap entry cannot persist; tighten it or drop it, never truncate by hand:
|
|
28
28
|
|
|
29
|
-
- `
|
|
29
|
+
- `fingerprint` — the deterministic content-version token: `learner-` + the first 12 hex chars of `sha1(normalized_rule)`. Recompute it from the fully consolidated rule; never estimate it.
|
|
30
|
+
- `id` — set `id = fingerprint` for a new capture. On an exact stamped consolidation the writer carries forward the deterministic primary target id, while `fingerprint` changes with the new content.
|
|
30
31
|
- `rule` — the actionable learning, **≤ 240 characters and ≤ 2 lines** per `LEARNINGS_CONTRACT`.
|
|
31
32
|
- `why` — the causal claim (why the rule holds).
|
|
32
33
|
- `provenance` — stable refs behind the candidate: the originating task id(s), plus any PR/issue/commit refs the task recorded. At most 20 entries. This is also where scope markers live (below).
|
|
@@ -47,9 +48,9 @@ LEARNINGS_FILE=$(node -e 'import("@codyswann/lisa/learnings").then(async m => {
|
|
|
47
48
|
For each candidate entry:
|
|
48
49
|
|
|
49
50
|
1. **Consolidation check (mandatory before writing).** Parse existing entries with `parseLearningsFile` from `@codyswann/lisa/learnings` and look for a related entry — same failure class, overlapping topic, or near-duplicate wording.
|
|
50
|
-
- **Related entry found** → consolidate, do not sibling.
|
|
51
|
+
- **Related entry found** → consolidate, do not sibling. Copy each target's exact parsed version stamp and write via `persistConsolidatedLearning(projectRoot, entry, { supersede: [{ id: <related id>, fingerprint: <related fingerprint> }], onStaleSupersede: targets => report(targets) })`, merging the still-true content of the superseded entry into the new rule and keeping the earliest `first_learned`. Stamps are checked together inside the lock: if any is stale, the writer removes none, safely appends the new fingerprint, and reports the mismatch. A near-duplicate sibling is a bug, not an entry.
|
|
51
52
|
- **No related entry** → append via `persistLearningEntry(projectRoot, entry)`.
|
|
52
|
-
- **Already present (same
|
|
53
|
+
- **Already present (same fingerprint)** → the writer throws on a duplicate fingerprint before mutation; treat that as a dropped-duplicate no-op and record it as such. Re-running over the same tasks leaves the ledger unchanged.
|
|
53
54
|
2. The writer re-asserts the entry and document budgets. An over-budget failure means consolidate harder or drop — never truncate by hand.
|
|
54
55
|
|
|
55
56
|
Persistence rides the implement flow's normal branch/PR: the code change and its learnings land in the same PR (satisfying "every persistence is a PR" with no new machinery). Never commit the ledger straight to the default branch and never hand-edit it.
|
|
@@ -75,7 +76,7 @@ One row per collected learning, mapping it to its terminal disposition:
|
|
|
75
76
|
- **Capture-only.** Create no skills, append to no human-authored rules file, file no issue anywhere — take no promotion decision of any kind. Every promotion (skill, eager rule, executable control, upstream ticket) is the gardener's ticket-gated job, and the ledger is your only output surface.
|
|
76
77
|
- **One write path.** The ledger changes only through `persistLearningEntry` / `persistConsolidatedLearning` from `@codyswann/lisa/learnings`, inside a PR. Never hand-edit the file.
|
|
77
78
|
- **Consolidate, never sibling.** A related existing entry is merged or superseded at write time (SLL-6 discipline), never duplicated.
|
|
78
|
-
- **Idempotent.** Deduplicate before persisting;
|
|
79
|
+
- **Idempotent.** Deduplicate before persisting; the deterministic fingerprint and stamped consolidation guarantee re-runs over the same tasks leave the ledger unchanged.
|
|
79
80
|
- **Headless-safe.** No interactive prompts; runs identically under an intake cron.
|
|
80
81
|
- **Never block the build.** If persistence fails, report the failure and let the primary flow continue — shipping the work outranks recording a learning about it.
|
|
81
82
|
- **No learning loops about learning.** Gardener tickets and learning PRs are not themselves learnings; never capture them.
|
|
@@ -22,9 +22,10 @@ then recency — that fit the token/entry budget, plus how many were omitted).
|
|
|
22
22
|
the bounded projection, not the full document. Do not duplicate numeric caps in
|
|
23
23
|
rules or prompts; the exported contract is the source of truth.
|
|
24
24
|
|
|
25
|
-
Each persisted entry has
|
|
25
|
+
Each persisted v2 entry has eight fields:
|
|
26
26
|
|
|
27
27
|
- `id`
|
|
28
|
+
- `fingerprint`
|
|
28
29
|
- `rule`
|
|
29
30
|
- `why`
|
|
30
31
|
- `provenance`
|
|
@@ -32,6 +33,36 @@ Each persisted entry has seven fields:
|
|
|
32
33
|
- `last_confirmed`
|
|
33
34
|
- `confidence`
|
|
34
35
|
|
|
36
|
+
`fingerprint` is the content-version token; `id` is the stable public identity.
|
|
37
|
+
A new entry starts with `id = fingerprint`. Consolidation passes exact
|
|
38
|
+
`{ id, fingerprint }` stamps copied from parsed entries. The writer checks the
|
|
39
|
+
whole target set inside its lock: an exact set is replaced together while the
|
|
40
|
+
deterministic primary id carries forward; any stale stamp removes nothing and
|
|
41
|
+
the new fingerprint is appended safely. Fingerprints are unique, so an
|
|
42
|
+
identical re-capture fails before mutation rather than gaining a sibling.
|
|
43
|
+
|
|
44
|
+
## v1 compatibility and mutation-only migration
|
|
45
|
+
|
|
46
|
+
`parseLearningsDocument` accepts both contract versions and reports
|
|
47
|
+
`sourceVersion`, normalized `entries`, `canonicalSource`, and
|
|
48
|
+
`sourceMaxTokens`. A v1 entry is normalized in memory with `fingerprint = id`,
|
|
49
|
+
which records the version-token job its old id already performed. A read never
|
|
50
|
+
rewrites the ledger. The next real writer mutation — append, exact stamped
|
|
51
|
+
consolidation, confirmation, overflow drain, or merge — publishes one atomic v2
|
|
52
|
+
document. Each source version is validated against its own derived budget; do
|
|
53
|
+
not copy either numeric ceiling into instructions. Stable ids and fingerprints
|
|
54
|
+
are bounded machine tokens, and the v2 budget is derived to absorb the maximum
|
|
55
|
+
per-entry fingerprint expansion for every v1 document the compatibility parser
|
|
56
|
+
accepts. That migration-closure invariant prevents an ordinary later mutation
|
|
57
|
+
from discovering that a previously accepted legacy document cannot be
|
|
58
|
+
published.
|
|
59
|
+
|
|
60
|
+
The three-way merge understands mixed v1/v2 sides. When two branches both
|
|
61
|
+
legitimately replace the same stable id from the same observed fingerprint, it
|
|
62
|
+
keeps both successors deterministically: one retains the stable id and the
|
|
63
|
+
other is keyed by its unique fingerprint. It never guesses when fingerprints
|
|
64
|
+
collide.
|
|
65
|
+
|
|
35
66
|
## Who writes the ledger
|
|
36
67
|
|
|
37
68
|
**Contract-mediated writers** — all going through the executable contract
|
|
@@ -39,6 +70,8 @@ Each persisted entry has seven fields:
|
|
|
39
70
|
|
|
40
71
|
- The **learner agent** at capture time appends or consolidates new entries
|
|
41
72
|
(`persistLearningEntry` / `persistConsolidatedLearning`) from task learnings.
|
|
73
|
+
Consolidations pass exact parsed `{ id, fingerprint }` stamps and report a
|
|
74
|
+
stale snapshot through `onStaleSupersede` instead of overwriting its winner.
|
|
42
75
|
It is capture-only: it never appends to host rules, creates skills, or
|
|
43
76
|
files upstream issues — promotion is the gardener's ticket-gated job.
|
|
44
77
|
- **`lisa-debrief-apply`** routes accepted debrief findings in the three
|
|
@@ -51,15 +51,16 @@ For each such Accepted row:
|
|
|
51
51
|
```
|
|
52
52
|
|
|
53
53
|
2. **Consolidation check (mandatory before writing).** Parse the existing entries with `parseLearningsFile` and look for one related to the row (same failure class, overlapping topic, or near-duplicate wording). Then write through the contract:
|
|
54
|
-
- **Related entry found** → consolidate
|
|
54
|
+
- **Related entry found** → consolidate with the exact parsed versions: `persistConsolidatedLearning(projectRoot, entry, { supersede: [{ id: <related id>, fingerprint: <related fingerprint> }], onStaleSupersede: targets => report(targets) })`. Every stamp is checked together inside the writer lock. If any is stale, the writer removes none, safely appends the new fingerprint, and reports the mismatch. Never append a near-duplicate sibling by choice — a sibling is a bug; the stale append is the deliberate concurrent-writer preservation path.
|
|
55
55
|
- **No related entry** → append via `persistLearningEntry(projectRoot, entry)`.
|
|
56
56
|
|
|
57
|
-
3. **Entry mapping (
|
|
58
|
-
- `
|
|
57
|
+
3. **Entry mapping (eight fields).**
|
|
58
|
+
- `fingerprint` — `debrief-` + the first 12 hex characters of `sha1(normalized_rule + "\n" + sorted_provenance.join("\n"))`, where the rule is lowercased with whitespace collapsed and provenance is sorted by codepoint. Compute it mechanically, never estimate it.
|
|
59
|
+
- `id` — initially `id = fingerprint`. On an exact stamped consolidation the writer carries forward the deterministic primary target id; report the returned id in the run summary.
|
|
59
60
|
- `rule` / `why` — from the row's `Summary` and the category-specific guidance in the routing table above (≤240 chars, ≤2 lines).
|
|
60
61
|
- `provenance` — **the triage-doc row's evidence links**. This is the same evidence link that doubles as the idempotency fingerprint below, so the row's provenance is what a later re-apply scans for.
|
|
61
62
|
- `first_learned` = `last_confirmed` = today (ISO date; on consolidation keep the superseded entry's earliest `first_learned`).
|
|
62
|
-
- `confidence` = **`high`**. A human marking the row **Accept** is corroboration — an independent human judgement that the learning is real — so a debrief-accepted entry starts higher than the learner's single-occurrence auto-capture (which defaults to `low`). The writer re-asserts the entry and token budgets; an over-budget failure means consolidate harder or drop, never truncate by hand.
|
|
63
|
+
- `confidence` = **`high`**. A human marking the row **Accept** is corroboration — an independent human judgement that the learning is real — so a debrief-accepted entry starts higher than the learner's single-occurrence auto-capture (which defaults to `low`). A duplicate fingerprint fails before mutation. The writer re-asserts the entry and token budgets; an over-budget failure means consolidate harder or drop, never truncate by hand.
|
|
63
64
|
|
|
64
65
|
**Machine-local memory is no longer a knowledge destination.** Auto-memory (`project_*.md`, `MEMORY.md`) remains available only for the assistant's *personal* collaboration notes — it is invisible to cloud runs and to teammates, so it can never hold shared project knowledge. **`AGENTS.md` is human-authored** agent operating instruction — it is the source of truth, and `CLAUDE.md` is only a one-line `@AGENTS.md` pointer — and the host-rules directory `.agents/rules/` is durable human-authored guidance; `apply` never writes to any of the three for these categories.
|
|
65
66
|
|
|
@@ -171,9 +171,9 @@ No learning content is ever committed without a PR — there is no other write p
|
|
|
171
171
|
```
|
|
172
172
|
|
|
173
173
|
3. **Consolidation check (mandatory before writing).** Parse the existing entries (`parseLearningsFile` from `@codyswann/lisa/learnings`) and look for entries related to the new rule (same failure class, overlapping topic, or near-duplicate wording). Then write through the executable contract — **never hand-edit the markdown**:
|
|
174
|
-
- **Related entry found** → consolidate
|
|
174
|
+
- **Related entry found** → consolidate with the exact versions returned by the parser: `persistConsolidatedLearning(projectRoot, entry, { supersede: [{ id: <related id>, fingerprint: <related fingerprint> }], onStaleSupersede: targets => report(targets) })`. The writer checks every stamp together inside the lock. If any target is absent or its fingerprint changed, the whole supersede is stale: it removes nothing, safely appends the new fingerprint, and reports the mismatch. Never append a near-duplicate sibling by choice — a sibling is a bug that fails review; the writer's stale append is the deliberate race-safe preservation path.
|
|
175
175
|
- **No related entry** → append via `persistLearningEntry(projectRoot, entry)` and state in the PR body why appending was correct.
|
|
176
|
-
- Entry mapping: `
|
|
176
|
+
- Entry mapping (eight fields): `fingerprint` = the deterministic Phase 0 fingerprint and initial `id = fingerprint`; `rule`/`why`/`provenance` from the candidate; `first_learned` = `last_confirmed` = today (ISO date; on consolidation keep the superseded entry's earliest `first_learned`); `confidence` = the judge's `high`/`low`. On an exact stamped consolidation the writer carries forward the deterministic primary target id while persisting the new fingerprint as the version token. A duplicate fingerprint fails before mutation. The writer re-asserts the entry and token budgets — an over-budget failure means consolidate harder or drop, never truncate by hand.
|
|
177
177
|
- **On a budget-forced drop, signal saturation once (never silent).** When the writer's budget re-assertion cannot fit the entry even after consolidating harder — a durable capture has to be DROPPED for budget — the ledger is saturated, and that pressure must be visible to an operator instead of swallowed. Emit **exactly one** tracker signal via `lisa-tracker-write` (`issue_type: Task`; GitHub trackers carry the `type:Task` label), then continue — dropping the capture never blocks the build. Follow the same marker-dedupe discipline as every other comment here (match on the **marker, never the title**; **exactly one marker per body**; the eventual-consistency guard when the search index is stale), with **one deliberate difference: dedupe against OPEN signals only.** A *closed* saturation ticket means room was already reclaimed, so a fresh saturation is a new actionable event — searching closed tickets too (as the drop/upstream markers do) would permanently suppress every later saturation.
|
|
178
178
|
|
|
179
179
|
The saturation fingerprint keys on the **ledger, not the candidate**, so the signal fires once per saturation episode — never once per capture:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lisa-openclaw",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.21.0",
|
|
4
4
|
"description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Cody Swann"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lisa-openclaw",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.21.0",
|
|
4
4
|
"description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, across Claude and Codex.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Cody Swann"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lisa-openclaw",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.21.0",
|
|
4
4
|
"description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Cody Swann"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lisa-openclaw",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.21.0",
|
|
4
4
|
"description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Cody Swann"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lisa-openclaw",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.21.0",
|
|
4
4
|
"description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Cody Swann"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: learner
|
|
3
|
-
description: "Post-implementation learning agent. Capture-only — collects task learnings, builds
|
|
3
|
+
description: "Post-implementation learning agent. Capture-only — collects task learnings, builds eight-field entries, and persists them to the machine-managed ledger through the executable contract with provenance. Never promotes: it creates no skills, appends no rules, files no upstream issues; promotion is exclusively the gardener's ticket-gated job."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Learner Agent
|
|
@@ -22,11 +22,12 @@ Why this shape: promotion without a human gate lets agents unilaterally rewrite
|
|
|
22
22
|
|
|
23
23
|
If no learnings exist, report "No learnings to process" and complete.
|
|
24
24
|
|
|
25
|
-
### Step 2: Build the
|
|
25
|
+
### Step 2: Build the Eight-Field Entry
|
|
26
26
|
|
|
27
27
|
For each `mistake`/`learning` candidate, build the ledger entry the executable contract validates. The `LEARNINGS_CONTRACT` caps apply — an over-cap entry cannot persist; tighten it or drop it, never truncate by hand:
|
|
28
28
|
|
|
29
|
-
- `
|
|
29
|
+
- `fingerprint` — the deterministic content-version token: `learner-` + the first 12 hex chars of `sha1(normalized_rule)`. Recompute it from the fully consolidated rule; never estimate it.
|
|
30
|
+
- `id` — set `id = fingerprint` for a new capture. On an exact stamped consolidation the writer carries forward the deterministic primary target id, while `fingerprint` changes with the new content.
|
|
30
31
|
- `rule` — the actionable learning, **≤ 240 characters and ≤ 2 lines** per `LEARNINGS_CONTRACT`.
|
|
31
32
|
- `why` — the causal claim (why the rule holds).
|
|
32
33
|
- `provenance` — stable refs behind the candidate: the originating task id(s), plus any PR/issue/commit refs the task recorded. At most 20 entries. This is also where scope markers live (below).
|
|
@@ -47,9 +48,9 @@ LEARNINGS_FILE=$(node -e 'import("@codyswann/lisa/learnings").then(async m => {
|
|
|
47
48
|
For each candidate entry:
|
|
48
49
|
|
|
49
50
|
1. **Consolidation check (mandatory before writing).** Parse existing entries with `parseLearningsFile` from `@codyswann/lisa/learnings` and look for a related entry — same failure class, overlapping topic, or near-duplicate wording.
|
|
50
|
-
- **Related entry found** → consolidate, do not sibling.
|
|
51
|
+
- **Related entry found** → consolidate, do not sibling. Copy each target's exact parsed version stamp and write via `persistConsolidatedLearning(projectRoot, entry, { supersede: [{ id: <related id>, fingerprint: <related fingerprint> }], onStaleSupersede: targets => report(targets) })`, merging the still-true content of the superseded entry into the new rule and keeping the earliest `first_learned`. Stamps are checked together inside the lock: if any is stale, the writer removes none, safely appends the new fingerprint, and reports the mismatch. A near-duplicate sibling is a bug, not an entry.
|
|
51
52
|
- **No related entry** → append via `persistLearningEntry(projectRoot, entry)`.
|
|
52
|
-
- **Already present (same
|
|
53
|
+
- **Already present (same fingerprint)** → the writer throws on a duplicate fingerprint before mutation; treat that as a dropped-duplicate no-op and record it as such. Re-running over the same tasks leaves the ledger unchanged.
|
|
53
54
|
2. The writer re-asserts the entry and document budgets. An over-budget failure means consolidate harder or drop — never truncate by hand.
|
|
54
55
|
|
|
55
56
|
Persistence rides the implement flow's normal branch/PR: the code change and its learnings land in the same PR (satisfying "every persistence is a PR" with no new machinery). Never commit the ledger straight to the default branch and never hand-edit it.
|
|
@@ -75,7 +76,7 @@ One row per collected learning, mapping it to its terminal disposition:
|
|
|
75
76
|
- **Capture-only.** Create no skills, append to no human-authored rules file, file no issue anywhere — take no promotion decision of any kind. Every promotion (skill, eager rule, executable control, upstream ticket) is the gardener's ticket-gated job, and the ledger is your only output surface.
|
|
76
77
|
- **One write path.** The ledger changes only through `persistLearningEntry` / `persistConsolidatedLearning` from `@codyswann/lisa/learnings`, inside a PR. Never hand-edit the file.
|
|
77
78
|
- **Consolidate, never sibling.** A related existing entry is merged or superseded at write time (SLL-6 discipline), never duplicated.
|
|
78
|
-
- **Idempotent.** Deduplicate before persisting;
|
|
79
|
+
- **Idempotent.** Deduplicate before persisting; the deterministic fingerprint and stamped consolidation guarantee re-runs over the same tasks leave the ledger unchanged.
|
|
79
80
|
- **Headless-safe.** No interactive prompts; runs identically under an intake cron.
|
|
80
81
|
- **Never block the build.** If persistence fails, report the failure and let the primary flow continue — shipping the work outranks recording a learning about it.
|
|
81
82
|
- **No learning loops about learning.** Gardener tickets and learning PRs are not themselves learnings; never capture them.
|