kushi-agents 4.0.0 → 4.2.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/.github/copilot-instructions.kushi.md +1 -0
- package/bin/cli.mjs +10 -0
- package/package.json +1 -1
- package/plugin/instructions/identity-resolution.instructions.md +66 -0
- package/plugin/instructions/tracking.instructions.md +165 -0
- package/plugin/instructions/workiq-only.instructions.md +1 -0
- package/plugin/prompts/aggregate.prompt.md +2 -0
- package/plugin/prompts/ask.prompt.md +2 -0
- package/plugin/prompts/bootstrap.prompt.md +3 -1
- package/plugin/prompts/consolidate.prompt.md +3 -1
- package/plugin/prompts/fde-intake.prompt.md +2 -0
- package/plugin/prompts/fde-report.prompt.md +2 -0
- package/plugin/prompts/fde-triage.prompt.md +2 -0
- package/plugin/prompts/refresh.prompt.md +3 -1
- package/plugin/prompts/state.prompt.md +3 -1
- package/plugin/skills/bootstrap-project/SKILL.md +16 -1
- package/plugin/templates/init/project-evidence.template.yml +17 -7
- package/src/check-workiq.mjs +125 -0
- package/src/main.mjs +54 -0
|
@@ -37,6 +37,7 @@ Project Q&A also auto-dispatches when the user names a known project under the e
|
|
|
37
37
|
- `.kushi/instructions/` — doctrine (citations, WorkIQ-first, freshness gates)
|
|
38
38
|
- `.kushi/reference-packs/` — bundled domain doctrine (override at project / workspace / packaged layers)
|
|
39
39
|
- `.kushi/config/` — **user-editable** (project-evidence.yml, integrations.yml, reference-overrides). Seeded on first install; never overwritten on upgrade.
|
|
40
|
+
- `.kushi/tracking/` — **agent working memory** (runs/, qa/, fde/, research/). Per-run Markdown journals: what was asked, what was done, what was decided, what's still open. Gitignored by default. See `instructions/tracking.instructions.md`.
|
|
40
41
|
- `.kushi/kushi-install.json` — profile manifest written by the installer
|
|
41
42
|
|
|
42
43
|
Full docs: <https://gim-home.github.io/kushi/>
|
package/bin/cli.mjs
CHANGED
|
@@ -29,6 +29,13 @@ if (args.includes('--help') || args.includes('-h')) {
|
|
|
29
29
|
check (useful for scripted or agent-driven installs)
|
|
30
30
|
--no-settings Skip .vscode/settings.json update (vscode target only)
|
|
31
31
|
--no-instructions Skip .github/copilot-instructions.md merge (vscode target only)
|
|
32
|
+
|
|
33
|
+
WorkIQ (REQUIRED — Kushi cannot pull evidence without it):
|
|
34
|
+
--with-workiq Auto-install WorkIQ via winget (Windows) / brew (macOS)
|
|
35
|
+
--workiq-path <abs> Use this explicit path to the workiq binary
|
|
36
|
+
--skip-workiq-check Bypass the WorkIQ pre-flight check (CI / inspection only —
|
|
37
|
+
bootstrap/refresh will block until WorkIQ is installed)
|
|
38
|
+
|
|
32
39
|
--help, -h Show this help
|
|
33
40
|
|
|
34
41
|
After install, talk to Kushi:
|
|
@@ -62,6 +69,9 @@ const options = {
|
|
|
62
69
|
noInstructions: args.includes('--no-instructions'),
|
|
63
70
|
target,
|
|
64
71
|
profile: getFlag('--profile'),
|
|
72
|
+
withWorkiq: args.includes('--with-workiq'),
|
|
73
|
+
workiqPath: getFlag('--workiq-path'),
|
|
74
|
+
skipWorkiqCheck: args.includes('--skip-workiq-check'),
|
|
65
75
|
};
|
|
66
76
|
|
|
67
77
|
main(options).catch((err) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kushi-agents",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.2.0",
|
|
4
4
|
"description": "Install Kushi — multi-source project evidence agent with snapshot+stream capture across Email, Teams, OneNote, SharePoint, Meetings, CRM, ADO. WorkIQ-only for M365 sources (Graph / m365_* FORBIDDEN as fallbacks; user-paste is first-class). Host-agnostic.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
---
|
|
2
|
+
applyTo: "**"
|
|
3
|
+
description: "Identity auto-resolution — Kushi never asks the user for alias / email / display_name. On the first bootstrap (or whenever those fields are <auto> / placeholder in .kushi/config/project-evidence.yml), Kushi resolves them from WorkIQ in a single call, persists them, and continues. Skipped entirely if the user has set explicit values."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Identity Resolution — Don't Ask, Probe
|
|
7
|
+
|
|
8
|
+
Kushi must not prompt the user for `alias`, `email`, or `display_name`. These are derivable from WorkIQ in one call, and asking is poor UX.
|
|
9
|
+
|
|
10
|
+
## When to resolve
|
|
11
|
+
|
|
12
|
+
On the **first step of every prompt** that reads contributor identity (bootstrap, refresh, aggregate, ask, fde-*, propose-ado, apply-ado), check `<workspace>/.kushi/config/project-evidence.yml`:
|
|
13
|
+
|
|
14
|
+
* If `alias`, `email`, or `display_name` is **missing**, set to `<auto>`, or matches a placeholder pattern (`<your-alias>`, `<Your Full Name>`, `your.email@example.com`) → **resolve from WorkIQ**.
|
|
15
|
+
* If all three are explicit non-placeholder values → **skip**. Respect the user's override.
|
|
16
|
+
|
|
17
|
+
## How to resolve
|
|
18
|
+
|
|
19
|
+
Single WorkIQ call:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
workiq ask -q "Who am I? Return my UPN (email), display name, and mail nickname as JSON: {\"upn\":\"...\",\"displayName\":\"...\",\"mailNickname\":\"...\"}"
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Map the response:
|
|
26
|
+
|
|
27
|
+
| Config field | Source | Fallback if missing |
|
|
28
|
+
|----------------|-------------------------------------|--------------------------------------|
|
|
29
|
+
| `email` | `upn` | Block — must be present |
|
|
30
|
+
| `display_name` | `displayName` | Same as `alias` |
|
|
31
|
+
| `alias` | `mailNickname` | `upn.split('@')[0]` (lowercase) |
|
|
32
|
+
|
|
33
|
+
## After resolution
|
|
34
|
+
|
|
35
|
+
1. **Persist back** to `<workspace>/.kushi/config/project-evidence.yml` (preserving comments + indentation). The user sees the resolved values on next open; no surprise.
|
|
36
|
+
2. **Echo back** to the user, one line:
|
|
37
|
+
> ✓ Identity: `Alex Smith <alex@microsoft.com>` (alias=`alex`). Edit `.kushi/config/project-evidence.yml` to override.
|
|
38
|
+
3. **Continue** the prompt.
|
|
39
|
+
|
|
40
|
+
## Failure modes
|
|
41
|
+
|
|
42
|
+
| Scenario | Behavior |
|
|
43
|
+
|-----------------------------------------------|------------------------------------------------------------------------------------------------------------------------------|
|
|
44
|
+
| WorkIQ returns auth error | Block: "Sign in to WorkIQ first: `workiq accept-eula && workiq ask -q ping`". Do not proceed. |
|
|
45
|
+
| WorkIQ returns empty / NO_RESULTS | Block: "WorkIQ could not resolve your identity. Try `workiq ask -q 'who am I'` and retry." |
|
|
46
|
+
| WorkIQ binary missing | This should already have been caught by the installer's pre-flight. If reached, block with the same install hint. |
|
|
47
|
+
| User has explicit non-placeholder values | Skip resolution entirely. Never overwrite user-set values. |
|
|
48
|
+
| Alias collision with another contributor | Bootstrap detects existing `Evidence/<alias>/` whose `contributors.yml` records a different email → ask the user to disambiguate (suggest `<alias>-<tenant-prefix>` e.g. `alex-ms`). |
|
|
49
|
+
|
|
50
|
+
## What NOT to do
|
|
51
|
+
|
|
52
|
+
* Do NOT ask the user `What alias should Kushi use?`. The legacy onboarding prompt is gone.
|
|
53
|
+
* Do NOT call `m365_*` / Graph as a fallback. WorkIQ is the single source of identity truth (`workiq-first.instructions.md`).
|
|
54
|
+
* Do NOT resolve on every run. Once persisted, the config values are authoritative.
|
|
55
|
+
|
|
56
|
+
## Integration with other doctrine
|
|
57
|
+
|
|
58
|
+
* `workiq-first.instructions.md` — identity resolution is the canonical example of WorkIQ-first. Add to the inventory.
|
|
59
|
+
* `bootstrap-project` SKILL — Step 0 is identity resolution. Step 1 is project context.
|
|
60
|
+
* `tracking.instructions.md` — the resolved identity goes into the tracking artifact's frontmatter under `actor:`.
|
|
61
|
+
|
|
62
|
+
## References
|
|
63
|
+
|
|
64
|
+
* `workiq-first.instructions.md` — the parent doctrine.
|
|
65
|
+
* `engagement-root-resolution.instructions.md` — `projects_root` resolution (separate from identity).
|
|
66
|
+
* `templates/init/project-evidence.template.yml` — defaults to `<auto>` for these three fields.
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
---
|
|
2
|
+
applyTo: "**"
|
|
3
|
+
description: "Kushi tracking convention — every Kushi prompt/skill writes its working memory (what it was asked, what it did, what it decided, what's still open) to `<workspace>/.kushi/tracking/` so users can see, edit, diff, and resume the agent's work. This is host-agnostic (VS Code Chat, Clawpilot, Cursor) and complements — never replaces — Evidence/ (canonical outputs) or State/ (rollups)."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Tracking — Agent Working Memory
|
|
7
|
+
|
|
8
|
+
Kushi agents must leave a visible trail. Every meaningful run produces a small Markdown artifact under `<workspace>/.kushi/tracking/` describing what was asked, what was done, what was decided, and what is still open.
|
|
9
|
+
|
|
10
|
+
This is **the journey**, not the **output**. Outputs land under `Evidence/`, `State/`, `Reports/`, `ado-updates/`, etc. Tracking files explain *why* and *how* those outputs ended up the way they did, so the user (or a future agent) can pick up where you left off.
|
|
11
|
+
|
|
12
|
+
## Why this exists
|
|
13
|
+
|
|
14
|
+
* **Visible thinking.** The user can read what the agent considered and rejected, not just the final artifact.
|
|
15
|
+
* **Reliable handoff.** Stable filenames mean Bootstrap → Refresh → State → Ask never loses context across `/clear`, new chats, or host swaps.
|
|
16
|
+
* **Resumability.** A 60-minute pull that died at 80% can be resumed from its last tracking entry instead of restarted.
|
|
17
|
+
* **Audit + replay.** Diff-able, grep-able, commit-able (or gitignored — user's choice).
|
|
18
|
+
* **Single convention across hosts.** Same shape in VS Code Chat, Clawpilot, Cursor, Cline.
|
|
19
|
+
|
|
20
|
+
## Folder layout
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
<workspace>/.kushi/tracking/
|
|
24
|
+
.gitignore ← ignore everything by default
|
|
25
|
+
runs/{{YYYY-MM-DD}}-<project>-<verb>.md ← bootstrap / refresh / aggregate / state / consolidate
|
|
26
|
+
qa/{{YYYY-MM-DD}}-<project>-<question-slug>.md ← /ask answers + citations, archived
|
|
27
|
+
fde/intake/{{YYYY-MM-DD}}-<project>-<slug>.md ← /fde-intake drafts
|
|
28
|
+
fde/report/{{YYYY-MM-DD}}-<project>-<slug>.md ← /fde-report drafts
|
|
29
|
+
fde/triage/{{YYYY-MM-DD}}-<project>-<slug>.md ← /fde-triage drafts
|
|
30
|
+
research/{{YYYY-MM-DD}}-<topic>.md ← optional deep-dive notes
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Rules:
|
|
34
|
+
|
|
35
|
+
* Filenames start with `YYYY-MM-DD` (ISO date, UTC if ambiguous) so chronological sort works everywhere.
|
|
36
|
+
* `<project>` is the engagement folder name (slugified — lowercase, hyphenated, no spaces).
|
|
37
|
+
* `<verb>` is the prompt name without slash (`bootstrap`, `refresh`, ...).
|
|
38
|
+
* `<slug>` / `<question-slug>` is 3–6 word kebab-case derived from the user's ask.
|
|
39
|
+
* Create directories as needed on first write.
|
|
40
|
+
|
|
41
|
+
## On first write — seed `.gitignore`
|
|
42
|
+
|
|
43
|
+
If `<workspace>/.kushi/tracking/` does not yet exist, create it and write `<workspace>/.kushi/tracking/.gitignore` with:
|
|
44
|
+
|
|
45
|
+
```gitignore
|
|
46
|
+
# Kushi tracking files are working memory, not source of truth.
|
|
47
|
+
# Outputs live under Evidence/, State/, Reports/, ado-updates/.
|
|
48
|
+
# Uncomment the next line to start committing tracking artifacts.
|
|
49
|
+
*
|
|
50
|
+
!.gitignore
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
A user who wants to commit their agent transcripts deletes `*` from this file. Default is private.
|
|
54
|
+
|
|
55
|
+
## Required sections in every tracking artifact
|
|
56
|
+
|
|
57
|
+
Every tracking file is Markdown with frontmatter + a small set of named sections. Keep it short — this is a journal, not a report.
|
|
58
|
+
|
|
59
|
+
```markdown
|
|
60
|
+
---
|
|
61
|
+
prompt: bootstrap # /bootstrap, /refresh, /ask, /fde-intake, ...
|
|
62
|
+
project: hca # slugified engagement folder name
|
|
63
|
+
window: last 30 days # bootstrap/refresh only; otherwise omit
|
|
64
|
+
started: 2026-05-19T14:02:00-04:00
|
|
65
|
+
finished: 2026-05-19T14:38:12-04:00 # omit if still in progress
|
|
66
|
+
status: complete # complete | in-progress | blocked | failed
|
|
67
|
+
host: vscode # vscode | clawpilot | cursor | cline | other
|
|
68
|
+
kushi_version: 4.1.0
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
## Ask
|
|
72
|
+
|
|
73
|
+
> Verbatim or near-verbatim of what the user asked for. One short paragraph.
|
|
74
|
+
|
|
75
|
+
## Inputs resolved
|
|
76
|
+
|
|
77
|
+
- Engagement root: `C:/.../Engagement Assets`
|
|
78
|
+
- Project folder: `HCA Healthcare`
|
|
79
|
+
- Alias: `ushak`
|
|
80
|
+
- Config: `<workspace>/.kushi/config/project-evidence.yml`
|
|
81
|
+
|
|
82
|
+
## Steps taken
|
|
83
|
+
|
|
84
|
+
1. Resolved project context via `engagement-root-resolution.instructions.md`.
|
|
85
|
+
2. Ran `pull-email` (WorkIQ) → 142 messages, 30-day window.
|
|
86
|
+
3. Ran `pull-teams` (WorkIQ) → 11 chats, 308 messages.
|
|
87
|
+
4. … (one line per meaningful step)
|
|
88
|
+
|
|
89
|
+
## Decisions
|
|
90
|
+
|
|
91
|
+
- Skipped `pull-crm` — `integrations.yml` has no `crm.engagement_id` for this project.
|
|
92
|
+
- Used WorkIQ-only path; no `m365_*` fallback triggered.
|
|
93
|
+
|
|
94
|
+
## Outputs
|
|
95
|
+
|
|
96
|
+
- `HCA Healthcare/Evidence/ushak/email/snapshot/2026-05-19.md`
|
|
97
|
+
- `HCA Healthcare/Evidence/ushak/teams/snapshot/2026-05-19.md`
|
|
98
|
+
- `HCA Healthcare/State/00_overview.md` (updated)
|
|
99
|
+
|
|
100
|
+
## Open questions / next steps
|
|
101
|
+
|
|
102
|
+
- ADO field `Custom.FDEStatusSummary` is empty — recommend running `/fde-report hca` next.
|
|
103
|
+
- 3 OneNote pages returned `page-body-unavailable`; see notes in `Evidence/ushak/onenote/run-notes.md`.
|
|
104
|
+
|
|
105
|
+
## Errors / fallbacks
|
|
106
|
+
|
|
107
|
+
- None.
|
|
108
|
+
|
|
109
|
+
## Citations
|
|
110
|
+
|
|
111
|
+
- `Evidence/ushak/email/snapshot/2026-05-19.md` · 2026-05-19
|
|
112
|
+
- `Evidence/ushak/teams/snapshot/2026-05-19.md` · 2026-05-19
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Section rules:
|
|
116
|
+
|
|
117
|
+
* **Ask** — required. One short paragraph.
|
|
118
|
+
* **Steps taken** — required. One bullet per meaningful action. Skip trivial tool calls.
|
|
119
|
+
* **Decisions** — required when you chose A over B, skipped a step, or applied a fallback.
|
|
120
|
+
* **Outputs** — required. Bullet list of files written/updated this run.
|
|
121
|
+
* **Open questions / next steps** — required, even if empty (write "None.").
|
|
122
|
+
* **Errors / fallbacks** — required when anything failed, retried, or fell back to a classified-fallback path (e.g., WorkIQ → `m365_*`).
|
|
123
|
+
* **Citations** — required when the artifact references Evidence files; same format as everywhere else in Kushi (`<source-path> · <YYYY-MM-DD>`).
|
|
124
|
+
|
|
125
|
+
## When to write
|
|
126
|
+
|
|
127
|
+
* **First step of every prompt run:** create the file with frontmatter (`status: in-progress`) so a crash leaves something behind.
|
|
128
|
+
* **As you go:** append "Steps taken" lines. Update "Outputs" when files land.
|
|
129
|
+
* **Last step of every prompt run:** set `status: complete` (or `blocked` / `failed`), set `finished`, and fill in the closing sections.
|
|
130
|
+
|
|
131
|
+
If the prompt runs multiple sub-skills in parallel, the orchestrating prompt owns the tracking file. Sub-skills do not write their own runs/ entry; they report back and the parent appends.
|
|
132
|
+
|
|
133
|
+
## When NOT to write
|
|
134
|
+
|
|
135
|
+
* `intro`, `status`, `self-check` — trivial / introspective. Skip the tracking file.
|
|
136
|
+
* Any prompt that does nothing but read a single file and answer.
|
|
137
|
+
* Dry-run / preview invocations (`--dry-run`, `--preview`) — log to stdout only.
|
|
138
|
+
|
|
139
|
+
## Interaction with other doctrine
|
|
140
|
+
|
|
141
|
+
* `update-ledger.instructions.md` — write-path skills (ADO apply, future CRM apply) still write a **ledger** under `<project>/ado-updates/<date>/`. The tracking file additionally records that a write happened and links to the ledger. Ledger is authoritative for *what was written*; tracking is the *story around it*.
|
|
142
|
+
* `evidence-layout-canonical.instructions.md` — tracking files are NEVER a substitute for Evidence/. Evidence/ is the contract; tracking is the journal.
|
|
143
|
+
* `answer-from-evidence.instructions.md` — `/ask` writes its answer to `qa/` *in addition to* returning it in chat, so the same question asked tomorrow can be answered from the archive (with a freshness check).
|
|
144
|
+
|
|
145
|
+
## Cross-host behavior
|
|
146
|
+
|
|
147
|
+
* Path is always relative to the **workspace root** (the folder the user opened in VS Code / Clawpilot / Cursor).
|
|
148
|
+
* In Clawpilot specifically, the workspace root is whichever folder the user is operating on (an engagement folder, a code repo, etc.) — *not* `~/.copilot/m-skills/kushi/`. The Kushi install location and the tracking location are independent.
|
|
149
|
+
* The Clawpilot weekly automation (`~/.copilot/kushi-projects.json`) is unaffected — it operates on engagement folders and produces tracking artifacts in each engagement folder's `.kushi/tracking/`.
|
|
150
|
+
|
|
151
|
+
## Self-check coverage
|
|
152
|
+
|
|
153
|
+
Future self-check rule **C14: tracking-artifact required** will verify:
|
|
154
|
+
|
|
155
|
+
* Every prompt under `plugin/prompts/` (except the opt-out list above) references this instruction file.
|
|
156
|
+
* Every prompt's closing step is "write/update the tracking artifact".
|
|
157
|
+
|
|
158
|
+
C14 is added when this convention reaches 1.0 across all prompts.
|
|
159
|
+
|
|
160
|
+
## References
|
|
161
|
+
|
|
162
|
+
* `evidence-layout-canonical.instructions.md` — Evidence/ shape (the canonical output).
|
|
163
|
+
* `update-ledger.instructions.md` — write-path ledger (orthogonal, additive).
|
|
164
|
+
* `citation-ledger.instructions.md` — citation format used inside tracking artifacts.
|
|
165
|
+
* `engagement-root-resolution.instructions.md` — how to resolve `<project>` for the filename slug.
|
|
@@ -28,6 +28,7 @@ Applies to ALL evidence retrieval from these M365 sources:
|
|
|
28
28
|
- Email bodies and attachments
|
|
29
29
|
- SharePoint file contents (when text extraction is needed)
|
|
30
30
|
- Calendar events (when not already known by id)
|
|
31
|
+
- **Contributor identity** (UPN / displayName / mailNickname) — see `identity-resolution.instructions.md` for the canonical "who am I?" probe.
|
|
31
32
|
|
|
32
33
|
**Out of scope** (these are NOT WorkIQ — they remain on their direct paths):
|
|
33
34
|
|
|
@@ -22,3 +22,5 @@ This is the **pull-only** verb. Every enabled source is pulled and per-user stre
|
|
|
22
22
|
```
|
|
23
23
|
|
|
24
24
|
See `skills/aggregate-project/SKILL.md` for the full sequence and output contract.
|
|
25
|
+
|
|
26
|
+
Tracking: see `tracking.instructions.md`. Write `<workspace>/.kushi/tracking/runs/{{YYYY-MM-DD}}-<project>-aggregate.md` as the final step.
|
|
@@ -14,3 +14,5 @@ Read-only. NEVER triggers a `pull-*` skill — if evidence is stale or missing,
|
|
|
14
14
|
You don't actually need this prompt — `ask-project` auto-routes whenever your message names a known project and asks a question (what / who / when / status / summarize / etc.). The slash form just provides an explicit handle.
|
|
15
15
|
|
|
16
16
|
Delegates to `ask-project` skill.
|
|
17
|
+
|
|
18
|
+
Tracking: see `tracking.instructions.md`. Archive every answer to `<workspace>/.kushi/tracking/qa/{{YYYY-MM-DD}}-<project>-<question-slug>.md` (frontmatter + Ask + Answer + Citations + freshness note).
|
|
@@ -20,4 +20,6 @@ Produces:
|
|
|
20
20
|
- `<engagement-root>/<project>/Evidence/{contributors.yml, run-log.yml, <alias>/.settings.yml, <alias>/{email,teams,meetings,onenote,sharepoint,crm,ado}/{snapshot,stream}/}`
|
|
21
21
|
- `<engagement-root>/<project>/State/{00..09}_*.md`
|
|
22
22
|
|
|
23
|
-
Delegates to `bootstrap-project` skill. After scaffolding, calls each `pull-<source>` skill, then `build-state`.
|
|
23
|
+
Delegates to `bootstrap-project` skill. After scaffolding, calls each `pull-<source>` skill, then `build-state`.
|
|
24
|
+
|
|
25
|
+
Tracking: see `tracking.instructions.md`. Write `<workspace>/.kushi/tracking/runs/{{YYYY-MM-DD}}-<project>-bootstrap.md` as the final step.
|
|
@@ -18,4 +18,6 @@ Writes:
|
|
|
18
18
|
|
|
19
19
|
Provenance tags retained (source: <alias>/<source>/<file>) per `citation-ledger.instructions.md`.
|
|
20
20
|
|
|
21
|
-
Delegates to `consolidate-evidence` skill.
|
|
21
|
+
Delegates to `consolidate-evidence` skill.
|
|
22
|
+
|
|
23
|
+
Tracking: see `tracking.instructions.md`. Write `<workspace>/.kushi/tracking/runs/{{YYYY-MM-DD}}-<project>-consolidate.md` as the final step.
|
|
@@ -39,3 +39,5 @@ Authors (first time) or updates (subsequent runs) the **FDE Intake** at `<engage
|
|
|
39
39
|
- `skills/fde-intake/SKILL.md` for the full step-by-step.
|
|
40
40
|
- `@Kushi fde-triage <project>` — produces the 7-file triage bundle that builds ON the intake.
|
|
41
41
|
- `@Kushi fde-report <project> stage-readiness` — separate "should we advance the stage?" check.
|
|
42
|
+
|
|
43
|
+
Tracking: see `tracking.instructions.md`. Write `<workspace>/.kushi/tracking/fde/intake/{{YYYY-MM-DD}}-<project>-<slug>.md` as the final step.
|
|
@@ -44,3 +44,5 @@ Generates an FDE-shaped engagement report. Read-only against Evidence; no outbou
|
|
|
44
44
|
- `skills/fde-report/SKILL.md` for the full step-by-step.
|
|
45
45
|
- `@Kushi fde-intake <project>` — precursor first-artifact intake document.
|
|
46
46
|
- `@Kushi fde-triage <project>` — full 7-file triage bundle (analysis + fitness + risk + 6Q + mobilization readiness + executive readout + reuse lens + validation warnings).
|
|
47
|
+
|
|
48
|
+
Tracking: see `tracking.instructions.md`. Write `<workspace>/.kushi/tracking/fde/report/{{YYYY-MM-DD}}-<project>-<shape>.md` as the final step.
|
|
@@ -44,3 +44,5 @@ Re-running on the same day overwrites files 00–06 in place and **merges file 0
|
|
|
44
44
|
- `skills/fde-triage/SKILL.md` for the full step-by-step.
|
|
45
45
|
- `@Kushi fde-intake <project>` — first-artifact intake document (precursor to the bundle).
|
|
46
46
|
- `@Kushi fde-report <project> [shape]` — individual report shapes (weekly / short / long / fitness / stage-readiness).
|
|
47
|
+
|
|
48
|
+
Tracking: see `tracking.instructions.md`. Write `<workspace>/.kushi/tracking/fde/triage/{{YYYY-MM-DD}}-<project>-bundle.md` as the final step (one summary entry, not 7 — the bundle itself lives under `Reports/triage/`).
|
|
@@ -14,4 +14,6 @@ Window resolution (per `refresh-project` skill):
|
|
|
14
14
|
|
|
15
15
|
Output is always weekly-bucketed regardless of input window.
|
|
16
16
|
|
|
17
|
-
Delegates to `refresh-project` skill. Skips `pull-<source>` for sources marked disabled in `integrations.yml` or whose config is missing.
|
|
17
|
+
Delegates to `refresh-project` skill. Skips `pull-<source>` for sources marked disabled in `integrations.yml` or whose config is missing.
|
|
18
|
+
|
|
19
|
+
Tracking: see `tracking.instructions.md`. Write `<workspace>/.kushi/tracking/runs/{{YYYY-MM-DD}}-<project>-refresh.md` as the final step.
|
|
@@ -14,4 +14,6 @@ Pure renderer. Reads:
|
|
|
14
14
|
Writes:
|
|
15
15
|
- `<engagement-root>/<project>/State/{00_overview, 01_decisions, 02_stakeholders, 03_architecture-and-solution, 04_workshops-and-key-meetings, 05_action-items, 06_risks-and-issues, 07_timeline-and-milestones, 08_artifacts-and-deliverables, 09_open-questions}.md`
|
|
16
16
|
|
|
17
|
-
Delegates to `build-state` skill. Use this when you've manually edited Evidence files and want State refreshed without re-pulling.
|
|
17
|
+
Delegates to `build-state` skill. Use this when you've manually edited Evidence files and want State refreshed without re-pulling.
|
|
18
|
+
|
|
19
|
+
Tracking: see `tracking.instructions.md`. Write `<workspace>/.kushi/tracking/runs/{{YYYY-MM-DD}}-<project>-state.md` as the final step.
|
|
@@ -35,10 +35,25 @@ After every run (success or coverage-gaps), write `<project>/bootstrap-status.md
|
|
|
35
35
|
|
|
36
36
|
- `<project>` — engagement name (fuzzy-matched per `engagement-root-resolution.instructions.md`).
|
|
37
37
|
- `<window>` — defaults to **last 30 days** (override with `last N days` / `since <date>`).
|
|
38
|
-
- Implicit: current contributor `<alias>` (
|
|
38
|
+
- Implicit: current contributor `<alias>` (resolved in Step 0 — see below).
|
|
39
39
|
|
|
40
40
|
## Steps
|
|
41
41
|
|
|
42
|
+
### Step 0 — Identity resolution (REQUIRED, never asks the user)
|
|
43
|
+
|
|
44
|
+
Per `identity-resolution.instructions.md`. Read `<workspace>/.kushi/config/project-evidence.yml`:
|
|
45
|
+
|
|
46
|
+
* If `alias`, `email`, or `display_name` is missing / `<auto>` / matches a placeholder → call WorkIQ once:
|
|
47
|
+
```
|
|
48
|
+
workiq ask -q "Who am I? Return UPN, displayName, mailNickname as JSON."
|
|
49
|
+
```
|
|
50
|
+
Map `upn → email`, `displayName → display_name`, `mailNickname → alias` (fallback `email.split('@')[0]`).
|
|
51
|
+
* Persist resolved values back to the YAML (preserve comments).
|
|
52
|
+
* Echo one line: `✓ Identity: <displayName> <<UPN>> (alias=<alias>). Edit .kushi/config/project-evidence.yml to override.`
|
|
53
|
+
* If all three are already explicit non-placeholder values → skip silently.
|
|
54
|
+
|
|
55
|
+
Hard stop if WorkIQ returns auth error or empty — print the WorkIQ sign-in hint and exit. Never fall back to asking the user.
|
|
56
|
+
|
|
42
57
|
### Step 1 — Machine preflight (SETUP)
|
|
43
58
|
|
|
44
59
|
Verify in order. Stop on hard failures.
|
|
@@ -5,14 +5,23 @@
|
|
|
5
5
|
# maintains their own. Nothing here is a secret, but it IS personal —
|
|
6
6
|
# add `.kushi/config/` to .gitignore before committing the rest of .kushi/.
|
|
7
7
|
#
|
|
8
|
-
#
|
|
8
|
+
# IDENTITY — auto-detected on first bootstrap.
|
|
9
|
+
# On the first run of `bootstrap <project>`, Kushi asks WorkIQ "who am I?"
|
|
10
|
+
# and fills these three fields in for you (UPN, displayName, mailNickname).
|
|
11
|
+
# You only need to override them if you want a different folder name or
|
|
12
|
+
# a friendlier display label. Leave them at the placeholder values to
|
|
13
|
+
# trigger auto-detection.
|
|
9
14
|
|
|
10
|
-
#
|
|
11
|
-
|
|
15
|
+
# Optional override — short id used as your Evidence/ subfolder name.
|
|
16
|
+
# Leave as <auto> to derive from the part before "@" in your email.
|
|
17
|
+
alias: <auto>
|
|
12
18
|
|
|
13
|
-
#
|
|
14
|
-
|
|
15
|
-
|
|
19
|
+
# Optional override — friendly label used in run logs.
|
|
20
|
+
# Leave as <auto> to pull from WorkIQ's displayName.
|
|
21
|
+
display_name: <auto>
|
|
22
|
+
|
|
23
|
+
# Optional override — your work email. Leave as <auto> to pull from WorkIQ.
|
|
24
|
+
email: <auto>
|
|
16
25
|
|
|
17
26
|
# FILL ME IN — where your engagement-root lives. The parent folder containing
|
|
18
27
|
# one subfolder per project (typically synced from a team SharePoint library).
|
|
@@ -35,4 +44,5 @@ active_projects:
|
|
|
35
44
|
# 2. `workiq` on PATH
|
|
36
45
|
# 3. ~/.kushi/bin/workiq.cmd (Windows) / ~/.kushi/bin/workiq (Linux/macOS)
|
|
37
46
|
# workiq:
|
|
38
|
-
# cli_path: 'C:\Users\<you>\.kushi\bin\workiq.cmd'
|
|
47
|
+
# cli_path: 'C:\Users\<you>\.kushi\bin\workiq.cmd'
|
|
48
|
+
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { spawnSync } from 'node:child_process';
|
|
2
|
+
import { existsSync, statSync } from 'node:fs';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import os from 'node:os';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Probe for a working WorkIQ install.
|
|
8
|
+
*
|
|
9
|
+
* Resolution order:
|
|
10
|
+
* 1. explicit absolute path supplied via --workiq-path / opts.workiqPath
|
|
11
|
+
* 2. `workiq` on PATH (via `where` on Windows, `command -v` elsewhere)
|
|
12
|
+
* 3. Kushi-managed bin: ~/.kushi/bin/workiq.cmd (Win) or ~/.kushi/bin/workiq
|
|
13
|
+
*
|
|
14
|
+
* Returns:
|
|
15
|
+
* { ok: true, path, version } — usable WorkIQ found
|
|
16
|
+
* { ok: false, reason, hint } — not found / not runnable
|
|
17
|
+
*
|
|
18
|
+
* Reasons:
|
|
19
|
+
* 'not-found' — no workiq binary anywhere we looked
|
|
20
|
+
* 'path-invalid' — explicit --workiq-path was given but the file doesn't exist
|
|
21
|
+
* 'not-executable' — found but `--version` failed (corrupt install, missing deps, etc.)
|
|
22
|
+
*/
|
|
23
|
+
export function checkWorkIQ(opts = {}) {
|
|
24
|
+
const isWin = process.platform === 'win32';
|
|
25
|
+
const homeBin = path.join(
|
|
26
|
+
os.homedir(),
|
|
27
|
+
'.kushi',
|
|
28
|
+
'bin',
|
|
29
|
+
isWin ? 'workiq.cmd' : 'workiq',
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
if (opts.workiqPath) {
|
|
33
|
+
const abs = path.resolve(opts.workiqPath);
|
|
34
|
+
if (!existsSync(abs) || !statSync(abs).isFile()) {
|
|
35
|
+
return {
|
|
36
|
+
ok: false,
|
|
37
|
+
reason: 'path-invalid',
|
|
38
|
+
hint: `--workiq-path "${opts.workiqPath}" does not point at an existing file.`,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
return runVersion(abs);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const onPath = findOnPath('workiq');
|
|
45
|
+
if (onPath) return runVersion(onPath);
|
|
46
|
+
|
|
47
|
+
if (existsSync(homeBin) && statSync(homeBin).isFile()) {
|
|
48
|
+
return runVersion(homeBin);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return {
|
|
52
|
+
ok: false,
|
|
53
|
+
reason: 'not-found',
|
|
54
|
+
hint: installHint(),
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function findOnPath(name) {
|
|
59
|
+
const isWin = process.platform === 'win32';
|
|
60
|
+
const cmd = isWin ? 'where' : 'command';
|
|
61
|
+
const args = isWin ? [name] : ['-v', name];
|
|
62
|
+
const res = spawnSync(cmd, args, { encoding: 'utf-8', shell: !isWin });
|
|
63
|
+
if (res.status !== 0) return null;
|
|
64
|
+
const first = (res.stdout || '').split(/\r?\n/).map((s) => s.trim()).find(Boolean);
|
|
65
|
+
return first || null;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function runVersion(binPath) {
|
|
69
|
+
const res = spawnSync(binPath, ['--version'], { encoding: 'utf-8', timeout: 10_000 });
|
|
70
|
+
if (res.status !== 0) {
|
|
71
|
+
return {
|
|
72
|
+
ok: false,
|
|
73
|
+
reason: 'not-executable',
|
|
74
|
+
hint: `Found WorkIQ at ${binPath} but \`workiq --version\` failed (exit ${res.status}). Try reinstalling. ${installHint()}`,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
const version = (res.stdout || res.stderr || '').trim().split(/\r?\n/)[0] || 'unknown';
|
|
78
|
+
return { ok: true, path: binPath, version };
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function installHint() {
|
|
82
|
+
const plat = process.platform;
|
|
83
|
+
if (plat === 'win32') {
|
|
84
|
+
return 'Install with: winget install Microsoft.WorkIQ';
|
|
85
|
+
}
|
|
86
|
+
if (plat === 'darwin') {
|
|
87
|
+
return 'Install with: brew install --cask microsoft-workiq';
|
|
88
|
+
}
|
|
89
|
+
return 'See https://gim-home.github.io/kushi/getting-started/install-workiq/ for Linux instructions.';
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Best-effort auto-install via the platform's package manager.
|
|
94
|
+
* Only invoked when --with-workiq is passed. Non-blocking on failure —
|
|
95
|
+
* caller decides whether to hard-fail.
|
|
96
|
+
*
|
|
97
|
+
* Returns { ok, reason, output }.
|
|
98
|
+
*/
|
|
99
|
+
export function tryInstallWorkIQ() {
|
|
100
|
+
const plat = process.platform;
|
|
101
|
+
let cmd, args;
|
|
102
|
+
if (plat === 'win32') {
|
|
103
|
+
cmd = 'winget';
|
|
104
|
+
args = ['install', '--id', 'Microsoft.WorkIQ', '-e', '--accept-package-agreements', '--accept-source-agreements'];
|
|
105
|
+
} else if (plat === 'darwin') {
|
|
106
|
+
cmd = 'brew';
|
|
107
|
+
args = ['install', '--cask', 'microsoft-workiq'];
|
|
108
|
+
} else {
|
|
109
|
+
return {
|
|
110
|
+
ok: false,
|
|
111
|
+
reason: 'unsupported-platform',
|
|
112
|
+
output: 'Auto-install is not supported on Linux. See https://gim-home.github.io/kushi/getting-started/install-workiq/',
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const res = spawnSync(cmd, args, { encoding: 'utf-8', stdio: 'inherit' });
|
|
117
|
+
if (res.error || res.status !== 0) {
|
|
118
|
+
return {
|
|
119
|
+
ok: false,
|
|
120
|
+
reason: 'install-failed',
|
|
121
|
+
output: res.error ? res.error.message : `${cmd} exited with status ${res.status}`,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
return { ok: true, output: `${cmd} ${args.join(' ')} succeeded` };
|
|
125
|
+
}
|
package/src/main.mjs
CHANGED
|
@@ -17,6 +17,7 @@ import { copyAssets, copyProjectFiles } from './copy-assets.mjs';
|
|
|
17
17
|
import { mergeSettings } from './settings.mjs';
|
|
18
18
|
import { mergeCopilotInstructions } from './copilot-instructions.mjs';
|
|
19
19
|
import { seedConfig } from './seed-config.mjs';
|
|
20
|
+
import { checkWorkIQ, tryInstallWorkIQ } from './check-workiq.mjs';
|
|
20
21
|
import {
|
|
21
22
|
resolveProfile,
|
|
22
23
|
makeIncludeFilter,
|
|
@@ -71,6 +72,9 @@ export async function main(options = {}) {
|
|
|
71
72
|
console.log(` Profile chain: ${resolved.chain.join(' -> ')}`);
|
|
72
73
|
console.log(` ${resolved.description}\n`);
|
|
73
74
|
|
|
75
|
+
// Hard prerequisite: WorkIQ. Kushi cannot pull evidence without it.
|
|
76
|
+
await preflightWorkIQ(options);
|
|
77
|
+
|
|
74
78
|
if (target === TARGET_CLAWPILOT) {
|
|
75
79
|
await installClawpilot(options, resolved, version);
|
|
76
80
|
} else {
|
|
@@ -290,6 +294,56 @@ async function confirmOverwriteIfExists(fullDest, displayDest, force) {
|
|
|
290
294
|
}
|
|
291
295
|
}
|
|
292
296
|
|
|
297
|
+
/**
|
|
298
|
+
* Hard prerequisite: WorkIQ must be installed and runnable before Kushi will
|
|
299
|
+
* copy any assets. Kushi's pull-* skills are useless without it. Three modes:
|
|
300
|
+
*
|
|
301
|
+
* --skip-workiq-check → print a warning and continue (CI / asset-inspection only)
|
|
302
|
+
* --with-workiq → attempt auto-install via winget/brew first, then re-check
|
|
303
|
+
* default → probe; on failure, print install hint and exit 1
|
|
304
|
+
*
|
|
305
|
+
* Always prints the resolved WorkIQ path + version on success so users have a
|
|
306
|
+
* record in their terminal scrollback.
|
|
307
|
+
*/
|
|
308
|
+
async function preflightWorkIQ(options) {
|
|
309
|
+
if (options.skipWorkiqCheck) {
|
|
310
|
+
console.warn(
|
|
311
|
+
' ⚠️ WorkIQ pre-flight skipped (--skip-workiq-check).',
|
|
312
|
+
);
|
|
313
|
+
console.warn(
|
|
314
|
+
' Kushi will install, but bootstrap/refresh will block until WorkIQ is present.\n',
|
|
315
|
+
);
|
|
316
|
+
return;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
let result = checkWorkIQ({ workiqPath: options.workiqPath });
|
|
320
|
+
|
|
321
|
+
if (!result.ok && options.withWorkiq) {
|
|
322
|
+
console.log(' WorkIQ not found — attempting auto-install (--with-workiq)…\n');
|
|
323
|
+
const ins = tryInstallWorkIQ();
|
|
324
|
+
if (!ins.ok) {
|
|
325
|
+
console.error(`\n ✖ Auto-install failed: ${ins.output}\n`);
|
|
326
|
+
console.error(` ${result.hint || ''}\n`);
|
|
327
|
+
process.exit(1);
|
|
328
|
+
}
|
|
329
|
+
result = checkWorkIQ({ workiqPath: options.workiqPath });
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
if (!result.ok) {
|
|
333
|
+
console.error('\n ✖ WorkIQ is required and was not found.\n');
|
|
334
|
+
console.error(' Kushi cannot capture evidence without WorkIQ. Install it first:\n');
|
|
335
|
+
console.error(` ${result.hint}\n`);
|
|
336
|
+
console.error(' Then run `workiq ask -q "ping"` to confirm sign-in, and re-run this installer.\n');
|
|
337
|
+
console.error(' Escape hatches (NOT recommended):');
|
|
338
|
+
console.error(' • --workiq-path <abs> supply a non-standard install path');
|
|
339
|
+
console.error(' • --with-workiq let the installer try winget/brew');
|
|
340
|
+
console.error(' • --skip-workiq-check install assets anyway (bootstrap will still block)\n');
|
|
341
|
+
process.exit(1);
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
console.log(` ✓ WorkIQ detected at ${result.path} (${result.version})\n`);
|
|
345
|
+
}
|
|
346
|
+
|
|
293
347
|
/**
|
|
294
348
|
* Detect whether the cwd looks like a sane install target and, if not, print
|
|
295
349
|
* an actionable message. Three cases:
|