@codyswann/lisa 2.244.0 → 2.245.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/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-implement/SKILL.md +2 -2
- package/plugins/lisa/agents/learner.md +61 -29
- package/plugins/lisa/rules/reference/project-learnings.md +19 -0
- package/plugins/lisa/skills/lisa-implement/SKILL.md +2 -2
- package/plugins/lisa-agy/agents/learner.md +61 -29
- package/plugins/lisa-agy/plugin.json +1 -1
- package/plugins/lisa-agy/skills/lisa-implement/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 +61 -29
- package/plugins/lisa-copilot/rules/reference/project-learnings.md +19 -0
- package/plugins/lisa-copilot/skills/lisa-implement/SKILL.md +2 -2
- package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cursor/agents/learner.md +61 -29
- package/plugins/lisa-cursor/rules/project-learnings-reference.mdc +19 -0
- package/plugins/lisa-cursor/skills/lisa-implement/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 +61 -29
- package/plugins/src/base/rules/reference/project-learnings.md +19 -0
- package/plugins/src/base/skills/lisa-implement/SKILL.md +2 -2
package/package.json
CHANGED
|
@@ -102,7 +102,7 @@
|
|
|
102
102
|
"form-data": ">=4.0.6"
|
|
103
103
|
},
|
|
104
104
|
"name": "@codyswann/lisa",
|
|
105
|
-
"version": "2.
|
|
105
|
+
"version": "2.245.0",
|
|
106
106
|
"description": "Claude Code governance framework that applies guardrails, guidance, and automated enforcement to projects",
|
|
107
107
|
"main": "dist/index.js",
|
|
108
108
|
"exports": {
|
|
@@ -70,7 +70,7 @@ Do not spawn a teammate whose agent type is not included in the recorded Roster
|
|
|
70
70
|
When deciding the agents to use, consider:
|
|
71
71
|
* Before any task is implemented, the agent team must explore the codebase for relevant research (documentation, code, git history, etc) and update each task's `metadata.relevant_documentation` with the findings.
|
|
72
72
|
* Each task must be reviewed by the team to make sure their verification passes.
|
|
73
|
-
* Each task must have their learnings
|
|
73
|
+
* Each task must have their learnings captured to the ledger by the learner subagent.
|
|
74
74
|
|
|
75
75
|
Using the general-purpose agent in Team Lead session, Determine the name of this plan
|
|
76
76
|
|
|
@@ -183,7 +183,7 @@ Each task must be reviewed by the team to make sure their verification passes.
|
|
|
183
183
|
|
|
184
184
|
Before marking a task complete, the implementing agent records concise MLD into `metadata.learnings` — mistakes (errors in its own trajectory), learnings (environment facts it discovered the hard way), and desires (context or tools it wished it had). Empty (`learnings: []`) is a valid result: never re-prompt for content, and never grade or score self-reports — a scored MLD would reward plausible self-commentary over good outcomes.
|
|
185
185
|
|
|
186
|
-
Each task must have their learnings
|
|
186
|
+
Each task must have their learnings captured to the ledger by the learner subagent.
|
|
187
187
|
|
|
188
188
|
Before shutting down the team, execute the Verify flow:
|
|
189
189
|
|
|
@@ -1,50 +1,82 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: learner
|
|
3
|
-
description: Post-implementation learning agent.
|
|
3
|
+
description: Post-implementation learning agent. Capture-only — collects task learnings, builds seven-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
|
|
7
7
|
|
|
8
|
-
You run the "learn" phase after implementation.
|
|
8
|
+
You run the "learn" phase after implementation. You are **capture-only**: your entire job is to move durable task learnings into the machine-managed ledger (`PROJECT_LEARNINGS.md`) with provenance, deduplicated and consolidated. You take **no promotion decisions** — no skills, no rule appends, no upstream issues. Every promotion of a learning to a higher rung (skill, eager rule, executable control, upstream ticket) is the gardener's job (work stream 6 of PRD #1729), gated by a human flipping a tracker ticket to `status:ready`. The ledger is the single front door; you are its writer.
|
|
9
|
+
|
|
10
|
+
Why this shape: promotion without a human gate lets agents unilaterally rewrite their own standing instructions. Automated learnings live **only** in the ledger — a separate, budgeted, contract-mediated document — never in any human-authored rules file. Capture is idempotent — the same learning from the same task never produces two entries.
|
|
9
11
|
|
|
10
12
|
## Workflow
|
|
11
13
|
|
|
12
|
-
### Step 1: Collect Learnings
|
|
14
|
+
### Step 1: Collect and Dedupe Learnings
|
|
15
|
+
|
|
16
|
+
1. Read all tasks using `TaskList` and `TaskGet`.
|
|
17
|
+
2. For each completed task, read `metadata.learnings`.
|
|
18
|
+
3. Honor the MLD kind-tags (documented by #1732): each learning may be tagged `mistake`, `learning`, or `desire`. A **plain string remains valid** and is treated as `kind: learning`. A tagged item may arrive as an object of the shape `{ kind, note, evidence? }` (`note` is the learning text; `evidence` is the optional refs behind it) or as a string prefixed with its kind (e.g. `mistake: ...`); read whichever shape is present and default an untagged item to `kind: learning`.
|
|
19
|
+
- `mistake` and `learning` → candidate ledger entries (Steps 2–3).
|
|
20
|
+
- `desire` → **not** a ledger entry; routed to a tooling-gap marker (Step 3, "Desires").
|
|
21
|
+
4. Compile a **deduplicated** list — never process the same insight twice. Deduplicate on normalized rule text (lowercased, whitespace collapsed) so the same learning surfaced by two tasks collapses to one candidate that cites both tasks in its provenance.
|
|
22
|
+
|
|
23
|
+
If no learnings exist, report "No learnings to process" and complete.
|
|
24
|
+
|
|
25
|
+
### Step 2: Build the Seven-Field Entry
|
|
26
|
+
|
|
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
|
+
|
|
29
|
+
- `id` — a stable dedupe key. Use `learner-` + the first 12 hex chars of `sha1(normalized_rule)` so the same rule always yields the same id (this is what makes re-runs idempotent — the writer throws on a duplicate id).
|
|
30
|
+
- `rule` — the actionable learning, **≤ 240 characters and ≤ 2 lines** per `LEARNINGS_CONTRACT`.
|
|
31
|
+
- `why` — the causal claim (why the rule holds).
|
|
32
|
+
- `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).
|
|
33
|
+
- `first_learned` — today (ISO `YYYY-MM-DD`). On consolidation, keep the **earliest** `first_learned` of the entries being merged.
|
|
34
|
+
- `last_confirmed` — today (ISO `YYYY-MM-DD`).
|
|
35
|
+
- `confidence` — one of `low` | `medium` | `high`. Use `high` only when the failure **class** is corroborated by more than one occurrence (a prior issue/PR/revert/rejection on a different occasion). Use `medium` for a single occurrence that nonetheless carries independent corroborating evidence (a cited failure log, an external doc, or a reviewer confirmation) — stronger than a lone observation, short of a proven recurring class. Otherwise a single-occurrence learning is **`low`** — default to `low` unless corroboration is present.
|
|
13
36
|
|
|
14
|
-
|
|
15
|
-
2. For each completed task, check `metadata.learnings`
|
|
16
|
-
3. Compile a deduplicated list
|
|
37
|
+
**Upstream candidates are marked, never filed.** When a learning's root cause is a Lisa-managed surface (a Lisa skill, gate, agent, hook, or template misbehaved), the classification does not disappear — you record it for the gardener to route. Add the literal token `scope:upstream-candidate` to the entry's `provenance[]`. That marker is the documented handoff: the gardener reads it and decides how to route it (a local fix or an upstream ticket). **You never file an issue.**
|
|
17
38
|
|
|
18
|
-
### Step
|
|
39
|
+
### Step 3: Persist Through the Executable Contract
|
|
19
40
|
|
|
20
|
-
|
|
41
|
+
No learning content is ever hand-written into the markdown. The only write path is the executable Lisa learnings contract exported by `@codyswann/lisa/learnings`. Resolve the ledger path from config — never hardcode it — exactly as `lisa-persist-learning` Phase 3.2/3.3 documents:
|
|
21
42
|
|
|
22
|
-
|
|
23
|
-
-
|
|
24
|
-
|
|
25
|
-
agent, or hook mis-behaved or should have caught something and didn't. Project rules can't
|
|
26
|
-
fix the harness; file it upstream so every host project gets the fix.
|
|
27
|
-
- **OMIT** -- too narrow, already documented, or temporary. Discard.
|
|
43
|
+
```bash
|
|
44
|
+
LEARNINGS_FILE=$(node -e 'import("@codyswann/lisa/learnings").then(async m => { const c = await m.readProjectConfig(process.cwd()); console.log(m.resolveProjectLearningsFile(c)); })')
|
|
45
|
+
```
|
|
28
46
|
|
|
29
|
-
|
|
47
|
+
For each candidate entry:
|
|
30
48
|
|
|
31
|
-
|
|
32
|
-
-
|
|
33
|
-
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
49
|
+
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. Write via `persistConsolidatedLearning(projectRoot, entry, { supersede: [<related ids>] })`, merging the still-true content of the superseded entry into the new rule and keeping the earliest `first_learned`. A near-duplicate sibling is a bug, not an entry.
|
|
51
|
+
- **No related entry** → append via `persistLearningEntry(projectRoot, entry)`.
|
|
52
|
+
- **Already present (same id)** → the writer throws on a duplicate id; treat that as a dropped-duplicate no-op and record it as such. Re-running over the same tasks leaves the ledger unchanged.
|
|
53
|
+
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
|
+
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.
|
|
56
|
+
|
|
57
|
+
**Desires (`kind: desire`) — a tooling-gap candidate, never a ledger entry.** A desire is a wish for tooling that does not yet exist; it is not a durable rule about the code, so it does not belong in the ledger. Record it for the gardener by writing it back to the originating task with `TaskUpdate`, appending to `metadata.tooling_gap_candidates` (an array) an object marked with the stable marker string `lisa-tooling-gap`:
|
|
58
|
+
|
|
59
|
+
```json
|
|
60
|
+
{ "marker": "lisa-tooling-gap", "desire": "<the wished-for capability>", "why": "<what it would unblock>", "provenance": ["<task id>", "<refs>"] }
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
The `lisa-tooling-gap` marker is the documented handoff the gardener scans for. You create no issue and no ledger entry for a desire.
|
|
38
64
|
|
|
39
65
|
### Step 4: Output Summary
|
|
40
66
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
|
67
|
+
One row per collected learning, mapping it to its terminal disposition:
|
|
68
|
+
|
|
69
|
+
| Learning | Disposition |
|
|
70
|
+
|----------|-------------|
|
|
71
|
+
| [learning text] | entry `<id>` \| merged-into `<id>` \| dropped-duplicate \| desire-recorded (tooling-gap) |
|
|
44
72
|
|
|
45
73
|
## Rules
|
|
46
74
|
|
|
47
|
-
-
|
|
48
|
-
-
|
|
49
|
-
-
|
|
50
|
-
-
|
|
75
|
+
- **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
|
+
- **One write path.** The ledger changes only through `persistLearningEntry` / `persistConsolidatedLearning` from `@codyswann/lisa/learnings`, inside a PR. Never hand-edit the file.
|
|
77
|
+
- **Consolidate, never sibling.** A related existing entry is merged or superseded at write time (SLL-6 discipline), never duplicated.
|
|
78
|
+
- **Idempotent.** Deduplicate before persisting; stable ids and consolidation guarantee re-runs over the same tasks leave the ledger unchanged.
|
|
79
|
+
- **Headless-safe.** No interactive prompts; runs identically under an intake cron.
|
|
80
|
+
- **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
|
+
- **No learning loops about learning.** Gardener tickets and learning PRs are not themselves learnings; never capture them.
|
|
82
|
+
- If no learnings exist, report "No learnings to process" and complete.
|
|
@@ -27,6 +27,25 @@ Each persisted entry has seven fields:
|
|
|
27
27
|
- `last_confirmed`
|
|
28
28
|
- `confidence`
|
|
29
29
|
|
|
30
|
+
## Who writes the ledger
|
|
31
|
+
|
|
32
|
+
The ledger's contract-mediated writers — all going through the executable
|
|
33
|
+
contract (`@codyswann/lisa/learnings`), never a hand-edit — are:
|
|
34
|
+
|
|
35
|
+
- The **learner agent** at capture time appends or consolidates new entries
|
|
36
|
+
(`persistLearningEntry` / `persistConsolidatedLearning`) from task learnings.
|
|
37
|
+
It is capture-only: it never appends to `PROJECT_RULES.md`, creates skills, or
|
|
38
|
+
files upstream issues — promotion is the gardener's ticket-gated job.
|
|
39
|
+
- The **build-intake flows** advance `last_confirmed` at claim time
|
|
40
|
+
(`confirmLearningEntry`, below).
|
|
41
|
+
- **`lisa-debrief-apply`** reroutes debrief findings into the ledger once #1733
|
|
42
|
+
ships; until then it is a legacy writer outside the contract (it still routes
|
|
43
|
+
to machine-local memory and `PROJECT_RULES.md`).
|
|
44
|
+
|
|
45
|
+
Promotion to a higher rung (skill, eager rule, executable control, upstream
|
|
46
|
+
ticket) is never a writer here — it is the gardener's job, gated by a human
|
|
47
|
+
flipping a tracker ticket to `status:ready`.
|
|
48
|
+
|
|
30
49
|
## Claim-time confirmation (`last_confirmed`)
|
|
31
50
|
|
|
32
51
|
`last_confirmed` is advanced at claim time by the build-intake flows (step
|
|
@@ -70,7 +70,7 @@ Do not spawn a teammate whose agent type is not included in the recorded Roster
|
|
|
70
70
|
When deciding the agents to use, consider:
|
|
71
71
|
* Before any task is implemented, the agent team must explore the codebase for relevant research (documentation, code, git history, etc) and update each task's `metadata.relevant_documentation` with the findings.
|
|
72
72
|
* Each task must be reviewed by the team to make sure their verification passes.
|
|
73
|
-
* Each task must have their learnings
|
|
73
|
+
* Each task must have their learnings captured to the ledger by the learner subagent.
|
|
74
74
|
|
|
75
75
|
Using the general-purpose agent in Team Lead session, Determine the name of this plan
|
|
76
76
|
|
|
@@ -183,7 +183,7 @@ Each task must be reviewed by the team to make sure their verification passes.
|
|
|
183
183
|
|
|
184
184
|
Before marking a task complete, the implementing agent records concise MLD into `metadata.learnings` — mistakes (errors in its own trajectory), learnings (environment facts it discovered the hard way), and desires (context or tools it wished it had). Empty (`learnings: []`) is a valid result: never re-prompt for content, and never grade or score self-reports — a scored MLD would reward plausible self-commentary over good outcomes.
|
|
185
185
|
|
|
186
|
-
Each task must have their learnings
|
|
186
|
+
Each task must have their learnings captured to the ledger by the learner subagent.
|
|
187
187
|
|
|
188
188
|
Before shutting down the team, execute the Verify flow:
|
|
189
189
|
|
|
@@ -1,50 +1,82 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: learner
|
|
3
|
-
description: Post-implementation learning agent.
|
|
3
|
+
description: Post-implementation learning agent. Capture-only — collects task learnings, builds seven-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
|
|
7
7
|
|
|
8
|
-
You run the "learn" phase after implementation.
|
|
8
|
+
You run the "learn" phase after implementation. You are **capture-only**: your entire job is to move durable task learnings into the machine-managed ledger (`PROJECT_LEARNINGS.md`) with provenance, deduplicated and consolidated. You take **no promotion decisions** — no skills, no rule appends, no upstream issues. Every promotion of a learning to a higher rung (skill, eager rule, executable control, upstream ticket) is the gardener's job (work stream 6 of PRD #1729), gated by a human flipping a tracker ticket to `status:ready`. The ledger is the single front door; you are its writer.
|
|
9
|
+
|
|
10
|
+
Why this shape: promotion without a human gate lets agents unilaterally rewrite their own standing instructions. Automated learnings live **only** in the ledger — a separate, budgeted, contract-mediated document — never in any human-authored rules file. Capture is idempotent — the same learning from the same task never produces two entries.
|
|
9
11
|
|
|
10
12
|
## Workflow
|
|
11
13
|
|
|
12
|
-
### Step 1: Collect Learnings
|
|
14
|
+
### Step 1: Collect and Dedupe Learnings
|
|
15
|
+
|
|
16
|
+
1. Read all tasks using `TaskList` and `TaskGet`.
|
|
17
|
+
2. For each completed task, read `metadata.learnings`.
|
|
18
|
+
3. Honor the MLD kind-tags (documented by #1732): each learning may be tagged `mistake`, `learning`, or `desire`. A **plain string remains valid** and is treated as `kind: learning`. A tagged item may arrive as an object of the shape `{ kind, note, evidence? }` (`note` is the learning text; `evidence` is the optional refs behind it) or as a string prefixed with its kind (e.g. `mistake: ...`); read whichever shape is present and default an untagged item to `kind: learning`.
|
|
19
|
+
- `mistake` and `learning` → candidate ledger entries (Steps 2–3).
|
|
20
|
+
- `desire` → **not** a ledger entry; routed to a tooling-gap marker (Step 3, "Desires").
|
|
21
|
+
4. Compile a **deduplicated** list — never process the same insight twice. Deduplicate on normalized rule text (lowercased, whitespace collapsed) so the same learning surfaced by two tasks collapses to one candidate that cites both tasks in its provenance.
|
|
22
|
+
|
|
23
|
+
If no learnings exist, report "No learnings to process" and complete.
|
|
24
|
+
|
|
25
|
+
### Step 2: Build the Seven-Field Entry
|
|
26
|
+
|
|
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
|
+
|
|
29
|
+
- `id` — a stable dedupe key. Use `learner-` + the first 12 hex chars of `sha1(normalized_rule)` so the same rule always yields the same id (this is what makes re-runs idempotent — the writer throws on a duplicate id).
|
|
30
|
+
- `rule` — the actionable learning, **≤ 240 characters and ≤ 2 lines** per `LEARNINGS_CONTRACT`.
|
|
31
|
+
- `why` — the causal claim (why the rule holds).
|
|
32
|
+
- `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).
|
|
33
|
+
- `first_learned` — today (ISO `YYYY-MM-DD`). On consolidation, keep the **earliest** `first_learned` of the entries being merged.
|
|
34
|
+
- `last_confirmed` — today (ISO `YYYY-MM-DD`).
|
|
35
|
+
- `confidence` — one of `low` | `medium` | `high`. Use `high` only when the failure **class** is corroborated by more than one occurrence (a prior issue/PR/revert/rejection on a different occasion). Use `medium` for a single occurrence that nonetheless carries independent corroborating evidence (a cited failure log, an external doc, or a reviewer confirmation) — stronger than a lone observation, short of a proven recurring class. Otherwise a single-occurrence learning is **`low`** — default to `low` unless corroboration is present.
|
|
13
36
|
|
|
14
|
-
|
|
15
|
-
2. For each completed task, check `metadata.learnings`
|
|
16
|
-
3. Compile a deduplicated list
|
|
37
|
+
**Upstream candidates are marked, never filed.** When a learning's root cause is a Lisa-managed surface (a Lisa skill, gate, agent, hook, or template misbehaved), the classification does not disappear — you record it for the gardener to route. Add the literal token `scope:upstream-candidate` to the entry's `provenance[]`. That marker is the documented handoff: the gardener reads it and decides how to route it (a local fix or an upstream ticket). **You never file an issue.**
|
|
17
38
|
|
|
18
|
-
### Step
|
|
39
|
+
### Step 3: Persist Through the Executable Contract
|
|
19
40
|
|
|
20
|
-
|
|
41
|
+
No learning content is ever hand-written into the markdown. The only write path is the executable Lisa learnings contract exported by `@codyswann/lisa/learnings`. Resolve the ledger path from config — never hardcode it — exactly as `lisa-persist-learning` Phase 3.2/3.3 documents:
|
|
21
42
|
|
|
22
|
-
|
|
23
|
-
-
|
|
24
|
-
|
|
25
|
-
agent, or hook mis-behaved or should have caught something and didn't. Project rules can't
|
|
26
|
-
fix the harness; file it upstream so every host project gets the fix.
|
|
27
|
-
- **OMIT** -- too narrow, already documented, or temporary. Discard.
|
|
43
|
+
```bash
|
|
44
|
+
LEARNINGS_FILE=$(node -e 'import("@codyswann/lisa/learnings").then(async m => { const c = await m.readProjectConfig(process.cwd()); console.log(m.resolveProjectLearningsFile(c)); })')
|
|
45
|
+
```
|
|
28
46
|
|
|
29
|
-
|
|
47
|
+
For each candidate entry:
|
|
30
48
|
|
|
31
|
-
|
|
32
|
-
-
|
|
33
|
-
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
49
|
+
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. Write via `persistConsolidatedLearning(projectRoot, entry, { supersede: [<related ids>] })`, merging the still-true content of the superseded entry into the new rule and keeping the earliest `first_learned`. A near-duplicate sibling is a bug, not an entry.
|
|
51
|
+
- **No related entry** → append via `persistLearningEntry(projectRoot, entry)`.
|
|
52
|
+
- **Already present (same id)** → the writer throws on a duplicate id; treat that as a dropped-duplicate no-op and record it as such. Re-running over the same tasks leaves the ledger unchanged.
|
|
53
|
+
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
|
+
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.
|
|
56
|
+
|
|
57
|
+
**Desires (`kind: desire`) — a tooling-gap candidate, never a ledger entry.** A desire is a wish for tooling that does not yet exist; it is not a durable rule about the code, so it does not belong in the ledger. Record it for the gardener by writing it back to the originating task with `TaskUpdate`, appending to `metadata.tooling_gap_candidates` (an array) an object marked with the stable marker string `lisa-tooling-gap`:
|
|
58
|
+
|
|
59
|
+
```json
|
|
60
|
+
{ "marker": "lisa-tooling-gap", "desire": "<the wished-for capability>", "why": "<what it would unblock>", "provenance": ["<task id>", "<refs>"] }
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
The `lisa-tooling-gap` marker is the documented handoff the gardener scans for. You create no issue and no ledger entry for a desire.
|
|
38
64
|
|
|
39
65
|
### Step 4: Output Summary
|
|
40
66
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
|
67
|
+
One row per collected learning, mapping it to its terminal disposition:
|
|
68
|
+
|
|
69
|
+
| Learning | Disposition |
|
|
70
|
+
|----------|-------------|
|
|
71
|
+
| [learning text] | entry `<id>` \| merged-into `<id>` \| dropped-duplicate \| desire-recorded (tooling-gap) |
|
|
44
72
|
|
|
45
73
|
## Rules
|
|
46
74
|
|
|
47
|
-
-
|
|
48
|
-
-
|
|
49
|
-
-
|
|
50
|
-
-
|
|
75
|
+
- **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
|
+
- **One write path.** The ledger changes only through `persistLearningEntry` / `persistConsolidatedLearning` from `@codyswann/lisa/learnings`, inside a PR. Never hand-edit the file.
|
|
77
|
+
- **Consolidate, never sibling.** A related existing entry is merged or superseded at write time (SLL-6 discipline), never duplicated.
|
|
78
|
+
- **Idempotent.** Deduplicate before persisting; stable ids and consolidation guarantee re-runs over the same tasks leave the ledger unchanged.
|
|
79
|
+
- **Headless-safe.** No interactive prompts; runs identically under an intake cron.
|
|
80
|
+
- **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
|
+
- **No learning loops about learning.** Gardener tickets and learning PRs are not themselves learnings; never capture them.
|
|
82
|
+
- If no learnings exist, report "No learnings to process" and complete.
|
|
@@ -70,7 +70,7 @@ Do not spawn a teammate whose agent type is not included in the recorded Roster
|
|
|
70
70
|
When deciding the agents to use, consider:
|
|
71
71
|
* Before any task is implemented, the agent team must explore the codebase for relevant research (documentation, code, git history, etc) and update each task's `metadata.relevant_documentation` with the findings.
|
|
72
72
|
* Each task must be reviewed by the team to make sure their verification passes.
|
|
73
|
-
* Each task must have their learnings
|
|
73
|
+
* Each task must have their learnings captured to the ledger by the learner subagent.
|
|
74
74
|
|
|
75
75
|
Using the general-purpose agent in Team Lead session, Determine the name of this plan
|
|
76
76
|
|
|
@@ -183,7 +183,7 @@ Each task must be reviewed by the team to make sure their verification passes.
|
|
|
183
183
|
|
|
184
184
|
Before marking a task complete, the implementing agent records concise MLD into `metadata.learnings` — mistakes (errors in its own trajectory), learnings (environment facts it discovered the hard way), and desires (context or tools it wished it had). Empty (`learnings: []`) is a valid result: never re-prompt for content, and never grade or score self-reports — a scored MLD would reward plausible self-commentary over good outcomes.
|
|
185
185
|
|
|
186
|
-
Each task must have their learnings
|
|
186
|
+
Each task must have their learnings captured to the ledger by the learner subagent.
|
|
187
187
|
|
|
188
188
|
Before shutting down the team, execute the Verify flow:
|
|
189
189
|
|
|
@@ -1,50 +1,82 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: learner
|
|
3
|
-
description: Post-implementation learning agent.
|
|
3
|
+
description: Post-implementation learning agent. Capture-only — collects task learnings, builds seven-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
|
|
7
7
|
|
|
8
|
-
You run the "learn" phase after implementation.
|
|
8
|
+
You run the "learn" phase after implementation. You are **capture-only**: your entire job is to move durable task learnings into the machine-managed ledger (`PROJECT_LEARNINGS.md`) with provenance, deduplicated and consolidated. You take **no promotion decisions** — no skills, no rule appends, no upstream issues. Every promotion of a learning to a higher rung (skill, eager rule, executable control, upstream ticket) is the gardener's job (work stream 6 of PRD #1729), gated by a human flipping a tracker ticket to `status:ready`. The ledger is the single front door; you are its writer.
|
|
9
|
+
|
|
10
|
+
Why this shape: promotion without a human gate lets agents unilaterally rewrite their own standing instructions. Automated learnings live **only** in the ledger — a separate, budgeted, contract-mediated document — never in any human-authored rules file. Capture is idempotent — the same learning from the same task never produces two entries.
|
|
9
11
|
|
|
10
12
|
## Workflow
|
|
11
13
|
|
|
12
|
-
### Step 1: Collect Learnings
|
|
14
|
+
### Step 1: Collect and Dedupe Learnings
|
|
15
|
+
|
|
16
|
+
1. Read all tasks using `TaskList` and `TaskGet`.
|
|
17
|
+
2. For each completed task, read `metadata.learnings`.
|
|
18
|
+
3. Honor the MLD kind-tags (documented by #1732): each learning may be tagged `mistake`, `learning`, or `desire`. A **plain string remains valid** and is treated as `kind: learning`. A tagged item may arrive as an object of the shape `{ kind, note, evidence? }` (`note` is the learning text; `evidence` is the optional refs behind it) or as a string prefixed with its kind (e.g. `mistake: ...`); read whichever shape is present and default an untagged item to `kind: learning`.
|
|
19
|
+
- `mistake` and `learning` → candidate ledger entries (Steps 2–3).
|
|
20
|
+
- `desire` → **not** a ledger entry; routed to a tooling-gap marker (Step 3, "Desires").
|
|
21
|
+
4. Compile a **deduplicated** list — never process the same insight twice. Deduplicate on normalized rule text (lowercased, whitespace collapsed) so the same learning surfaced by two tasks collapses to one candidate that cites both tasks in its provenance.
|
|
22
|
+
|
|
23
|
+
If no learnings exist, report "No learnings to process" and complete.
|
|
24
|
+
|
|
25
|
+
### Step 2: Build the Seven-Field Entry
|
|
26
|
+
|
|
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
|
+
|
|
29
|
+
- `id` — a stable dedupe key. Use `learner-` + the first 12 hex chars of `sha1(normalized_rule)` so the same rule always yields the same id (this is what makes re-runs idempotent — the writer throws on a duplicate id).
|
|
30
|
+
- `rule` — the actionable learning, **≤ 240 characters and ≤ 2 lines** per `LEARNINGS_CONTRACT`.
|
|
31
|
+
- `why` — the causal claim (why the rule holds).
|
|
32
|
+
- `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).
|
|
33
|
+
- `first_learned` — today (ISO `YYYY-MM-DD`). On consolidation, keep the **earliest** `first_learned` of the entries being merged.
|
|
34
|
+
- `last_confirmed` — today (ISO `YYYY-MM-DD`).
|
|
35
|
+
- `confidence` — one of `low` | `medium` | `high`. Use `high` only when the failure **class** is corroborated by more than one occurrence (a prior issue/PR/revert/rejection on a different occasion). Use `medium` for a single occurrence that nonetheless carries independent corroborating evidence (a cited failure log, an external doc, or a reviewer confirmation) — stronger than a lone observation, short of a proven recurring class. Otherwise a single-occurrence learning is **`low`** — default to `low` unless corroboration is present.
|
|
13
36
|
|
|
14
|
-
|
|
15
|
-
2. For each completed task, check `metadata.learnings`
|
|
16
|
-
3. Compile a deduplicated list
|
|
37
|
+
**Upstream candidates are marked, never filed.** When a learning's root cause is a Lisa-managed surface (a Lisa skill, gate, agent, hook, or template misbehaved), the classification does not disappear — you record it for the gardener to route. Add the literal token `scope:upstream-candidate` to the entry's `provenance[]`. That marker is the documented handoff: the gardener reads it and decides how to route it (a local fix or an upstream ticket). **You never file an issue.**
|
|
17
38
|
|
|
18
|
-
### Step
|
|
39
|
+
### Step 3: Persist Through the Executable Contract
|
|
19
40
|
|
|
20
|
-
|
|
41
|
+
No learning content is ever hand-written into the markdown. The only write path is the executable Lisa learnings contract exported by `@codyswann/lisa/learnings`. Resolve the ledger path from config — never hardcode it — exactly as `lisa-persist-learning` Phase 3.2/3.3 documents:
|
|
21
42
|
|
|
22
|
-
|
|
23
|
-
-
|
|
24
|
-
|
|
25
|
-
agent, or hook mis-behaved or should have caught something and didn't. Project rules can't
|
|
26
|
-
fix the harness; file it upstream so every host project gets the fix.
|
|
27
|
-
- **OMIT** -- too narrow, already documented, or temporary. Discard.
|
|
43
|
+
```bash
|
|
44
|
+
LEARNINGS_FILE=$(node -e 'import("@codyswann/lisa/learnings").then(async m => { const c = await m.readProjectConfig(process.cwd()); console.log(m.resolveProjectLearningsFile(c)); })')
|
|
45
|
+
```
|
|
28
46
|
|
|
29
|
-
|
|
47
|
+
For each candidate entry:
|
|
30
48
|
|
|
31
|
-
|
|
32
|
-
-
|
|
33
|
-
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
49
|
+
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. Write via `persistConsolidatedLearning(projectRoot, entry, { supersede: [<related ids>] })`, merging the still-true content of the superseded entry into the new rule and keeping the earliest `first_learned`. A near-duplicate sibling is a bug, not an entry.
|
|
51
|
+
- **No related entry** → append via `persistLearningEntry(projectRoot, entry)`.
|
|
52
|
+
- **Already present (same id)** → the writer throws on a duplicate id; treat that as a dropped-duplicate no-op and record it as such. Re-running over the same tasks leaves the ledger unchanged.
|
|
53
|
+
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
|
+
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.
|
|
56
|
+
|
|
57
|
+
**Desires (`kind: desire`) — a tooling-gap candidate, never a ledger entry.** A desire is a wish for tooling that does not yet exist; it is not a durable rule about the code, so it does not belong in the ledger. Record it for the gardener by writing it back to the originating task with `TaskUpdate`, appending to `metadata.tooling_gap_candidates` (an array) an object marked with the stable marker string `lisa-tooling-gap`:
|
|
58
|
+
|
|
59
|
+
```json
|
|
60
|
+
{ "marker": "lisa-tooling-gap", "desire": "<the wished-for capability>", "why": "<what it would unblock>", "provenance": ["<task id>", "<refs>"] }
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
The `lisa-tooling-gap` marker is the documented handoff the gardener scans for. You create no issue and no ledger entry for a desire.
|
|
38
64
|
|
|
39
65
|
### Step 4: Output Summary
|
|
40
66
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
|
67
|
+
One row per collected learning, mapping it to its terminal disposition:
|
|
68
|
+
|
|
69
|
+
| Learning | Disposition |
|
|
70
|
+
|----------|-------------|
|
|
71
|
+
| [learning text] | entry `<id>` \| merged-into `<id>` \| dropped-duplicate \| desire-recorded (tooling-gap) |
|
|
44
72
|
|
|
45
73
|
## Rules
|
|
46
74
|
|
|
47
|
-
-
|
|
48
|
-
-
|
|
49
|
-
-
|
|
50
|
-
-
|
|
75
|
+
- **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
|
+
- **One write path.** The ledger changes only through `persistLearningEntry` / `persistConsolidatedLearning` from `@codyswann/lisa/learnings`, inside a PR. Never hand-edit the file.
|
|
77
|
+
- **Consolidate, never sibling.** A related existing entry is merged or superseded at write time (SLL-6 discipline), never duplicated.
|
|
78
|
+
- **Idempotent.** Deduplicate before persisting; stable ids and consolidation guarantee re-runs over the same tasks leave the ledger unchanged.
|
|
79
|
+
- **Headless-safe.** No interactive prompts; runs identically under an intake cron.
|
|
80
|
+
- **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
|
+
- **No learning loops about learning.** Gardener tickets and learning PRs are not themselves learnings; never capture them.
|
|
82
|
+
- If no learnings exist, report "No learnings to process" and complete.
|
|
@@ -27,6 +27,25 @@ Each persisted entry has seven fields:
|
|
|
27
27
|
- `last_confirmed`
|
|
28
28
|
- `confidence`
|
|
29
29
|
|
|
30
|
+
## Who writes the ledger
|
|
31
|
+
|
|
32
|
+
The ledger's contract-mediated writers — all going through the executable
|
|
33
|
+
contract (`@codyswann/lisa/learnings`), never a hand-edit — are:
|
|
34
|
+
|
|
35
|
+
- The **learner agent** at capture time appends or consolidates new entries
|
|
36
|
+
(`persistLearningEntry` / `persistConsolidatedLearning`) from task learnings.
|
|
37
|
+
It is capture-only: it never appends to `PROJECT_RULES.md`, creates skills, or
|
|
38
|
+
files upstream issues — promotion is the gardener's ticket-gated job.
|
|
39
|
+
- The **build-intake flows** advance `last_confirmed` at claim time
|
|
40
|
+
(`confirmLearningEntry`, below).
|
|
41
|
+
- **`lisa-debrief-apply`** reroutes debrief findings into the ledger once #1733
|
|
42
|
+
ships; until then it is a legacy writer outside the contract (it still routes
|
|
43
|
+
to machine-local memory and `PROJECT_RULES.md`).
|
|
44
|
+
|
|
45
|
+
Promotion to a higher rung (skill, eager rule, executable control, upstream
|
|
46
|
+
ticket) is never a writer here — it is the gardener's job, gated by a human
|
|
47
|
+
flipping a tracker ticket to `status:ready`.
|
|
48
|
+
|
|
30
49
|
## Claim-time confirmation (`last_confirmed`)
|
|
31
50
|
|
|
32
51
|
`last_confirmed` is advanced at claim time by the build-intake flows (step
|
|
@@ -70,7 +70,7 @@ Do not spawn a teammate whose agent type is not included in the recorded Roster
|
|
|
70
70
|
When deciding the agents to use, consider:
|
|
71
71
|
* Before any task is implemented, the agent team must explore the codebase for relevant research (documentation, code, git history, etc) and update each task's `metadata.relevant_documentation` with the findings.
|
|
72
72
|
* Each task must be reviewed by the team to make sure their verification passes.
|
|
73
|
-
* Each task must have their learnings
|
|
73
|
+
* Each task must have their learnings captured to the ledger by the learner subagent.
|
|
74
74
|
|
|
75
75
|
Using the general-purpose agent in Team Lead session, Determine the name of this plan
|
|
76
76
|
|
|
@@ -183,7 +183,7 @@ Each task must be reviewed by the team to make sure their verification passes.
|
|
|
183
183
|
|
|
184
184
|
Before marking a task complete, the implementing agent records concise MLD into `metadata.learnings` — mistakes (errors in its own trajectory), learnings (environment facts it discovered the hard way), and desires (context or tools it wished it had). Empty (`learnings: []`) is a valid result: never re-prompt for content, and never grade or score self-reports — a scored MLD would reward plausible self-commentary over good outcomes.
|
|
185
185
|
|
|
186
|
-
Each task must have their learnings
|
|
186
|
+
Each task must have their learnings captured to the ledger by the learner subagent.
|
|
187
187
|
|
|
188
188
|
Before shutting down the team, execute the Verify flow:
|
|
189
189
|
|