kushi-agents 5.4.1 → 5.4.3
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/README.md +8 -0
- package/package.json +1 -1
- package/plugin/plugin.json +27 -7
- package/plugin/prompts/create-skill.prompt.md +26 -0
- package/plugin/prompts/doctor.prompt.md +31 -0
- package/plugin/prompts/explain.prompt.md +22 -0
- package/plugin/prompts/global.prompt.md +28 -0
- package/plugin/prompts/lint.prompt.md +28 -0
- package/plugin/prompts/promote.prompt.md +26 -0
- package/plugin/prompts/schema-evolve.prompt.md +27 -0
- package/plugin/prompts/teach.prompt.md +25 -0
- package/src/setup-wizard.mjs +39 -8
- package/src/setup-wizard.test.mjs +19 -1
package/README.md
CHANGED
|
@@ -218,6 +218,14 @@ The Evidence/ folder produced by every profile is a **stable public contract**
|
|
|
218
218
|
| `apply-ado` | **preview** | n/a | Gated apply skill. v0.1.0-preview is dry-mode only (writes `planned.jsonl`); real ADO PATCH/POST lands in v0.1.x. |
|
|
219
219
|
| `vertex-link` | **preview** | n/a | One-time link of a kushi project to a vertex repo `<customer>/<initiative>` (multi-binding supported). Populates `kushi.yaml#vertex`. Re-run with `--reconfigure` to change. |
|
|
220
220
|
| `emit-vertex` | **preview** | n/a | Render vertex-shaped artifacts from kushi Evidence/+State/ — weekly status, decisions, workshops, comms, living-doc diff proposals. Stages first, validates against vertex's own schemas, applies on demand. |
|
|
221
|
+
| `doctor` | core+ | n/a | v5.4.0 — Aggregated health check (env, self-check, evals, skill-checker, live-install drift, global wiki). `--json` for CI; `--strict` to fail on yellow. |
|
|
222
|
+
| `lint` | standard+ | n/a | v5.1.0 — Run wiki-lint checks against `State/` (contradictions, stale claims, orphans, missing cross-refs, data gaps). Writes `State/reports/lint-YYYY-MM-DD.md`. |
|
|
223
|
+
| `teach` | standard+ | n/a | v5.2.0 — Persist a reusable fact/preference/pattern under `.kushi/learnings/`. |
|
|
224
|
+
| `explain` | standard+ | n/a | v5.2.0 — Retrieve a previously taught fact/preference/pattern from `.kushi/learnings/`. |
|
|
225
|
+
| `promote` | standard+ | n/a | v5.3.0 — Copy a project State page into the global wiki at `~/.kushi-global/` with identifier redaction + back-link + dual log. Refuses without `--force` when identifiers detected. |
|
|
226
|
+
| `global` (init/status/ask/lint) | standard+ | n/a | v5.3.0 — Manage the per-user cross-engagement wiki at `~/.kushi-global/State/`. |
|
|
227
|
+
| `schema-evolve` | standard+ | n/a | v5.2.0 — Migrate `kushi.yaml` and Evidence/ layouts across schema versions; idempotent + dry-run by default. |
|
|
228
|
+
| `create-skill` / `check-skill` | full | n/a | v5.0.4 — Skill-authoring harness (scaffold a new skill; lint/retrofit every SKILL.md against `skill-authoring.instructions.md`). |
|
|
221
229
|
|
|
222
230
|
See [Quickstart](https://gim-home.github.io/kushi/getting-started/quickstart/) for the full workflow.
|
|
223
231
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kushi-agents",
|
|
3
|
-
"version": "5.4.
|
|
3
|
+
"version": "5.4.3",
|
|
4
4
|
"description": "Install Kushi — multi-source project evidence agent with Comprehensive Structured Capture (CSC) into weekly-only files across Email, Teams, OneNote, Loop, SharePoint, Meetings, CRM, ADO. Meetings retain a sibling verbatim/ audit folder. WorkIQ-only for M365 sources (Graph / m365_* FORBIDDEN as fallbacks; user-paste is first-class). Host-agnostic.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
package/plugin/plugin.json
CHANGED
|
@@ -11,6 +11,8 @@
|
|
|
11
11
|
"skills": [
|
|
12
12
|
"intro",
|
|
13
13
|
"self-check",
|
|
14
|
+
"doctor",
|
|
15
|
+
"eval",
|
|
14
16
|
"setup",
|
|
15
17
|
"pull-email",
|
|
16
18
|
"pull-teams",
|
|
@@ -18,6 +20,7 @@
|
|
|
18
20
|
"pull-onenote",
|
|
19
21
|
"pull-loop",
|
|
20
22
|
"pull-sharepoint",
|
|
23
|
+
"pull-misc",
|
|
21
24
|
"pull-crm",
|
|
22
25
|
"pull-ado",
|
|
23
26
|
"aggregate-project",
|
|
@@ -34,7 +37,8 @@
|
|
|
34
37
|
"status",
|
|
35
38
|
"ask",
|
|
36
39
|
"vertex-link",
|
|
37
|
-
"emit-vertex"
|
|
40
|
+
"emit-vertex",
|
|
41
|
+
"doctor"
|
|
38
42
|
],
|
|
39
43
|
"instructions": "*",
|
|
40
44
|
"templates": [
|
|
@@ -50,7 +54,8 @@
|
|
|
50
54
|
"pull",
|
|
51
55
|
"ask",
|
|
52
56
|
"vertex-link",
|
|
53
|
-
"emit-vertex"
|
|
57
|
+
"emit-vertex",
|
|
58
|
+
"doctor"
|
|
54
59
|
]
|
|
55
60
|
},
|
|
56
61
|
"standard": {
|
|
@@ -64,7 +69,11 @@
|
|
|
64
69
|
"fde-triage",
|
|
65
70
|
"link-entities",
|
|
66
71
|
"dashboard",
|
|
67
|
-
"tour"
|
|
72
|
+
"tour",
|
|
73
|
+
"lint-state",
|
|
74
|
+
"teach",
|
|
75
|
+
"promote",
|
|
76
|
+
"schema-evolve"
|
|
68
77
|
],
|
|
69
78
|
"prompts": [
|
|
70
79
|
"bootstrap",
|
|
@@ -92,15 +101,23 @@
|
|
|
92
101
|
"fde-triage",
|
|
93
102
|
"link-entities",
|
|
94
103
|
"dashboard",
|
|
95
|
-
"tour"
|
|
104
|
+
"tour",
|
|
105
|
+
"lint",
|
|
106
|
+
"teach",
|
|
107
|
+
"explain",
|
|
108
|
+
"promote",
|
|
109
|
+
"schema-evolve"
|
|
96
110
|
],
|
|
97
111
|
"_": null
|
|
98
112
|
},
|
|
99
113
|
"full": {
|
|
100
114
|
"extends": "standard",
|
|
101
|
-
"description": "Standard + State/ rollup. Adds the opinionated outcome-based State/ files (decisions, stakeholders, architecture, action items, risks, timeline, artifacts, open questions) built on top of Evidence
|
|
115
|
+
"description": "Standard + State/ rollup + global cross-engagement wiki + skill-authoring harness. Adds the opinionated outcome-based State/ files (decisions, stakeholders, architecture, action items, risks, timeline, artifacts, open questions) built on top of Evidence/, plus ~/.kushi-global/ wiki tooling and skill-creator/skill-checker for contributors. On this profile, bootstrap/refresh call build-state at the end.",
|
|
102
116
|
"skills": [
|
|
103
|
-
"build-state"
|
|
117
|
+
"build-state",
|
|
118
|
+
"global-wiki",
|
|
119
|
+
"skill-creator",
|
|
120
|
+
"skill-checker"
|
|
104
121
|
],
|
|
105
122
|
"prompts": [
|
|
106
123
|
"state"
|
|
@@ -110,7 +127,10 @@
|
|
|
110
127
|
],
|
|
111
128
|
"reference_packs": [],
|
|
112
129
|
"verbs": [
|
|
113
|
-
"state"
|
|
130
|
+
"state",
|
|
131
|
+
"global",
|
|
132
|
+
"create-skill",
|
|
133
|
+
"check-skill"
|
|
114
134
|
]
|
|
115
135
|
},
|
|
116
136
|
"preview": {
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: create-skill
|
|
3
|
+
description: "Scaffold a new kushi skill from the skill-creator harness."
|
|
4
|
+
argument-hint: "Skill name + optional --description '...'. Example: 'create-skill pull-confluence'."
|
|
5
|
+
agent: kushi
|
|
6
|
+
tools: [search, read/readFile, edit, 'execute/runInTerminal', agent]
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## User Input
|
|
10
|
+
|
|
11
|
+
```text
|
|
12
|
+
${input:name_and_flags:Skill name + optional flags, e.g. 'pull-confluence --description "Pull from Confluence"'}
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
# /create-skill
|
|
16
|
+
|
|
17
|
+
Route to `@Kushi create-skill <name>`.
|
|
18
|
+
|
|
19
|
+
Scaffolds a new skill under `plugin/skills/<name>/` with SKILL.md frontmatter,
|
|
20
|
+
description placeholder, references/ folder, and example test stub. Output
|
|
21
|
+
conforms to `skill-authoring.instructions.md` so `check-skill` passes on first
|
|
22
|
+
run.
|
|
23
|
+
|
|
24
|
+
Companion verb: `/check-skill <name>` lints + retrofits an existing skill.
|
|
25
|
+
|
|
26
|
+
Delegates to `skill-creator` skill.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: doctor
|
|
3
|
+
description: "Aggregated health check — env, self-check, evals, skill-checker, install drift, global wiki."
|
|
4
|
+
argument-hint: "No project needed; runs system-wide diagnostics. Flags: --json (CI), --strict (fail on yellow)."
|
|
5
|
+
agent: kushi
|
|
6
|
+
tools: [search, read/readFile, 'execute/runInTerminal', agent]
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## User Input
|
|
10
|
+
|
|
11
|
+
```text
|
|
12
|
+
${input:flags:Optional flags (--json, --strict). Empty for human-readable run.}
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
# /doctor
|
|
16
|
+
|
|
17
|
+
Route to `@Kushi doctor` — aggregated health check covering:
|
|
18
|
+
|
|
19
|
+
- **env** — node, pwsh, kushi version, install layout
|
|
20
|
+
- **self-check** `-Deep` — D1..D41 doctrine checks
|
|
21
|
+
- **evals** `:canary` — golden-set regression check
|
|
22
|
+
- **skill-checker** `-All` — every SKILL.md against `skill-authoring.instructions.md`
|
|
23
|
+
- **live-install drift** — repo source vs installed `~/.copilot/m-skills/kushi/` and `~/.vscode/chat/skills/kushi/`
|
|
24
|
+
- **global wiki** — `~/.kushi-global/State/` shape + run-log
|
|
25
|
+
|
|
26
|
+
Output: colored ribbon (GREEN / YELLOW / RED) + per-finding fix.
|
|
27
|
+
|
|
28
|
+
Read-only by default. No pulls, no writes.
|
|
29
|
+
|
|
30
|
+
Delegates to the `doctor` skill (`skills/doctor/doctor.ps1`). For CI:
|
|
31
|
+
`pwsh -File skills/doctor/doctor.ps1 --json --strict`.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: explain
|
|
3
|
+
description: "Retrieve a previously taught fact / preference / pattern from .kushi/learnings/."
|
|
4
|
+
argument-hint: "Topic. Example: 'explain HCA naming-convention'."
|
|
5
|
+
agent: kushi
|
|
6
|
+
tools: [search, read/readFile, agent]
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## User Input
|
|
10
|
+
|
|
11
|
+
```text
|
|
12
|
+
${input:topic:Topic, e.g. 'HCA naming-convention'}
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
# /explain
|
|
16
|
+
|
|
17
|
+
Route to `@Kushi explain <topic>`.
|
|
18
|
+
|
|
19
|
+
Looks up `.kushi/learnings/<slug>.md` (or fuzzy-match by topic substring) and renders
|
|
20
|
+
the body + history. Read-only — never mutates the learning. Companion to `/teach`.
|
|
21
|
+
|
|
22
|
+
Delegates to `teach` skill (explain mode).
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: global
|
|
3
|
+
description: "Manage the per-user cross-engagement wiki at ~/.kushi-global/State/."
|
|
4
|
+
argument-hint: "Sub-verb: init | status | ask <question> | lint. Example: 'global ask what's our default pull window?'"
|
|
5
|
+
agent: kushi
|
|
6
|
+
tools: [search, read/readFile, edit, agent]
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## User Input
|
|
10
|
+
|
|
11
|
+
```text
|
|
12
|
+
${input:subverb_and_args:Sub-verb + args, e.g. 'init', 'status', 'ask what's our default pull window?', 'lint'}
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
# /global
|
|
16
|
+
|
|
17
|
+
Route to `@Kushi global <sub-verb>`.
|
|
18
|
+
|
|
19
|
+
Manages the cross-engagement wiki at `~/.kushi-global/State/` (override with
|
|
20
|
+
`KUSHI_GLOBAL_ROOT` for tests). Sub-verbs:
|
|
21
|
+
|
|
22
|
+
- `init` — scaffold the global wiki layout (decisions/, patterns/, glossary/, run-log).
|
|
23
|
+
- `status` — show last-promoted pages + recent activity from the dual log.
|
|
24
|
+
- `ask <q>` — citation-only Q&A over the global wiki (mirrors `kushi ask <project>` shape).
|
|
25
|
+
- `lint` — wiki-lint over the global wiki (same checks as project lint).
|
|
26
|
+
|
|
27
|
+
Delegates to `global-wiki` skill. Companion verb: `/promote` copies a project
|
|
28
|
+
page up into the global wiki with identifier redaction.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: lint
|
|
3
|
+
description: "Run wiki-lint checks against State/ — contradictions, stale claims, orphans, gaps."
|
|
4
|
+
argument-hint: "Project name; runs against <project>/State/ and writes State/reports/lint-YYYY-MM-DD.md"
|
|
5
|
+
agent: kushi
|
|
6
|
+
tools: [search, read/readFile, edit, agent]
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## User Input
|
|
10
|
+
|
|
11
|
+
```text
|
|
12
|
+
${input:project:Project name, e.g. HCA}
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
# /lint
|
|
16
|
+
|
|
17
|
+
Route to `@Kushi lint <project>`.
|
|
18
|
+
|
|
19
|
+
Runs the v5.1.0 `lint-state` skill against `<engagement-root>/<project>/State/`:
|
|
20
|
+
- contradiction detection (claim A vs claim B with same subject)
|
|
21
|
+
- stale claims (>14d without source-evidence freshness)
|
|
22
|
+
- orphan pages (no inbound cross-refs)
|
|
23
|
+
- missing required cross-refs per page type
|
|
24
|
+
- data gaps (entities referenced but not pulled)
|
|
25
|
+
|
|
26
|
+
Writes `<project>/State/reports/lint-YYYY-MM-DD.md`. Read-only against Evidence/.
|
|
27
|
+
|
|
28
|
+
Delegates to `lint-state` skill.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: promote
|
|
3
|
+
description: "Copy a project State page into the global wiki with identifier redaction + back-link + dual log."
|
|
4
|
+
argument-hint: "Project + page. Example: 'promote HCA decisions/macc-terms'."
|
|
5
|
+
agent: kushi
|
|
6
|
+
tools: [search, read/readFile, edit, agent]
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## User Input
|
|
10
|
+
|
|
11
|
+
```text
|
|
12
|
+
${input:project_and_page:Project + relative State page, e.g. 'HCA decisions/macc-terms'}
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
# /promote
|
|
16
|
+
|
|
17
|
+
Route to `@Kushi promote <project> <page>`.
|
|
18
|
+
|
|
19
|
+
Copies `<engagement-root>/<project>/State/<page>.md` into `~/.kushi-global/State/<page>.md`:
|
|
20
|
+
- runs the customer-identifier redactor (refuses without `--force` when hits detected)
|
|
21
|
+
- inserts a back-link to the source project page
|
|
22
|
+
- appends entries to both the project run-log and the global wiki dual log
|
|
23
|
+
|
|
24
|
+
Companion verb: `/global ask <q>` retrieves promoted content.
|
|
25
|
+
|
|
26
|
+
Delegates to `promote` skill.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: schema-evolve
|
|
3
|
+
description: "Migrate kushi.yaml + Evidence/ across schema versions. Idempotent + dry-run by default."
|
|
4
|
+
argument-hint: "Project. Flags: --apply (real run), --to <version>. Example: 'schema-evolve HCA --apply'."
|
|
5
|
+
agent: kushi
|
|
6
|
+
tools: [search, read/readFile, edit, agent]
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## User Input
|
|
10
|
+
|
|
11
|
+
```text
|
|
12
|
+
${input:project_and_flags:Project + flags, e.g. 'HCA' (dry-run), 'HCA --apply', 'HCA --to 5.2.0 --apply'}
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
# /schema-evolve
|
|
16
|
+
|
|
17
|
+
Route to `@Kushi schema-evolve <project>`.
|
|
18
|
+
|
|
19
|
+
Walks `<engagement-root>/<project>/` and applies schema migrations declared under
|
|
20
|
+
`plugin/schemas/migrations/` to bring `kushi.yaml`, run-log, and Evidence/ layout
|
|
21
|
+
to the current (or `--to`-pinned) schema version.
|
|
22
|
+
|
|
23
|
+
- Default: dry-run — prints planned changes, writes nothing.
|
|
24
|
+
- `--apply` — performs the migration; idempotent (safe to re-run).
|
|
25
|
+
- `--to <ver>` — pin a target version (default = current).
|
|
26
|
+
|
|
27
|
+
Delegates to `schema-evolve` skill.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: teach
|
|
3
|
+
description: "Persist a reusable fact / preference / pattern under .kushi/learnings/."
|
|
4
|
+
argument-hint: "Topic + body. Example: 'teach HCA naming-convention: services are kebab-case'."
|
|
5
|
+
agent: kushi
|
|
6
|
+
tools: [search, read/readFile, edit, agent]
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## User Input
|
|
10
|
+
|
|
11
|
+
```text
|
|
12
|
+
${input:topic_and_body:Topic + body, e.g. 'HCA naming-convention: services are kebab-case'}
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
# /teach
|
|
16
|
+
|
|
17
|
+
Route to `@Kushi teach <topic>`.
|
|
18
|
+
|
|
19
|
+
Writes a single self-contained learning file under `.kushi/learnings/<slug>.md`
|
|
20
|
+
with frontmatter `topic`, `created`, `last_updated`. Idempotent — re-teach updates
|
|
21
|
+
the existing file in place and appends a `history` entry.
|
|
22
|
+
|
|
23
|
+
Companion verb: `/explain <topic>` retrieves the learning without modifying it.
|
|
24
|
+
|
|
25
|
+
Delegates to `teach` skill.
|
package/src/setup-wizard.mjs
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
// kushi v5.4.
|
|
1
|
+
// kushi v5.4.2 — interactive setup wizard.
|
|
2
2
|
// Non-interactive overrides (used by tests + CI):
|
|
3
|
-
// KUSHI_WIZARD_ROOT
|
|
4
|
-
// KUSHI_WIZARD_HOSTS
|
|
5
|
-
// KUSHI_WIZARD_GLOBAL
|
|
6
|
-
//
|
|
7
|
-
//
|
|
3
|
+
// KUSHI_WIZARD_ROOT — engagement root path
|
|
4
|
+
// KUSHI_WIZARD_HOSTS — comma list: clawpilot,vscode (or "both")
|
|
5
|
+
// KUSHI_WIZARD_GLOBAL — "y" or "n"
|
|
6
|
+
// KUSHI_WIZARD_WORKSPACE — "y" or "n" — scaffold cwd as a kushi workspace
|
|
7
|
+
// KUSHI_INSTALL_ROOT — override ~/.copilot/ for install target (test isolation)
|
|
8
|
+
// KUSHI_SKIP_INSTALL — "1" to skip the actual install step (tests)
|
|
8
9
|
|
|
9
10
|
import fs from 'node:fs';
|
|
10
11
|
import path from 'node:path';
|
|
@@ -41,7 +42,7 @@ function makePrompter() {
|
|
|
41
42
|
const v = process.env[key];
|
|
42
43
|
return (typeof v === 'string' && v.length > 0) ? v : null;
|
|
43
44
|
};
|
|
44
|
-
if (fromEnv('KUSHI_WIZARD_ROOT') || fromEnv('KUSHI_WIZARD_HOSTS') || fromEnv('KUSHI_WIZARD_GLOBAL')) {
|
|
45
|
+
if (fromEnv('KUSHI_WIZARD_ROOT') || fromEnv('KUSHI_WIZARD_HOSTS') || fromEnv('KUSHI_WIZARD_GLOBAL') || fromEnv('KUSHI_WIZARD_WORKSPACE')) {
|
|
45
46
|
return { interactive: false, ask: async (_q, _def, envKey) => fromEnv(envKey) };
|
|
46
47
|
}
|
|
47
48
|
if (!process.stdin.isTTY) {
|
|
@@ -60,15 +61,23 @@ function makePrompter() {
|
|
|
60
61
|
export async function runSetupWizard({ args = [] } = {}) {
|
|
61
62
|
const detectedRoot = detectEngagementRoot();
|
|
62
63
|
const detectedHosts = detectHosts();
|
|
64
|
+
const cwd = process.cwd();
|
|
65
|
+
const cwdHasKushi = fs.existsSync(path.join(cwd, '.kushi'));
|
|
66
|
+
const defaultWorkspace = cwdHasKushi ? 'n' : 'y';
|
|
63
67
|
const p = makePrompter();
|
|
64
68
|
|
|
65
69
|
console.log('');
|
|
66
|
-
console.log(' kushi setup wizard —
|
|
70
|
+
console.log(' kushi setup wizard — 4 questions, then I install.');
|
|
67
71
|
console.log('');
|
|
68
72
|
|
|
69
73
|
const root = (await p.ask(' Where is your engagement root?', detectedRoot, 'KUSHI_WIZARD_ROOT')) || detectedRoot;
|
|
70
74
|
const hosts = (await p.ask(' Install for clawpilot / vscode / both?', detectedHosts, 'KUSHI_WIZARD_HOSTS')) || detectedHosts;
|
|
71
75
|
const wantGlobal = (await p.ask(' Enable global wiki at ~/.kushi-global/?', 'y', 'KUSHI_WIZARD_GLOBAL')) || 'y';
|
|
76
|
+
const wantWorkspace = (await p.ask(
|
|
77
|
+
` Scaffold current directory (${cwd}) as a kushi workspace?${cwdHasKushi ? ' (already present)' : ''}`,
|
|
78
|
+
defaultWorkspace,
|
|
79
|
+
'KUSHI_WIZARD_WORKSPACE',
|
|
80
|
+
)) || defaultWorkspace;
|
|
72
81
|
|
|
73
82
|
if (p.close) p.close();
|
|
74
83
|
|
|
@@ -76,6 +85,8 @@ export async function runSetupWizard({ args = [] } = {}) {
|
|
|
76
85
|
engagementRoot: root,
|
|
77
86
|
hosts: hosts.toLowerCase(),
|
|
78
87
|
globalWiki: /^y/i.test(wantGlobal),
|
|
88
|
+
workspaceInstall: /^y/i.test(wantWorkspace),
|
|
89
|
+
workspacePath: cwd,
|
|
79
90
|
};
|
|
80
91
|
|
|
81
92
|
console.log('');
|
|
@@ -83,6 +94,7 @@ export async function runSetupWizard({ args = [] } = {}) {
|
|
|
83
94
|
console.log(` engagement root: ${answers.engagementRoot}`);
|
|
84
95
|
console.log(` hosts: ${answers.hosts}`);
|
|
85
96
|
console.log(` global wiki: ${answers.globalWiki ? 'yes' : 'no'}`);
|
|
97
|
+
console.log(` workspace: ${answers.workspaceInstall ? `yes (${cwd})` : 'no'}`);
|
|
86
98
|
console.log('');
|
|
87
99
|
|
|
88
100
|
if (process.env.KUSHI_SKIP_INSTALL === '1') {
|
|
@@ -122,6 +134,25 @@ export async function runSetupWizard({ args = [] } = {}) {
|
|
|
122
134
|
}
|
|
123
135
|
}
|
|
124
136
|
|
|
137
|
+
if (answers.workspaceInstall) {
|
|
138
|
+
try {
|
|
139
|
+
const { main } = await import('./main.mjs');
|
|
140
|
+
await main({
|
|
141
|
+
force: false,
|
|
142
|
+
yes: true,
|
|
143
|
+
noSettings: false,
|
|
144
|
+
noInstructions: false,
|
|
145
|
+
target: 'vscode',
|
|
146
|
+
profile: undefined,
|
|
147
|
+
withWorkiq: false,
|
|
148
|
+
workiqPath: undefined,
|
|
149
|
+
skipWorkiqCheck: true,
|
|
150
|
+
});
|
|
151
|
+
} catch (err) {
|
|
152
|
+
console.error(` workspace install skipped: ${err.message}`);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
125
156
|
console.log('');
|
|
126
157
|
console.log(' ✅ wizard complete — next steps:');
|
|
127
158
|
console.log(' kushi doctor');
|
|
@@ -31,18 +31,20 @@ async function withEnv(envOverrides, fn) {
|
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
test('setup-wizard: env-driven cases (sequential to avoid env race)', async (t) => {
|
|
34
|
-
await t.test('case 1: env overrides resolve all
|
|
34
|
+
await t.test('case 1: env overrides resolve all four prompts', async () => {
|
|
35
35
|
const root = path.join(TESTTMP, `wizard-root-${Date.now()}-1`);
|
|
36
36
|
fs.mkdirSync(root, { recursive: true });
|
|
37
37
|
const result = await withEnv({
|
|
38
38
|
KUSHI_WIZARD_ROOT: root,
|
|
39
39
|
KUSHI_WIZARD_HOSTS: 'clawpilot',
|
|
40
40
|
KUSHI_WIZARD_GLOBAL: 'n',
|
|
41
|
+
KUSHI_WIZARD_WORKSPACE: 'n',
|
|
41
42
|
KUSHI_SKIP_INSTALL: '1',
|
|
42
43
|
}, () => runSetupWizard());
|
|
43
44
|
assert.equal(result.engagementRoot, root, 'root from env');
|
|
44
45
|
assert.equal(result.hosts, 'clawpilot', 'host from env');
|
|
45
46
|
assert.equal(result.globalWiki, false, 'global wiki off');
|
|
47
|
+
assert.equal(result.workspaceInstall, false, 'workspace off');
|
|
46
48
|
});
|
|
47
49
|
|
|
48
50
|
await t.test('case 2: "both" hosts retained in answers', async () => {
|
|
@@ -52,6 +54,7 @@ test('setup-wizard: env-driven cases (sequential to avoid env race)', async (t)
|
|
|
52
54
|
KUSHI_WIZARD_ROOT: root,
|
|
53
55
|
KUSHI_WIZARD_HOSTS: 'both',
|
|
54
56
|
KUSHI_WIZARD_GLOBAL: 'n',
|
|
57
|
+
KUSHI_WIZARD_WORKSPACE: 'n',
|
|
55
58
|
KUSHI_SKIP_INSTALL: '1',
|
|
56
59
|
}, () => runSetupWizard());
|
|
57
60
|
assert.equal(result.hosts, 'both');
|
|
@@ -64,6 +67,7 @@ test('setup-wizard: env-driven cases (sequential to avoid env race)', async (t)
|
|
|
64
67
|
KUSHI_WIZARD_ROOT: installRoot,
|
|
65
68
|
KUSHI_WIZARD_HOSTS: 'clawpilot',
|
|
66
69
|
KUSHI_WIZARD_GLOBAL: 'y',
|
|
70
|
+
KUSHI_WIZARD_WORKSPACE: 'n',
|
|
67
71
|
KUSHI_SKIP_INSTALL: '1',
|
|
68
72
|
KUSHI_INSTALL_ROOT: installRoot,
|
|
69
73
|
}, () => runSetupWizard());
|
|
@@ -71,4 +75,18 @@ test('setup-wizard: env-driven cases (sequential to avoid env race)', async (t)
|
|
|
71
75
|
assert.equal(result.globalWiki, true);
|
|
72
76
|
assert.equal(result.engagementRoot, installRoot);
|
|
73
77
|
});
|
|
78
|
+
|
|
79
|
+
await t.test('case 4: workspace scaffold opt-in records cwd', async () => {
|
|
80
|
+
const root = path.join(TESTTMP, `wizard-root-${Date.now()}-4`);
|
|
81
|
+
fs.mkdirSync(root, { recursive: true });
|
|
82
|
+
const result = await withEnv({
|
|
83
|
+
KUSHI_WIZARD_ROOT: root,
|
|
84
|
+
KUSHI_WIZARD_HOSTS: 'clawpilot',
|
|
85
|
+
KUSHI_WIZARD_GLOBAL: 'n',
|
|
86
|
+
KUSHI_WIZARD_WORKSPACE: 'y',
|
|
87
|
+
KUSHI_SKIP_INSTALL: '1',
|
|
88
|
+
}, () => runSetupWizard());
|
|
89
|
+
assert.equal(result.workspaceInstall, true, 'workspace install requested');
|
|
90
|
+
assert.equal(result.workspacePath, process.cwd(), 'workspace path = cwd');
|
|
91
|
+
});
|
|
74
92
|
});
|