kushi-agents 4.4.3 → 4.4.4
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 +1 -0
- package/package.json +1 -1
- package/plugin/agents/kushi.agent.md +4 -2
- package/plugin/instructions/workiq-only.instructions.md +2 -2
- package/plugin/plugin.json +4 -1
- package/plugin/prompts/setup.prompt.md +29 -0
- package/plugin/skills/bootstrap-project/SKILL.md +1 -5
- package/plugin/skills/setup/SKILL.md +174 -0
- package/plugin/templates/init/project-evidence.template.yml +6 -2
- package/src/check-workiq.mjs +76 -15
- package/src/main.mjs +11 -2
package/README.md
CHANGED
|
@@ -79,6 +79,7 @@ The Evidence/ folder produced by every profile is a **stable public contract**
|
|
|
79
79
|
|
|
80
80
|
| Verb | Profile | Window | What it does |
|
|
81
81
|
|------|---------|--------|--------------|
|
|
82
|
+
| `setup` | core+ | n/a | Functionally verify WorkIQ is reachable + auto-fill contributor identity. Idempotent. Run once per machine before first `bootstrap`/`refresh`. |
|
|
82
83
|
| `aggregate` | core+ | last watermark → now | Pull every enabled source + consolidate. **No State/ rebuild.** |
|
|
83
84
|
| `bootstrap` | standard+ | 30 days (default) | First-time setup — scaffold folders, lay configs side-by-side, initial pull. Profile-aware (builds State only on `full`). |
|
|
84
85
|
| `refresh` | standard+ | last watermark → now | Pull only what changed. Profile-aware (rebuilds State only on `full`). |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kushi-agents",
|
|
3
|
-
"version": "4.4.
|
|
3
|
+
"version": "4.4.4",
|
|
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": {
|
|
@@ -16,7 +16,7 @@ Kushi ships in three profiles. The installed profile is recorded in `kushi-insta
|
|
|
16
16
|
|
|
17
17
|
| Profile | What's installed | Verbs available |
|
|
18
18
|
|---|---|---|
|
|
19
|
-
| `core` | Aggregator only: `pull-*`, `consolidate-evidence`, `aggregate-project`, `ask-project`, `project-status`, `self-check`, `intro` | `aggregate`, `consolidate`, `status`, `pull`, `ask` |
|
|
19
|
+
| `core` | Aggregator only: `setup`, `pull-*`, `consolidate-evidence`, `aggregate-project`, `ask-project`, `project-status`, `self-check`, `intro` | `setup`, `aggregate`, `consolidate`, `status`, `pull`, `ask` |
|
|
20
20
|
| `standard` *(default)* | core + `bootstrap-project`, `refresh-project`, `fde-intake`, `fde-report`, `fde-triage` + FDE reference pack | core + `bootstrap`, `refresh`, `fde-intake`, `fde-report`, `fde-triage` |
|
|
21
21
|
| `full` | standard + `build-state` | standard + `state` |
|
|
22
22
|
| **`preview`** *(opt-in)* | standard + `propose-ado-update`, `apply-ado-update` | standard + `propose-ado`, `apply-ado` |
|
|
@@ -29,6 +29,7 @@ The Evidence/ folder produced by `aggregate` is the **public contract** between
|
|
|
29
29
|
|
|
30
30
|
| Verb | Profile | Default window | Calls (in order) |
|
|
31
31
|
|---|---|---|---|
|
|
32
|
+
| `@Kushi setup` | core+ | n/a (read-only) | `setup` — functional WorkIQ ping + identity auto-fill. Idempotent; safe to re-run. Required before first bootstrap/refresh. |
|
|
32
33
|
| `@Kushi aggregate <project>` | core+ | since last watermark | `aggregate-project` → `pull-*` (all enabled) → `consolidate-evidence`. **No build-state.** |
|
|
33
34
|
| `@Kushi aggregate <project> last N days` / `since <date>` / `<from>..<to>` | core+ | as supplied | same |
|
|
34
35
|
| `@Kushi bootstrap <project>` | standard+ | last 30 days | `bootstrap-project` → `pull-*` → `consolidate-evidence` → (full only) `build-state` |
|
|
@@ -85,8 +86,9 @@ See `instructions/snapshot-vs-stream.instructions.md` for the full rule.
|
|
|
85
86
|
|
|
86
87
|
When a user message arrives:
|
|
87
88
|
|
|
88
|
-
1. Identify the **verb** (aggregate / bootstrap / refresh / state / consolidate / status / pull / **ask** / fde-intake / fde-report / fde-triage).
|
|
89
|
+
1. Identify the **verb** (setup / aggregate / bootstrap / refresh / state / consolidate / status / pull / **ask** / fde-intake / fde-report / fde-triage).
|
|
89
90
|
- If the message starts with an explicit producer verb → use it.
|
|
91
|
+
- **setup** dispatches immediately on `setup`, `verify workiq`, `who am I to kushi`, `fix my install`, `setup kushi`.
|
|
90
92
|
- Else if the message contains a known project name AND a question shape (interrogative, "status of", "summarize", bare `<project> <topic>`) → `ask`.
|
|
91
93
|
- Else → ask the user to clarify.
|
|
92
94
|
2. **Profile check**: confirm the chosen verb is listed in `kushi-install.json#verbs`. If not, surface: *"Verb `<verb>` requires the `<profile>` profile. Re-install with `npx kushi-agents --clawpilot --profile <profile> --force`."* and stop.
|
|
@@ -48,7 +48,7 @@ For every M365 source in scope:
|
|
|
48
48
|
|
|
49
49
|
## Canonical WorkIQ commands (CODIFIED — do not re-discover)
|
|
50
50
|
|
|
51
|
-
The CLI is
|
|
51
|
+
The CLI is resolved in this order: `<workspace>/.kushi/config/user/project-evidence.yml workiq.cli_path` → `Get-Command workiq` (PATH) → `~/.copilot/bin/workiq[.cmd]` (Clawpilot-managed convenience fallback, probed only if it already exists). The legacy `~/.kushi/bin/workiq.cmd` path was removed in v4.4.4 — see the `setup` skill for the functional verification flow.
|
|
52
52
|
|
|
53
53
|
Invocation shape:
|
|
54
54
|
|
|
@@ -153,7 +153,7 @@ List my Teams meetings between <YYYY-MM-DD> and <YYYY-MM-DD> where the subject c
|
|
|
153
153
|
|
|
154
154
|
Before the first WorkIQ query in a run:
|
|
155
155
|
|
|
156
|
-
1. Resolve CLI path: `<workspace>/.kushi/config/user/project-evidence.yml workiq.cli_path` → `Get-Command workiq` → `~/.
|
|
156
|
+
1. Resolve CLI path: `<workspace>/.kushi/config/user/project-evidence.yml workiq.cli_path` → `Get-Command workiq` → `~/.copilot/bin/workiq[.cmd]` (Clawpilot-managed, only if present). If none resolves → log `workiq-not-on-path`, write evidence file pointing at install docs, STOP this source. The legacy `~/.kushi/bin/workiq.cmd` probe was removed in v4.4.4; the `setup` skill handles the recovery flow.
|
|
157
157
|
2. Probe with `workiq ask -q "ping"`. If EULA prompt → `workiq accept-eula` once, retry.
|
|
158
158
|
3. Capture `--version` once into run-log for audit.
|
|
159
159
|
|
package/plugin/plugin.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kushi",
|
|
3
3
|
"description": "Multi-source project evidence + Q&A agent. Snapshot + stream capture across Email, Teams, OneNote, SharePoint, Meetings, CRM, ADO; plus read-only natural-language Q&A over the captured evidence. WorkIQ-only for M365 sources (Graph / m365_* FORBIDDEN as fallbacks; user-paste is first-class). Host-agnostic. Three install profiles: core (aggregator only), standard (default — adds bootstrap/refresh + FDE authoring), full (adds State/ rollup).",
|
|
4
|
-
"version": "3.12.
|
|
4
|
+
"version": "3.12.2",
|
|
5
5
|
"author": "ushakrishnan",
|
|
6
6
|
"repository": "https://github.com/gim-home/kushi",
|
|
7
7
|
"default_profile": "standard",
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
"skills": [
|
|
12
12
|
"intro",
|
|
13
13
|
"self-check",
|
|
14
|
+
"setup",
|
|
14
15
|
"pull-email",
|
|
15
16
|
"pull-teams",
|
|
16
17
|
"pull-meetings",
|
|
@@ -24,6 +25,7 @@
|
|
|
24
25
|
"ask-project"
|
|
25
26
|
],
|
|
26
27
|
"prompts": [
|
|
28
|
+
"setup",
|
|
27
29
|
"aggregate",
|
|
28
30
|
"consolidate",
|
|
29
31
|
"status",
|
|
@@ -36,6 +38,7 @@
|
|
|
36
38
|
],
|
|
37
39
|
"reference_packs": [],
|
|
38
40
|
"verbs": [
|
|
41
|
+
"setup",
|
|
39
42
|
"aggregate",
|
|
40
43
|
"consolidate",
|
|
41
44
|
"status",
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: setup
|
|
3
|
+
description: "Functionally verify WorkIQ is reachable + auto-fill contributor identity into project-evidence.yml. Run once per machine; idempotent."
|
|
4
|
+
argument-hint: "(no args) — pings WorkIQ, captures identity, persists to ~/.kushi config"
|
|
5
|
+
agent: kushi
|
|
6
|
+
tools: [search, read/readFile, edit, agent]
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## User Input
|
|
10
|
+
|
|
11
|
+
```text
|
|
12
|
+
(none)
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
# /setup
|
|
16
|
+
|
|
17
|
+
Route to `@Kushi setup`.
|
|
18
|
+
|
|
19
|
+
Runs the **setup** skill:
|
|
20
|
+
|
|
21
|
+
1. Resolves the workiq CLI path (pinned `cli_path` → PATH → Clawpilot-managed `~/.copilot/bin/workiq` fallback). **No `~/.kushi/bin/` filesystem probe** (removed in v4.4.4).
|
|
22
|
+
2. Functionally verifies WorkIQ by sending: *"Who am I? Return UPN, displayName, mailNickname as JSON."*
|
|
23
|
+
3. Parses the response and writes `identity` (alias / display_name / email) into `<workspace>/.kushi/config/user/project-evidence.yml`, preserving comments.
|
|
24
|
+
4. On failure, walks the user through install / sign-in / retry using `ask_user` (no outbound sends).
|
|
25
|
+
5. Prints a green status table summarizing host, cli_path, identity, and persistence target.
|
|
26
|
+
|
|
27
|
+
**Idempotent.** Re-running on a healthy machine re-verifies the connection and exits cleanly — bootstrap / refresh are blocked until this skill records `identity_status: verified`.
|
|
28
|
+
|
|
29
|
+
Delegates to `setup` skill.
|
|
@@ -61,11 +61,7 @@ Hard stop if WorkIQ returns auth error or empty — print the WorkIQ sign-in hin
|
|
|
61
61
|
Verify in order. Stop on hard failures.
|
|
62
62
|
|
|
63
63
|
1. **OS + host runtime** — display OS + Node/PowerShell version. Informational.
|
|
64
|
-
2. **WorkIQ install (REQUIRED, hard stop)** — read `<workspace>/.kushi/config/user/project-evidence.yml workiq.cli_path`. If missing, probe
|
|
65
|
-
- `$HOME\.kushi\bin\workiq.cmd`
|
|
66
|
-
- `$env:LOCALAPPDATA\Programs\WorkIQ\workiq.cmd`
|
|
67
|
-
- `$env:ProgramFiles\WorkIQ\workiq.cmd`
|
|
68
|
-
If found, persist path. If not found, ask user for path (or to install). Test with `<workiq.cli_path> --help`. Without WorkIQ, M365 sources will all fail — STOP.
|
|
64
|
+
2. **WorkIQ install (REQUIRED, hard stop)** — read `<workspace>/.kushi/config/user/project-evidence.yml workiq.cli_path`. If missing, dispatch the `setup` skill (which does a functional `workiq ask -q "Who am I?"` check, captures identity, and walks the user through install/sign-in on failure). **Do NOT probe `$HOME\.kushi\bin\` — removed in v4.4.4** because it triggered VS Code's "Allow reading external directory?" prompt even on machines where workiq was already on PATH. If `setup` returns `identity_status: skipped-*`, STOP — bootstrap is blocked until WorkIQ is reachable.
|
|
69
65
|
3. **Conditional az login** — only if `<workspace>/.kushi/config/shared/integrations.yml` OR `<workspace>/.kushi/config/shared/integrations.yml` exists. Per `az-auth-conditional.instructions.md`. Soft warning on failure, never blocking.
|
|
70
66
|
4. **Engagement-root resolution** — per `engagement-root-resolution.instructions.md`. Persist to `<workspace>/.kushi/config/user/project-evidence.yml engagement_root` if newly resolved.
|
|
71
67
|
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: "setup"
|
|
3
|
+
version: "1.0.0"
|
|
4
|
+
description: "First-run machine setup for Kushi. Functionally verifies WorkIQ is reachable by sending a real query, captures contributor identity (alias / display_name / email) from the response, persists it to `<workspace>/.kushi/config/user/project-evidence.yml`, and walks the user through workiq install/start if it is not running. Idempotent — re-running on a healthy machine prints a green status table and exits. Modeled on the wss-cto-write-connect `setup.agent.md` Step 6 pattern: ping the service, ask the user nothing the service can already answer."
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Skill: setup
|
|
8
|
+
|
|
9
|
+
> **Doctrine**: WorkIQ is a **service**, not a binary on disk. This skill probes it functionally (sends a real query) instead of probing the filesystem. Avoids the v3.x `~/.kushi/bin/` external-directory prompt and the dead-config UX where `<auto>` placeholders surface to the user.
|
|
10
|
+
>
|
|
11
|
+
> **No outbound messages.** This skill never sends Teams / email / RSVP. Identity capture only writes the local YAML.
|
|
12
|
+
>
|
|
13
|
+
> **Idempotent.** Re-running on a machine where everything is healthy prints the green status table and exits cleanly. Safe to wire into `bootstrap-project` Step 1.
|
|
14
|
+
|
|
15
|
+
Run this skill when:
|
|
16
|
+
|
|
17
|
+
- The user says `setup`, `kushi setup`, `verify workiq`, `who am I to kushi`, `fix my install`, `setup kushi`.
|
|
18
|
+
- The installer finished and printed `Run \`setup\` once to verify WorkIQ + auto-fill identity`.
|
|
19
|
+
- A `pull-*` or `bootstrap-project` skill is about to fire its first WorkIQ query in a workspace whose `project-evidence.yml#identity` is still `<auto>` / missing.
|
|
20
|
+
|
|
21
|
+
## What it does
|
|
22
|
+
|
|
23
|
+
1. Detects the host runtime + workiq.cli_path (no filesystem probes beyond an explicit `cli_path`).
|
|
24
|
+
2. **Functionally verifies WorkIQ** by sending one query: *"Who am I? Return UPN, displayName, mailNickname as JSON."*
|
|
25
|
+
3. On success, persists the captured identity to `<workspace>/.kushi/config/user/project-evidence.yml#identity` (preserving comments + other keys).
|
|
26
|
+
4. On failure, walks the user through starting WorkIQ via the host's documented entry point, then retries.
|
|
27
|
+
5. Prints a final status table the user can screenshot to file with IT support.
|
|
28
|
+
|
|
29
|
+
## Inputs
|
|
30
|
+
|
|
31
|
+
None. The skill discovers everything it needs.
|
|
32
|
+
|
|
33
|
+
Optional flags surfaced by the user:
|
|
34
|
+
- `non-interactive` / `--yes` — skip `ask_user` retries on failure; emit a single actionable error and exit.
|
|
35
|
+
- `verbose` — print every probe step + raw workiq response.
|
|
36
|
+
|
|
37
|
+
## Steps
|
|
38
|
+
|
|
39
|
+
### Step 1 — Detect host runtime (informational)
|
|
40
|
+
|
|
41
|
+
Run `node --version`, `pwsh --version` (or `powershell -Command "$PSVersionTable.PSVersion"`), and capture the platform (`win32` / `darwin` / `linux`). Display:
|
|
42
|
+
|
|
43
|
+
```
|
|
44
|
+
🔍 Host: <platform> · Node <ver> · PowerShell <ver>
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Never blocking. Used only for the final status table.
|
|
48
|
+
|
|
49
|
+
### Step 2 — Resolve workiq CLI path (NO filesystem probe beyond explicit cli_path)
|
|
50
|
+
|
|
51
|
+
Resolution order (FIRST match wins):
|
|
52
|
+
|
|
53
|
+
1. **Explicit pin** — read `<workspace>/.kushi/config/user/project-evidence.yml#workiq.cli_path`. If present and the file exists on disk, use it.
|
|
54
|
+
2. **PATH lookup** — run `Get-Command workiq -ErrorAction SilentlyContinue` (Windows) / `command -v workiq` (Unix). If a result is returned, use the first executable hit.
|
|
55
|
+
3. **Host integration** — if the host is Clawpilot and `~/.copilot/bin/workiq[.cmd]` exists (this is the Clawpilot-managed location, not a kushi-managed location), use it as a final convenience fallback. **Do NOT probe `~/.kushi/bin/` — that path is removed from kushi doctrine as of v4.4.4.**
|
|
56
|
+
|
|
57
|
+
If none of the three resolves, jump to **Step 4 — Recovery prompt** with reason `cli-not-resolved`.
|
|
58
|
+
|
|
59
|
+
### Step 3 — Functional verification (the actual check)
|
|
60
|
+
|
|
61
|
+
Send this exact query (PowerShell shape — adapt single-quoting for bash):
|
|
62
|
+
|
|
63
|
+
```powershell
|
|
64
|
+
& "<resolved-cli-path>" ask -q 'Who am I? Return UPN, displayName, mailNickname strictly as a single JSON object with keys upn, displayName, mailNickname. No prose, no markdown fences.' 2>&1
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Timeout: 30 seconds. Capture both stdout and stderr.
|
|
68
|
+
|
|
69
|
+
**Parse the response.** Look for a JSON object containing all three keys. Strip any leading `request-id:` line that WorkIQ prepends. If WorkIQ wrapped the JSON in markdown fences (```json ... ```), strip them.
|
|
70
|
+
|
|
71
|
+
| Outcome | Next |
|
|
72
|
+
|---|---|
|
|
73
|
+
| Valid JSON with non-empty `upn`, `displayName`, `mailNickname` | Go to Step 5 (persist identity) |
|
|
74
|
+
| WorkIQ returned a summary / refusal / empty | Retry ONCE with stricter prompt: *"Output ONLY the JSON object, nothing else. Do not narrate, do not explain. {upn, displayName, mailNickname}."* If still no JSON, jump to Step 4 with reason `workiq-no-identity`. |
|
|
75
|
+
| Process timed out | Step 4 with reason `workiq-timeout` |
|
|
76
|
+
| Non-zero exit (auth error, ENOENT, etc.) | Step 4 with reason `workiq-exit-<code>` |
|
|
77
|
+
|
|
78
|
+
### Step 4 — Recovery prompt (only on Step-2 or Step-3 failure)
|
|
79
|
+
|
|
80
|
+
Display the platform-appropriate install/start block. Use `ask_user` to drive the recovery loop.
|
|
81
|
+
|
|
82
|
+
**Recovery messages by reason:**
|
|
83
|
+
|
|
84
|
+
```
|
|
85
|
+
cli-not-resolved (Windows)
|
|
86
|
+
⚙️ WorkIQ CLI not found.
|
|
87
|
+
|
|
88
|
+
Kushi could not locate the workiq executable in:
|
|
89
|
+
- <workspace>/.kushi/config/user/project-evidence.yml#workiq.cli_path (unset or path missing)
|
|
90
|
+
- the system PATH (no `workiq` on PATH)
|
|
91
|
+
- ~/.copilot/bin/workiq.cmd (Clawpilot-managed fallback; not present)
|
|
92
|
+
|
|
93
|
+
To install / start WorkIQ:
|
|
94
|
+
1. Open a NEW terminal window (keep this one open).
|
|
95
|
+
2. Run: winget install Microsoft.WorkIQ
|
|
96
|
+
(macOS: brew install --cask microsoft-workiq)
|
|
97
|
+
3. After install completes, run: workiq accept-eula
|
|
98
|
+
4. Then run: workiq ask -q "ping" — should print a non-empty response.
|
|
99
|
+
5. Come back to this window when done.
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
```
|
|
103
|
+
workiq-no-identity / workiq-timeout / workiq-exit-*
|
|
104
|
+
⚙️ WorkIQ is installed but did not respond to the identity query.
|
|
105
|
+
|
|
106
|
+
Likely causes (in priority order):
|
|
107
|
+
1. Not signed in. Run: workiq ask -q "ping"
|
|
108
|
+
(You'll be prompted to sign in on first call.)
|
|
109
|
+
2. Off-corpnet / VPN required. Reconnect and retry.
|
|
110
|
+
3. WorkIQ daemon not running. (Host-specific. Clawpilot users: restart Clawpilot.
|
|
111
|
+
VS Code Chat users: restart the workiq host process.)
|
|
112
|
+
4. Tenant misconfiguration. Check the configured tenant in your WorkIQ profile.
|
|
113
|
+
|
|
114
|
+
When ready, type 'retry' below.
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
`ask_user` choices:
|
|
118
|
+
|
|
119
|
+
- `retry` — re-run Step 3.
|
|
120
|
+
- `change-path` — prompt for an absolute path. Validate the file exists, persist to `project-evidence.yml#workiq.cli_path`, then re-run Step 2 → Step 3.
|
|
121
|
+
- `skip` — write a stub identity (`alias: 'unknown'`, `display_name: '(WorkIQ unreachable)'`, `email: 'unknown@unknown'`) AND mark `<workspace>/.kushi/config/user/project-evidence.yml#identity_status: "skipped-workiq-down"`. **bootstrap / refresh MUST refuse to run while `identity_status: skipped-*` is set**, surfacing "Run `setup` first" as the gate.
|
|
122
|
+
|
|
123
|
+
Recovery loop budget: **3 retries**. After the third failure, force `skip` mode and exit cleanly. Never crash — the user still has read-only verbs available.
|
|
124
|
+
|
|
125
|
+
### Step 5 — Persist identity (success path)
|
|
126
|
+
|
|
127
|
+
Open `<workspace>/.kushi/config/user/project-evidence.yml`. If the file does not exist, create it from `templates/init/project-evidence.template.yml`. Update the `identity:` block in place (preserve every other key + every comment) using a YAML-comment-safe rewrite. Map:
|
|
128
|
+
|
|
129
|
+
| WorkIQ field | YAML field | Notes |
|
|
130
|
+
|---|---|---|
|
|
131
|
+
| `upn` | `identity.email` | Verbatim. |
|
|
132
|
+
| `displayName` | `identity.display_name` | Verbatim. |
|
|
133
|
+
| `mailNickname` | `identity.alias` | Lowercase. Fallback to `email.split('@')[0]` if missing. |
|
|
134
|
+
|
|
135
|
+
Also write:
|
|
136
|
+
|
|
137
|
+
- `identity_status: "verified"` (so bootstrap/refresh stop pestering)
|
|
138
|
+
- `identity_verified_at: "<ISO-8601 UTC>"`
|
|
139
|
+
- `workiq.cli_path: "<resolved-path>"` (only if it was discovered via PATH or host-integration and not yet pinned)
|
|
140
|
+
|
|
141
|
+
### Step 6 — Print status table
|
|
142
|
+
|
|
143
|
+
```
|
|
144
|
+
WorkIQ Setup Complete
|
|
145
|
+
─────────────────────
|
|
146
|
+
✅ Host: win32 · Node v22.x · PowerShell 7.x
|
|
147
|
+
✅ workiq.cli_path C:\Users\<you>\.copilot\bin\workiq.cmd
|
|
148
|
+
✅ Identity Usha Krishnan <ushak@microsoft.com> (alias=ushak)
|
|
149
|
+
✅ Persisted to <workspace>/.kushi/config/user/project-evidence.yml
|
|
150
|
+
|
|
151
|
+
Next: kushi bootstrap <project> to bootstrap a project
|
|
152
|
+
kushi refresh <project> to refresh evidence
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
If recovery ended in `skip`, change the trailing lines to:
|
|
156
|
+
|
|
157
|
+
```
|
|
158
|
+
⚠️ WorkIQ unreachable. Identity not verified.
|
|
159
|
+
Re-run `setup` once WorkIQ is running. bootstrap / refresh are blocked
|
|
160
|
+
until then; `ask`, `status`, and Q&A verbs remain available.
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
## Notes
|
|
164
|
+
|
|
165
|
+
- This skill writes ONLY to `<workspace>/.kushi/config/user/project-evidence.yml`. It does NOT touch `shared/integrations.yml` (team-owned) or any project-level file.
|
|
166
|
+
- The functional check replaces the pre-v4.4.4 filesystem-probe pattern in `check-workiq.mjs` + `bootstrap-project SKILL.md` Step 1.2. Those still ship for backwards-compat at install time but are no longer the source of truth for "is WorkIQ healthy."
|
|
167
|
+
- See `instructions/identity-resolution.instructions.md` for the contract this skill implements.
|
|
168
|
+
|
|
169
|
+
## References
|
|
170
|
+
|
|
171
|
+
- `instructions/workiq-only.instructions.md` — WorkIQ-only doctrine for M365 sources.
|
|
172
|
+
- `instructions/identity-resolution.instructions.md` — contributor identity contract.
|
|
173
|
+
- `instructions/communication-guidelines.instructions.md` — chat-reply tone for the recovery prompts.
|
|
174
|
+
- `instructions/status-taxonomy.instructions.md` — `identity_status` value vocabulary.
|
|
@@ -42,7 +42,11 @@ active_projects:
|
|
|
42
42
|
# (Optional) Path to the WorkIQ CLI. If omitted, Kushi resolves in this order:
|
|
43
43
|
# 1. this `cli_path` value
|
|
44
44
|
# 2. `workiq` on PATH
|
|
45
|
-
# 3. ~/.
|
|
45
|
+
# 3. ~/.copilot/bin/workiq[.cmd] (Clawpilot-managed convenience fallback —
|
|
46
|
+
# probed ONLY if it already exists; never created by kushi)
|
|
47
|
+
# The legacy ~/.kushi/bin/ path is no longer probed (removed in v4.4.4 to avoid
|
|
48
|
+
# the VS Code "Allow reading external directory?" prompt). Run the `setup` skill
|
|
49
|
+
# to functionally verify WorkIQ is reachable and auto-fill your identity.
|
|
46
50
|
# workiq:
|
|
47
|
-
# cli_path: 'C:\
|
|
51
|
+
# cli_path: 'C:\Program Files\WorkIQ\workiq.cmd'
|
|
48
52
|
|
package/src/check-workiq.mjs
CHANGED
|
@@ -6,10 +6,17 @@ import os from 'node:os';
|
|
|
6
6
|
/**
|
|
7
7
|
* Probe for a working WorkIQ install.
|
|
8
8
|
*
|
|
9
|
-
* Resolution order:
|
|
9
|
+
* Resolution order (NO kushi-owned filesystem probe — see v4.4.4 doctrine):
|
|
10
10
|
* 1. explicit absolute path supplied via --workiq-path / opts.workiqPath
|
|
11
11
|
* 2. `workiq` on PATH (via `where` on Windows, `command -v` elsewhere)
|
|
12
|
-
* 3.
|
|
12
|
+
* 3. Clawpilot-managed convenience fallback: ~/.copilot/bin/workiq[.cmd]
|
|
13
|
+
* (only probed when it ALREADY exists — never created, never assumed)
|
|
14
|
+
*
|
|
15
|
+
* The old `~/.kushi/bin/workiq.cmd` probe was removed in v4.4.4: it caused
|
|
16
|
+
* VS Code to surface an "Allow reading external directory?" prompt for `bin`
|
|
17
|
+
* even on machines where workiq was already discoverable via PATH. The
|
|
18
|
+
* functional verification now happens in the `setup` skill via a real
|
|
19
|
+
* `workiq ask -q "Who am I?"` call, not a filesystem probe.
|
|
13
20
|
*
|
|
14
21
|
* Returns:
|
|
15
22
|
* { ok: true, path, version } — usable WorkIQ found
|
|
@@ -19,16 +26,9 @@ import os from 'node:os';
|
|
|
19
26
|
* 'not-found' — no workiq binary anywhere we looked
|
|
20
27
|
* 'path-invalid' — explicit --workiq-path was given but the file doesn't exist
|
|
21
28
|
* 'not-executable' — found but `--version` failed (corrupt install, missing deps, etc.)
|
|
29
|
+
* 'not-responsive' — runs `--version` ok but functional ping returned no JSON-shaped output
|
|
22
30
|
*/
|
|
23
31
|
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
32
|
if (opts.workiqPath) {
|
|
33
33
|
const abs = path.resolve(opts.workiqPath);
|
|
34
34
|
if (!existsSync(abs) || !statSync(abs).isFile()) {
|
|
@@ -44,9 +44,8 @@ export function checkWorkIQ(opts = {}) {
|
|
|
44
44
|
const onPath = findOnPath('workiq');
|
|
45
45
|
if (onPath) return runVersion(onPath);
|
|
46
46
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
}
|
|
47
|
+
const clawpilotBin = clawpilotManagedBin();
|
|
48
|
+
if (clawpilotBin) return runVersion(clawpilotBin);
|
|
50
49
|
|
|
51
50
|
return {
|
|
52
51
|
ok: false,
|
|
@@ -55,6 +54,27 @@ export function checkWorkIQ(opts = {}) {
|
|
|
55
54
|
};
|
|
56
55
|
}
|
|
57
56
|
|
|
57
|
+
/**
|
|
58
|
+
* Clawpilot installs workiq at ~/.copilot/bin/workiq[.cmd] as part of its own
|
|
59
|
+
* setup. We probe it ONLY if it already exists — we never create the dir, and
|
|
60
|
+
* we never probe `~/.kushi/bin/` (the v3.x location, removed in v4.4.4).
|
|
61
|
+
*/
|
|
62
|
+
function clawpilotManagedBin() {
|
|
63
|
+
const isWin = process.platform === 'win32';
|
|
64
|
+
const candidate = path.join(
|
|
65
|
+
os.homedir(),
|
|
66
|
+
'.copilot',
|
|
67
|
+
'bin',
|
|
68
|
+
isWin ? 'workiq.cmd' : 'workiq',
|
|
69
|
+
);
|
|
70
|
+
try {
|
|
71
|
+
if (existsSync(candidate) && statSync(candidate).isFile()) return candidate;
|
|
72
|
+
} catch {
|
|
73
|
+
// permission denied / external-dir prompt declined — treat as not present
|
|
74
|
+
}
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
|
|
58
78
|
function findOnPath(name) {
|
|
59
79
|
const isWin = process.platform === 'win32';
|
|
60
80
|
const cmd = isWin ? 'where' : 'command';
|
|
@@ -106,13 +126,54 @@ function runVersion(binPath) {
|
|
|
106
126
|
return { ok: true, path: binPath, version };
|
|
107
127
|
}
|
|
108
128
|
|
|
129
|
+
/**
|
|
130
|
+
* Functional check — sends a real `workiq ask -q "ping"` and confirms a
|
|
131
|
+
* non-empty response. Used by the installer's preflight AFTER runVersion()
|
|
132
|
+
* passes, so we don't ship users to bootstrap with a workiq binary that
|
|
133
|
+
* exists but can't actually answer queries (sign-in missing, daemon down,
|
|
134
|
+
* tenant misconfigured, etc.).
|
|
135
|
+
*
|
|
136
|
+
* Returns the same shape as runVersion(). On a soft failure we still return
|
|
137
|
+
* { ok: true } and just attach `.warning` so the installer can print a hint
|
|
138
|
+
* without hard-failing — the `setup` skill is responsible for the deep
|
|
139
|
+
* recovery flow.
|
|
140
|
+
*/
|
|
141
|
+
export function pingWorkIQ(binPath, { timeoutMs = 30_000 } = {}) {
|
|
142
|
+
const isWin = process.platform === 'win32';
|
|
143
|
+
const res = isWin
|
|
144
|
+
? spawnSync(`"${binPath}" ask -q "ping"`, {
|
|
145
|
+
encoding: 'utf-8',
|
|
146
|
+
timeout: timeoutMs,
|
|
147
|
+
shell: true,
|
|
148
|
+
})
|
|
149
|
+
: spawnSync(binPath, ['ask', '-q', 'ping'], {
|
|
150
|
+
encoding: 'utf-8',
|
|
151
|
+
timeout: timeoutMs,
|
|
152
|
+
});
|
|
153
|
+
const stdout = (res.stdout || '').trim();
|
|
154
|
+
const stderr = (res.stderr || '').trim();
|
|
155
|
+
if (res.status !== 0) {
|
|
156
|
+
return {
|
|
157
|
+
ok: true,
|
|
158
|
+
warning: `workiq ping returned exit ${res.status}. Run \`workiq ask -q "ping"\` manually to confirm sign-in. (${stderr.split(/\r?\n/)[0] || 'no stderr'})`,
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
if (!stdout) {
|
|
162
|
+
return {
|
|
163
|
+
ok: true,
|
|
164
|
+
warning: 'workiq ping returned empty stdout. The CLI is reachable but may not be signed in. Run `workiq ask -q "ping"` manually.',
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
return { ok: true };
|
|
168
|
+
}
|
|
169
|
+
|
|
109
170
|
function installHint() {
|
|
110
171
|
const plat = process.platform;
|
|
111
172
|
if (plat === 'win32') {
|
|
112
|
-
return 'Install with: winget install Microsoft.WorkIQ';
|
|
173
|
+
return 'Install with: winget install Microsoft.WorkIQ — then run `workiq ask -q "ping"` to sign in.';
|
|
113
174
|
}
|
|
114
175
|
if (plat === 'darwin') {
|
|
115
|
-
return 'Install with: brew install --cask microsoft-workiq';
|
|
176
|
+
return 'Install with: brew install --cask microsoft-workiq — then run `workiq ask -q "ping"` to sign in.';
|
|
116
177
|
}
|
|
117
178
|
return 'See https://gim-home.github.io/kushi/getting-started/install-workiq/ for Linux instructions.';
|
|
118
179
|
}
|
package/src/main.mjs
CHANGED
|
@@ -16,7 +16,7 @@ import { copyAssets } from './copy-assets.mjs';
|
|
|
16
16
|
import { mergeSettings } from './settings.mjs';
|
|
17
17
|
import { mergeCopilotInstructions } from './copilot-instructions.mjs';
|
|
18
18
|
import { seedConfig } from './seed-config.mjs';
|
|
19
|
-
import { checkWorkIQ, tryInstallWorkIQ } from './check-workiq.mjs';
|
|
19
|
+
import { checkWorkIQ, pingWorkIQ, tryInstallWorkIQ } from './check-workiq.mjs';
|
|
20
20
|
import {
|
|
21
21
|
resolveProfile,
|
|
22
22
|
makeIncludeFilter,
|
|
@@ -317,7 +317,16 @@ async function preflightWorkIQ(options) {
|
|
|
317
317
|
process.exit(1);
|
|
318
318
|
}
|
|
319
319
|
|
|
320
|
-
console.log(` ✓ WorkIQ detected at ${result.path} (${result.version})
|
|
320
|
+
console.log(` ✓ WorkIQ detected at ${result.path} (${result.version})`);
|
|
321
|
+
|
|
322
|
+
// Functional ping — confirm the binary actually answers queries, not just
|
|
323
|
+
// that it exists. Soft warning only; the `setup` skill does the deep
|
|
324
|
+
// recovery + identity capture on first verb run.
|
|
325
|
+
const ping = pingWorkIQ(result.path);
|
|
326
|
+
if (ping.warning) {
|
|
327
|
+
console.warn(` ⚠ ${ping.warning}`);
|
|
328
|
+
}
|
|
329
|
+
console.log(' Next: run `setup` once to verify sign-in + auto-fill your identity.\n');
|
|
321
330
|
}
|
|
322
331
|
|
|
323
332
|
/**
|