@codyswann/lisa 2.75.1 → 2.77.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/commands/doctor.md +6 -0
- package/plugins/lisa/scripts/doctor-report.mjs +132 -0
- package/plugins/lisa/skills/doctor/SKILL.md +114 -0
- package/plugins/lisa/skills/doctor/agents/openai.yaml +4 -0
- package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo/.codex-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-nestjs/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.codex-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-rails/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/.codex-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-wiki/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
- package/plugins/src/base/commands/doctor.md +6 -0
- package/plugins/src/base/scripts/doctor-report.mjs +132 -0
- package/plugins/src/base/skills/doctor/SKILL.md +114 -0
package/package.json
CHANGED
|
@@ -82,7 +82,7 @@
|
|
|
82
82
|
"lodash": ">=4.18.1"
|
|
83
83
|
},
|
|
84
84
|
"name": "@codyswann/lisa",
|
|
85
|
-
"version": "2.
|
|
85
|
+
"version": "2.77.0",
|
|
86
86
|
"description": "Claude Code governance framework that applies guardrails, guidance, and automated enforcement to projects",
|
|
87
87
|
"main": "dist/index.js",
|
|
88
88
|
"exports": {
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Audit whether the current repository is ready to use Lisa. Runs grouped read-only readiness checks for config, runtime surfaces, tracker/source access, automation prerequisites, and optional project/wiki coordination, then reports PASS/WARN/FAIL/SKIP results plus an overall verdict."
|
|
3
|
+
argument-hint: "[--fix=false]"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Use the /lisa:doctor skill to audit whether the current repository is ready to use Lisa, report grouped PASS/WARN/FAIL/SKIP checks, and emit an overall readiness verdict. $ARGUMENTS
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Shared doctor report helpers for the base Lisa doctor surface.
|
|
4
|
+
*
|
|
5
|
+
* The first doctor milestone needs a stable grouped output contract before the
|
|
6
|
+
* repo adds real readiness probes. Keep this file dependency-free so future
|
|
7
|
+
* doctor scripts can reuse it from plugin distributions and downstream repos.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
export const DOCTOR_STATUSES = ["PASS", "WARN", "FAIL", "SKIP"];
|
|
11
|
+
export const DOCTOR_VERDICTS = ["READY", "READY_WITH_WARNINGS", "NOT_READY"];
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @typedef {"PASS" | "WARN" | "FAIL" | "SKIP"} DoctorStatus
|
|
15
|
+
* @typedef {"READY" | "READY_WITH_WARNINGS" | "NOT_READY"} DoctorVerdict
|
|
16
|
+
*
|
|
17
|
+
* @typedef {{
|
|
18
|
+
* readonly id: string
|
|
19
|
+
* readonly status: DoctorStatus
|
|
20
|
+
* readonly summary: string
|
|
21
|
+
* readonly observed?: string
|
|
22
|
+
* readonly remediation?: string
|
|
23
|
+
* }} DoctorCheck
|
|
24
|
+
*
|
|
25
|
+
* @typedef {{
|
|
26
|
+
* readonly id: string
|
|
27
|
+
* readonly title: string
|
|
28
|
+
* readonly checks: readonly DoctorCheck[]
|
|
29
|
+
* }} DoctorGroup
|
|
30
|
+
*
|
|
31
|
+
* @typedef {{
|
|
32
|
+
* readonly generatedAt?: string
|
|
33
|
+
* readonly groups: readonly DoctorGroup[]
|
|
34
|
+
* }} DoctorReportInput
|
|
35
|
+
*/
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* @param {readonly DoctorGroup[]} groups
|
|
39
|
+
* @returns {DoctorVerdict}
|
|
40
|
+
*/
|
|
41
|
+
export function computeDoctorVerdict(groups) {
|
|
42
|
+
const checks = groups.flatMap(group => group.checks);
|
|
43
|
+
if (checks.some(check => check.status === "FAIL")) {
|
|
44
|
+
return "NOT_READY";
|
|
45
|
+
}
|
|
46
|
+
if (checks.some(check => check.status === "WARN")) {
|
|
47
|
+
return "READY_WITH_WARNINGS";
|
|
48
|
+
}
|
|
49
|
+
return "READY";
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* @param {readonly DoctorGroup[]} groups
|
|
54
|
+
* @returns {Record<DoctorStatus, number>}
|
|
55
|
+
*/
|
|
56
|
+
export function countDoctorStatuses(groups) {
|
|
57
|
+
return groups
|
|
58
|
+
.flatMap(group => group.checks)
|
|
59
|
+
.reduce(
|
|
60
|
+
(counts, check) => ({
|
|
61
|
+
...counts,
|
|
62
|
+
[check.status]: counts[check.status] + 1,
|
|
63
|
+
}),
|
|
64
|
+
{ PASS: 0, WARN: 0, FAIL: 0, SKIP: 0 }
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* @param {DoctorReportInput} input
|
|
70
|
+
* @returns {{ readonly verdict: DoctorVerdict, readonly counts: Record<DoctorStatus, number>, readonly text: string }}
|
|
71
|
+
*/
|
|
72
|
+
export function renderDoctorReport(input) {
|
|
73
|
+
const groups = input.groups.map(normalizeGroup);
|
|
74
|
+
const verdict = computeDoctorVerdict(groups);
|
|
75
|
+
const counts = countDoctorStatuses(groups);
|
|
76
|
+
const lines = [
|
|
77
|
+
`Overall verdict: ${verdict}`,
|
|
78
|
+
`Counts: ${DOCTOR_STATUSES.map(status => `${counts[status]} ${status}`).join(", ")}`,
|
|
79
|
+
];
|
|
80
|
+
|
|
81
|
+
if (input.generatedAt) {
|
|
82
|
+
lines.push(`Generated at: ${input.generatedAt}`);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
for (const group of groups) {
|
|
86
|
+
lines.push("", `${group.id}. ${group.title}`);
|
|
87
|
+
if (group.checks.length === 0) {
|
|
88
|
+
lines.push("- SKIP empty-group: no checks registered yet");
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
for (const check of group.checks) {
|
|
92
|
+
lines.push(`- ${check.status} ${check.id}: ${check.summary}`);
|
|
93
|
+
if (check.observed) {
|
|
94
|
+
lines.push(` Observed: ${check.observed}`);
|
|
95
|
+
}
|
|
96
|
+
if (check.remediation) {
|
|
97
|
+
lines.push(` Remediation: ${check.remediation}`);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return {
|
|
103
|
+
verdict,
|
|
104
|
+
counts,
|
|
105
|
+
text: `${lines.join("\n")}\n`,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* @param {DoctorGroup} group
|
|
111
|
+
* @returns {DoctorGroup}
|
|
112
|
+
*/
|
|
113
|
+
function normalizeGroup(group) {
|
|
114
|
+
return {
|
|
115
|
+
...group,
|
|
116
|
+
checks: group.checks.map(normalizeCheck),
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* @param {DoctorCheck} check
|
|
122
|
+
* @returns {DoctorCheck}
|
|
123
|
+
*/
|
|
124
|
+
function normalizeCheck(check) {
|
|
125
|
+
const normalizedStatus = DOCTOR_STATUSES.includes(check.status)
|
|
126
|
+
? check.status
|
|
127
|
+
: "FAIL";
|
|
128
|
+
return {
|
|
129
|
+
...check,
|
|
130
|
+
status: normalizedStatus,
|
|
131
|
+
};
|
|
132
|
+
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: doctor
|
|
3
|
+
description: "Audit whether the current repository is ready to use Lisa. Runs grouped read-only checks across project detection, Lisa config, runtime distribution surfaces, tracker/source preflight access, automation prerequisites, optional GitHub Project coordination, and optional wiki delegation, then reports PASS/WARN/FAIL/SKIP results plus an overall readiness verdict (`READY`, `READY_WITH_WARNINGS`, or `NOT_READY`)."
|
|
4
|
+
allowed-tools: ["Skill", "Bash", "Read", "Glob", "Grep"]
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Doctor: $ARGUMENTS
|
|
8
|
+
|
|
9
|
+
Run a read-only Lisa readiness audit for the current repository.
|
|
10
|
+
|
|
11
|
+
## Purpose
|
|
12
|
+
|
|
13
|
+
`/lisa:doctor` is the deterministic answer to "is this repo actually ready to use Lisa?" It audits
|
|
14
|
+
the repository in grouped sections, reports each check as `PASS`, `WARN`, `FAIL`, or `SKIP`, and
|
|
15
|
+
emits one overall verdict: `READY`, `READY_WITH_WARNINGS`, or `NOT_READY`.
|
|
16
|
+
|
|
17
|
+
The command is repository-scoped. It validates only what can be observed from the current repo,
|
|
18
|
+
current machine, and current runtime. It does **not** create automations, labels, tracker items, or
|
|
19
|
+
other external state as part of the default audit path.
|
|
20
|
+
|
|
21
|
+
## Inputs
|
|
22
|
+
|
|
23
|
+
- Optional flags in `$ARGUMENTS` that narrow or tune read-only validation.
|
|
24
|
+
- The current repository root and its Lisa config files (`.lisa.config.json`,
|
|
25
|
+
`.lisa.config.local.json`) when present.
|
|
26
|
+
|
|
27
|
+
## Confirmation policy
|
|
28
|
+
|
|
29
|
+
Do **not** ask whether to proceed. Once invoked, run the read-only audit, print the grouped
|
|
30
|
+
results, emit the overall verdict, and stop.
|
|
31
|
+
|
|
32
|
+
Specifically forbidden:
|
|
33
|
+
|
|
34
|
+
- Previewing the number of checks and asking whether to continue.
|
|
35
|
+
- Offering "run a few checks first" or "dry-run vs real run" choices. This skill is already the
|
|
36
|
+
read-only path.
|
|
37
|
+
- Performing setup mutations just because a failing check discovered something missing.
|
|
38
|
+
|
|
39
|
+
The only legitimate reasons to stop early are:
|
|
40
|
+
|
|
41
|
+
- The current working directory cannot be resolved to a repository/root the audit can inspect.
|
|
42
|
+
- The runtime blocks all required local reads needed to even classify the repo.
|
|
43
|
+
|
|
44
|
+
## Audit contract
|
|
45
|
+
|
|
46
|
+
Doctor reports grouped checks in a stable, human-readable structure. The grouped sections include,
|
|
47
|
+
as applicable to the current repo:
|
|
48
|
+
|
|
49
|
+
1. **Project detection and runtime basics** — detect the project root, package/runtime surface, and
|
|
50
|
+
whether Lisa is installed where the repo expects it.
|
|
51
|
+
2. **Lisa config readiness** — read `.lisa.config.json` and `.lisa.config.local.json` using the
|
|
52
|
+
same local-overrides-global semantics defined by `config-resolution`; report missing required
|
|
53
|
+
keys, incompatible combinations, and committed-vs-local locality problems as findings rather
|
|
54
|
+
than mutating config.
|
|
55
|
+
3. **Tracker/source preflight** — perform read-only readiness checks for the configured `tracker`
|
|
56
|
+
and `source` only. If a required CLI, MCP surface, or auth context is unavailable in the current
|
|
57
|
+
runtime, report that explicitly instead of pretending the repo is ready.
|
|
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.
|
|
60
|
+
5. **Automation readiness** — inspect whether the configured queue source/tracker and scheduling
|
|
61
|
+
prerequisites are observable, but do **not** create, edit, or delete automations during doctor.
|
|
62
|
+
6. **Optional GitHub Project coordination** — when `github.projects.v2` is configured, delegate
|
|
63
|
+
the shared validation read to `github-project-v2` instead of reimplementing ad-hoc GraphQL
|
|
64
|
+
checks. Honor the `required=false` vs `required=true` semantics documented by
|
|
65
|
+
`config-resolution`: best-effort failures are `WARN`, required-mode failures are `FAIL`.
|
|
66
|
+
7. **Optional wiki delegation** — when a repo-local `wiki/` exists, either summarize the
|
|
67
|
+
specialized `lisa-wiki-doctor` verdict or explicitly report that deeper wiki checks are
|
|
68
|
+
available there. The base doctor stays narrower than full wiki migration enforcement.
|
|
69
|
+
|
|
70
|
+
If a check family is not applicable to the current repo, report `SKIP` with the reason.
|
|
71
|
+
|
|
72
|
+
## Output contract
|
|
73
|
+
|
|
74
|
+
The final report must:
|
|
75
|
+
|
|
76
|
+
- Separate observed facts from remediation advice.
|
|
77
|
+
- Print every check with one of `PASS`, `WARN`, `FAIL`, or `SKIP`.
|
|
78
|
+
- Emit exactly one overall verdict: `READY`, `READY_WITH_WARNINGS`, or `NOT_READY`.
|
|
79
|
+
- Stay read-only by default.
|
|
80
|
+
|
|
81
|
+
Render the report in grouped sections using the shared `scripts/doctor-report.mjs` contract:
|
|
82
|
+
|
|
83
|
+
- Start with `Overall verdict: <VERDICT>` and one `Counts:` line covering `PASS`, `WARN`, `FAIL`,
|
|
84
|
+
and `SKIP`.
|
|
85
|
+
- Then print each group as `<group-id>. <group-title>`.
|
|
86
|
+
- Under each group, print one line per check as `- <STATUS> <check-id>: <summary>`.
|
|
87
|
+
- When available, print `Observed:` and `Remediation:` lines beneath the check so the report keeps
|
|
88
|
+
facts separate from advice.
|
|
89
|
+
- If a group has no applicable checks yet, render it as a grouped `SKIP` with the reason instead of
|
|
90
|
+
silently omitting the section.
|
|
91
|
+
|
|
92
|
+
The verdict ladder is:
|
|
93
|
+
|
|
94
|
+
- `READY` — no `FAIL` and no `WARN`.
|
|
95
|
+
- `READY_WITH_WARNINGS` — no `FAIL`, but one or more `WARN`.
|
|
96
|
+
- `NOT_READY` — one or more `FAIL`.
|
|
97
|
+
|
|
98
|
+
## Delegation and reuse
|
|
99
|
+
|
|
100
|
+
- Reuse `config-resolution` for config and lifecycle role defaults instead of inventing a second
|
|
101
|
+
schema.
|
|
102
|
+
- Reuse the existing `github-project-v2` chokepoint for GitHub Project coordination checks instead
|
|
103
|
+
of inlining bespoke access logic.
|
|
104
|
+
- Reuse ideas from `lisa-wiki-doctor` for grouped verdict rendering where they fit, while keeping
|
|
105
|
+
the Lisa-wide doctor narrower than the wiki-specific migration/readiness workflow.
|
|
106
|
+
|
|
107
|
+
## Rules
|
|
108
|
+
|
|
109
|
+
- Never mutate repository, tracker, or automation state on the default doctor path.
|
|
110
|
+
- Never hardcode tracker/source label names outside the documented defaults plus configured
|
|
111
|
+
overrides from `config-resolution`.
|
|
112
|
+
- Never silently treat an unavailable check surface as success; report `WARN`, `FAIL`, or `SKIP`
|
|
113
|
+
with the explicit missing dependency.
|
|
114
|
+
- Never turn wiki-specific checks into a requirement for non-wiki repos.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lisa-openclaw",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.77.0",
|
|
4
4
|
"description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Cody Swann"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lisa-openclaw",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.77.0",
|
|
4
4
|
"description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, across Claude and Codex.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Cody Swann"
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Audit whether the current repository is ready to use Lisa. Runs grouped read-only readiness checks for config, runtime surfaces, tracker/source access, automation prerequisites, and optional project/wiki coordination, then reports PASS/WARN/FAIL/SKIP results plus an overall verdict."
|
|
3
|
+
argument-hint: "[--fix=false]"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Use the /lisa:doctor skill to audit whether the current repository is ready to use Lisa, report grouped PASS/WARN/FAIL/SKIP checks, and emit an overall readiness verdict. $ARGUMENTS
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Shared doctor report helpers for the base Lisa doctor surface.
|
|
4
|
+
*
|
|
5
|
+
* The first doctor milestone needs a stable grouped output contract before the
|
|
6
|
+
* repo adds real readiness probes. Keep this file dependency-free so future
|
|
7
|
+
* doctor scripts can reuse it from plugin distributions and downstream repos.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
export const DOCTOR_STATUSES = ["PASS", "WARN", "FAIL", "SKIP"];
|
|
11
|
+
export const DOCTOR_VERDICTS = ["READY", "READY_WITH_WARNINGS", "NOT_READY"];
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @typedef {"PASS" | "WARN" | "FAIL" | "SKIP"} DoctorStatus
|
|
15
|
+
* @typedef {"READY" | "READY_WITH_WARNINGS" | "NOT_READY"} DoctorVerdict
|
|
16
|
+
*
|
|
17
|
+
* @typedef {{
|
|
18
|
+
* readonly id: string
|
|
19
|
+
* readonly status: DoctorStatus
|
|
20
|
+
* readonly summary: string
|
|
21
|
+
* readonly observed?: string
|
|
22
|
+
* readonly remediation?: string
|
|
23
|
+
* }} DoctorCheck
|
|
24
|
+
*
|
|
25
|
+
* @typedef {{
|
|
26
|
+
* readonly id: string
|
|
27
|
+
* readonly title: string
|
|
28
|
+
* readonly checks: readonly DoctorCheck[]
|
|
29
|
+
* }} DoctorGroup
|
|
30
|
+
*
|
|
31
|
+
* @typedef {{
|
|
32
|
+
* readonly generatedAt?: string
|
|
33
|
+
* readonly groups: readonly DoctorGroup[]
|
|
34
|
+
* }} DoctorReportInput
|
|
35
|
+
*/
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* @param {readonly DoctorGroup[]} groups
|
|
39
|
+
* @returns {DoctorVerdict}
|
|
40
|
+
*/
|
|
41
|
+
export function computeDoctorVerdict(groups) {
|
|
42
|
+
const checks = groups.flatMap(group => group.checks);
|
|
43
|
+
if (checks.some(check => check.status === "FAIL")) {
|
|
44
|
+
return "NOT_READY";
|
|
45
|
+
}
|
|
46
|
+
if (checks.some(check => check.status === "WARN")) {
|
|
47
|
+
return "READY_WITH_WARNINGS";
|
|
48
|
+
}
|
|
49
|
+
return "READY";
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* @param {readonly DoctorGroup[]} groups
|
|
54
|
+
* @returns {Record<DoctorStatus, number>}
|
|
55
|
+
*/
|
|
56
|
+
export function countDoctorStatuses(groups) {
|
|
57
|
+
return groups
|
|
58
|
+
.flatMap(group => group.checks)
|
|
59
|
+
.reduce(
|
|
60
|
+
(counts, check) => ({
|
|
61
|
+
...counts,
|
|
62
|
+
[check.status]: counts[check.status] + 1,
|
|
63
|
+
}),
|
|
64
|
+
{ PASS: 0, WARN: 0, FAIL: 0, SKIP: 0 }
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* @param {DoctorReportInput} input
|
|
70
|
+
* @returns {{ readonly verdict: DoctorVerdict, readonly counts: Record<DoctorStatus, number>, readonly text: string }}
|
|
71
|
+
*/
|
|
72
|
+
export function renderDoctorReport(input) {
|
|
73
|
+
const groups = input.groups.map(normalizeGroup);
|
|
74
|
+
const verdict = computeDoctorVerdict(groups);
|
|
75
|
+
const counts = countDoctorStatuses(groups);
|
|
76
|
+
const lines = [
|
|
77
|
+
`Overall verdict: ${verdict}`,
|
|
78
|
+
`Counts: ${DOCTOR_STATUSES.map(status => `${counts[status]} ${status}`).join(", ")}`,
|
|
79
|
+
];
|
|
80
|
+
|
|
81
|
+
if (input.generatedAt) {
|
|
82
|
+
lines.push(`Generated at: ${input.generatedAt}`);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
for (const group of groups) {
|
|
86
|
+
lines.push("", `${group.id}. ${group.title}`);
|
|
87
|
+
if (group.checks.length === 0) {
|
|
88
|
+
lines.push("- SKIP empty-group: no checks registered yet");
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
for (const check of group.checks) {
|
|
92
|
+
lines.push(`- ${check.status} ${check.id}: ${check.summary}`);
|
|
93
|
+
if (check.observed) {
|
|
94
|
+
lines.push(` Observed: ${check.observed}`);
|
|
95
|
+
}
|
|
96
|
+
if (check.remediation) {
|
|
97
|
+
lines.push(` Remediation: ${check.remediation}`);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return {
|
|
103
|
+
verdict,
|
|
104
|
+
counts,
|
|
105
|
+
text: `${lines.join("\n")}\n`,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* @param {DoctorGroup} group
|
|
111
|
+
* @returns {DoctorGroup}
|
|
112
|
+
*/
|
|
113
|
+
function normalizeGroup(group) {
|
|
114
|
+
return {
|
|
115
|
+
...group,
|
|
116
|
+
checks: group.checks.map(normalizeCheck),
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* @param {DoctorCheck} check
|
|
122
|
+
* @returns {DoctorCheck}
|
|
123
|
+
*/
|
|
124
|
+
function normalizeCheck(check) {
|
|
125
|
+
const normalizedStatus = DOCTOR_STATUSES.includes(check.status)
|
|
126
|
+
? check.status
|
|
127
|
+
: "FAIL";
|
|
128
|
+
return {
|
|
129
|
+
...check,
|
|
130
|
+
status: normalizedStatus,
|
|
131
|
+
};
|
|
132
|
+
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: doctor
|
|
3
|
+
description: "Audit whether the current repository is ready to use Lisa. Runs grouped read-only checks across project detection, Lisa config, runtime distribution surfaces, tracker/source preflight access, automation prerequisites, optional GitHub Project coordination, and optional wiki delegation, then reports PASS/WARN/FAIL/SKIP results plus an overall readiness verdict (`READY`, `READY_WITH_WARNINGS`, or `NOT_READY`)."
|
|
4
|
+
allowed-tools: ["Skill", "Bash", "Read", "Glob", "Grep"]
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Doctor: $ARGUMENTS
|
|
8
|
+
|
|
9
|
+
Run a read-only Lisa readiness audit for the current repository.
|
|
10
|
+
|
|
11
|
+
## Purpose
|
|
12
|
+
|
|
13
|
+
`/lisa:doctor` is the deterministic answer to "is this repo actually ready to use Lisa?" It audits
|
|
14
|
+
the repository in grouped sections, reports each check as `PASS`, `WARN`, `FAIL`, or `SKIP`, and
|
|
15
|
+
emits one overall verdict: `READY`, `READY_WITH_WARNINGS`, or `NOT_READY`.
|
|
16
|
+
|
|
17
|
+
The command is repository-scoped. It validates only what can be observed from the current repo,
|
|
18
|
+
current machine, and current runtime. It does **not** create automations, labels, tracker items, or
|
|
19
|
+
other external state as part of the default audit path.
|
|
20
|
+
|
|
21
|
+
## Inputs
|
|
22
|
+
|
|
23
|
+
- Optional flags in `$ARGUMENTS` that narrow or tune read-only validation.
|
|
24
|
+
- The current repository root and its Lisa config files (`.lisa.config.json`,
|
|
25
|
+
`.lisa.config.local.json`) when present.
|
|
26
|
+
|
|
27
|
+
## Confirmation policy
|
|
28
|
+
|
|
29
|
+
Do **not** ask whether to proceed. Once invoked, run the read-only audit, print the grouped
|
|
30
|
+
results, emit the overall verdict, and stop.
|
|
31
|
+
|
|
32
|
+
Specifically forbidden:
|
|
33
|
+
|
|
34
|
+
- Previewing the number of checks and asking whether to continue.
|
|
35
|
+
- Offering "run a few checks first" or "dry-run vs real run" choices. This skill is already the
|
|
36
|
+
read-only path.
|
|
37
|
+
- Performing setup mutations just because a failing check discovered something missing.
|
|
38
|
+
|
|
39
|
+
The only legitimate reasons to stop early are:
|
|
40
|
+
|
|
41
|
+
- The current working directory cannot be resolved to a repository/root the audit can inspect.
|
|
42
|
+
- The runtime blocks all required local reads needed to even classify the repo.
|
|
43
|
+
|
|
44
|
+
## Audit contract
|
|
45
|
+
|
|
46
|
+
Doctor reports grouped checks in a stable, human-readable structure. The grouped sections include,
|
|
47
|
+
as applicable to the current repo:
|
|
48
|
+
|
|
49
|
+
1. **Project detection and runtime basics** — detect the project root, package/runtime surface, and
|
|
50
|
+
whether Lisa is installed where the repo expects it.
|
|
51
|
+
2. **Lisa config readiness** — read `.lisa.config.json` and `.lisa.config.local.json` using the
|
|
52
|
+
same local-overrides-global semantics defined by `config-resolution`; report missing required
|
|
53
|
+
keys, incompatible combinations, and committed-vs-local locality problems as findings rather
|
|
54
|
+
than mutating config.
|
|
55
|
+
3. **Tracker/source preflight** — perform read-only readiness checks for the configured `tracker`
|
|
56
|
+
and `source` only. If a required CLI, MCP surface, or auth context is unavailable in the current
|
|
57
|
+
runtime, report that explicitly instead of pretending the repo is ready.
|
|
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.
|
|
60
|
+
5. **Automation readiness** — inspect whether the configured queue source/tracker and scheduling
|
|
61
|
+
prerequisites are observable, but do **not** create, edit, or delete automations during doctor.
|
|
62
|
+
6. **Optional GitHub Project coordination** — when `github.projects.v2` is configured, delegate
|
|
63
|
+
the shared validation read to `github-project-v2` instead of reimplementing ad-hoc GraphQL
|
|
64
|
+
checks. Honor the `required=false` vs `required=true` semantics documented by
|
|
65
|
+
`config-resolution`: best-effort failures are `WARN`, required-mode failures are `FAIL`.
|
|
66
|
+
7. **Optional wiki delegation** — when a repo-local `wiki/` exists, either summarize the
|
|
67
|
+
specialized `lisa-wiki-doctor` verdict or explicitly report that deeper wiki checks are
|
|
68
|
+
available there. The base doctor stays narrower than full wiki migration enforcement.
|
|
69
|
+
|
|
70
|
+
If a check family is not applicable to the current repo, report `SKIP` with the reason.
|
|
71
|
+
|
|
72
|
+
## Output contract
|
|
73
|
+
|
|
74
|
+
The final report must:
|
|
75
|
+
|
|
76
|
+
- Separate observed facts from remediation advice.
|
|
77
|
+
- Print every check with one of `PASS`, `WARN`, `FAIL`, or `SKIP`.
|
|
78
|
+
- Emit exactly one overall verdict: `READY`, `READY_WITH_WARNINGS`, or `NOT_READY`.
|
|
79
|
+
- Stay read-only by default.
|
|
80
|
+
|
|
81
|
+
Render the report in grouped sections using the shared `scripts/doctor-report.mjs` contract:
|
|
82
|
+
|
|
83
|
+
- Start with `Overall verdict: <VERDICT>` and one `Counts:` line covering `PASS`, `WARN`, `FAIL`,
|
|
84
|
+
and `SKIP`.
|
|
85
|
+
- Then print each group as `<group-id>. <group-title>`.
|
|
86
|
+
- Under each group, print one line per check as `- <STATUS> <check-id>: <summary>`.
|
|
87
|
+
- When available, print `Observed:` and `Remediation:` lines beneath the check so the report keeps
|
|
88
|
+
facts separate from advice.
|
|
89
|
+
- If a group has no applicable checks yet, render it as a grouped `SKIP` with the reason instead of
|
|
90
|
+
silently omitting the section.
|
|
91
|
+
|
|
92
|
+
The verdict ladder is:
|
|
93
|
+
|
|
94
|
+
- `READY` — no `FAIL` and no `WARN`.
|
|
95
|
+
- `READY_WITH_WARNINGS` — no `FAIL`, but one or more `WARN`.
|
|
96
|
+
- `NOT_READY` — one or more `FAIL`.
|
|
97
|
+
|
|
98
|
+
## Delegation and reuse
|
|
99
|
+
|
|
100
|
+
- Reuse `config-resolution` for config and lifecycle role defaults instead of inventing a second
|
|
101
|
+
schema.
|
|
102
|
+
- Reuse the existing `github-project-v2` chokepoint for GitHub Project coordination checks instead
|
|
103
|
+
of inlining bespoke access logic.
|
|
104
|
+
- Reuse ideas from `lisa-wiki-doctor` for grouped verdict rendering where they fit, while keeping
|
|
105
|
+
the Lisa-wide doctor narrower than the wiki-specific migration/readiness workflow.
|
|
106
|
+
|
|
107
|
+
## Rules
|
|
108
|
+
|
|
109
|
+
- Never mutate repository, tracker, or automation state on the default doctor path.
|
|
110
|
+
- Never hardcode tracker/source label names outside the documented defaults plus configured
|
|
111
|
+
overrides from `config-resolution`.
|
|
112
|
+
- Never silently treat an unavailable check surface as success; report `WARN`, `FAIL`, or `SKIP`
|
|
113
|
+
with the explicit missing dependency.
|
|
114
|
+
- Never turn wiki-specific checks into a requirement for non-wiki repos.
|