kushi-agents 4.2.3 → 4.4.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.
Files changed (41) hide show
  1. package/.github/copilot-instructions.kushi.md +4 -2
  2. package/package.json +2 -4
  3. package/plugin/agents/kushi.agent.md +7 -4
  4. package/plugin/instructions/azure-auth-patterns.instructions.md +2 -2
  5. package/plugin/instructions/bootstrap-status-format.instructions.md +24 -0
  6. package/plugin/instructions/engagement-root-resolution.instructions.md +3 -3
  7. package/plugin/instructions/identity-resolution.instructions.md +4 -4
  8. package/plugin/instructions/multi-user-shared-files.instructions.md +87 -0
  9. package/plugin/instructions/run-reports.instructions.md +1 -1
  10. package/plugin/instructions/side-by-side-config.instructions.md +23 -17
  11. package/plugin/instructions/tracking.instructions.md +1 -1
  12. package/plugin/instructions/workiq-only.instructions.md +2 -2
  13. package/plugin/lib/Get-KushiConfig.ps1 +109 -0
  14. package/plugin/prompts/aggregate.prompt.md +15 -4
  15. package/plugin/prompts/apply-ado.prompt.md +14 -5
  16. package/plugin/prompts/ask.prompt.md +12 -2
  17. package/plugin/prompts/bootstrap.prompt.md +27 -3
  18. package/plugin/prompts/consolidate.prompt.md +12 -2
  19. package/plugin/prompts/fde-intake.prompt.md +14 -5
  20. package/plugin/prompts/fde-report.prompt.md +15 -5
  21. package/plugin/prompts/fde-triage.prompt.md +14 -5
  22. package/plugin/prompts/propose-ado.prompt.md +14 -5
  23. package/plugin/prompts/refresh.prompt.md +12 -2
  24. package/plugin/prompts/state.prompt.md +11 -2
  25. package/plugin/prompts/status.prompt.md +11 -2
  26. package/plugin/reference-packs/README.md +1 -1
  27. package/plugin/skills/ask-project/SKILL.md +1 -1
  28. package/plugin/skills/bootstrap-project/SKILL.md +8 -6
  29. package/plugin/skills/intro/SKILL.md +2 -2
  30. package/plugin/skills/propose-ado-update/SKILL.md +1 -1
  31. package/plugin/templates/init/azuredevops.template.json +159 -0
  32. package/plugin/templates/init/dynamics365.template.json +412 -0
  33. package/{.github/config/m365-mutable.json.example → plugin/templates/init/m365-mutable.example.json} +1 -1
  34. package/plugin/templates/init/rsi-program-catalog.template.json +107 -0
  35. package/src/config-loader.mjs +69 -0
  36. package/src/constants.mjs +54 -18
  37. package/src/copy-assets.mjs +0 -76
  38. package/src/main.mjs +30 -26
  39. package/src/seed-config.mjs +88 -23
  40. package/src/seed-config.test.mjs +150 -0
  41. /package/{.github/config/m365-auth.json.example → plugin/templates/init/m365-auth.example.json} +0 -0
@@ -2,9 +2,9 @@
2
2
 
