kushi-agents 3.4.2 → 3.12.1

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 (69) hide show
  1. package/README.md +33 -0
  2. package/package.json +15 -3
  3. package/plugin/agents/kushi.agent.md +155 -147
  4. package/plugin/instructions/ado-bootstrap-discovery.instructions.md +111 -0
  5. package/plugin/instructions/ado-engagement-tree.instructions.md +73 -0
  6. package/plugin/instructions/answer-from-evidence.instructions.md +1 -1
  7. package/plugin/instructions/auth-and-retry.instructions.md +51 -16
  8. package/plugin/instructions/azure-auth-patterns.instructions.md +13 -6
  9. package/plugin/instructions/bootstrap-status-format.instructions.md +113 -0
  10. package/plugin/instructions/capture-learnings.instructions.md +95 -0
  11. package/plugin/instructions/cleanup-on-resolution.instructions.md +69 -0
  12. package/plugin/instructions/crm-bootstrap-discovery.instructions.md +79 -0
  13. package/plugin/instructions/crm-internal-vs-confirmed.instructions.md +79 -0
  14. package/plugin/instructions/evidence-confidence-ladder.instructions.md +66 -0
  15. package/plugin/instructions/evidence-layout-canonical.instructions.md +115 -0
  16. package/plugin/instructions/evidence-thoroughness.instructions.md +82 -12
  17. package/plugin/instructions/full-view-gate.instructions.md +91 -0
  18. package/plugin/instructions/m365-id-registry.instructions.md +134 -0
  19. package/plugin/instructions/meetings-verbatim-required.instructions.md +176 -0
  20. package/plugin/instructions/run-reports.instructions.md +129 -0
  21. package/plugin/instructions/scope-boundaries.instructions.md +218 -0
  22. package/plugin/instructions/snapshot-vs-stream.instructions.md +2 -0
  23. package/plugin/instructions/update-ledger.instructions.md +132 -0
  24. package/plugin/instructions/verbatim-by-default.instructions.md +73 -0
  25. package/plugin/instructions/workiq-first.instructions.md +15 -31
  26. package/plugin/instructions/workiq-only.instructions.md +193 -0
  27. package/plugin/learnings/README.md +50 -0
  28. package/plugin/learnings/ado.md +45 -0
  29. package/plugin/learnings/crm.md +96 -0
  30. package/plugin/learnings/cross-cutting.md +36 -0
  31. package/plugin/learnings/email.md +33 -0
  32. package/plugin/learnings/meetings.md +30 -0
  33. package/plugin/learnings/misc.md +46 -0
  34. package/plugin/learnings/onenote.md +215 -0
  35. package/plugin/learnings/sharepoint.md +5 -0
  36. package/plugin/learnings/teams.md +5 -0
  37. package/plugin/plugin.json +22 -2
  38. package/plugin/prompts/apply-ado.prompt.md +14 -0
  39. package/plugin/prompts/propose-ado.prompt.md +12 -0
  40. package/plugin/reference-packs/fde/crm-field-manifest.md +165 -0
  41. package/plugin/skills/apply-ado-update/SKILL.md +125 -0
  42. package/plugin/skills/ask-project/SKILL.md +2 -0
  43. package/plugin/skills/bootstrap-project/SKILL.md +81 -3
  44. package/plugin/skills/propose-ado-update/SKILL.md +108 -0
  45. package/plugin/skills/pull-ado/SKILL.md +173 -23
  46. package/plugin/skills/pull-crm/SKILL.md +168 -15
  47. package/plugin/skills/pull-email/SKILL.md +139 -22
  48. package/plugin/skills/pull-meetings/SKILL.md +109 -25
  49. package/plugin/skills/pull-misc/README.md +84 -0
  50. package/plugin/skills/pull-misc/SKILL.md +257 -0
  51. package/plugin/skills/pull-misc/runner.mjs +280 -0
  52. package/plugin/skills/pull-onenote/README.md +90 -0
  53. package/plugin/skills/pull-onenote/SKILL.md +400 -51
  54. package/plugin/skills/pull-onenote/runner.mjs +356 -0
  55. package/plugin/skills/pull-onenote/scripts/recapture-section-url.mjs +295 -0
  56. package/plugin/skills/pull-onenote/write-snapshot.mjs +271 -0
  57. package/plugin/skills/pull-sharepoint/SKILL.md +44 -12
  58. package/plugin/skills/pull-teams/SKILL.md +40 -11
  59. package/plugin/skills/refresh-project/SKILL.md +33 -2
  60. package/plugin/skills/self-check/run.ps1 +186 -4
  61. package/plugin/templates/ado-update/discussion-comment.template.md +26 -0
  62. package/plugin/templates/ado-update/integrations-ado-writes.example.yml +49 -0
  63. package/plugin/templates/ado-update/proposed.template.md +78 -0
  64. package/plugin/templates/init/external-links.template.txt +30 -0
  65. package/plugin/templates/init/project-integrations.template.yml +57 -2
  66. package/plugin/templates/snapshot/meeting-verbatim.template.md +110 -0
  67. package/plugin/templates/snapshot/meetings-series-index.template.md +3 -1
  68. package/plugin/templates/snapshot/onenote-page.template.md +92 -23
  69. package/plugin/templates/weekly/meetings-stream.template.md +11 -6
