@codyswann/lisa 2.351.0 → 2.353.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-overwrite/scripts/lisa-hooks/block-instruction-file-edits.sh +1 -1
- package/all/copy-overwrite/scripts/lisa-hooks/block-shell-json-parsing.sh +1 -1
- package/all/create-only/.agents/rules/README.md +45 -0
- package/dist/cli/doctor-lisa-owned-artifacts.d.ts +18 -0
- package/dist/cli/doctor-lisa-owned-artifacts.d.ts.map +1 -0
- package/dist/cli/doctor-lisa-owned-artifacts.js +129 -0
- package/dist/cli/doctor-lisa-owned-artifacts.js.map +1 -0
- package/dist/cli/doctor.d.ts.map +1 -1
- package/dist/cli/doctor.js +2 -0
- package/dist/cli/doctor.js.map +1 -1
- package/dist/codex/scripts/_extract-edit-paths.sh +1 -1
- package/dist/codex/scripts/format-on-edit.sh +1 -1
- package/dist/codex/scripts/lint-on-edit.sh +1 -1
- package/dist/codex/scripts/rubocop-on-edit.sh +1 -1
- package/dist/codex/scripts/sg-scan-on-edit.sh +1 -1
- package/dist/configs/eslint/cdk.js +2 -2
- package/dist/configs/eslint/cdk.js.map +1 -1
- package/dist/configs/eslint/nestjs.js +2 -2
- package/dist/configs/eslint/nestjs.js.map +1 -1
- package/dist/configs/eslint/typescript.js +2 -2
- package/dist/configs/eslint/typescript.js.map +1 -1
- package/dist/core/host-rules-pointer.d.ts +33 -0
- package/dist/core/host-rules-pointer.d.ts.map +1 -0
- package/dist/core/host-rules-pointer.js +115 -0
- package/dist/core/host-rules-pointer.js.map +1 -0
- package/dist/core/instruction-files-migration.d.ts +3 -2
- package/dist/core/instruction-files-migration.d.ts.map +1 -1
- package/dist/core/instruction-files-migration.js +62 -64
- package/dist/core/instruction-files-migration.js.map +1 -1
- package/dist/core/learnings.d.ts +1 -1
- package/dist/core/learnings.d.ts.map +1 -1
- package/dist/core/learnings.js +1 -1
- package/dist/core/learnings.js.map +1 -1
- package/dist/core/lisa-owned-templates.d.ts +34 -0
- package/dist/core/lisa-owned-templates.d.ts.map +1 -0
- package/dist/core/lisa-owned-templates.js +41 -0
- package/dist/core/lisa-owned-templates.js.map +1 -0
- package/dist/core/lisa.d.ts.map +1 -1
- package/dist/core/lisa.js +5 -1
- package/dist/core/lisa.js.map +1 -1
- package/dist/core/project-config.d.ts +39 -9
- package/dist/core/project-config.d.ts.map +1 -1
- package/dist/core/project-config.js +37 -10
- package/dist/core/project-config.js.map +1 -1
- package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
- package/dist/core/upstream-evidence-manifest.js +42 -26
- package/dist/core/upstream-evidence-manifest.js.map +1 -1
- package/dist/opencode/plugin-templates/lisa-block-instruction-file-edits.ts +1 -1
- package/dist/strategies/copy-overwrite.d.ts +13 -6
- package/dist/strategies/copy-overwrite.d.ts.map +1 -1
- package/dist/strategies/copy-overwrite.js +16 -7
- package/dist/strategies/copy-overwrite.js.map +1 -1
- package/dist/sync/registry.d.ts.map +1 -1
- package/dist/sync/registry.js +0 -6
- package/dist/sync/registry.js.map +1 -1
- package/expo/create-only/.github/workflows/maestro-e2e.yml +10 -1
- package/expo/create-only/.github/workflows/nightly-e2e-health.yml +5 -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-debrief/SKILL.md +1 -1
- package/plugins/lisa/.codex-plugin/skills/lisa-debrief-apply/SKILL.md +3 -3
- package/plugins/lisa/.codex-plugin/skills/lisa-doctor/SKILL.md +4 -1
- package/plugins/lisa/.codex-plugin/skills/lisa-improve-harness/SKILL.md +2 -2
- package/plugins/lisa/.codex-plugin/skills/lisa-learnings-audit/SKILL.md +6 -3
- package/plugins/lisa/.codex-plugin/skills/lisa-linear-access/SKILL.md +34 -0
- package/plugins/lisa/.codex-plugin/skills/lisa-validate-tracker-mapping/SKILL.md +33 -4
- package/plugins/lisa/agents/learnings-synthesizer.md +1 -1
- package/plugins/lisa/agents/skill-evaluator.md +1 -1
- package/plugins/lisa/hooks/block-instruction-file-edits.sh +1 -1
- package/plugins/lisa/hooks/block-shell-json-parsing.sh +1 -1
- package/plugins/lisa/rules/eager/config-resolution.md +6 -3
- package/plugins/lisa/rules/eager/project-learnings.md +3 -2
- package/plugins/lisa/rules/reference/config-resolution.md +17 -2
- package/plugins/lisa/rules/reference/intent-routing.md +1 -1
- package/plugins/lisa/rules/reference/project-learnings.md +6 -4
- package/plugins/lisa/rules/reference/promotion-contract.md +2 -1
- package/plugins/lisa/scripts/queue-contract-resolution.mjs +50 -1
- package/plugins/lisa/skills/lisa-debrief/SKILL.md +1 -1
- package/plugins/lisa/skills/lisa-debrief-apply/SKILL.md +3 -3
- package/plugins/lisa/skills/lisa-doctor/SKILL.md +4 -1
- package/plugins/lisa/skills/lisa-improve-harness/SKILL.md +2 -2
- package/plugins/lisa/skills/lisa-learnings-audit/SKILL.md +6 -3
- package/plugins/lisa/skills/lisa-linear-access/SKILL.md +34 -0
- package/plugins/lisa/skills/lisa-validate-tracker-mapping/SKILL.md +33 -4
- package/plugins/lisa-agy/agents/learnings-synthesizer.md +1 -1
- package/plugins/lisa-agy/agents/skill-evaluator.md +1 -1
- package/plugins/lisa-agy/hooks/block-instruction-file-edits.sh +1 -1
- package/plugins/lisa-agy/hooks/block-shell-json-parsing.sh +1 -1
- package/plugins/lisa-agy/plugin.json +1 -1
- package/plugins/lisa-agy/scripts/queue-contract-resolution.mjs +50 -1
- package/plugins/lisa-agy/skills/lisa-debrief/SKILL.md +1 -1
- package/plugins/lisa-agy/skills/lisa-debrief-apply/SKILL.md +3 -3
- package/plugins/lisa-agy/skills/lisa-doctor/SKILL.md +4 -1
- package/plugins/lisa-agy/skills/lisa-improve-harness/SKILL.md +2 -2
- package/plugins/lisa-agy/skills/lisa-learnings-audit/SKILL.md +6 -3
- package/plugins/lisa-agy/skills/lisa-linear-access/SKILL.md +34 -0
- package/plugins/lisa-agy/skills/lisa-validate-tracker-mapping/SKILL.md +33 -4
- 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/learnings-synthesizer.agent.md +1 -1
- package/plugins/lisa-copilot/agents/skill-evaluator.agent.md +1 -1
- package/plugins/lisa-copilot/hooks/block-instruction-file-edits.sh +1 -1
- package/plugins/lisa-copilot/hooks/block-shell-json-parsing.sh +1 -1
- package/plugins/lisa-copilot/rules/eager/config-resolution.md +6 -3
- package/plugins/lisa-copilot/rules/eager/project-learnings.md +3 -2
- package/plugins/lisa-copilot/rules/reference/config-resolution.md +17 -2
- package/plugins/lisa-copilot/rules/reference/intent-routing.md +1 -1
- package/plugins/lisa-copilot/rules/reference/project-learnings.md +6 -4
- package/plugins/lisa-copilot/rules/reference/promotion-contract.md +2 -1
- package/plugins/lisa-copilot/scripts/queue-contract-resolution.mjs +50 -1
- package/plugins/lisa-copilot/skills/lisa-debrief/SKILL.md +1 -1
- package/plugins/lisa-copilot/skills/lisa-debrief-apply/SKILL.md +3 -3
- package/plugins/lisa-copilot/skills/lisa-doctor/SKILL.md +4 -1
- package/plugins/lisa-copilot/skills/lisa-improve-harness/SKILL.md +2 -2
- package/plugins/lisa-copilot/skills/lisa-learnings-audit/SKILL.md +6 -3
- package/plugins/lisa-copilot/skills/lisa-linear-access/SKILL.md +34 -0
- package/plugins/lisa-copilot/skills/lisa-validate-tracker-mapping/SKILL.md +33 -4
- package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cursor/agents/learnings-synthesizer.md +1 -1
- package/plugins/lisa-cursor/agents/skill-evaluator.md +1 -1
- package/plugins/lisa-cursor/hooks/block-instruction-file-edits.sh +1 -1
- package/plugins/lisa-cursor/hooks/block-shell-json-parsing.sh +1 -1
- package/plugins/lisa-cursor/rules/config-resolution-reference.mdc +17 -2
- package/plugins/lisa-cursor/rules/config-resolution.mdc +6 -3
- package/plugins/lisa-cursor/rules/intent-routing-reference.mdc +1 -1
- package/plugins/lisa-cursor/rules/project-learnings-reference.mdc +6 -4
- package/plugins/lisa-cursor/rules/project-learnings.mdc +3 -2
- package/plugins/lisa-cursor/rules/promotion-contract-reference.mdc +2 -1
- package/plugins/lisa-cursor/scripts/queue-contract-resolution.mjs +50 -1
- package/plugins/lisa-cursor/skills/lisa-debrief/SKILL.md +1 -1
- package/plugins/lisa-cursor/skills/lisa-debrief-apply/SKILL.md +3 -3
- package/plugins/lisa-cursor/skills/lisa-doctor/SKILL.md +4 -1
- package/plugins/lisa-cursor/skills/lisa-improve-harness/SKILL.md +2 -2
- package/plugins/lisa-cursor/skills/lisa-learnings-audit/SKILL.md +6 -3
- package/plugins/lisa-cursor/skills/lisa-linear-access/SKILL.md +34 -0
- package/plugins/lisa-cursor/skills/lisa-validate-tracker-mapping/SKILL.md +33 -4
- 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/hooks/block-suppress-directives.sh +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-copilot/hooks/block-suppress-directives.sh +1 -1
- package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript-cursor/hooks/block-suppress-directives.sh +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/learnings-synthesizer.md +1 -1
- package/plugins/src/base/agents/skill-evaluator.md +1 -1
- package/plugins/src/base/hooks/block-instruction-file-edits.sh +1 -1
- package/plugins/src/base/hooks/block-shell-json-parsing.sh +1 -1
- package/plugins/src/base/rules/eager/config-resolution.md +6 -3
- package/plugins/src/base/rules/eager/project-learnings.md +3 -2
- package/plugins/src/base/rules/reference/config-resolution.md +17 -2
- package/plugins/src/base/rules/reference/intent-routing.md +1 -1
- package/plugins/src/base/rules/reference/project-learnings.md +6 -4
- package/plugins/src/base/rules/reference/promotion-contract.md +2 -1
- package/plugins/src/base/scripts/queue-contract-resolution.mjs +50 -1
- package/plugins/src/base/skills/lisa-debrief/SKILL.md +1 -1
- package/plugins/src/base/skills/lisa-debrief-apply/SKILL.md +3 -3
- package/plugins/src/base/skills/lisa-doctor/SKILL.md +4 -1
- package/plugins/src/base/skills/lisa-improve-harness/SKILL.md +2 -2
- package/plugins/src/base/skills/lisa-learnings-audit/SKILL.md +6 -3
- package/plugins/src/base/skills/lisa-linear-access/SKILL.md +34 -0
- package/plugins/src/base/skills/lisa-validate-tracker-mapping/SKILL.md +33 -4
- package/plugins/src/typescript/hooks/block-suppress-directives.sh +1 -1
- package/typescript/copy-overwrite/scripts/check-nightly-e2e-health.mjs +76 -10
- package/all/create-only/.claude/rules/PROJECT_RULES.md +0 -17
|
@@ -34,7 +34,7 @@ Each persisted entry has seven fields:
|
|
|
34
34
|
|
|
35
35
|
- The **learner agent** at capture time appends or consolidates new entries
|
|
36
36
|
(`persistLearningEntry` / `persistConsolidatedLearning`) from task learnings.
|
|
37
|
-
It is capture-only: it never appends to
|
|
37
|
+
It is capture-only: it never appends to host rules, creates skills, or
|
|
38
38
|
files upstream issues — promotion is the gardener's ticket-gated job.
|
|
39
39
|
- **`lisa-debrief-apply`** routes accepted debrief findings in the three
|
|
40
40
|
knowledge categories — recurring gotcha, process friction, convention drift —
|
|
@@ -42,7 +42,8 @@ Each persisted entry has seven fields:
|
|
|
42
42
|
`persistConsolidatedLearning`, with consolidation-at-write), provenance drawn
|
|
43
43
|
from the triage row's evidence links and a `high` starting confidence because
|
|
44
44
|
a human Accept is corroboration. It no longer writes to machine-local memory,
|
|
45
|
-
|
|
45
|
+
the host-rules directory `.agents/rules/` (or a surviving legacy
|
|
46
|
+
`PROJECT_RULES.md`), or `AGENTS.md` (the human-authored source of truth, of
|
|
46
47
|
which `CLAUDE.md` is only a `@AGENTS.md` pointer) for these categories.
|
|
47
48
|
- The **build-intake flows** advance `last_confirmed` at claim time
|
|
48
49
|
(`confirmLearningEntry`, below).
|
|
@@ -77,9 +78,10 @@ warning, apply no entry, and do not block unrelated work.
|
|
|
77
78
|
Precedence:
|
|
78
79
|
|
|
79
80
|
1. System, developer, user, and repo instructions still outrank learnings.
|
|
80
|
-
2. Committed
|
|
81
|
+
2. Committed host rules (`.agents/rules/`) remain durable human-authored
|
|
82
|
+
guidance.
|
|
81
83
|
3. Project learnings add recent operational knowledge, but never rewrite or
|
|
82
|
-
append to
|
|
84
|
+
append to host rules.
|
|
83
85
|
|
|
84
86
|
## Task telemetry (MLD) is not context
|
|
85
87
|
|
|
@@ -121,6 +121,7 @@ and lets reviewers diff against a single source of truth.
|
|
|
121
121
|
- **The gardener** (`lisa-learnings-audit`): embeds the AC template above into
|
|
122
122
|
EXECUTABLE-CONTROL promotion tickets and applies the eager-tier admission
|
|
123
123
|
policy when auditing.
|
|
124
|
-
- **
|
|
124
|
+
- **Host-rules owners** (`.agents/rules/`, plus any surviving legacy
|
|
125
|
+
`PROJECT_RULES.md`): that surface is human-authored only; machine
|
|
125
126
|
writes go to the learnings ledger, and promotions out of it arrive as
|
|
126
127
|
gardener tickets governed by this contract.
|
|
@@ -32,6 +32,24 @@ const DEFAULT_LINEAR_BUILD_DONE = {
|
|
|
32
32
|
production: "Done",
|
|
33
33
|
};
|
|
34
34
|
|
|
35
|
+
// The state names a stock Linear team creates brand-new Issues into. `ready`
|
|
36
|
+
// must name a lane a human moves an Issue INTO, so it may never be one of
|
|
37
|
+
// these: the claimable lane would stop meaning "a human flipped this to
|
|
38
|
+
// build-ready" and start meaning "nobody has touched this", and build-intake
|
|
39
|
+
// would dispatch work nobody approved.
|
|
40
|
+
//
|
|
41
|
+
// This list is a STATIC backstop for the stock names, which is the case that
|
|
42
|
+
// actually bit us. It cannot see a team that renamed its default — only the
|
|
43
|
+
// live `Team.defaultIssueState` can, which is why `/lisa:validate-tracker-mapping`
|
|
44
|
+
// carries the authoritative arm (`INVERTED`) and this one carries the arm that
|
|
45
|
+
// needs no network and therefore always runs.
|
|
46
|
+
const LINEAR_STOCK_DEFAULT_CREATED_STATES = [
|
|
47
|
+
"todo",
|
|
48
|
+
"to do",
|
|
49
|
+
"backlog",
|
|
50
|
+
"triage",
|
|
51
|
+
];
|
|
52
|
+
|
|
35
53
|
const DEFAULT_GITHUB_LINEAR_PRD_ROLES = {
|
|
36
54
|
draft: "prd-draft",
|
|
37
55
|
ready: "prd-ready",
|
|
@@ -272,6 +290,35 @@ export function resolvePrdLifecycleRoles(
|
|
|
272
290
|
}
|
|
273
291
|
}
|
|
274
292
|
|
|
293
|
+
/**
|
|
294
|
+
* Reject a Linear `ready` override that names a state a stock team creates
|
|
295
|
+
* brand-new Issues into.
|
|
296
|
+
*
|
|
297
|
+
* Failing loudly is the safe direction. An operator staring at a hard error has
|
|
298
|
+
* a broken queue; an operator with a silently inverted gate has agents shipping
|
|
299
|
+
* work no human approved, which is the failure mode that produced this guard.
|
|
300
|
+
*
|
|
301
|
+
* @param {string} configured The resolved `linear.workflow.ready` name.
|
|
302
|
+
* @returns {string} The same name, once it is proven not to be a default lane.
|
|
303
|
+
* @throws {Error} When the name is a stock default created state.
|
|
304
|
+
*/
|
|
305
|
+
function assertLinearReadyIsNotDefaultState(configured) {
|
|
306
|
+
const normalized = configured.trim().toLowerCase();
|
|
307
|
+
|
|
308
|
+
if (!LINEAR_STOCK_DEFAULT_CREATED_STATES.includes(normalized)) {
|
|
309
|
+
return configured;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
throw new Error(
|
|
313
|
+
`linear.workflow.ready is set to "${configured.trim()}", which is where Linear puts a ` +
|
|
314
|
+
"brand-new Issue. That inverts the build-ready gate: the claimable lane would mean " +
|
|
315
|
+
'"nobody has touched this" instead of "a human marked this ready", so intake would ' +
|
|
316
|
+
"claim untouched backlog items. Point linear.workflow.ready at a dedicated state a " +
|
|
317
|
+
"human moves Issues into (the default is `Ready`), then re-run /lisa:setup:linear to " +
|
|
318
|
+
"create it if the team does not have one."
|
|
319
|
+
);
|
|
320
|
+
}
|
|
321
|
+
|
|
275
322
|
/**
|
|
276
323
|
* Resolve the build lifecycle roles for the configured tracker vendor.
|
|
277
324
|
*
|
|
@@ -307,7 +354,9 @@ export function resolveBuildLifecycleRoles(
|
|
|
307
354
|
vendor: "linear",
|
|
308
355
|
kind: "workflow",
|
|
309
356
|
roles: {
|
|
310
|
-
ready:
|
|
357
|
+
ready: assertLinearReadyIsNotDefaultState(
|
|
358
|
+
config.linear?.workflow?.ready || "Ready"
|
|
359
|
+
),
|
|
311
360
|
claimed: config.linear?.workflow?.claimed || "In Progress",
|
|
312
361
|
review: config.linear?.workflow?.review || "In Review",
|
|
313
362
|
blocked: config.linear?.workflow?.blocked || "Blocked",
|
|
@@ -72,7 +72,7 @@ A markdown triage document at `./debrief/<initiative-slug>-<YYYY-MM-DD>.md` (or
|
|
|
72
72
|
- `Summary` — one sentence
|
|
73
73
|
- `Category`
|
|
74
74
|
- `Evidence` — links to the source ticket comment / PR comment / commit / test file (multiple allowed)
|
|
75
|
-
- `Recommended persistence destination` — the agent's best guess for where this should land if accepted (e.g., "Edge Case Brainstorm checklist → Navigation & URL state", "learnings ledger via the executable contract", "new tooling-gap ticket", "upstream Lisa issue"). Never name machine-local auto-memory,
|
|
75
|
+
- `Recommended persistence destination` — the agent's best guess for where this should land if accepted (e.g., "Edge Case Brainstorm checklist → Navigation & URL state", "learnings ledger via the executable contract", "new tooling-gap ticket", "upstream Lisa issue"). Never name machine-local auto-memory, the host-rules directory `.agents/rules/`, or `AGENTS.md` — those are not persistence destinations.
|
|
76
76
|
- `Disposition` — empty checkbox-style field the human will fill: `[ ] Accept` / `[ ] Reject` / `[ ] Defer` plus a free-text reason
|
|
77
77
|
4. **Source map** — appendix listing every work item and PR walked, so the human can verify completeness.
|
|
78
78
|
|
|
@@ -18,7 +18,7 @@ A path or URL to a Debrief triage document produced by `lisa-debrief`. The docum
|
|
|
18
18
|
|
|
19
19
|
1. **Verify the doc exists and parses.** If the file cannot be read or the expected sections are missing, stop and report — do not guess.
|
|
20
20
|
2. **Confirm dispositions exist.** If every row is unmarked, stop and ask the human to triage first. A pristine doc is a no-op, not an error to silently swallow.
|
|
21
|
-
3. **Identify the destination map.** Read the project's `.lisa.config.json` (or stack defaults) for: edge-case checklist file (default: `plugins/src/base/rules/intent-routing.md`'s Edge Case Brainstorm sub-flow), the committed learnings ledger path (resolve it — never hardcode — via `resolveProjectLearningsFile` from `@codyswann/lisa/learnings`: the `learnings.file` override, else the default `.lisa/PROJECT_LEARNINGS.md`), tracker for new tickets. The three knowledge categories (recurring gotcha, process friction, convention drift) all land in the ledger now; machine-local auto-memory and
|
|
21
|
+
3. **Identify the destination map.** Read the project's `.lisa.config.json` (or stack defaults) for: edge-case checklist file (default: `plugins/src/base/rules/intent-routing.md`'s Edge Case Brainstorm sub-flow), the committed learnings ledger path (resolve it — never hardcode — via `resolveProjectLearningsFile` from `@codyswann/lisa/learnings`: the `learnings.file` override, else the default `.lisa/PROJECT_LEARNINGS.md`), tracker for new tickets. The three knowledge categories (recurring gotcha, process friction, convention drift) all land in the ledger now; machine-local auto-memory and host rules (`.agents/rules/`) / `AGENTS.md` are no longer knowledge destinations (see [Ledger persistence](#ledger-persistence-knowledge-categories)).
|
|
22
22
|
|
|
23
23
|
## Routing rules
|
|
24
24
|
|
|
@@ -61,13 +61,13 @@ For each such Accepted row:
|
|
|
61
61
|
- `first_learned` = `last_confirmed` = today (ISO date; on consolidation keep the superseded entry's earliest `first_learned`).
|
|
62
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
63
|
|
|
64
|
-
**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
|
|
64
|
+
**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
65
|
|
|
66
66
|
## Idempotency
|
|
67
67
|
|
|
68
68
|
`apply` is safe to re-run. Each Accepted row carries an evidence link that doubles as a fingerprint. Before writing, check whether the destination already cites that fingerprint:
|
|
69
69
|
|
|
70
|
-
- **Knowledge categories (gotcha, friction, drift) → ledger.** Parse the ledger once with `parseLearningsFile` from `@codyswann/lisa/learnings` and scan the entries' `provenance` for the row's evidence link. If any entry's provenance already contains it, the row is already persisted — skip the write. This replaces the old scattered-file greps (memory files,
|
|
70
|
+
- **Knowledge categories (gotcha, friction, drift) → ledger.** Parse the ledger once with `parseLearningsFile` from `@codyswann/lisa/learnings` and scan the entries' `provenance` for the row's evidence link. If any entry's provenance already contains it, the row is already persisted — skip the write. This replaces the old scattered-file greps (memory files, host rules, `AGENTS.md`): provenance in the single governed ledger is now the one fingerprint surface.
|
|
71
71
|
- **Other categories** keep their existing destination check (the tracker for the ticket marker, the PRD for the defect comment, `intent-routing.md` for the edge-case citation).
|
|
72
72
|
|
|
73
73
|
If the fingerprint is already present, skip the write and note the row as `already-applied` in the run summary. This lets the human triage a doc incrementally (mark a few, run apply, mark more, run apply again) without producing duplicates.
|
|
@@ -56,7 +56,10 @@ as applicable to the current repo:
|
|
|
56
56
|
and `source` only. If a required CLI, MCP surface, or auth context is unavailable in the current
|
|
57
57
|
runtime, report that explicitly instead of pretending the repo is ready.
|
|
58
58
|
4. **Runtime distribution surfaces** — confirm the command, skill, hook, and related distribution
|
|
59
|
-
surfaces relevant to this repo are present where Lisa expects them on the active runtime
|
|
59
|
+
surfaces relevant to this repo are present where Lisa expects them on the active runtime, and
|
|
60
|
+
that the Lisa-owned enforcement artifacts (`scripts/lisa-hooks/*`,
|
|
61
|
+
`scripts/lisa-enforcement-fallback.sh`) match the installed Lisa version rather than an older
|
|
62
|
+
copy. Present-but-stale is a finding: a guard whose fix never landed enforces the old behavior.
|
|
60
63
|
5. **Automation readiness** — inspect whether the configured queue source/tracker and scheduling
|
|
61
64
|
prerequisites are observable, but do **not** create, edit, or delete automations during doctor.
|
|
62
65
|
6. **Optional GitHub Project coordination** — when `github.projects.v2` is configured, delegate
|
|
@@ -341,7 +341,7 @@ Any durable lesson the loop produced is **submitted** to `lisa-persist-learning`
|
|
|
341
341
|
only write path per the `project-learnings` rule) as a candidate; its hostile-default judge — not
|
|
342
342
|
this skill, and not the caller — decides the disposition. A dropped candidate is recorded in
|
|
343
343
|
`Known limits`, never reported as routed or owned. This skill never writes the learnings file,
|
|
344
|
-
|
|
344
|
+
host rules (`.agents/rules/`), or `CLAUDE.md` itself, and never promotes a learning to a higher rung (that
|
|
345
345
|
is the gardener's ticket-gated job).
|
|
346
346
|
|
|
347
347
|
## Idempotency
|
|
@@ -483,5 +483,5 @@ its face, because a single-trajectory loop always has limits.
|
|
|
483
483
|
- **Bounded claims.** One trajectory supports one trajectory's claim. No comparative,
|
|
484
484
|
longitudinal, or population claims; `Known limits` is never empty.
|
|
485
485
|
- **One write path for learnings.** Durable lessons are submitted to `lisa-persist-learning` for
|
|
486
|
-
judgment; this skill never edits the learnings ledger
|
|
486
|
+
judgment; this skill never edits the learnings ledger or any rules tree (host `.agents/rules/` included),
|
|
487
487
|
and never promotes a learning to a higher rung.
|
|
@@ -49,9 +49,12 @@ memorized list:
|
|
|
49
49
|
— stronger than an omission count, because room was not merely tight, a real
|
|
50
50
|
capture was turned away. Drain it every run (see The audit cycle).
|
|
51
51
|
3. **Rules trees** — the plugin `rules/eager/` + `rules/reference/` pairs AND
|
|
52
|
-
the host project's `.
|
|
53
|
-
|
|
54
|
-
|
|
52
|
+
the host project's canonical host-rules directory `.agents/rules/`, plus any
|
|
53
|
+
retired-but-surviving single-file rules the project still carries
|
|
54
|
+
(`.claude/rules/PROJECT_RULES.md`, or a legacy `projectRulesFile` path).
|
|
55
|
+
All of it is human-authored only — the gardener proposes, it never rewrites —
|
|
56
|
+
and its existing sections are still audit candidates; first-run candidates
|
|
57
|
+
come from exactly there.
|
|
55
58
|
4. **Skills** — `.claude/skills/` and the plugin skill roots the runtime
|
|
56
59
|
exposes (descriptions are eager context; bodies load on invoke).
|
|
57
60
|
5. **The wiki index** — `wiki/index.md` when the project has a wiki.
|
|
@@ -106,6 +106,40 @@ linear_graphql() {
|
|
|
106
106
|
Map operation names to Linear GraphQL queries/mutations in this access skill.
|
|
107
107
|
Consumers pass business-shaped arguments only; they do not embed GraphQL.
|
|
108
108
|
|
|
109
|
+
## `list-workflow-states` — the team's states, and which one it creates into
|
|
110
|
+
|
|
111
|
+
`list-workflow-states team:<ID>` returns one node per state with `id`, `name`,
|
|
112
|
+
`type`, `position`, and **`isTeamDefault`**.
|
|
113
|
+
|
|
114
|
+
`isTeamDefault` is `true` for the single state named by the team's
|
|
115
|
+
`defaultIssueState` — where Linear puts every brand-new Issue. Callers need it to
|
|
116
|
+
enforce the rule that `linear.workflow.ready` must be a lane a human moves an
|
|
117
|
+
Issue **into**: pointing `ready` at the default inverts the gate, so the
|
|
118
|
+
claimable lane means "nobody has touched this" rather than "a human marked this
|
|
119
|
+
ready", and build-intake dispatches unapproved work. `/lisa:setup:linear` refuses
|
|
120
|
+
to resolve `ready` onto it, and `/lisa:validate-tracker-mapping` classifies a
|
|
121
|
+
config that already does as `INVERTED`.
|
|
122
|
+
|
|
123
|
+
It belongs on this operation rather than in a separate `get-team` call because
|
|
124
|
+
every caller that needs it is already enumerating states, and a second round trip
|
|
125
|
+
is a second chance for the two answers to disagree. A team with no
|
|
126
|
+
`defaultIssueState` set yields `isTeamDefault: false` on every node — report that
|
|
127
|
+
honestly; do not fall back to guessing by name or position.
|
|
128
|
+
|
|
129
|
+
```graphql
|
|
130
|
+
query($teamId:String!){
|
|
131
|
+
team(id:$teamId){
|
|
132
|
+
defaultIssueState{ id }
|
|
133
|
+
states(first:100){ nodes{ id name type position } }
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
Set `isTeamDefault` per node by comparing `node.id` against
|
|
139
|
+
`team.defaultIssueState.id`. On the MCP substrate, which exposes states without
|
|
140
|
+
the team's default, resolve the default through the team record and join on `id`
|
|
141
|
+
the same way.
|
|
142
|
+
|
|
109
143
|
## `history` — transition history (read-only)
|
|
110
144
|
|
|
111
145
|
`history id:<ID>` returns an Issue's ordered past state changes — the raw
|
|
@@ -71,7 +71,8 @@ Resolve the **effective** role → name mapping using the same defaults `/lisa:i
|
|
|
71
71
|
- **Missing / empty tracker**: report `UNRESOLVABLE` with setup guidance (`/lisa:setup:jira`, `/lisa:setup:github`, or `/lisa:setup:linear`). Do not default to JIRA.
|
|
72
72
|
- **JIRA build workflow** (`jira.workflow`): `ready`, `claimed`, optional `review`, `blocked`, and each `done.<env>` (`dev` / `staging` / `production`). Defaults: `Ready`, `In Progress`, `Code Review`, `Blocked`, `{dev: "On Dev", staging: "On Stg", production: "Done"}`.
|
|
73
73
|
- **GitHub build/prd labels** (`github.labels.build`, `github.labels.prd`): each configured label string.
|
|
74
|
-
- **Linear build
|
|
74
|
+
- **Linear build workflow** (`linear.workflow`): `ready`, `claimed`, `review`, `blocked`, and each `done.<env>` — native workflow **states**, the Linear analogue of `jira.workflow`, not of `github.labels`. Defaults: `Ready`, `In Progress`, `In Review`, `Blocked`, `{dev: "On Dev", staging: "On Stg", production: "Done"}`.
|
|
75
|
+
- **Linear labels** (`linear.labels`): the `prd.*` map plus the one surviving build-lane key, the `human_needed` marker (`linear.labels.build.human_needed`). A config that predates the state model may still carry `ready` / `claimed` / `blocked` / `done` under `linear.labels.build`; those are **inert** — nothing reads them. Do not audit them against the live label set, and do not report them as drift. Report them once as a migration note pointing at `/lisa:setup:linear`, which removes them.
|
|
75
76
|
- **Notion PRD values** (`notion.values`): each configured select-option value, validated against the `notion.statusProperty` property's options.
|
|
76
77
|
- **Confluence PRD parents** (`confluence.parents`): each configured parent page id, validated by existence.
|
|
77
78
|
|
|
@@ -103,7 +104,9 @@ gh label list --repo "$REPO" --limit 200 --json name -q '.[].name'
|
|
|
103
104
|
|
|
104
105
|
### Linear / Notion / Confluence
|
|
105
106
|
|
|
106
|
-
Enumerate via the corresponding access surface (
|
|
107
|
+
Enumerate via the corresponding access surface (`lisa-linear-access` workflow states + labels; Notion data-source select options for `notion.statusProperty`; Confluence page-exists check per parent id). Same compare-exact-case contract as JIRA.
|
|
108
|
+
|
|
109
|
+
For Linear, `lisa-linear-access operation: list-workflow-states` returns each state's `name`, `type`, `position` and `isTeamDefault` (the access layer sets it from the team's `defaultIssueState`). **Keep `isTeamDefault`** — Step 4 needs it, and it is the only authoritative answer to "which state does this team create Issues into". Do not approximate it with a name guess: `Todo` is merely the stock name, and a team that renamed its `defaultIssueState` is exactly the case a name guess misses.
|
|
107
110
|
|
|
108
111
|
## Step 4 — Compare (exact case)
|
|
109
112
|
|
|
@@ -113,10 +116,14 @@ For each `(role, configured-name)` pair, classify against the live name set:
|
|
|
113
116
|
- **CASE_DRIFT** — a case-insensitive match exists but no exact-case match (e.g. config `"On Stg"` vs live `"ON STG"`). Canonical = the live exact name.
|
|
114
117
|
- **MISSING** — no case-insensitive match exists. The name was renamed beyond recognition or deleted.
|
|
115
118
|
|
|
119
|
+
One role carries a further check that name-existence cannot express:
|
|
120
|
+
|
|
121
|
+
- **INVERTED** — Linear only, `ready` only: the configured state exists, but it is the team's **default created state** (`isTeamDefault`). This is worse than a name that does not resolve. The name resolves perfectly, so every existence check passes while the gate runs backwards: `ready` is supposed to mean "a human moved this Issue here", and the team's default means "nobody has touched this". Build-intake claims from that lane, so an INVERTED mapping dispatches work no human ever approved. Measured on the first team it hit: 20 Issues in the claimable lane, 12 never marked ready — including decision tickets shaped like leaves, which the leaf-only gate cannot catch either. Report it even when every other role is VALID.
|
|
122
|
+
|
|
116
123
|
A project's verdict:
|
|
117
124
|
|
|
118
125
|
- **VALID** — every role is VALID.
|
|
119
|
-
- **DRIFTED** — at least one CASE_DRIFT or
|
|
126
|
+
- **DRIFTED** — at least one CASE_DRIFT, MISSING, or INVERTED role, none of which is UNRESOLVABLE. An INVERTED `ready` is never VALID, no matter how cleanly it resolves.
|
|
120
127
|
- **UNRESOLVABLE** — the live set couldn't be enumerated (auth mismatch, missing tracker config, access failure). Distinguish this loudly from VALID — an unresolved audit is not a passing audit.
|
|
121
128
|
|
|
122
129
|
## Step 5 — Report
|
|
@@ -134,7 +141,17 @@ Per project, print a terminal-first section:
|
|
|
134
141
|
done.production Done Done VALID
|
|
135
142
|
```
|
|
136
143
|
|
|
137
|
-
|
|
144
|
+
An INVERTED `ready` gets a full line rather than a one-word status, because the operator reading it is not necessarily an engineer and the word alone does not convey the stakes:
|
|
145
|
+
|
|
146
|
+
```
|
|
147
|
+
ready Todo Todo INVERTED
|
|
148
|
+
"Todo" is the state this Linear team puts every NEW issue into, so the
|
|
149
|
+
build queue is currently claiming issues nobody marked ready. Pick or
|
|
150
|
+
create a state a person moves an issue into (Lisa's default is "Ready")
|
|
151
|
+
via /lisa:setup:linear, then set linear.workflow.ready to it.
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
End with a roll-up: counts of VALID / DRIFTED / UNRESOLVABLE projects and the exact next command (`… repair=true` when drift is auto-repairable; an admin note when a status is genuinely MISSING; `/lisa:setup:linear` when a `ready` is INVERTED).
|
|
138
155
|
|
|
139
156
|
## Step 6 — Repair (only when `repair=true`)
|
|
140
157
|
|
|
@@ -166,6 +183,18 @@ Compute the closest live candidates (case-insensitive token/substring overlap, t
|
|
|
166
183
|
|
|
167
184
|
Only write on an explicit pick. Never auto-select. If the user leaves it unchanged, keep the project `DRIFTED` and surface the admin remediation (add the status back, or fix it in the tracker).
|
|
168
185
|
|
|
186
|
+
### INVERTED — never auto-repair
|
|
187
|
+
|
|
188
|
+
**Never auto-repair an INVERTED `ready`, even with `repair=true`.** Every other classification has one correct answer that the live tracker already knows: CASE_DRIFT has the canonical casing, MISSING has a shortlist of near-matches. INVERTED has neither. The configured name is live and correctly cased; what is wrong is which lane the project chose to mean "build-ready", and nothing in the config or the tracker records what the human intended instead. Guessing would silently repoint the queue at a lane that may hold nothing, or worse, at another lane the team fills automatically — swapping one wrong answer for a quieter one.
|
|
189
|
+
|
|
190
|
+
The team may also genuinely not have a dedicated ready lane yet, in which case the repair is to **create a state**, not to rewrite a string — `/lisa:validate-tracker-mapping` audits config, it does not mutate the tracker.
|
|
191
|
+
|
|
192
|
+
So: present the team's non-default states via `AskUserQuestion`, and write `linear.workflow.ready` only on an explicit pick. If none fits, or the user declines, leave the config untouched, keep the project `DRIFTED`, and hand off:
|
|
193
|
+
|
|
194
|
+
> Linear has no dedicated build-ready state on this team. Run `/lisa:setup:linear` — it offers to create `Ready` and records the mapping.
|
|
195
|
+
|
|
196
|
+
Until then, say plainly that the build queue is claiming unapproved work and that pausing build intake is the safe interim.
|
|
197
|
+
|
|
169
198
|
### Invalidate the verification cache
|
|
170
199
|
|
|
171
200
|
After any JIRA repair, clear the `setup-jira` reachability cache so it re-verifies the new mapping:
|
|
@@ -44,7 +44,7 @@ Map every finding to exactly one category. When a finding could fit two, pick th
|
|
|
44
44
|
|
|
45
45
|
A finding that does not fit any of the eight is itself a signal — surface it under an additional ad-hoc category `Uncategorized` with a note explaining why no category fit. Better to surface than to drop.
|
|
46
46
|
|
|
47
|
-
The destination column is a **hint for the human triaging the row**, not the routing decision: `lisa-debrief-apply` routes on the category, never on this column. Keep the hint honest anyway — a human decides Accept/Reject partly on where the learning will land. The three knowledge categories (recurring gotcha, process friction, convention drift) all land in the committed learnings ledger through the executable contract. Machine-local auto-memory (`project_*.md`, `MEMORY.md`),
|
|
47
|
+
The destination column is a **hint for the human triaging the row**, not the routing decision: `lisa-debrief-apply` routes on the category, never on this column. Keep the hint honest anyway — a human decides Accept/Reject partly on where the learning will land. The three knowledge categories (recurring gotcha, process friction, convention drift) all land in the committed learnings ledger through the executable contract. Machine-local auto-memory (`project_*.md`, `MEMORY.md`), the host-rules directory `.agents/rules/`, and `AGENTS.md` (whose `CLAUDE.md` is only a `@AGENTS.md` pointer) are **never** destinations — the first is invisible to cloud runs and teammates, and the latter two are human-authored surfaces that agents do not write.
|
|
48
48
|
|
|
49
49
|
## Dedupe rules
|
|
50
50
|
|
|
@@ -18,7 +18,7 @@ Rungs are ordered by context cost and enforcement strength. Decision vocabulary:
|
|
|
18
18
|
| Rung | Recommendation | Destination | Enters context | Admission policy |
|
|
19
19
|
| --- | --- | --- | --- | --- |
|
|
20
20
|
| 6 | EXECUTABLE-CONTROL | Lint / ast-grep / type / test / hook / `package.lisa.json` force | Never — diagnostic fires on violation | Mechanically decidable + stable + recurred |
|
|
21
|
-
| 5 | EAGER-RULE |
|
|
21
|
+
| 5 | EAGER-RULE | Host rules: `.agents/rules/` (project scope) · plugin `rules/eager/` (upstream scope) | Unconditionally, every session | **Earned by failure evidence** (repeated misses despite retrievability); demotion-biased |
|
|
22
22
|
| 4 | SKILL | `.claude/skills/<name>/SKILL.md` | Description eager; body on invoke | Procedural, complex, recognizable trigger |
|
|
23
23
|
| 3 | WIKI | Wiki page + index entry | Only when routed to | Durable reference knowledge |
|
|
24
24
|
| 2 | KEEP-IN-LEDGER | `PROJECT_LEARNINGS.md` (bounded contract projection) | Bounded projection only | Default landing zone; probationary, expiring |
|
|
@@ -117,7 +117,7 @@ WHERE IT GOES INSTEAD — take the first one that fits:
|
|
|
117
117
|
That is a project rule — but do not write it yourself. Capture it with
|
|
118
118
|
\`/lisa:persist-learning\` so it lands in the learnings ledger with provenance
|
|
119
119
|
and a confidence score. The gardener (\`/lisa:learnings:audit\`) then proposes
|
|
120
|
-
promotion into \`.
|
|
120
|
+
promotion into the host-rules directory \`.agents/rules/\` as a human-gated ticket.
|
|
121
121
|
|
|
122
122
|
2. It changes how an existing skill should behave. Edit that skill's SKILL.md.
|
|
123
123
|
Knowledge belongs next to the procedure it modifies, not in a global preamble.
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
# Text tools (grep/sed/cut/awk) break on valid JSON — multiline values, escaped
|
|
4
4
|
# quotes, reordered keys, nested objects — producing silently wrong output
|
|
5
5
|
# instead of errors. jq is the required tool for structural JSON reads and
|
|
6
|
-
# writes in shell. Promoted from
|
|
6
|
+
# writes in shell. Promoted from host-rules prose to an executable
|
|
7
7
|
# control by the learnings gardener (issue #1787).
|
|
8
8
|
#
|
|
9
9
|
# Precision-first: this hook fires only on high-confidence STRUCTURAL parsing
|
|
@@ -32,6 +32,24 @@ const DEFAULT_LINEAR_BUILD_DONE = {
|
|
|
32
32
|
production: "Done",
|
|
33
33
|
};
|
|
34
34
|
|
|
35
|
+
// The state names a stock Linear team creates brand-new Issues into. `ready`
|
|
36
|
+
// must name a lane a human moves an Issue INTO, so it may never be one of
|
|
37
|
+
// these: the claimable lane would stop meaning "a human flipped this to
|
|
38
|
+
// build-ready" and start meaning "nobody has touched this", and build-intake
|
|
39
|
+
// would dispatch work nobody approved.
|
|
40
|
+
//
|
|
41
|
+
// This list is a STATIC backstop for the stock names, which is the case that
|
|
42
|
+
// actually bit us. It cannot see a team that renamed its default — only the
|
|
43
|
+
// live `Team.defaultIssueState` can, which is why `/lisa:validate-tracker-mapping`
|
|
44
|
+
// carries the authoritative arm (`INVERTED`) and this one carries the arm that
|
|
45
|
+
// needs no network and therefore always runs.
|
|
46
|
+
const LINEAR_STOCK_DEFAULT_CREATED_STATES = [
|
|
47
|
+
"todo",
|
|
48
|
+
"to do",
|
|
49
|
+
"backlog",
|
|
50
|
+
"triage",
|
|
51
|
+
];
|
|
52
|
+
|
|
35
53
|
const DEFAULT_GITHUB_LINEAR_PRD_ROLES = {
|
|
36
54
|
draft: "prd-draft",
|
|
37
55
|
ready: "prd-ready",
|
|
@@ -272,6 +290,35 @@ export function resolvePrdLifecycleRoles(
|
|
|
272
290
|
}
|
|
273
291
|
}
|
|
274
292
|
|
|
293
|
+
/**
|
|
294
|
+
* Reject a Linear `ready` override that names a state a stock team creates
|
|
295
|
+
* brand-new Issues into.
|
|
296
|
+
*
|
|
297
|
+
* Failing loudly is the safe direction. An operator staring at a hard error has
|
|
298
|
+
* a broken queue; an operator with a silently inverted gate has agents shipping
|
|
299
|
+
* work no human approved, which is the failure mode that produced this guard.
|
|
300
|
+
*
|
|
301
|
+
* @param {string} configured The resolved `linear.workflow.ready` name.
|
|
302
|
+
* @returns {string} The same name, once it is proven not to be a default lane.
|
|
303
|
+
* @throws {Error} When the name is a stock default created state.
|
|
304
|
+
*/
|
|
305
|
+
function assertLinearReadyIsNotDefaultState(configured) {
|
|
306
|
+
const normalized = configured.trim().toLowerCase();
|
|
307
|
+
|
|
308
|
+
if (!LINEAR_STOCK_DEFAULT_CREATED_STATES.includes(normalized)) {
|
|
309
|
+
return configured;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
throw new Error(
|
|
313
|
+
`linear.workflow.ready is set to "${configured.trim()}", which is where Linear puts a ` +
|
|
314
|
+
"brand-new Issue. That inverts the build-ready gate: the claimable lane would mean " +
|
|
315
|
+
'"nobody has touched this" instead of "a human marked this ready", so intake would ' +
|
|
316
|
+
"claim untouched backlog items. Point linear.workflow.ready at a dedicated state a " +
|
|
317
|
+
"human moves Issues into (the default is `Ready`), then re-run /lisa:setup:linear to " +
|
|
318
|
+
"create it if the team does not have one."
|
|
319
|
+
);
|
|
320
|
+
}
|
|
321
|
+
|
|
275
322
|
/**
|
|
276
323
|
* Resolve the build lifecycle roles for the configured tracker vendor.
|
|
277
324
|
*
|
|
@@ -307,7 +354,9 @@ export function resolveBuildLifecycleRoles(
|
|
|
307
354
|
vendor: "linear",
|
|
308
355
|
kind: "workflow",
|
|
309
356
|
roles: {
|
|
310
|
-
ready:
|
|
357
|
+
ready: assertLinearReadyIsNotDefaultState(
|
|
358
|
+
config.linear?.workflow?.ready || "Ready"
|
|
359
|
+
),
|
|
311
360
|
claimed: config.linear?.workflow?.claimed || "In Progress",
|
|
312
361
|
review: config.linear?.workflow?.review || "In Review",
|
|
313
362
|
blocked: config.linear?.workflow?.blocked || "Blocked",
|
|
@@ -72,7 +72,7 @@ A markdown triage document at `./debrief/<initiative-slug>-<YYYY-MM-DD>.md` (or
|
|
|
72
72
|
- `Summary` — one sentence
|
|
73
73
|
- `Category`
|
|
74
74
|
- `Evidence` — links to the source ticket comment / PR comment / commit / test file (multiple allowed)
|
|
75
|
-
- `Recommended persistence destination` — the agent's best guess for where this should land if accepted (e.g., "Edge Case Brainstorm checklist → Navigation & URL state", "learnings ledger via the executable contract", "new tooling-gap ticket", "upstream Lisa issue"). Never name machine-local auto-memory,
|
|
75
|
+
- `Recommended persistence destination` — the agent's best guess for where this should land if accepted (e.g., "Edge Case Brainstorm checklist → Navigation & URL state", "learnings ledger via the executable contract", "new tooling-gap ticket", "upstream Lisa issue"). Never name machine-local auto-memory, the host-rules directory `.agents/rules/`, or `AGENTS.md` — those are not persistence destinations.
|
|
76
76
|
- `Disposition` — empty checkbox-style field the human will fill: `[ ] Accept` / `[ ] Reject` / `[ ] Defer` plus a free-text reason
|
|
77
77
|
4. **Source map** — appendix listing every work item and PR walked, so the human can verify completeness.
|
|
78
78
|
|
|
@@ -18,7 +18,7 @@ A path or URL to a Debrief triage document produced by `lisa-debrief`. The docum
|
|
|
18
18
|
|
|
19
19
|
1. **Verify the doc exists and parses.** If the file cannot be read or the expected sections are missing, stop and report — do not guess.
|
|
20
20
|
2. **Confirm dispositions exist.** If every row is unmarked, stop and ask the human to triage first. A pristine doc is a no-op, not an error to silently swallow.
|
|
21
|
-
3. **Identify the destination map.** Read the project's `.lisa.config.json` (or stack defaults) for: edge-case checklist file (default: `plugins/src/base/rules/intent-routing.md`'s Edge Case Brainstorm sub-flow), the committed learnings ledger path (resolve it — never hardcode — via `resolveProjectLearningsFile` from `@codyswann/lisa/learnings`: the `learnings.file` override, else the default `.lisa/PROJECT_LEARNINGS.md`), tracker for new tickets. The three knowledge categories (recurring gotcha, process friction, convention drift) all land in the ledger now; machine-local auto-memory and
|
|
21
|
+
3. **Identify the destination map.** Read the project's `.lisa.config.json` (or stack defaults) for: edge-case checklist file (default: `plugins/src/base/rules/intent-routing.md`'s Edge Case Brainstorm sub-flow), the committed learnings ledger path (resolve it — never hardcode — via `resolveProjectLearningsFile` from `@codyswann/lisa/learnings`: the `learnings.file` override, else the default `.lisa/PROJECT_LEARNINGS.md`), tracker for new tickets. The three knowledge categories (recurring gotcha, process friction, convention drift) all land in the ledger now; machine-local auto-memory and host rules (`.agents/rules/`) / `AGENTS.md` are no longer knowledge destinations (see [Ledger persistence](#ledger-persistence-knowledge-categories)).
|
|
22
22
|
|
|
23
23
|
## Routing rules
|
|
24
24
|
|
|
@@ -61,13 +61,13 @@ For each such Accepted row:
|
|
|
61
61
|
- `first_learned` = `last_confirmed` = today (ISO date; on consolidation keep the superseded entry's earliest `first_learned`).
|
|
62
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
63
|
|
|
64
|
-
**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
|
|
64
|
+
**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
65
|
|
|
66
66
|
## Idempotency
|
|
67
67
|
|
|
68
68
|
`apply` is safe to re-run. Each Accepted row carries an evidence link that doubles as a fingerprint. Before writing, check whether the destination already cites that fingerprint:
|
|
69
69
|
|
|
70
|
-
- **Knowledge categories (gotcha, friction, drift) → ledger.** Parse the ledger once with `parseLearningsFile` from `@codyswann/lisa/learnings` and scan the entries' `provenance` for the row's evidence link. If any entry's provenance already contains it, the row is already persisted — skip the write. This replaces the old scattered-file greps (memory files,
|
|
70
|
+
- **Knowledge categories (gotcha, friction, drift) → ledger.** Parse the ledger once with `parseLearningsFile` from `@codyswann/lisa/learnings` and scan the entries' `provenance` for the row's evidence link. If any entry's provenance already contains it, the row is already persisted — skip the write. This replaces the old scattered-file greps (memory files, host rules, `AGENTS.md`): provenance in the single governed ledger is now the one fingerprint surface.
|
|
71
71
|
- **Other categories** keep their existing destination check (the tracker for the ticket marker, the PRD for the defect comment, `intent-routing.md` for the edge-case citation).
|
|
72
72
|
|
|
73
73
|
If the fingerprint is already present, skip the write and note the row as `already-applied` in the run summary. This lets the human triage a doc incrementally (mark a few, run apply, mark more, run apply again) without producing duplicates.
|
|
@@ -56,7 +56,10 @@ as applicable to the current repo:
|
|
|
56
56
|
and `source` only. If a required CLI, MCP surface, or auth context is unavailable in the current
|
|
57
57
|
runtime, report that explicitly instead of pretending the repo is ready.
|
|
58
58
|
4. **Runtime distribution surfaces** — confirm the command, skill, hook, and related distribution
|
|
59
|
-
surfaces relevant to this repo are present where Lisa expects them on the active runtime
|
|
59
|
+
surfaces relevant to this repo are present where Lisa expects them on the active runtime, and
|
|
60
|
+
that the Lisa-owned enforcement artifacts (`scripts/lisa-hooks/*`,
|
|
61
|
+
`scripts/lisa-enforcement-fallback.sh`) match the installed Lisa version rather than an older
|
|
62
|
+
copy. Present-but-stale is a finding: a guard whose fix never landed enforces the old behavior.
|
|
60
63
|
5. **Automation readiness** — inspect whether the configured queue source/tracker and scheduling
|
|
61
64
|
prerequisites are observable, but do **not** create, edit, or delete automations during doctor.
|
|
62
65
|
6. **Optional GitHub Project coordination** — when `github.projects.v2` is configured, delegate
|
|
@@ -341,7 +341,7 @@ Any durable lesson the loop produced is **submitted** to `lisa-persist-learning`
|
|
|
341
341
|
only write path per the `project-learnings` rule) as a candidate; its hostile-default judge — not
|
|
342
342
|
this skill, and not the caller — decides the disposition. A dropped candidate is recorded in
|
|
343
343
|
`Known limits`, never reported as routed or owned. This skill never writes the learnings file,
|
|
344
|
-
|
|
344
|
+
host rules (`.agents/rules/`), or `CLAUDE.md` itself, and never promotes a learning to a higher rung (that
|
|
345
345
|
is the gardener's ticket-gated job).
|
|
346
346
|
|
|
347
347
|
## Idempotency
|
|
@@ -483,5 +483,5 @@ its face, because a single-trajectory loop always has limits.
|
|
|
483
483
|
- **Bounded claims.** One trajectory supports one trajectory's claim. No comparative,
|
|
484
484
|
longitudinal, or population claims; `Known limits` is never empty.
|
|
485
485
|
- **One write path for learnings.** Durable lessons are submitted to `lisa-persist-learning` for
|
|
486
|
-
judgment; this skill never edits the learnings ledger
|
|
486
|
+
judgment; this skill never edits the learnings ledger or any rules tree (host `.agents/rules/` included),
|
|
487
487
|
and never promotes a learning to a higher rung.
|
|
@@ -49,9 +49,12 @@ memorized list:
|
|
|
49
49
|
— stronger than an omission count, because room was not merely tight, a real
|
|
50
50
|
capture was turned away. Drain it every run (see The audit cycle).
|
|
51
51
|
3. **Rules trees** — the plugin `rules/eager/` + `rules/reference/` pairs AND
|
|
52
|
-
the host project's `.
|
|
53
|
-
|
|
54
|
-
|
|
52
|
+
the host project's canonical host-rules directory `.agents/rules/`, plus any
|
|
53
|
+
retired-but-surviving single-file rules the project still carries
|
|
54
|
+
(`.claude/rules/PROJECT_RULES.md`, or a legacy `projectRulesFile` path).
|
|
55
|
+
All of it is human-authored only — the gardener proposes, it never rewrites —
|
|
56
|
+
and its existing sections are still audit candidates; first-run candidates
|
|
57
|
+
come from exactly there.
|
|
55
58
|
4. **Skills** — `.claude/skills/` and the plugin skill roots the runtime
|
|
56
59
|
exposes (descriptions are eager context; bodies load on invoke).
|
|
57
60
|
5. **The wiki index** — `wiki/index.md` when the project has a wiki.
|
|
@@ -106,6 +106,40 @@ linear_graphql() {
|
|
|
106
106
|
Map operation names to Linear GraphQL queries/mutations in this access skill.
|
|
107
107
|
Consumers pass business-shaped arguments only; they do not embed GraphQL.
|
|
108
108
|
|
|
109
|
+
## `list-workflow-states` — the team's states, and which one it creates into
|
|
110
|
+
|
|
111
|
+
`list-workflow-states team:<ID>` returns one node per state with `id`, `name`,
|
|
112
|
+
`type`, `position`, and **`isTeamDefault`**.
|
|
113
|
+
|
|
114
|
+
`isTeamDefault` is `true` for the single state named by the team's
|
|
115
|
+
`defaultIssueState` — where Linear puts every brand-new Issue. Callers need it to
|
|
116
|
+
enforce the rule that `linear.workflow.ready` must be a lane a human moves an
|
|
117
|
+
Issue **into**: pointing `ready` at the default inverts the gate, so the
|
|
118
|
+
claimable lane means "nobody has touched this" rather than "a human marked this
|
|
119
|
+
ready", and build-intake dispatches unapproved work. `/lisa:setup:linear` refuses
|
|
120
|
+
to resolve `ready` onto it, and `/lisa:validate-tracker-mapping` classifies a
|
|
121
|
+
config that already does as `INVERTED`.
|
|
122
|
+
|
|
123
|
+
It belongs on this operation rather than in a separate `get-team` call because
|
|
124
|
+
every caller that needs it is already enumerating states, and a second round trip
|
|
125
|
+
is a second chance for the two answers to disagree. A team with no
|
|
126
|
+
`defaultIssueState` set yields `isTeamDefault: false` on every node — report that
|
|
127
|
+
honestly; do not fall back to guessing by name or position.
|
|
128
|
+
|
|
129
|
+
```graphql
|
|
130
|
+
query($teamId:String!){
|
|
131
|
+
team(id:$teamId){
|
|
132
|
+
defaultIssueState{ id }
|
|
133
|
+
states(first:100){ nodes{ id name type position } }
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
Set `isTeamDefault` per node by comparing `node.id` against
|
|
139
|
+
`team.defaultIssueState.id`. On the MCP substrate, which exposes states without
|
|
140
|
+
the team's default, resolve the default through the team record and join on `id`
|
|
141
|
+
the same way.
|
|
142
|
+
|
|
109
143
|
## `history` — transition history (read-only)
|
|
110
144
|
|
|
111
145
|
`history id:<ID>` returns an Issue's ordered past state changes — the raw
|