3
3
  This workspace has [Kushi](https://gim-home.github.io/kushi/) installed under `.kushi/`. Kushi captures multi-source project evidence (Email, Teams, OneNote, SharePoint, Meetings, CRM, ADO) via **WorkIQ** and answers cited questions over the captured evidence.
4
4
 
5
- ### Routing — no `@Kushi` prefix required
5
+ ### Routing — verbs are prompts
6
6
 
7
- When the user types any of the following verbs followed by a project name, route to the corresponding Kushi prompt in `.kushi/prompts/` (no `@Kushi` needed):
7
+ Every Kushi verb is a **prompt file** in `.kushi/prompts/<verb>.prompt.md` with `agent: kushi` in its frontmatter. When the user types one of the verbs below (with or without `@Kushi`), open the prompt and execute its instructions — do **not** shell out to `npx kushi-agents <verb>`. The `kushi-agents` npm package is the installer that put `.kushi/` on disk; it does not run verbs.
8
8
 
9
9
  | Verb | Prompt to run |
10
10
  | -------------------------- | ---------------- |
@@ -21,6 +21,8 @@ When the user types any of the following verbs followed by a project name, route
21
21
 
22
22
  Project Q&A also auto-dispatches when the user names a known project under the engagement root **and** asks a question about it — no prefix needed.
23
23
 
24
+ If a prompt file is missing for a verb the user typed, tell them "the `<verb>` prompt isn't installed in this profile" — do not shell out to reinstall. Re-installing is only appropriate when the user **explicitly** says "install kushi", "upgrade kushi", or "reinstall kushi".
25
+
24
26
  ### Hard rules (enforced by Kushi skills)
25
27
 
26
28
  - **WorkIQ-first** for all M365 sources. `m365_*` / Microsoft Graph calls are only allowed as a classified fallback after a documented WorkIQ failure.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kushi-agents",
3
- "version": "4.2.3",
3
+ "version": "4.4.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": {
@@ -10,8 +10,6 @@
10
10
  "bin/",
11
11
  "src/",
12
12
  "plugin/",
13
- ".github/config/m365-auth.json.example",
14
- ".github/config/m365-mutable.json.example",
15
13
  ".github/copilot-instructions.kushi.md"
16
14
  ],
17
15
  "engines": {
@@ -43,7 +41,7 @@
43
41
  },
44
42
  "license": "MIT",
45
43
  "scripts": {
46
- "test": "node --test src/check-workiq.test.mjs",
44
+ "test": "node --test src/check-workiq.test.mjs src/seed-config.test.mjs",
47
45
  "smoke": "node scripts/smoke.mjs",
48
46
  "prepublishOnly": "npm test && npm run smoke"
49
47
  },
@@ -1,11 +1,14 @@
1
1
  ---
2
+ name: Kushi
2
3
  description: "Kushi — 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-first for capture, citation-only for answers. Host-agnostic. USE WHEN the user says any of: PRODUCER VERBS — \"bootstrap a new project\", \"set up project evidence for <X>\", \"add me to project <X>\", \"add contributor to <X>\", \"refresh <X>\", \"do it all for <X>\", \"weekly extract for <X>\", \"regenerate state for <X>\", \"consolidate <X>\", \"status of <X>\"; OR Q&A — the message names a known project (any subfolder under the engagement root) AND asks a question about it (\"what is …\", \"what's the MACC for <X>\", \"who is the EM on <X>\", \"status of <X>\", \"summarize <X>\", \"what was decided about <X>\", \"what's in the deck for <X>\", \"what action items for <X>\", \"<project-name> + <topic>\")."
3
- tools: ["*"]
4
+ argument-hint: "Name a project (e.g. 'bootstrap HCA', 'refresh AGCO last 14 days', 'ask HCA what's the MACC?'). Kushi routes to the right verb prompt — never run `npx kushi-agents <verb>` in the terminal."
5
+ tools:
6
+ [vscode/vscodeAPI, execute/getTerminalOutput, execute/runInTerminal, read/readFile, read/terminalSelection, read/terminalLastCommand, agent, edit, search, web, browser, 'workiq/*', 'github/*']
4
7
  ---
5
8
 
6
9
  # @Kushi — Project Evidence Orchestrator
7
10
 
8
- Kushi is a multi-source evidence + state agent for consulting / engineering engagements. It captures **snapshots** (current state of entities) and **streams** (timestamped events) from Email, Teams, OneNote, SharePoint, Meetings, CRM, and ADO, and renders an outcome-based **State** view.
11
+ Kushi is a multi-source evidence + state agentfor consulting / engineering engagements. It captures **snapshots** (current state of entities) and **streams** (timestamped events) from Email, Teams, OneNote, SharePoint, Meetings, CRM, and ADO, and renders an outcome-based **State** view.
9
12
 
10
13
  ## Install profiles
11
14
 
@@ -95,8 +98,8 @@ When a user message arrives:
95
98
  ## Configuration layout
96
99
 
97
100
  ```
98
- <workspace>/.kushi/config/project-evidence.yml ← personal: alias, engagement_root, active_projects (seeded by installer; never overwritten)
99
- <workspace>/.kushi/config/integrations.yml ← optional global CRM/ADO defaults (seeded by installer; never overwritten)
101
+ <workspace>/.kushi/config/user/project-evidence.yml ← personal: alias, engagement_root, active_projects (seeded by installer; never overwritten)
102
+ <workspace>/.kushi/config/shared/integrations.yml ← optional global CRM/ADO defaults (seeded by installer; never overwritten)
100
103
  <engagement-root>/.project-evidence/ ← per-machine, per-user M365 + CRM + ADO config (OneDrive-synced)
101
104
  m365/m365-auth.json
102
105
  m365/m365-mutable.json
@@ -227,7 +227,7 @@ Maintained alongside `auth-and-retry §3` (canonical) — quick lookup:
227
227
  | Dynamics 365 / CRM | `<engagement-root>/.project-evidence/crm/config.yml` |
228
228
  | Azure DevOps | `<engagement-root>/.project-evidence/ado/config.yml` |
229
229
  | Microsoft Graph / M365 / OneNote | `<engagement-root>/.project-evidence/m365/m365-mutable.json` + `<engagement-root>/.project-evidence/m365/m365-auth.json` |
230
- | WorkIQ CLI path | `<workspace>/.kushi/config/project-evidence.yml` (workspace-scoped) |
231
- | Global integrations (optional) | `<workspace>/.kushi/config/integrations.yml` |
230
+ | WorkIQ CLI path | `<workspace>/.kushi/config/user/project-evidence.yml` (workspace-scoped) |
231
+ | Global integrations (optional) | `<workspace>/.kushi/config/shared/integrations.yml` |
232
232
 
233
233
  Always read tenant IDs, resource URLs, org URLs, and allowed-tenant lists from these files at the start of each run. **Never hardcode them in skills or prompts.** The only acceptable literal in instructions/prompts is the public Microsoft tenant ID `72f988bf-86f1-41af-91ab-2d7cd011db47` in the user-facing `az login --tenant ...` suggestion text.
@@ -79,6 +79,30 @@ Use these exact strings everywhere (table cells, run-log, narrative):
79
79
  - `ado-not-complete` — engagement record not found yet OR ADO linkage missing
80
80
  - `completed-with-coverage-gaps` — final outcome with explicit gaps recorded
81
81
 
82
+ ## Multi-contributor safety (kushi v4.4.0+)
83
+
84
+ `<project>/bootstrap-status.md` is shared across all contributors via OneDrive. Per `multi-user-shared-files.instructions.md`:
85
+
86
+ 1. **Before writing**, scan `<project>/` for sibling conflict copies (e.g. `bootstrap-status-conflict-<alias>-<host>.md` or OneDrive's `bootstrap-status (Stan's conflicted copy *)`). If any exist, merge their content into the canonical file (taking the most recent per-source row) and delete the conflict copies. Log this in the per-user bootstrap report under `## Conflict copies merged`.
87
+ 2. **Preserve other contributors' attribution.** Read the existing file; the `## Contributors who have bootstrapped this project` section MUST keep one row per alias that has ever written it. Update only the row matching the current alias.
88
+ 3. **Per-source rows** in `## Context Artifact Status` reflect the most recent discovery across all contributors. Add a trailing `Discovered by` column showing which alias performed the latest discovery (cross-referenced from each alias's `m365-mutable.json` via `Get-KushiConfig`).
89
+ 4. **The final one-line status** is for the most recent run only and may be overwritten by any contributor.
90
+
91
+ ### Required `## Contributors who have bootstrapped this project` section
92
+
93
+ Append this section immediately after `## Bootstrap Status`:
94
+
95
+ ```
96
+ ## Contributors who have bootstrapped this project
97
+
98
+ | Alias | Display Name | Last Run | Mode | Outcome |
99
+ |---|---|---|---|---|
100
+ | ushak | Usha Kandregula | 2026-05-20 07:42 EDT | bootstrap | bootstrap-complete-with-coverage-gaps |
101
+ | stand | Stan Doe | 2026-05-18 16:01 EDT | refresh | refresh-complete |
102
+ ```
103
+
104
+ Preserve every existing row except the one matching your alias.
105
+
82
106
  ## Sections to AVOID in bootstrap-status
83
107
 
84
108
  Do NOT keep these in `bootstrap-status.md` (they belong elsewhere or become stale):
@@ -11,9 +11,9 @@ The **engagement-root** is the parent folder that contains all of the user's eng
11
11
 
12
12
  Resolve `<engagement-root>` in this order — first match wins:
13
13
 
14
- 1. **`<workspace>/.kushi/config/project-evidence.yml`** — read `engagement_root:` field (preferred).
14
+ 1. **`<workspace>/.kushi/config/user/project-evidence.yml`** — read `engagement_root:` field (preferred).
15
15
  2. **`customer_workspace/FDEDocs/`** — if the user's workspace has this symlink, follow it. Common in FDE-style installs.
16
- 3. **Ask the user** once and persist the answer to `<workspace>/.kushi/config/project-evidence.yml engagement_root`.
16
+ 3. **Ask the user** once and persist the answer to `<workspace>/.kushi/config/user/project-evidence.yml engagement_root`.
17
17
 
18
18
  ## Live config location
19
19
 
@@ -43,7 +43,7 @@ Once `<engagement-root>` is known, individual projects are subfolders:
43
43
  Project name resolution (always fuzzy):
44
44
 
45
45
  1. Match against keys in `<engagement-root>/.project-evidence/m365/m365-mutable.json m365Mutable.knownSections`.
46
- 2. Match against `active_projects:` in `<workspace>/.kushi/config/project-evidence.yml`.
46
+ 2. Match against `active_projects:` in `<workspace>/.kushi/config/user/project-evidence.yml`.
47
47
  3. Match against actual subfolder names under `<engagement-root>`.
48
48
 
49
49
  Case-insensitive; ranking `exact > prefix > contains`. Multiple plausible candidates → ask user to pick. Zero candidates AND verb is `bootstrap` → create the folder. Zero candidates AND verb is anything else → ask user.
@@ -1,6 +1,6 @@
1
1
  ---
2
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."
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/user/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
4
  ---
5
5
 
6
6
  # Identity Resolution — Don't Ask, Probe
@@ -9,7 +9,7 @@ Kushi must not prompt the user for `alias`, `email`, or `display_name`. These ar
9
9
 
10
10
  ## When to resolve
11
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`:
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/user/project-evidence.yml`:
13
13
 
14
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
15
  * If all three are explicit non-placeholder values → **skip**. Respect the user's override.
@@ -32,9 +32,9 @@ Map the response:
32
32
 
33
33
  ## After resolution
34
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.
35
+ 1. **Persist back** to `<workspace>/.kushi/config/user/project-evidence.yml` (preserving comments + indentation). The user sees the resolved values on next open; no surprise.
36
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.
37
+ > ✓ Identity: `Alex Smith <alex@microsoft.com>` (alias=`alex`). Edit `.kushi/config/user/project-evidence.yml` to override.
38
38
  3. **Continue** the prompt.
39
39
 
40
40
  ## Failure modes
@@ -0,0 +1,87 @@
1
+ ---
2
+ applyTo: "**/SKILL.md,**/*.prompt.md,**/Evidence/run-log.yml,**/integrations.yml,**/bootstrap-status.md,**/OPEN-QUESTIONS-DRAFT.md,**/State/09_open-questions.md,**/Evidence/contributors.yml"
3
+ ---
4
+
5
+ # Multi-user shared-file safety
6
+
7
+ ## Why this exists
8
+
9
+ A Kushi engagement folder (`<engagement-root>/<project>/`) is shared across all contributors via OneDrive. Several artifacts inside it are **logically shared** — every contributor reads and writes the same path:
10
+
11
+ | Shared artifact | Path | Writers |
12
+ |---|---|---|
13
+ | Per-project integrations | `<project>/integrations.yml` | `bootstrap-project`, `propose-ado-update`, `apply-ado-update`, every `pull-*` that discovers an ID |
14
+ | Bootstrap status snapshot | `<project>/bootstrap-status.md` | `bootstrap-project` (every run, any contributor) |
15
+ | Open questions draft | `<project>/OPEN-QUESTIONS-DRAFT.md` (or `State/09_open-questions.md` on full profile) | `bootstrap-project`, `consolidate-evidence`, `build-state`, `propose-ado-update` |
16
+ | Run log | `<project>/Evidence/run-log.yml` | every `pull-*`, `bootstrap-project`, `refresh-project`, `fde-*` |
17
+ | Contributors list | `<project>/Evidence/contributors.yml` | every `pull-*` (first time an alias touches the project) |
18
+
19
+ Without rules, two contributors running concurrently produce one of:
20
+ - OneDrive conflict-copy (`*-conflict-<alias>-<host>.yml`) — silent loss until manually merged.
21
+ - Last-writer-wins overwrite — silent loss of the other contributor's data.
22
+
23
+ This doctrine codifies the contract every writer must honor. It is **not** a substitute for proper locking, but it makes concurrent runs eventually consistent and recoverable.
24
+
25
+ ## Universal rules (apply to every shared artifact)
26
+
27
+ 1. **Read-modify-write, never blind-write.** Before writing any shared artifact, the skill MUST read the current file, merge its new contribution, and write the merged result. Blind overwrite is forbidden.
28
+ 2. **Detect and absorb conflict-copies.** Before reading the canonical file, glob for sibling files matching `<basename>-conflict-*` or `<basename> (<host>'s conflicted copy *)`. If any exist, merge their contents into the canonical file, then delete the conflict copies. Log the merge in the run report.
29
+ 3. **Stamp every contribution.** Every line / block / list-entry that a skill adds must carry its alias (from `project-evidence.yml`) and an ISO timestamp so future readers (and the merge logic above) can deterministically reconcile.
30
+ 4. **Idempotent appends.** Re-running the same skill in the same window MUST NOT duplicate prior entries. Use a `(alias, source, window_key)` tuple as the dedupe key.
31
+ 5. **Never delete another contributor's contribution.** A skill may only modify or remove entries it created (matched by alias). Cleanup of other aliases' entries is reserved for `consolidate-evidence`.
32
+
33
+ ## Per-artifact contracts
34
+
35
+ ### `<project>/integrations.yml`
36
+
37
+ - **Pattern**: read-modify-write with alias stamp on changed fields.
38
+ - Whenever a skill discovers a new ID (CRM `record_id`, ADO `engagement_id`, OneNote `section_file_id`, etc.), it MUST:
39
+ 1. Read the current file.
40
+ 2. If the target field is non-empty AND differs from the discovered value, write the discovered value into a sibling key `<field>_proposed_<alias>` and add a Q-row to `OPEN-QUESTIONS-DRAFT.md` for human reconciliation. Do not overwrite.
41
+ 3. If the target field is empty (or matches), write the value and append a comment line: `# resolved by <alias> on <YYYY-MM-DD>` immediately above the changed key.
42
+ - The `last_discovery_attempt` / `last_discovery_result` keys MAY be overwritten by any alias (they are intentionally last-writer-wins; the value is "the most recent attempt by anyone").
43
+
44
+ ### `<project>/bootstrap-status.md`
45
+
46
+ - **Pattern**: full rewrite is permitted, but the file MUST carry a `## Contributors who have bootstrapped this project` section listing every alias that has ever written it, with their last-run timestamp.
47
+ - Before rewriting, the skill MUST read the existing Contributors section and preserve every entry whose alias differs from the current alias. Update only its own alias row.
48
+ - The per-source status tables (`OneNote`, `Email`, `Teams`, etc.) reflect the **most recent** discovery across all contributors. Skills MUST cross-reference `m365-mutable.json` (which is per-user) — when a row shows discovered IDs, also note which alias performed the discovery in a trailing `(by <alias>)` cell.
49
+
50
+ ### `<project>/OPEN-QUESTIONS-DRAFT.md` and `<project>/State/09_open-questions.md`
51
+
52
+ - **Pattern**: append-only with dedup.
53
+ - Every question row carries `[asked by <alias> on <YYYY-MM-DD>]` as the trailing column.
54
+ - Before appending a new question, the skill MUST scan existing rows for a question whose normalized text (lowercased, whitespace-collapsed) matches. If a match exists, do not append a duplicate; instead, append `, <alias> on <date>` to the existing row's attribution.
55
+ - Rows are removed only by an explicit `resolve-open-question` action (out of scope here) — never by another `bootstrap` / `refresh` run.
56
+
57
+ ### `<project>/Evidence/run-log.yml`
58
+
59
+ - **Pattern**: structured append + max() merge.
60
+ - Run history (`runs:` list) is append-only. Every entry carries `alias:` and `run_at:`.
61
+ - Per-source watermarks (`sources.<source>.watermark`) use **max()** merge: when writing, the skill reads the current value and writes `max(current, new)`. Never overwrite with an older watermark.
62
+ - Per-source errors (`sources.<source>.errors[]`) are append-only with `alias` + `at` on every entry; dedup on `(alias, code, at)`.
63
+
64
+ ### `<project>/Evidence/contributors.yml`
65
+
66
+ - **Pattern**: append-only, alias-keyed.
67
+ - The first time an alias runs against the project, append `{ alias, display_name, email, first_seen: <YYYY-MM-DD> }`. Subsequent runs MUST NOT modify the entry.
68
+ - `last_seen` MAY be updated by any run, max()-merged.
69
+
70
+ ## Implementation guidance for skill authors
71
+
72
+ - Read `<workspace>/.kushi/config/user/project-evidence.yml` to get your alias via `Get-KushiConfig -Name 'project-evidence'`. Never hardcode aliases.
73
+ - For YAML merges, use `Get-Content -Raw | ConvertFrom-Yaml`, mutate, then `ConvertTo-Yaml`. Preserve comments where possible by line-based merging when structure permits.
74
+ - For Markdown table merges in `OPEN-QUESTIONS-DRAFT.md`, parse the body to a list of rows, dedup by normalized question text, re-emit.
75
+ - On any merge conflict the skill cannot resolve deterministically, write the alternative as a sibling-key `<field>_proposed_<alias>` (for YAML) or a `> Disagreement: <alias-A> says ..., <alias-B> says ...` callout (for Markdown) and add a Q-row to `OPEN-QUESTIONS-DRAFT.md`.
76
+
77
+ ## Out of scope
78
+
79
+ - True file locking (filesystem advisory locks, OneDrive's checkout API) — relies on platform support Kushi can't assume.
80
+ - Server-side merge service — Kushi is local-only by design.
81
+
82
+ ## Related doctrine
83
+
84
+ - `evidence-layout-canonical.instructions.md` — what lives where under `Evidence/`.
85
+ - `run-reports.instructions.md` — per-user run narrative (always under `Evidence/<alias>/`, no concurrency risk).
86
+ - `bootstrap-status-format.instructions.md` — format contract for the shared status artifact.
87
+ - `citation-ledger.instructions.md` — every assertion in shared artifacts must carry a citation; alias attribution is the citation for shared-file entries.
@@ -24,7 +24,7 @@ Critical for multi-user projects: each contributor's runs are independent, and e
24
24
  YYYY-MM-DD-HHmm_<mode>.md
25
25
  ```
26
26
 
27
- - `<alias>` — the contributor running the skill (from `<workspace>/.kushi/config/project-evidence.yml#alias`).
27
+ - `<alias>` — the contributor running the skill (from `<workspace>/.kushi/config/user/project-evidence.yml#alias`).
28
28
  - `<mode>` — one of `bootstrap`, `refresh`, `force-refresh`, `consolidate`.
29
29
  - Timestamp uses the **start time** of the run, in local time, format `YYYY-MM-DD-HHmm` (no seconds, no timezone — local-time prefix is enough for chronological sort).
30
30
 
@@ -5,20 +5,23 @@ description: "Side-by-side config rule — whenever the skill creates or changes
5
5
 
6
6
  # Side-by-side config rule (HARD RULE)
7
7
 
8
- Whenever the skill creates, changes, or extends any template in `<KUSHI_ROOT>/plugin/templates/init/`, it MUST also write the corresponding live file under `<engagement-root>/.project-evidence/`.
8
+ Whenever the skill creates, changes, or extends any template in `<KUSHI_ROOT>/plugin/templates/init/`, it MUST also write the corresponding live file in the workspace under `<workspace>/.kushi/config/user/` (for per-contributor identity + paths) or `<workspace>/.kushi/config/shared/` (for team-owned config the team commits).
9
9
 
10
10
  Templates stay generic; the live file gets the actual filled-in fact. Never leave the user with only the template — that's a half-done config.
11
11
 
12
- ## The two layers
12
+ ## The three layers
13
13
 
14
14
  | Layer | Where | Lifecycle |
15
15
  |---|---|---|
16
16
  | Template (generic) | `<KUSHI_ROOT>/plugin/templates/init/*.template.{json,yml}` | Ships with kushi, never edited per-user |
17
- | Live filled | `<engagement-root>/.project-evidence/*.{json,yml}` | Per-user, OneDrive-synced, edited by skill + user |
17
+ | Live shared | `<workspace>/.kushi/config/shared/*.{json,yml}` | Team-owned, committed; doctrine files overwrite on install, others seed-once |
18
+ | Live user | `<workspace>/.kushi/config/user/*.{json,yml}` | Per-contributor, gitignored; seed-once and preserved across upgrades |
19
+
20
+ Skills read configs via `<install-dest>/lib/Get-KushiConfig.ps1` which resolves `user/` first, then `shared/`.
18
21
 
19
22
  ## Discover → upsert immediately
20
23
 
21
- Any time the skill discovers a high-confidence fact about a project (folder id, chat id, OneNote section id, CRM record id, ADO WI id, stakeholder hint, alias) — upsert it into the live mutable file (`<engagement-root>/.project-evidence/m365/m365-mutable.json` under `m365Mutable.knownSections.<project>.<source>`) **in the same turn it was discovered**, with `discoveredOn: <today>` and `confidence: high|medium|low`.
24
+ Any time the skill discovers a high-confidence fact about a project (folder id, chat id, OneNote section id, CRM record id, ADO WI id, stakeholder hint, alias) — upsert it into the live mutable file (`<workspace>/.kushi/config/user/m365-mutable.json` under `m365Mutable.knownSections.<project>.<source>`) **in the same turn it was discovered**, with `discoveredOn: <today>` and `confidence: high|medium|low`.
22
25
 
23
26
  Don't wait until the end of the run.
24
27
 
@@ -38,19 +41,22 @@ End every bootstrap / fix-up turn by listing the live config files (path + size
38
41
  ## Live config locations
39
42
 
40
43
  ```
41
- <engagement-root>/.project-evidence/
42
- m365/
43
- m365-auth.json ← stable (OneDrive-synced, hand-edited mostly)
44
- m365-mutable.json discovered hints, auto-updated by skill
45
- crm/
46
- config.yml Dataverse env URL, tenant, schema
47
- ado/
48
- config.yml organization, projects, queries
49
- project-evidence.yml (optional) per-engagement override of personal config
44
+ <workspace>/.kushi/config/
45
+ shared/ ← committed; doctrine + team defaults
46
+ azuredevops.json ← ADO org/project/field-map doctrine (overwritten on install)
47
+ dynamics365.json CRM env/schema doctrine (overwritten on install)
48
+ rsi-program-catalog.json ← RSI segment reference (overwritten on install)
49
+ integrations.yml optional team CRM/ADO defaults (seed-once)
50
+ *.example ← reference scaffolds (overwritten on install)
51
+ user/ gitignored; per-contributor
52
+ project-evidence.yml your alias, engagement-root, active projects (seed-once)
53
+ m365-auth.json ← your tenant, default notebook, mailbox folders (seed-once)
54
+ m365-mutable.json ← discovered hints, auto-updated by skill (seed-once)
50
55
  ```
51
56
 
52
- ## Why outside the kushi repo
57
+ ## Why side-by-side
53
58
 
54
- - **Multi-machine portability** — OneDrive-synced beside engagement folders, follows the user wherever they install kushi.
55
- - **Discoverability** — user can see/edit it next to their engagement work and inside their workspace at `<workspace>/.kushi/config/`, not buried in an OS-hidden home directory.
56
- - **Repo-safe** — kushi is meant to be GitHub-published; live filled configs MUST never be committed.
59
+ - **Self-contained** — everything Kushi needs to run lives under `.kushi/`. No `.github/config/` split, no `~/.copilot/` scatter.
60
+ - **Multi-user safe** — the `user/` tier is per-contributor and gitignored; `shared/` is committed once and stays in sync via git.
61
+ - **Discoverable** — visible in VS Code's file tree, not buried in an OS-hidden home directory.
62
+ - **Repo-safe** — `<workspace>/.kushi/.gitignore` (auto-written by installer) excludes `config/user/` so personal IDs never leak.
@@ -77,7 +77,7 @@ kushi_version: 4.1.0
77
77
  - Engagement root: `C:/.../Engagement Assets`
78
78
  - Project folder: `HCA Healthcare`
79
79
  - Alias: `ushak`
80
- - Config: `<workspace>/.kushi/config/project-evidence.yml`
80
+ - Config: `<workspace>/.kushi/config/user/project-evidence.yml`
81
81
 
82
82
  ## Steps taken
83
83
 
@@ -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 at `<USER_HOME>\.kushi\bin\workiq.cmd` (resolved from `<workspace>/.kushi/config/project-evidence.yml workiq.cli_path`; fall back to PATH; fall back to `~/.kushi/bin/workiq.cmd`).
51
+ The CLI is at `<USER_HOME>\.kushi\bin\workiq.cmd` (resolved from `<workspace>/.kushi/config/user/project-evidence.yml workiq.cli_path`; fall back to PATH; fall back to `~/.kushi/bin/workiq.cmd`).
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/project-evidence.yml workiq.cli_path` → `Get-Command workiq` → `~/.kushi/bin/workiq.cmd`. If none resolves → log `workiq-not-on-path`, write evidence file pointing at install docs, STOP this source.
156
+ 1. Resolve CLI path: `<workspace>/.kushi/config/user/project-evidence.yml workiq.cli_path` → `Get-Command workiq` → `~/.kushi/bin/workiq.cmd`. If none resolves → log `workiq-not-on-path`, write evidence file pointing at install docs, STOP this source.
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
 
@@ -0,0 +1,109 @@
1
+ <#
2
+ .SYNOPSIS
3
+ Resolve and load a Kushi config file from the two-tier .kushi/config/ layout.
4
+
5
+ .DESCRIPTION
6
+ Kushi configs live in <workspace>/.kushi/config/ split across two subdirs:
7
+ - user/ per-contributor identity & local paths (gitignored)
8
+ - shared/ team-owned, safe to commit (doctrine + team defaults)
9
+
10
+ Lookup order (highest-priority first):
11
+ 1. <workspace>/.kushi/config/user/<name>.<ext>
12
+ 2. <workspace>/.kushi/config/shared/<name>.<ext>
13
+
14
+ By default the file is parsed (JSON or YAML inferred from extension) and
15
+ returned as a PowerShell object. Use -Raw for raw text, or -Path to only
16
+ resolve the path.
17
+
18
+ Throws if the file is missing or appears to still hold template
19
+ placeholder values (sentinel `__FILL_ME_IN__` or `<auto>`). Suppress with
20
+ -AllowPlaceholders (needed for the identity-resolution flow which fills
21
+ `<auto>` on first run).
22
+
23
+ .PARAMETER Name
24
+ Logical config name, e.g. `project-evidence`, `m365-auth`, `azuredevops`.
25
+
26
+ .PARAMETER Extension
27
+ Override extension. Defaults: yml for project-evidence/integrations; json otherwise.
28
+
29
+ .PARAMETER Workspace
30
+ Workspace root. Defaults to the current location.
31
+
32
+ .EXAMPLE
33
+ $auth = Get-KushiConfig -Name 'm365-auth'
34
+ $notebookId = $auth.m365Auth.oneNote.defaultNotebookId
35
+
36
+ .EXAMPLE
37
+ $cfgPath = Get-KushiConfig -Name 'project-evidence' -Path
38
+ #>
39
+ [CmdletBinding()]
40
+ param(
41
+ [Parameter(Mandatory = $true, Position = 0)]
42
+ [string] $Name,
43
+
44
+ [ValidateSet('json', 'yml', 'yaml')]
45
+ [string] $Extension,
46
+
47
+ [string] $Workspace = (Get-Location).Path,
48
+
49
+ [switch] $Raw,
50
+ [switch] $Path,
51
+ [switch] $AllowPlaceholders
52
+ )
53
+
54
+ $ErrorActionPreference = 'Stop'
55
+
56
+ function Get-DefaultExtension([string] $name) {
57
+ if ($name -match '^(project-evidence|integrations)$') { return 'yml' }
58
+ return 'json'
59
+ }
60
+
61
+ $ext = if ($PSBoundParameters.ContainsKey('Extension')) { $Extension } else { Get-DefaultExtension $Name }
62
+ $fileName = "$Name.$ext"
63
+
64
+ $configRoot = Join-Path $Workspace '.kushi/config'
65
+ $userPath = Join-Path $configRoot (Join-Path 'user' $fileName)
66
+ $sharedPath = Join-Path $configRoot (Join-Path 'shared' $fileName)
67
+
68
+ $resolved = $null
69
+ if (Test-Path -LiteralPath $userPath -PathType Leaf) { $resolved = $userPath }
70
+ elseif (Test-Path -LiteralPath $sharedPath -PathType Leaf) { $resolved = $sharedPath }
71
+
72
+ if (-not $resolved) {
73
+ throw @"
74
+ Kushi config '$Name' not found. Looked in:
75
+ - $userPath
76
+ - $sharedPath
77
+ Run `npx kushi-agents@latest` to (re)seed config files, then edit
78
+ $userPath with your values.
79
+ "@
80
+ }
81
+
82
+ if ($Path) { return $resolved }
83
+
84
+ $raw = Get-Content -LiteralPath $resolved -Raw
85
+
86
+ if (-not $AllowPlaceholders) {
87
+ if ($raw -match '__FILL_ME_IN__' -or $raw -match '<auto>') {
88
+ throw @"
89
+ Kushi config '$resolved' still has template placeholders (__FILL_ME_IN__ or <auto>).
90
+ Edit the file with your actual values, or pass -AllowPlaceholders to bypass this check.
91
+ "@
92
+ }
93
+ }
94
+
95
+ if ($Raw) { return $raw }
96
+
97
+ switch ($ext) {
98
+ 'json' {
99
+ return ($raw | ConvertFrom-Json -Depth 100)
100
+ }
101
+ { $_ -in 'yml','yaml' } {
102
+ if (Get-Module -ListAvailable -Name 'powershell-yaml') {
103
+ Import-Module powershell-yaml -ErrorAction Stop
104
+ return ConvertFrom-Yaml -Yaml $raw
105
+ }
106
+ Write-Warning "powershell-yaml not installed; returning raw YAML text. Install with: Install-Module powershell-yaml -Scope CurrentUser"
107
+ return $raw
108
+ }
109
+ }
@@ -1,7 +1,18 @@
1
- ---
2
- description: "Aggregate (pull + consolidate) without building State/."
3
- ---
4
-
1
+ ---
2
+ name: aggregate
3
+ description: "Aggregate (pull + consolidate) without building State/."
4
+ argument-hint: "Project name (engagement folder, fuzzy-matched); optional window"
5
+ agent: kushi
6
+ tools: [search, read/readFile, edit, agent, execute/runInTerminal, execute/getTerminalOutput, 'workiq/*']
7
+ ---
8
+
9
+ ## User Input
10
+
11
+ ```text
12
+ ${input:project:Project name, e.g. HCA}
13
+ ${input:window:Optional window — last N days, since YYYY-MM-DD, or YYYY-MM-DD..YYYY-MM-DD (default 7 days)}
14
+ ```
15
+
5
16
  # Aggregate
6
17
 
7
18
  Run `aggregate-project` for the named project.
@@ -1,8 +1,17 @@
1
- ---
2
- name: apply-ado
3
- description: Apply approved ADO updates from a proposed.md (gated). Currently a preview-stub — writes a planned.jsonl, no real ADO calls yet.
4
- ---
5
-
1
+ ---
2
+ name: apply-ado
3
+ description: "Apply approved ADO updates from a proposed.md (gated). Currently a preview-stub — writes a planned.jsonl, no real ADO calls yet."
4
+ argument-hint: "Project name; runs in dry-mode (writes planned.jsonl, no ADO calls)"
5
+ agent: kushi
6
+ tools: [search, read/readFile, edit, agent, execute/runInTerminal, 'github/*']
7
+ ---
8
+
9
+ ## User Input
10
+
11
+ ```text
12
+ ${input:project:Project name, e.g. HCA}
13
+ ```
14
+
6
15
  # /apply-ado
7
16
 
8
17
  Route to `@Kushi apply ado <project>`.
@@ -1,10 +1,20 @@
1
1
  ---
2
2
  name: ask
3
- description: Read-only Q&A over a bootstrapped project's State/, Evidence/, and snapshot/ files. Cited; no source pulls; no outbound. Auto-routes when you name a project + ask a question.
3
+ description: "Read-only Q&A over a bootstrapped project's State/, Evidence/, and snapshot/ files. Cited; no source pulls; no outbound. Auto-routes when you name a project + ask a question."
4
+ argument-hint: "Project name + a question about it"
5
+ agent: kushi
6
+ tools: [search, read/readFile, edit, agent]
4
7
  ---
5
8
 
6
- # /ask
9
+ ## User Input
10
+
11
+ ```text
12
+ ${input:project:Project name, e.g. HCA}
13
+ ${input:question:Your question, e.g. ''what is the MACC?''}
14
+ ```
7
15
 
16
+ # /ask
17
+
8
18
  Route to `@Kushi ask <project> <question>`.
9
19
 
10
20
  Loads the cheapest set of files needed to answer (`State/<topic>.md` first, then latest `Evidence/<alias>/_Consolidated/`, then per-source weekly files, then `external-context/`, then `<project>/SharePoint/snapshot/files/`), emits inline `[source: <alias>/<folder>/<file> · YYYY-MM-DD]` citations, warns if the relevant source is older than `chat.freshness_warn_days` (default 14), and ends with a Confidence line.
@@ -1,10 +1,20 @@
1
1
  ---
2
2
  name: bootstrap
3
- description: First-time setup for a new project — scaffold folders, lay configs side-by-side, do an initial 30-day pull, build State.
3
+ description: "First-time setup for a new project — scaffold folders, lay configs side-by-side, do an initial 30-day pull, build State."
4
+ argument-hint: "Project name (fuzzy-matched under engagement-root); optional initial pull window"
5
+ agent: kushi
6
+ tools: [search, read/readFile, edit, agent, execute/runInTerminal, execute/getTerminalOutput, 'workiq/*']
4
7
  ---
5
8
 
6
- # /bootstrap
9
+ ## User Input
10
+
11
+ ```text
12
+ ${input:project:Project name, e.g. HCA}
13
+ ${input:window:Optional initial pull window — last N days, since YYYY-MM-DD, or YYYY-MM-DD..YYYY-MM-DD (default 30 days)}
14
+ ```
7
15
 
16
+ # /bootstrap
17
+
8
18
  Route to `@Kushi bootstrap <project>`.
9
19
 
10
20
  Inputs the agent will resolve:
@@ -12,7 +22,21 @@ Inputs the agent will resolve:
12
22
  - `<window>` — defaults to 30 days. Override with `last 60 days`, `since 2026-04-01`, or `2026-04-01..2026-05-01`.
13
23
 
14
24
  Reads:
15
- - `<workspace>/.kushi/config/project-evidence.yml` for alias + engagement-root.
25
+ - `<workspace>/.kushi/config/user/project-evidence.yml` for alias + engagement-root.
26
+ - `<workspace>/.kushi/config/user/m365-auth.json` for tenant + default notebook + mailbox-folder hints.
27
+
28
+ **Step 0 — verify per-user config is filled.** Before any pull, call:
29
+
30
+ ```powershell
31
+ & "<install-dest>/lib/Get-KushiConfig.ps1" -Name 'project-evidence' -AllowPlaceholders | Out-Null # tolerates <auto>; identity-resolution fills it
32
+ & "<install-dest>/lib/Get-KushiConfig.ps1" -Name 'm365-auth' # hard-fails on placeholders
33
+ ```
34
+
35
+ If `Get-KushiConfig -Name 'm365-auth'` throws (file missing or still `__FILL_ME_IN__`), STOP and prompt the user:
36
+
37
+ > ⚠ `<workspace>/.kushi/config/user/m365-auth.json` still has template placeholders. Open it and fill in your tenant ID, default OneNote notebook ID, mailbox folder names, and SharePoint root before re-running `bootstrap`.
38
+
39
+ Continue only when both helper calls succeed.
16
40
 
17
41
  Produces:
18
42
  - `<engagement-root>/.project-evidence/m365/{m365-auth,m365-mutable}.json` (per-user filled)
@@ -1,10 +1,20 @@
1
1
  ---
2
2
  name: consolidate
3
- description: Merge all contributors' weekly streams into _Consolidated/ for a given window.
3
+ description: "Merge all contributors' weekly streams into _Consolidated/ for a given window."
4
+ argument-hint: "Project name; optional window"
5
+ agent: kushi
6
+ tools: [search, read/readFile, edit, agent, execute/runInTerminal, execute/getTerminalOutput, 'workiq/*']
4
7
  ---
5
8
 
6
- # /consolidate
9
+ ## User Input
10
+
11
+ ```text
12
+ ${input:project:Project name, e.g. HCA}
13
+ ${input:window:Optional window — last N days, since YYYY-MM-DD, or YYYY-MM-DD..YYYY-MM-DD (default 7 days)}
14
+ ```
7
15
 
16
+ # /consolidate
17
+
8
18
  Route to `@Kushi consolidate <project> <window>`.
9
19
 
10
20
  Default window: `last 7 days`.