@@ -0,0 +1,176 @@
1
+ ---
2
+ applyTo: "**"
3
+ description: "HARD rule — meetings are an EXPIRING evidence class. Every meeting MUST have a sibling verbatim/ folder containing the raw chat thread + transcript text + recording URL. Curated 7-section snapshot is NOT a substitute; it cannot be rebuilt once the recording/transcript is purged by tenant retention."
4
+ ---
5
+
6
+ # Meetings verbatim is REQUIRED (HARD RULE, v3.10.0)
7
+
8
+ Meetings differ from every other evidence class in one critical way: **the source expires.**
9
+
10
+ - Teams recordings are deleted by tenant retention (default 60 days for many tenants; sometimes shorter).
11
+ - VTT transcripts are tied to the recording and disappear with it.
12
+ - Copilot recap cards persist only as long as the meeting object does.
13
+ - Attendee memory degrades to zero within weeks.
14
+
15
+ Email bodies, OneNote pages, SharePoint files, CRM records, and ADO work items all persist in their source systems indefinitely (or for years). Meetings do not. If the curated 7-section meeting summary is the only artifact kushi captures, and the recording later expires, **the evidence is unrecoverable**. This has happened in production (see `learnings/meetings.md` — FDE Intake John Deere, 2026-05-18).
16
+
17
+ ## The rule
18
+
19
+ For every meeting captured by `pull-meetings`, the skill MUST produce **two** outputs, not one:
20
+
21
+ 1. **Curated snapshot** — `Evidence/<alias>/Meetings/snapshot/<slug>.md` (existing) or `Evidence/<alias>/Meetings/stream/<week>_meetings-stream.md` per-meeting block (existing). 7-section doctrine summary. Human-readable.
22
+ 2. **Verbatim folder** — `Evidence/<alias>/Meetings/verbatim/<YYYY-MM-DD-HHMM>_<slug>/` (NEW, REQUIRED). Raw immutable artifacts that survive source expiry.
23
+
24
+ A per-meeting block in `stream/` that has NO sibling `verbatim/<...>/` folder is a **defect**, even if the curated block is rich and well-cited. Self-check rule **D13** enforces this in deep mode.
25
+
26
+ ## "Verbatim" means the FULL TRANSCRIPT TEXT — not just chat (HARD RULE)
27
+
28
+ The defining artifact of a meeting verbatim folder is **the full speaker-by-speaker transcript text of what was said in the meeting**. Chat messages are SUPPORTING evidence; they are **NOT** a substitute for the transcript.
29
+
30
+ Order of preference for the transcript artifact (highest fidelity first):
31
+
32
+ 1. **Raw VTT** (`transcript.vtt`) — verbatim, timestamped, per-speaker turns. Captured via `m365_get_transcript(joinUrl)` or the Graph `/me/onlineMeetings/{id}/transcripts/{tid}/content` endpoint with `Accept: text/vtt`. **Required first attempt.**
33
+ 2. **Plain-text transcript** (`transcript.txt`) — full speaker-by-speaker text without VTT formatting. Allowed only when raw VTT cannot be retrieved but a plain text dump is available (e.g. WorkIQ returns the full text but not the VTT bytes). Must include speaker names + at least timestamp markers.
34
+ 3. **Copilot recap summary** (`transcript-source.md`) — Copilot-generated SUMMARY returned by WorkIQ when both VTT and plain transcript are unavailable. Must carry the `WARNING: NOT a verbatim transcript` header. This is the LOWEST acceptable transcript-class artifact and only counts when nothing higher exists.
35
+ 4. **Chat reconstruction** (`chat-messages.json` + `chat-messages.md`) — the chat thread alone. **This is NOT a transcript.** A verbatim folder whose only "transcript" is chat reconstruction is marked `transcript-missing` in `coverage.md` and the meeting block in `stream/` carries `Source basis: ❌ no-transcript-recovered-chat-only`.
36
+
37
+ A verbatim folder is **transcript-complete** only when one of files 1, 2, or 3 exists with non-empty content. A folder with only chat is `transcript-missing` — a degraded state, not the goal. Self-check D13 distinguishes these two outcomes.
38
+
39
+ ## Transcript capture cascade — WorkIQ-only (HARD RULE, v3.11.0+)
40
+
41
+ Per `workiq-only.instructions.md`: kushi does NOT use `m365_get_transcript`, `m365_get_facilitator_notes`, `m365_list_meetings`, `m365_list_events`, or Graph REST for transcripts. They fail almost every call in this workspace. The capture cascade is short and codified:
42
+
43
+ 1. **WorkIQ — full transcript pull (REQUIRED first attempt)**:
44
+ ```
45
+ workiq ask -q "Find the Teams meeting titled \"<subject>\" that occurred on <YYYY-MM-DD>. Return the full transcript verbatim with speaker labels and timestamps. Do not summarize."
46
+ ```
47
+ - If output contains speaker turns (≥ ~10 distinct `Name:` lines) → strip the `request-id:` prefix lines, save body as `transcript.txt` with the standard header (source, query, request-id, fidelity).
48
+ - If output is a summary (paragraphs only, no speaker turns) → run the **doubled-strict retry** from `workiq-only.instructions.md`. If still summary-only, save as `transcript-source.md` with the `WARNING: NOT a verbatim transcript` header.
49
+
50
+ 2. **WorkIQ — Copilot recap (SUPPLEMENTARY, always attempt)**:
51
+ ```
52
+ workiq ask -q "Get the Copilot meeting recap (decisions, action items, key points) for the Teams meeting \"<subject>\" on <YYYY-MM-DD>. Return the FULL recap card verbatim. Do not summarize."
53
+ ```
54
+ - Save as `facilitator-notes.md`. This is supplementary; does NOT replace the transcript.
55
+
56
+ 3. **Chat structured dump (ALWAYS in parallel, allowed)**:
57
+ - `m365_list_chat_messages(chatId)` → `chat-messages.json` raw + `chat-messages.md` rendered.
58
+ - Chat-id is sourced from `boundaries.teams.chat_ids[]` in integrations.yml, OR from the WorkIQ meeting-discovery query if not pre-known:
59
+ ```
60
+ workiq ask -q "List my Teams meetings between <start> and <end> where the subject contains \"<token>\". Return subject, date, organizer, joinUrl, and Teams chat id."
61
+ ```
62
+ - **Allowed exception to workiq-only**: `m365_list_chat_messages` is a structured-data dump for the chat-id'd thread. It is NOT a transcript and NOT a fallback for one. It runs in parallel.
63
+
64
+ 4. **Recording URL discovery (WorkIQ)**:
65
+ ```
66
+ workiq ask -q "For the meeting \"<subject>\" on <YYYY-MM-DD>, return the SharePoint Stream recording URL if it exists, and the calendar event body."
67
+ ```
68
+ - Save URL(s) to `recording-url.txt`. If a `.mp4` URL is present and `m365_download_file` against the SharePoint item succeeds (size < 200MB), download to `recording.mp4` so a future transcription pass remains possible after the cloud copy expires.
69
+
70
+ 5. **Ask user to paste** (when 1 returns empty AND 2 returns empty):
71
+ - Prompt user to paste the transcript. Save to `transcript.txt` with header `User-pasted; WorkIQ returned no transcript on <ISO timestamp>`. This is a first-class evidence path, not a degradation.
72
+
73
+ **Forbidden paths** (do NOT attempt; do NOT log as cascade steps in coverage.md):
74
+ - `m365_get_transcript(joinUrl)` — FORBIDDEN. Use WorkIQ step 1.
75
+ - `m365_get_facilitator_notes(joinUrl)` — FORBIDDEN. Use WorkIQ step 2.
76
+ - `m365_list_meetings`, `m365_list_events` — FORBIDDEN for discovery. Use WorkIQ chat-id discovery in step 3.
77
+ - Graph REST `/me/onlineMeetings/.../transcripts/.../content` — FORBIDDEN. Use WorkIQ step 1.
78
+
79
+ If steps 1–2 both return empty AND user-paste in step 5 is declined: the meeting is **`transcript-unrecoverable`**. The verbatim folder still exists with chat (if any) + `coverage.md` documenting every WorkIQ attempt with request-ids. The stream/ block carries `Source basis: ❌ no-transcript-recovered-chat-only` and the run-log records `transcript-unrecoverable` as the source-level error signature.
80
+
81
+ ## Required contents of `verbatim/<YYYY-MM-DD-HHMM>_<slug>/`
82
+
83
+ Slug = lowercase ASCII, spaces→hyphens, max 60 chars, derived from meeting subject. Time = local 24h.
84
+
85
+ | File | When required | Source |
86
+ |---|---|---|
87
+ | `captured-at.txt` | Always | ISO timestamps + every path attempted (success + failures) + kushi version + REST endpoints used |
88
+ | `coverage.md` | Always | What was captured, what was attempted, what failed, source-basis classification |
89
+ | `transcript.vtt` | When `m365_get_transcript` or Graph REST returned VTT bytes | Raw VTT — highest fidelity; required first attempt |
90
+ | `transcript.txt` | When VTT unavailable but plain text retrieved (WorkIQ full-text or user paste) | Speaker-by-speaker plain text; second preference |
91
+ | `transcript-source.md` | When only a Copilot summary is available | WorkIQ markdown verbatim with `WARNING: NOT a verbatim transcript` header; lowest acceptable transcript-class artifact |
92
+ | `facilitator-notes.md` | When `m365_get_facilitator_notes` returned content | Copilot AI decisions + action items; supplementary, NOT a transcript |
93
+ | `chat-messages.json` | Always when meeting has a chat thread | Full `m365_list_chat_messages` raw API dump |
94
+ | `chat-messages.md` | Always when chat-messages.json exists | Human-readable rendering: sender + ISO timestamp + full body per message |
95
+ | `recording-url.txt` | When any recording URL is found in chat or event body | One URL per line; SharePoint/Stream URLs |
96
+ | `recording.mp4` | When `recording-url.txt` resolves and size < 200MB | `m365_download_file` of the recording binary; last-chance source for re-transcription after cloud expiry |
97
+ | `recap-card.md` | When a Copilot recap card was posted to chat | Verbatim card body |
98
+ | `attachments/` | When chat included shared files | `m365_download_file` of every attachment referenced by chat messages |
99
+
100
+ **Transcript-class file required.** A verbatim folder MUST contain at least ONE of `transcript.vtt` / `transcript.txt` / `transcript-source.md` to be classified `transcript-complete`. A folder with only `chat-messages.*` (no transcript-class file) is `transcript-missing` — the meeting is flagged in coverage.md and run-log as `transcript-unrecoverable` and the corresponding stream/ block carries `Source basis: ❌ no-transcript-recovered-chat-only`. Self-check D13 enforces both presence and classification.
101
+
102
+ ## Capture-on-pull execution order
103
+
104
+ Every step writes to `verbatim/` BEFORE producing the curated snapshot. The order is locked and is now WorkIQ-only for transcript capture (no `m365_get_transcript`, no Graph REST):
105
+
106
+ 1. Create `verbatim/<YYYY-MM-DD-HHMM>_<slug>/` and write `captured-at.txt` (started).
107
+ 2. **Transcript cascade — WorkIQ-only** (steps 1–5 of the cascade in "Transcript capture cascade — WorkIQ-only" above, in order — do not stop early):
108
+ - a. WorkIQ full-transcript pull → `transcript.txt` if speaker-turns returned, else `transcript-source.md` (with `WARNING: NOT a verbatim transcript` header) after the doubled-strict retry.
109
+ - b. WorkIQ Copilot recap → `facilitator-notes.md` (supplementary; not a transcript).
110
+ - c. WorkIQ recording-URL discovery → `recording-url.txt`; if `.mp4` URL present and size < 200MB, `m365_download_file` against the SharePoint item id → `recording.mp4` (binary download carve-out — WorkIQ does not return binaries).
111
+ - d. User-paste fallback (first-class) when (a) returns empty after doubled-strict retry → `transcript.txt` with `User-pasted; WorkIQ returned no transcript on <ISO>` header.
112
+ 3. **Chat capture (always, in parallel with step 2 — allowed structured-data dump)**: `m365_list_chat_messages(chatId)` → `chat-messages.json` + `chat-messages.md`. If it fails, run the WorkIQ Teams chat-thread prompt as fallback.
113
+ 4. Walk chat for attachments → `m365_download_file` each → `attachments/<original-name>` (binary download carve-out).
114
+ 5. Walk chat for Copilot recap card → `recap-card.md`.
115
+ 6. Classify the verbatim folder per "transcript-class file required" rule above:
116
+ - `transcript-complete` if any of transcript.vtt / transcript.txt / transcript-source.md is non-empty.
117
+ - `transcript-missing` otherwise.
118
+ 7. Write `coverage.md` with classification + per-path WorkIQ attempt log (every WorkIQ path attempted, with request-id).
119
+ 8. Update `captured-at.txt` with `completed_at` + `final_status`.
120
+ 9. **Only now** produce the curated snapshot/stream block, citing verbatim files relatively: `[source: Evidence/<alias>/meetings/verbatim/<dir>/transcript.txt · <date>]` (preferred) or `transcript-source.md` (with warning) or `chat-messages.md` if transcript-missing.
121
+
122
+ If steps 2(a-d) all return empty AND chat in step 3 is also empty: meeting is `unrecoverable`. Mark the per-meeting block `❌ source-expired-or-unrecoverable`, write `coverage.md` listing every WorkIQ attempt with request-ids, and ask the user to paste from memory/notes (paste lands in `transcript.txt` with the user-paste header).
123
+
124
+ **Note**: `transcript.vtt` is no longer produced because the only paths that yielded raw VTT (`m365_get_transcript` and Graph REST `/transcripts/.../content`) are FORBIDDEN per `workiq-only.instructions.md`. Existing pre-v3.12.0 `transcript.vtt` files in verbatim/ folders remain valid evidence and continue to satisfy the transcript-complete classification — they just won't be created by new runs.
125
+
126
+ ## Why a folder per meeting (not a flat file)
127
+
128
+ - Multiple artifact kinds per meeting (chat + transcript + recap + attachments) — a folder is the natural shape.
129
+ - Attachments are binary; they don't belong inline in a markdown file.
130
+ - Future capture additions (e.g. screen-share thumbnails, whiteboard exports) shouldn't break the layout.
131
+ - Easy to dedupe by directory existence on subsequent runs.
132
+
133
+ ## Naming
134
+
135
+ - Folder: `<YYYY-MM-DD>-<HHMM>_<slug>` — e.g. `2026-05-13-1530_fde-intake-john-deere`
136
+ - Slug rules: lowercase, ASCII, spaces and punctuation → single hyphen, collapse repeats, trim trailing hyphens, max 60 chars.
137
+ - Time: meeting start time in the user's local timezone (per `m365_get_mailbox_settings`), 24h, no separator.
138
+ - If two meetings share start time + slug: append `-2`, `-3`, etc.
139
+
140
+ ## Citation convention
141
+
142
+ Inside the curated snapshot/stream files, cite verbatim files with the kushi standard format:
143
+
144
+ ```
145
+ [source: Evidence/<alias>/meetings/verbatim/2026-05-13-1530_fde-intake-john-deere/chat-messages.md · 2026-05-13]
146
+ ```
147
+
148
+ The curated snapshot is the assertion; the verbatim file is the evidence. The two must always travel together.
149
+
150
+ ## What this is NOT
151
+
152
+ - This is NOT a backup of OneNote, email, or SharePoint. Those sources persist; we cite them in place.
153
+ - This is NOT a place for AI-generated summaries. `transcript-source.md` from WorkIQ is allowed because WorkIQ returns it as the only available form of the transcript; everything in verbatim/ must be source-derived, not Kushi-derived.
154
+ - This is NOT optional based on meeting size. A 5-minute side meeting with 3 chat messages still gets a verbatim folder.
155
+
156
+ ## Self-check enforcement (D13)
157
+
158
+ `plugin/skills/self-check/run.ps1` deep-mode rule D13 walks every per-meeting block in `Evidence/*/meetings/stream/*.md` and emits:
159
+
160
+ - **D13.a** — verbatim/<dir> missing entirely for a referenced meeting (HARD defect).
161
+ - **D13.b** — verbatim/<dir> exists but contains only `captured-at.txt` / `coverage.md` (cascade failed silently; HARD defect).
162
+ - **D13.c** — verbatim/<dir> contains chat-messages.* but no transcript-class file (`transcript.vtt`, `transcript.txt`, or `transcript-source.md`). Surfaces as `transcript-missing` warning. Not a hard defect if `coverage.md` documents the exhaustive cascade was attempted; IS a hard defect if any transcript path was skipped.
163
+
164
+ ## Anti-patterns (defects)
165
+
166
+ 1. **Verbatim folder absent** — per-meeting block in stream/ with no sibling verbatim/<...>/ dir. Hard defect.
167
+ 2. **Verbatim folder empty / captured-at-only** — capture cascade failed silently. Hard defect; surface in coverage.md and run-log.
168
+ 3. **Chat-only treated as transcript** — verbatim/ contains only chat-messages.* but coverage.md claims `transcript-complete`. Hard defect (misclassification of source basis).
169
+ 4. **Transcript cascade stopped early** — first path (m365_get_transcript) failed and skill jumped straight to chat without trying Graph REST fallback + WorkIQ strict pull + recording URL discovery. Hard defect — the cascade is exhaustive, not first-success.
170
+ 5. **Inline transcript in stream/** — pasting raw VTT into the stream file instead of writing to verbatim/transcript.vtt. Defect; bloats the curated file and obscures the audit trail.
171
+ 6. **Curated-only refresh** — refresh-project re-runs pull-meetings without re-checking that the verbatim folder is still intact (in case of accidental cleanup). The orchestrator should warn if verbatim/ for an existing meeting disappeared between runs.
172
+ 7. **AI-narrative substitution** — when no transcript and no chat exist, writing an inferred narrative as `transcript-source.md`. Forbidden; per `verbatim-by-default.instructions.md` anti-pattern #8.
173
+
174
+ ## Apply
175
+
176
+ `pull-meetings/SKILL.md` v2.2.0+ MUST cite this instruction in its front contracts blockquote. Templates `meetings-stream.template.md` and `meetings-series-index.template.md` MUST reference the verbatim/ folder location. Template `meeting-verbatim.template.md` defines the standard contents of a verbatim folder.
@@ -0,0 +1,129 @@
1
+ ---
2
+ applyTo: "**"
3
+ description: "Run-reports rule — every bootstrap and refresh MUST write a per-user, per-run report under <project>/Evidence/<alias>/refresh-reports/ so each contributor can see what was done when, what worked, what didn't, and what changed."
4
+ ---
5
+
6
+ # Run-reports (HARD RULE)
7
+
8
+ Every `bootstrap-project` and `refresh-project` invocation MUST produce a per-user, per-run report file in addition to updating `<project>/bootstrap-status.md` and `Evidence/run-log.yml`.
9
+
10
+ ## Why
11
+
12
+ `bootstrap-status.md` is the **current durable state** (per bootstrap-status-format.instructions.md — short, scannable, no run narrative).
13
+
14
+ `run-log.yml` is **structured history** (machine-readable, watermarks + per-source status).
15
+
16
+ Neither tells a user "what just happened in my last run" in narrative form. The per-user run report fills that gap. It's the contributor's audit trail of **what the agent did on their behalf** — what was pulled, what worked, what was skipped, what gaps remain, and what to do next.
17
+
18
+ Critical for multi-user projects: each contributor's runs are independent, and each user needs to see their own report without scrolling through everyone else's history.
19
+
20
+ ## Where it lives
21
+
22
+ ```
23
+ <engagement-root>/<project>/Evidence/<alias>/refresh-reports/
24
+ YYYY-MM-DD-HHmm_<mode>.md
25
+ ```
26
+
27
+ - `<alias>` — the contributor running the skill (from `~/.copilot/project-evidence.yml#alias`).
28
+ - `<mode>` — one of `bootstrap`, `refresh`, `force-refresh`, `consolidate`.
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
+
31
+ Newest at the bottom of `Get-ChildItem` listings (sortable by name = sortable by time).
32
+
33
+ ## Required structure
34
+
35
+ ```markdown
36
+ # Refresh Report — <project> — <YYYY-MM-DD HH:mm local>
37
+
38
+ - **Mode**: bootstrap | refresh | force-refresh | consolidate
39
+ - **Contributor**: <alias>
40
+ - **Window**: <effective window per source>
41
+ - **Profile**: standard | full | core
42
+ - **Started**: <ISO timestamp>
43
+ - **Ended**: <ISO timestamp>
44
+ - **Duration**: <Hh Mm Ss>
45
+
46
+ ## What was done
47
+
48
+ | Source | Action | Items pulled | Outcome | Notes |
49
+ |---|---|---|---|---|
50
+ | ado | snapshot+stream | 2 WIs / 6 comments / 24 revisions | resolved | ... |
51
+ | crm | snapshot | 1 record / 24 annotations | resolved | ... |
52
+ | email | stream | 47 messages / 12 threads | populated | ... |
53
+ | teams | stream | ... | ... | ... |
54
+ | meetings | snapshot+stream | ... | ... | ... |
55
+ | onenote | snapshot | ... | ... | ... |
56
+ | sharepoint | snapshot+stream | ... | ... | ... |
57
+
58
+ ## Resolutions this run
59
+
60
+ For each ID/folder/section newly resolved during this run, one bullet:
61
+ - `ado.engagement_id` resolved to `96944` (HCA - Engagement) — pinned to integrations.yml + m365-mutable.json.
62
+ - `crm.record_id` resolved to `e561b31e-...` — pinned + env override applied (iscrm.crm.dynamics.com).
63
+
64
+ ## Cleanups this run
65
+
66
+ Per `cleanup-on-resolution.instructions.md`. List entries pruned when a resolution succeeded:
67
+ - Removed stale `ado.last_discovery_result: 'no-match'` from integrations.yml (resolved this run).
68
+ - Removed `## Current Bootstrap Outcome` note `ADO context sync pending` from bootstrap-status.md.
69
+
70
+ ## Learnings appended
71
+
72
+ Per `capture-learnings.instructions.md`. List new entries written to `<KUSHI_ROOT>/plugin/learnings/<file>.md`:
73
+ - `learnings/crm.md` — "Custom entities don't expose Annotations as a navigation property" (HCA / pull-crm).
74
+ - `learnings/ado.md` — "$top=500 exceeds permissible range on workItems updates endpoint" (HCA / pull-ado).
75
+
76
+ ## Skips & gaps
77
+
78
+ What was deliberately skipped or couldn't be retrieved, with reason:
79
+ - `sharepoint` — no folder pinned in `integrations.yml#boundaries.sharepoint.folder_paths`; root-fallback would be too noisy. ACTION: ask user to pin folder, or accept root-scope on next run.
80
+ - `meetings` transcripts — 2 of 5 meetings had no transcript; chat-reconstruction used.
81
+
82
+ ## Files written
83
+
84
+ | Path | Bytes | Type |
85
+ |---|---|---|
86
+ | `Evidence/<alias>/ado/snapshot/engagement-96944.md` | 18,420 | snapshot |
87
+ | `Evidence/<alias>/ado/snapshot/items/96571.md` | 4,210 | snapshot |
88
+ | `Evidence/<alias>/crm/snapshot/.../e561b31e-...md` | 24,180 | snapshot |
89
+ | `Evidence/<alias>/email/stream/2026-05-04_email-stream.md` | 38,910 | stream |
90
+ | ... | | |
91
+
92
+ ## Next steps for this contributor
93
+
94
+ Plain-language list. What the contributor should do next, e.g.:
95
+ - Review `Evidence/<alias>/email/stream/2026-05-04_email-stream.md` — 3 emails from James Gibbings have substantive customer needs that should land in `State/00_overview.md`.
96
+ - Pin a SharePoint folder for HCA in `integrations.yml#boundaries.sharepoint.folder_paths` so next refresh covers it.
97
+ - Re-run with `force-refresh HCA` if today's run looks partial.
98
+
99
+ ---
100
+
101
+ _Generated by kushi <version>. See `<KUSHI_ROOT>/plugin/instructions/run-reports.instructions.md` for the format spec._
102
+ ```
103
+
104
+ ## When sections are empty
105
+
106
+ Same rule as evidence-thoroughness: write `_None this run._` rather than omit a section. Empty section signals "checked, none" vs missing section signals "skipped".
107
+
108
+ ## Relationship to other artifacts
109
+
110
+ | Artifact | What it captures | Lifecycle |
111
+ |---|---|---|
112
+ | `<project>/bootstrap-status.md` | Current durable project state | Overwritten each bootstrap/refresh; short |
113
+ | `<project>/Evidence/run-log.yml` | Structured per-source history (watermarks, item counts, runs[]) | Append-only history block + replaceable per-source summary |
114
+ | `<project>/Evidence/<alias>/refresh-reports/<ts>_<mode>.md` | Narrative per-user per-run report | Append-only (one new file per run); never overwritten |
115
+ | `<KUSHI_ROOT>/plugin/learnings/<source>.md` | Cross-project doctrine (API quirks, fixes) | Append-only, kushi-repo-wide |
116
+
117
+ The four are complementary; do not collapse them.
118
+
119
+ ## When the report is generated
120
+
121
+ - `bootstrap-project` — at the END of the run, after all per-source pulls have completed (success or with coverage gaps). Write the file before announcing "bootstrap complete" to the user.
122
+ - `refresh-project` — same, at the END. Even if no source had new data ("no new evidence — state unchanged"), write a 1-section report saying so. The user needs to see the run happened.
123
+ - `force-refresh` (per `force-refresh.md` how-to) — same, with `Mode: force-refresh` so the report distinguishes deliberate re-pulls from incremental refreshes.
124
+
125
+ ## Self-check enforcement
126
+
127
+ `plugin/skills/self-check/run.ps1` deep-mode rule **D10** (added v3.7.6):
128
+ - Warns if `<project>/Evidence/<alias>/` exists but `refresh-reports/` is missing or empty after a run.
129
+ - Warns if `run-log.yml` shows a `runs[]` entry from today but no matching `refresh-reports/<today's-prefix>_*.md` exists.
@@ -0,0 +1,218 @@
1
+ ---
2
+ applyTo: "**"
3
+ description: "Scope & Boundaries — every WorkIQ ask MUST cite a configured boundary; CRM/ADO require config.yml. Discovery is bounded, not free-form. No improvisation, no figure-it-out."
4
+ ---
5
+
6
+ # Scope & Boundaries (HARD RULE — partial-determinism contract)
7
+
8
+ Kushi's credibility depends on **knowing where it is allowed to look** and refusing
9
+ to improvise outside that perimeter. WorkIQ is powerful but fuzzy; Microsoft Graph
10
+ is broad and easy to mis-scope; CRM and ADO are tenant-specific. Without explicit
11
+ boundaries, the same question can return different evidence on different runs — and
12
+ every cited assertion becomes "trust me, I asked WorkIQ".
13
+
14
+ This file defines the contract that every `pull-*` skill, every WorkIQ ask, every
15
+ host-fallback Graph call, and every CRM/ADO probe MUST honor.
16
+
17
+ ## The contract — three rules, no exceptions
18
+
19
+ ### Rule 1 — Every ask cites a configured boundary
20
+
21
+ Before issuing **any** WorkIQ query, `m365_*` host call, Graph REST call, or CRM/ADO
22
+ REST call, the skill MUST resolve the boundary it is operating inside from
23
+ `<engagement-root>/<project>/integrations.yml boundaries:` (per-source) or the
24
+ global `<engagement-root>/.project-evidence/{crm,ado}/config.yml` (auth +
25
+ tenant + org). The resolved boundary MUST be recorded in the evidence file's
26
+ `## Source Basis` block, e.g.:
27
+
28
+ ```
29
+ ## Source Basis
30
+ - path: workiq
31
+ - boundary: integrations.yml#boundaries.email.mailboxes=["Inbox","FDE-Intake"]
32
+ - boundary: integrations.yml#boundaries.email.sender_domains=["microsoft.com","hcahealthcare.com"]
33
+ - boundary: integrations.yml#boundaries.date_window_days=30
34
+ ```
35
+
36
+ A query issued without a citable boundary is a **defect** — the skill must refuse
37
+ and ask the user to update `integrations.yml boundaries:` (or the relevant
38
+ config.yml) instead of guessing.
39
+
40
+ ### Rule 2 — No source is queried outside its boundary
41
+
42
+ A boundary is **inclusive only**: only sources / mailboxes / channels / sections /
43
+ folders / domains explicitly listed are queried. There is no "and also widen if I
44
+ don't find enough" fallback. If the boundary is too narrow and a refresh comes
45
+ back light, the skill writes a Coverage Notes entry pointing at the boundary that
46
+ limited the scope and asks the user to widen it next run — it does NOT widen on
47
+ its own.
48
+
49
+ This is the partial-determinism contract: **the user controls scope; Kushi controls
50
+ depth.** Once the user has set the boundary, every refresh under that boundary
51
+ returns evidence over the same surface — no run-to-run drift.
52
+
53
+ ### Rule 3 — CRM & ADO require explicit config.yml; no inference, no narration-from-email
54
+
55
+ `pull-crm` and `pull-ado` (and the downstream `propose-ado-update` /
56
+ `apply-ado-update`) are **HARD-fail** without their global config.yml:
57
+
58
+ | Skill | Hard prerequisite | Failure message (verbatim) |
59
+ |---|---|---|
60
+ | `pull-crm` | `<engagement-root>/.project-evidence/crm/config.yml` exists with non-placeholder `environmentUrl` | `crm-config-missing — drop a filled config.yml at <engagement-root>/.project-evidence/crm/config.yml. See plugin/templates/init/crm-config.template.yml.` |
61
+ | `pull-ado` | `<engagement-root>/.project-evidence/ado/config.yml` exists with non-placeholder `organization` AND `defaultProject` | `ado-config-missing — drop a filled config.yml at <engagement-root>/.project-evidence/ado/config.yml. See plugin/templates/init/ado-config.template.yml.` |
62
+ | `propose-ado-update` | both above + `integrations.yml ado.engagement_id > 0` | per `propose-ado-update/SKILL.md` Prerequisites table |
63
+
64
+ Pre-v3.7.0 behavior allowed `pull-crm` to "narrate from email" when the live
65
+ config was missing — that is **explicitly forbidden as of v3.7.0**. CRM evidence
66
+ must come from CRM. Email evidence stays in the email source. Cross-source
67
+ synthesis happens at the consolidation step, not at the pull step.
68
+
69
+ ## The boundaries schema
70
+
71
+ Lives in `<engagement-root>/<project>/integrations.yml` under a top-level
72
+ `boundaries:` key. Every per-source key is **optional** — but if a source's
73
+ boundary is omitted, that source is **disabled** for the project (not silently
74
+ queried with defaults).
75
+
76
+ ```yaml
77
+ boundaries:
78
+ date_window_days: 30 # default lookback window for streams (snapshot ignores)
79
+
80
+ email:
81
+ mailboxes: # required if email enabled
82
+ - "Inbox"
83
+ - "Inbox/FDE Intake" # well-known names OR folder IDs
84
+ sender_domains: # optional — narrows by sender
85
+ - "microsoft.com"
86
+ - "hcahealthcare.com"
87
+ subject_keywords: # optional — additional narrowing
88
+ - "HCA"
89
+ - "FE-2026-001458"
90
+
91
+ teams:
92
+ chat_ids: # required if teams enabled — pinned, not fuzzy-discovered
93
+ - "19:meeting_…@thread.v2"
94
+ channel_ids: [] # required for channel evidence (empty = no channels)
95
+
96
+ meetings:
97
+ series_join_urls: # required if meetings enabled — pinned, not subject-keyword-fuzzy
98
+ - "https://teams.microsoft.com/l/meetup-join/…"
99
+ organizer_emails: [] # optional — additional filter
100
+
101
+ onenote:
102
+ section_file_ids: # required if onenote enabled — drive-item IDs (narrowest)
103
+ - "3d0ad388-fd6b-45a8-8619-60dd709b7ade"
104
+ notebooks: [] # optional — broaden if needed; section_file_ids preferred
105
+
106
+ sharepoint:
107
+ local_folders: # required if sharepoint enabled
108
+ - "C:\\…\\HCA"
109
+ site_urls: [] # optional — for online-only docs
110
+ drive_ids: [] # optional — Graph-direct access
111
+
112
+ crm:
113
+ entity_sets: # optional — overrides global defaultEntitySet
114
+ - "msdyn_engagements"
115
+ record_ids: # required if crm enabled — pinned record GUIDs
116
+ - "<guid>"
117
+ request_ids: # OR pinned FE-XXXXX IDs
118
+ - "FE-2026-001458"
119
+
120
+ ado:
121
+ area_paths: # required if ado enabled
122
+ - "ISE-Engagements\\HCA"
123
+ iteration_paths: [] # optional — for sprint-scoped queries
124
+ initiative_query: "" # optional — saved WIQL query ID
125
+ work_item_ids: [] # optional — pin specific work items
126
+ ```
127
+
128
+ ### Why this shape
129
+
130
+ - **Per-source, not per-skill** — one place to read; every `pull-*` consumes from
131
+ `boundaries.<source>`.
132
+ - **IDs preferred over names** — `chat_ids` over `chat_topics`, `section_file_ids`
133
+ over `section_names`, `record_ids` over `title_contains`. IDs survive renames;
134
+ names drift.
135
+ - **Required vs optional is explicit** — the schema doc above marks each.
136
+ Bootstrap scaffolds the required keys; missing required keys = source disabled.
137
+ - **No global default boundaries** — each project declares its own; the only
138
+ cross-project default is `date_window_days`. Engagements differ; boundaries
139
+ must too.
140
+
141
+ ## How `pull-*` skills MUST consume the boundary
142
+
143
+ Each per-source skill follows this template (already enforced in v3.7.0 SKILL.md
144
+ rewrites):
145
+
146
+ ```
147
+ 1. Resolve boundary:
148
+ - read integrations.yml#boundaries.<source>
149
+ - if missing or empty for a required key → REFUSE with explicit message:
150
+ "<source>-boundary-missing — add boundaries.<source>.<key> to
151
+ <engagement-root>/<project>/integrations.yml. See doctrine in
152
+ plugin/instructions/scope-boundaries.instructions.md."
153
+ 2. Issue every query scoped to the resolved boundary:
154
+ - WorkIQ ask: include boundary keys in the prompt
155
+ ("…in mailbox 'Inbox/FDE Intake' from senders @microsoft.com,@hcahealthcare.com…")
156
+ - m365_* host call: pass folder/chat/section/site IDs as filter args
157
+ - Graph REST: use exact resource paths, not /search?
158
+ 3. Record the boundary in `## Source Basis` of every evidence file written.
159
+ 4. If the boundary is too narrow (zero hits): write a Coverage Notes entry
160
+ citing the limiting boundary key. Do NOT widen the query.
161
+ ```
162
+
163
+ ## Bootstrap behavior (per `bootstrap-project/SKILL.md`)
164
+
165
+ On first run for a new project, bootstrap MUST:
166
+
167
+ 1. Create `<engagement-root>/<project>/integrations.yml` with the `boundaries:`
168
+ block scaffolded (every source as `_required: true` with empty value list).
169
+ 2. Detect which sources have enough hints in `m365-mutable.json` to auto-populate
170
+ the boundary (e.g. a previously discovered `section_file_id` populates
171
+ `boundaries.onenote.section_file_ids` automatically).
172
+ 3. For sources where bootstrap cannot auto-populate, write the source as
173
+ **disabled** (`enabled: false`) with a one-liner in `OPEN-QUESTIONS-DRAFT.md`
174
+ asking the user to fill the boundary and re-enable.
175
+ 4. For CRM and ADO, ALSO check that the global `<engagement-root>/.project-evidence/{crm,ado}/config.yml`
176
+ exists and has non-placeholder values; if not, scaffold from
177
+ `plugin/templates/init/{crm,ado}-config.template.yml` and park in
178
+ `OPEN-QUESTIONS-DRAFT.md` with the path the user needs to fill.
179
+
180
+ Bootstrap **never silently widens** an empty boundary by inferring from the rest
181
+ of the corpus. Empty boundary = source disabled = explicit user action required.
182
+
183
+ ## Coverage Notes — boundary-aware
184
+
185
+ Every per-entity Coverage Notes block (per `evidence-thoroughness.instructions.md`)
186
+ MUST now also enumerate which boundaries were hit and which were exhausted /
187
+ empty. Example:
188
+
189
+ ```
190
+ ## Coverage Notes
191
+ - Boundary: integrations.yml#boundaries.email.mailboxes=["Inbox","Inbox/FDE Intake"] — HIT (12 threads)
192
+ - Boundary: integrations.yml#boundaries.email.sender_domains=["microsoft.com","hcahealthcare.com"] — HIT (all 12 in-scope)
193
+ - Boundary: integrations.yml#boundaries.date_window_days=30 — HIT (full window)
194
+ - Source not queried: any mailbox outside boundary (by design — see scope-boundaries.instructions.md)
195
+ ```
196
+
197
+ ## What this rule replaces
198
+
199
+ - The pre-v3.7.0 "WorkIQ-first, fall back to Graph, then ask user" cascade is
200
+ REPLACED by "WorkIQ-only within boundary, ask user when WorkIQ fails after
201
+ doubled-strict retry." Per `workiq-only.instructions.md` (v3.11.0+), Graph /
202
+ `m365_*` are FORBIDDEN as fallbacks for in-scope M365 sources. There is no
203
+ scope expansion at any tier.
204
+ - The pre-v3.7.0 `pull-crm` "narrate from email" fallback is REMOVED. CRM
205
+ evidence requires CRM source.
206
+ - The pre-v3.7.0 fuzzy-discovery loops in `pull-ado` (title_contains, tags_contains)
207
+ are PRESERVED but only run inside `boundaries.ado.area_paths`.
208
+
209
+ ## Cross-references
210
+
211
+ - `evidence-thoroughness.instructions.md` — depth bar (orthogonal: depth applies
212
+ inside the boundary; this rule defines the boundary).
213
+ - `workiq-only.instructions.md` — query strategy (now scoped per Rule 1; Graph /
214
+ `m365_*` fallbacks FORBIDDEN for in-scope M365 sources).
215
+ - `bootstrap-project/SKILL.md` — scaffolding the boundaries block.
216
+ - `pull-*/SKILL.md` (all 7) — Boundaries (REQUIRED) sub-section enforces Rule 1+2.
217
+ - `pull-crm/SKILL.md` + `pull-ado/SKILL.md` — Hard prerequisites enforce Rule 3.
218
+ - `propose-ado-update/SKILL.md` — Prerequisites table (already enforces ADO config + engagement_id).
@@ -29,6 +29,8 @@ Every source produces evidence in TWO distinct shapes. Mixing them is a defect.
29
29
 
30
30
  ## Storage layout
31
31
 
32
+ > **Path is canonical** — every per-source artifact lives under `Evidence/<alias>/<source>/` and **nowhere else** under `<project>/`. Sibling folders like `<project>/email-context/`, `<project>/notes/`, `<project>/_Weekly Summaries/` are FORBIDDEN per `evidence-layout-canonical.instructions.md`. Bootstrap and refresh auto-migrate any legacy folders into `Evidence/<alias>/<source>/_legacy_*_pre-bootstrap/`.
33
+
32
34
  ```
33
35
  <engagement-root>/<project>/Evidence/<alias>/
34
36
  email/