kushi-agents 3.4.2 → 3.13.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 (73) hide show
  1. package/.github/copilot-instructions.kushi.md +38 -0
  2. package/README.md +33 -0
  3. package/bin/cli.mjs +2 -0
  4. package/package.json +17 -4
  5. package/plugin/agents/kushi.agent.md +155 -147
  6. package/plugin/instructions/ado-bootstrap-discovery.instructions.md +111 -0
  7. package/plugin/instructions/ado-engagement-tree.instructions.md +73 -0
  8. package/plugin/instructions/answer-from-evidence.instructions.md +1 -1
  9. package/plugin/instructions/auth-and-retry.instructions.md +51 -16
  10. package/plugin/instructions/azure-auth-patterns.instructions.md +13 -6
  11. package/plugin/instructions/bootstrap-status-format.instructions.md +113 -0
  12. package/plugin/instructions/capture-learnings.instructions.md +95 -0
  13. package/plugin/instructions/cleanup-on-resolution.instructions.md +69 -0
  14. package/plugin/instructions/crm-bootstrap-discovery.instructions.md +79 -0
  15. package/plugin/instructions/crm-internal-vs-confirmed.instructions.md +79 -0
  16. package/plugin/instructions/evidence-confidence-ladder.instructions.md +66 -0
  17. package/plugin/instructions/evidence-layout-canonical.instructions.md +115 -0
  18. package/plugin/instructions/evidence-thoroughness.instructions.md +82 -12
  19. package/plugin/instructions/full-view-gate.instructions.md +91 -0
  20. package/plugin/instructions/m365-id-registry.instructions.md +134 -0
  21. package/plugin/instructions/meetings-verbatim-required.instructions.md +176 -0
  22. package/plugin/instructions/run-reports.instructions.md +129 -0
  23. package/plugin/instructions/scope-boundaries.instructions.md +218 -0
  24. package/plugin/instructions/snapshot-vs-stream.instructions.md +2 -0
  25. package/plugin/instructions/update-ledger.instructions.md +132 -0
  26. package/plugin/instructions/verbatim-by-default.instructions.md +73 -0
  27. package/plugin/instructions/workiq-first.instructions.md +15 -31
  28. package/plugin/instructions/workiq-only.instructions.md +193 -0
  29. package/plugin/learnings/README.md +50 -0
  30. package/plugin/learnings/ado.md +45 -0
  31. package/plugin/learnings/crm.md +96 -0
  32. package/plugin/learnings/cross-cutting.md +36 -0
  33. package/plugin/learnings/email.md +33 -0
  34. package/plugin/learnings/meetings.md +30 -0
  35. package/plugin/learnings/misc.md +46 -0
  36. package/plugin/learnings/onenote.md +215 -0
  37. package/plugin/learnings/sharepoint.md +5 -0
  38. package/plugin/learnings/teams.md +5 -0
  39. package/plugin/plugin.json +22 -2
  40. package/plugin/prompts/apply-ado.prompt.md +14 -0
  41. package/plugin/prompts/propose-ado.prompt.md +12 -0
  42. package/plugin/reference-packs/fde/crm-field-manifest.md +165 -0
  43. package/plugin/skills/apply-ado-update/SKILL.md +125 -0
  44. package/plugin/skills/ask-project/SKILL.md +2 -0
  45. package/plugin/skills/bootstrap-project/SKILL.md +81 -3
  46. package/plugin/skills/propose-ado-update/SKILL.md +108 -0
  47. package/plugin/skills/pull-ado/SKILL.md +173 -23
  48. package/plugin/skills/pull-crm/SKILL.md +168 -15
  49. package/plugin/skills/pull-email/SKILL.md +139 -22
  50. package/plugin/skills/pull-meetings/SKILL.md +109 -25
  51. package/plugin/skills/pull-misc/README.md +84 -0
  52. package/plugin/skills/pull-misc/SKILL.md +257 -0
  53. package/plugin/skills/pull-misc/runner.mjs +280 -0
  54. package/plugin/skills/pull-onenote/README.md +90 -0
  55. package/plugin/skills/pull-onenote/SKILL.md +400 -51
  56. package/plugin/skills/pull-onenote/runner.mjs +356 -0
  57. package/plugin/skills/pull-onenote/scripts/recapture-section-url.mjs +295 -0
  58. package/plugin/skills/pull-onenote/write-snapshot.mjs +271 -0
  59. package/plugin/skills/pull-sharepoint/SKILL.md +44 -12
  60. package/plugin/skills/pull-teams/SKILL.md +40 -11
  61. package/plugin/skills/refresh-project/SKILL.md +33 -2
  62. package/plugin/skills/self-check/run.ps1 +186 -4
  63. package/plugin/templates/ado-update/discussion-comment.template.md +26 -0
  64. package/plugin/templates/ado-update/integrations-ado-writes.example.yml +49 -0
  65. package/plugin/templates/ado-update/proposed.template.md +78 -0
  66. package/plugin/templates/init/external-links.template.txt +30 -0
  67. package/plugin/templates/init/project-integrations.template.yml +57 -2
  68. package/plugin/templates/snapshot/meeting-verbatim.template.md +110 -0
  69. package/plugin/templates/snapshot/meetings-series-index.template.md +3 -1
  70. package/plugin/templates/snapshot/onenote-page.template.md +92 -23
  71. package/plugin/templates/weekly/meetings-stream.template.md +11 -6
  72. package/src/copilot-instructions.mjs +80 -0
  73. package/src/main.mjs +18 -1
@@ -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/
@@ -0,0 +1,132 @@
1
+ ---
2
+ applyTo: "**"
3
+ description: "Write-path doctrine for Kushi. Any skill that writes outside the engagement folder (currently: ADO Initiative field + Discussion comment) MUST flow through propose → review/approve → apply → append-to-ledger, with citation, confidence, fingerprint, and a reverse op recorded for every applied item. Read-only refresh and aggregation are NOT subject to this gate."
4
+ ---
5
+
6
+ # Update Ledger — Write-Path Doctrine
7
+
8
+ Kushi is read-first. Aggregation, refresh, ask, and report skills produce no external side effects — they only write inside the engagement folder under `Evidence/`, `State/`, `Reports/`, etc.
9
+
10
+ The **write path** — currently `apply-ado-update`, future possibly CRM / OneNote / SharePoint — is governed by this file. Any new write skill must follow these rules and pass self-check rule **C13** (write-path safety).
11
+
12
+ ## The 4 stages, every time
13
+
14
+ ```
15
+ propose → review (or auto-allowlist) → apply → append to ledger
16
+ ```
17
+
18
+ No write skill skips a stage. No write skill writes without a corresponding ledger entry in the same operation.
19
+
20
+ ## Where the ledger lives
21
+
22
+ ```
23
+ <engagement-root>/<project>/ado-updates/<YYYY-MM-DD>/
24
+ proposed.md ← from propose-ado-update (Markdown, human-reviewable)
25
+ ledger.jsonl ← from apply-ado-update (one line per applied write)
26
+ planned.jsonl ← preview-stub only: writes that would have happened
27
+ attachments/ ← optional: payloads sent to ADO (raw HTML for comments)
28
+ ```
29
+
30
+ One subfolder per run date, **inside the project folder** (sibling to `Evidence/`, `State/`, `Reports/`). Files are append-only — never edit a past ledger entry. Mistakes are corrected by appending a `revert` entry (see "Reversal").
31
+
32
+ ## Ledger entry schema
33
+
34
+ One JSON object per line (JSONL), one entry per applied write. Required fields:
35
+
36
+ | Field | Type | Notes |
37
+ |---|---|---|
38
+ | `timestamp` | ISO-8601 UTC | When the write was sent. |
39
+ | `initiativeId` | int | ADO work item ID written to. (Same value as `integrations.yml ado.engagement_id`.) |
40
+ | `org`, `project` | string | ADO org + project (so a ledger entry is unambiguous standalone). |
41
+ | `kind` | `"field"` \| `"comment"` | What was written. |
42
+ | `fieldRefName` | string \| null | For `kind: "field"` — the ADO reference name. Null for `comment`. |
43
+ | `currentValue` | string | Value just before the write (from the optimistic-lock pre-fetch). |
44
+ | `proposedValue` | string | Value sent in the write. |
45
+ | `appliedValue` | string | Value confirmed in the write response. May differ from proposed if ADO normalized it. |
46
+ | `revBefore`, `revAfter` | int | ADO `/rev` values before/after — together with `currentValue` they form the reversal anchor. |
47
+ | `approver` | string | `<alias>` for human, `auto:<rule-name>` for allowlisted auto-apply, never empty. |
48
+ | `confidence` | `"high" \| "medium" \| "low"` | Carried forward from `proposed.md`. |
49
+ | `evidenceCitations` | string[] | Each entry is `<source-path> · <YYYY-MM-DD>`. Min 1; entries with 0 citations MUST NOT be approved. |
50
+ | `fingerprint` | string | Deterministic, derived from project + week + initiativeId + kind. Used by duplicate detection on the next run. Format: `kushi-weekly-<YYYY-WW>-<initiativeId>-<kind>`. |
51
+ | `reverseOp` | object | What to do to undo this write. See "Reversal". |
52
+ | `result` | `"ok" \| "rev-mismatch" \| "duplicate-skipped" \| "error"` | Final disposition. |
53
+ | `errorMessage` | string \| null | Populated only when `result: "error"`. |
54
+ | `kushiVersion` | semver | The version of `kushi-agents` that wrote this entry. |
55
+
56
+ Anything else (correlation IDs, request payload hashes) is allowed but optional.
57
+
58
+ ## Reversal
59
+
60
+ Every ledger entry includes a `reverseOp` that, applied alone, restores the prior state:
61
+
62
+ ```json
63
+ "reverseOp": {
64
+ "kind": "field",
65
+ "fieldRefName": "Custom.FDEStatusSummary",
66
+ "patch": [
67
+ { "op": "test", "path": "/rev", "value": <revAfter> },
68
+ { "op": "add", "path": "/fields/Custom.FDEStatusSummary", "value": "<currentValue>" }
69
+ ]
70
+ }
71
+ ```
72
+
73
+ For comments, the reverse op is a `DELETE` of the comment ID returned by the POST:
74
+
75
+ ```json
76
+ "reverseOp": {
77
+ "kind": "comment",
78
+ "commentId": 9871,
79
+ "method": "DELETE",
80
+ "url": "https://dev.azure.com/{org}/{project}/_apis/wit/workItems/{id}/comments/9871?api-version=7.1-preview.4"
81
+ }
82
+ ```
83
+
84
+ A future `revert-ado-update` skill (not in v0.1.0-preview) will read the latest ledger and apply reverse ops in reverse chronological order, again gated by user approval.
85
+
86
+ ## Approval rules (HARD)
87
+
88
+ 1. **No write without an entry in `proposed.md`.** Apply skills MUST refuse to write items that aren't in the proposal, even if asked.
89
+ 2. **No write without ≥ 1 citation.** Items with empty `evidenceCitations` are rejected at the gate.
90
+ 3. **No silent overwrite of drift.** If the live ADO value differs from the `currentValue` recorded in `proposed.md`, the apply step MUST stop and require explicit re-approval (showing both values).
91
+ 4. **Auto-apply is opt-in, narrow, and per-field.** Allowed only when:
92
+ - `writes.<kind>.autoApply: true` in `<engagement-root>/.kushi/ado-update.yml`, AND
93
+ - `confidence == "high"`, AND
94
+ - The proposed value matches a configured pattern (e.g., `<MMM YYYY>: <text>` for `statusSummary` with `strategy: append-month`).
95
+ Items failing any of these auto-apply criteria fall back to interactive approval.
96
+ 5. **No bulk apply across projects.** One project per invocation. (Iterating projects is the orchestrator's job; the apply skill itself is single-project.)
97
+ 6. **No write outside the allowlist.** The apply skill must reject any field reference name or work-item ID not declared in the project's `integrations.yml ado.writes.allowlist.fields` (and the work-item ID must equal `ado.engagement_id`).
98
+
99
+ ## Duplicate detection
100
+
101
+ Before writing a comment, fetch the latest N comments on the work item and look for the Kushi fingerprint line:
102
+
103
+ ```
104
+ — Generated by Kushi v<version> · proposed <YYYY-MM-DD> · ledger:ado-updates/<YYYY-MM-DD>/ledger.jsonl
105
+ ```
106
+
107
+ If a comment with the same `kushi-weekly-<YYYY-WW>-<initiativeId>-comment` fingerprint exists for the current ISO week → record `result: "duplicate-skipped"` in the ledger and do NOT write again. Field updates use idempotency on the value itself (same `<MMM YYYY>: ...` line not duplicated).
108
+
109
+ ## What is NOT subject to this doctrine
110
+
111
+ - `aggregate`, `bootstrap`, `refresh`, `consolidate`, `pull-*` — pure reads from M365 + CRM + ADO. They write to the engagement folder only.
112
+ - `ask`, `fde-*`, `state`, `project-status` — pure local file operations.
113
+ - `self-check`, `intro` — never write outside the kushi install.
114
+
115
+ The gate exists because **writing into someone else's system of record demands an audit trail and a path back**. Reads inside the engagement folder do not.
116
+
117
+ ## Self-check coverage
118
+
119
+ A future self-check rule **C13: write-path safety** will verify:
120
+
121
+ - Every skill folder whose `SKILL.md` contains the word `PATCH` or `POST` (HTTP write verbs) outside a fenced quote → must reference this instruction file in its `## References` section.
122
+ - Every such skill must declare its allowlist source (config file path) explicitly in the SKILL.md.
123
+ - The repo MUST NOT contain a skill that issues an ADO write call without a corresponding `ledger.jsonl` append in the same code path.
124
+
125
+ C13 is not yet implemented in `self-check/run.ps1` — added when `apply-ado-update` graduates from preview-stub to write-enabled.
126
+
127
+ ## References
128
+
129
+ - `propose-ado-update` SKILL.md — produces the `proposed.md` this doctrine governs.
130
+ - `apply-ado-update` SKILL.md — the only code path authorized to write to ADO; consumes `proposed.md`, appends to `ledger.jsonl`.
131
+ - `azure-auth-patterns.instructions.md` — pre-flight + token + tenant guards that protect every write.
132
+ - `side-by-side-config.instructions.md` — `integrations.yml ado.writes:` follows the same template-vs-live pattern.
@@ -0,0 +1,73 @@
1
+ ---
2
+ applyTo: "**"
3
+ description: "Verbatim-by-default rule — every pull-* skill captures full bodies and full content as the default mode. Headlines / one-line summaries / 'preview only' are defects. The user does NOT have to ask for detail; detail is the contract."
4
+ ---
5
+
6
+ # Verbatim-by-default (HARD RULE)
7
+
8
+ Every `pull-<source>` skill captures **full content verbatim** as its default mode. The user does NOT have to say "more detail" or "give me the full body" — that's the contract, every time.
9
+
10
+ This restates and hardens the existing thoroughness contract in `evidence-thoroughness.instructions.md` with one additional rule: **the user asking for detail is a defect signal, not a feature request**.
11
+
12
+ ## What "verbatim" means per source
13
+
14
+ | Source | Default capture |
15
+ |---|---|
16
+ | Email | Full body of every message in scope, every header, every attachment metadata. NOT just subject + sender + 200-char preview. |
17
+ | Teams chats | Every message in every in-scope thread, full text, sender, timestamp, reactions, attachments, replies. NOT just an outcome line. |
18
+ | Meetings | Full transcript walk-through with verbatim quotes + timestamps, every attendee, every artifact link. NOT a 3-bullet "what happened". |
19
+ | OneNote | Full page bodies, every page in scope, last-modified + author. NOT page titles only. |
20
+ | SharePoint | Full extracted body of every key file + every recently-modified file (top-N) + every user-pinned file. NOT a folder tree alone. |
21
+ | CRM | Every field the API returns, all long-text fields verbatim, every annotation/note verbatim, every related activity. NOT a 5-field summary. |
22
+ | ADO | Engagement + every child WI; per-item all fields verbatim, every comment verbatim, every revision verbatim. NOT parent-only. |
23
+
24
+ ## Anti-patterns (defects to refuse, not negotiate)
25
+
26
+ The following are defects in any `pull-*` output. If the runtime detects one, it MUST auto-retry with stricter prompting per `thoroughness-detector.instructions.md` rather than ship the thin output.
27
+
28
+ 1. **Email preview-only** — capturing only `bodyPreview` (200 chars) instead of `body`. Defect.
29
+ 2. **"And N more"** — any phrase like "...and 12 more emails", "10 of 47 shown", "see source for rest". Defect.
30
+ 3. **Single-message-per-thread** — collapsing a 30-message thread into one "summary" line. Defect.
31
+ 4. **Speaker-name only transcripts** — listing meeting attendees and decisions without the chronological verbatim quotes. Defect.
32
+ 5. **Folder tree without bodies** — SharePoint snapshot that lists files but extracts no key-file bodies. Defect.
33
+ 6. **CRM "key fields"-only** — pulling only title + status + customer instead of every populated field + all long-text + all annotations. Defect.
34
+ 7. **ADO parent-only** — pulling the engagement WI without expanding the tree to every child + per-item comments + per-item revisions. Defect.
35
+ 8. **Inferred narrative as substitute for body** (NEW v3.7.6.1) — when a source returns no body / `page-body-unavailable` / `body-not-extractable`, writing an "AI Narrative Summary" that infers what the artifact "likely contains" from adjacent evidence (other emails, chat traffic, page titles, file names). This is fabrication, not capture, and it pollutes the citation chain. The correct behavior is to write the header + the unavailable marker + a `next_step` asking the user to paste — and STOP. Empty is the correct state until the body is actually retrieved.
36
+ 9. **Meeting summary without sibling verbatim/ folder** (NEW v3.10.0) — meetings are the one EXPIRING evidence class. A per-meeting curated block in `Evidence/<alias>/meetings/stream/*.md` without a matching `Evidence/<alias>/meetings/verbatim/<YYYY-MM-DD-HHMM>_<slug>/` directory is a defect even if the curated block is rich. See `meetings-verbatim-required.instructions.md` for the full contract and self-check rule D13. Rationale: Teams recordings and VTT transcripts are purged by tenant retention (often within 60 days). If the only artifact captured is the curated summary, the underlying evidence is unrecoverable once the source expires.
37
+
38
+ ## The "you should do better" defect
39
+
40
+ When a user reads evidence and says any of:
41
+
42
+ - "you should do better and get details better"
43
+ - "this is too light"
44
+ - "where's the detail from `<source>`?"
45
+ - "i want detail by default"
46
+ - "why is nothing captured?"
47
+
48
+ — that is the **highest-severity** thoroughness defect. Treat it as a hard rule violation, not a preference. Specifically:
49
+
50
+ 1. The skill that produced the thin output is at fault. Identify which `pull-*` skill underdelivered.
51
+ 2. Re-pull from source at full depth in the same turn (no asking for confirmation).
52
+ 3. Append a `learnings/<source>.md` entry per `capture-learnings.instructions.md` describing the miss + the fix.
53
+ 4. If the miss was a doctrinal gap (skill spec didn't require the thing), update the SKILL.md or this instruction in the same commit.
54
+
55
+ ## Orchestrator contract
56
+
57
+ `bootstrap-project` and `refresh-project` MUST dispatch every enabled `pull-<source>` skill that has its boundary satisfied. **Skipping a source silently is a defect** — if a source is not pulled, the orchestrator must:
58
+
59
+ 1. Log the skip with reason (`boundary-missing`, `auth-blocked`, `user-disabled`) in the per-user refresh report (per `run-reports.instructions.md`).
60
+ 2. Mark the source `not-pulled-this-run` in `bootstrap-status.md`'s Context Artifact Status table.
61
+ 3. Suggest the fix in the report's "Skips & gaps" section.
62
+
63
+ A run that pulled CRM + ADO but silently omitted email is a defect of the orchestrator, even if every individual `pull-*` it did invoke was perfect.
64
+
65
+ ## Self-check enforcement
66
+
67
+ `plugin/skills/self-check/run.ps1` deep-mode rule **D11** (added v3.7.6):
68
+ - For each per-user refresh report, warn if any source listed in `<project>/integrations.yml#boundaries.<source>` (with non-empty boundary) is absent from the report's "What was done" table.
69
+ - Warn on per-source evidence files smaller than the per-source minimum byte threshold (defaults: email-stream 5KB / week, teams-stream 5KB / week, meetings-stream 8KB / week, onenote-snapshot 3KB / page, sharepoint key file 2KB / file, crm-snapshot 4KB / record, ado-snapshot 3KB / WI). Below threshold suggests headlines-only.
70
+
71
+ ## Apply
72
+
73
+ Every `pull-*` SKILL.md MUST reference this instruction file in its frontmatter or first paragraph alongside `evidence-thoroughness.instructions.md`. The two are co-equal.
@@ -1,47 +1,31 @@
1
1
  ---
2
2
  applyTo: "**"
3
- description: "WorkIQ is the required path for all M365 + CRM + ADO source pulls. Graph REST is NOT a routine fallback; ask the user to paste when WorkIQ can't answer."
3
+ description: "DEPRECATED as of kushi v3.11.0. The canonical M365 doctrine is workiq-only.instructions.md. This file is preserved as a stub redirect — do NOT use any of the old Graph-REST-fallback language; it is OVERRIDDEN by workiq-only."
4
4
  ---
5
5
 
6
- # WorkIQ-required rule (HARD RULE)
6
+ # DEPRECATED see `workiq-only.instructions.md`
7
7
 
8
- WorkIQ is the **required** path for every source pull. Graph REST has known issues in this workspace (token rejection, OneNote 40001, Dataverse 501/415, SharePoint 403, mailbox throttling) and **MUST NOT** be used as a routine fallback — doing so produces thin metadata-only evidence that violates `evidence-thoroughness.instructions.md`. WorkIQ gives richer extraction (full page bodies, full transcript text, message-by-message thread reproduction).
8
+ This file is a **deprecation stub** as of kushi **v3.11.0** (formalised in **v3.12.0**).
9
9
 
10
- ## Resolution order (per source)
10
+ The previous "WorkIQ-first, Graph REST as last-resort fallback" cascade is **REMOVED**. It produced thin metadata-only evidence, silent fall-throughs, and a defect-looking trail in coverage.md because the Graph / `m365_*` host tools fail nearly every call in this workspace.
11
11
 
12
- For every source, try in order:
12
+ ## The new canonical rule
13
13
 
14
- 1. **WorkIQ** `<workiq.cli_path> ask -q "<question>"` (path resolved from `<USER_HOME>/.copilot/project-evidence.yml workiq.cli_path`, otherwise from PATH).
15
- 2. **Ask user to paste** — if WorkIQ is missing, unauthenticated, or returns insufficient content, ask the user to paste the data **verbatim** (NOT summarized). This is a first-class path, not an error.
16
- 3. **Graph REST / `m365_*` host tools** — **last resort only**, used non-blocking with an explicit `➖ partial via Graph REST` marker in the evidence file. Skills MUST NOT silently fall through to Graph when WorkIQ fails; the user must be informed and given a chance to paste.
14
+ All M365 evidence retrieval (Email, Teams, OneNote, SharePoint, Meetings, Calendar discovery) is governed by:
17
15
 
18
- **Always document which path succeeded** in the evidence file under `## Source Basis`.
16
+ **`plugin/instructions/workiq-only.instructions.md`** WorkIQ is the ONLY path. Graph REST and `m365_*` host tools are **FORBIDDEN** as fallbacks for in-scope M365 sources. The single allowed exception is `m365_list_chat_messages` as a parallel structured-data dump (`chat-messages.json`) alongside the WorkIQ pull NEVER as a substitute.
19
17
 
20
- If WorkIQ is not installed or not on PATH, the skill MUST surface this immediately with a link to `docs/getting-started/install-workiq.md` rather than degrading to thin Graph-only evidence.
18
+ When WorkIQ fails after a doubled-strict retry ask the user to paste verbatim. User-paste is a **first-class evidence path**, not a degradation.
21
19
 
22
- ## Per-source preferred WorkIQ queries
20
+ ## Out of WorkIQ scope (unchanged)
23
21
 
24
- | Source | WorkIQ query template |
25
- |---|---|
26
- | Email | `Find emails about <project> in folder <folder> between <start> and <end>, give me sender, recipients, full body, and reply chain` |
27
- | Teams Chats | `Show full message-by-message reproduction of <project> Teams threads between <start> and <end>` |
28
- | OneNote | `Get full page bodies from OneNote section <section> notebook <notebook> modified between <start> and <end>` |
29
- | SharePoint | `List SharePoint files for <project> modified between <start> and <end> with author and brief content summary` |
30
- | Meetings | `Get full transcript and Copilot recap for meeting <subject> on <date>` |
31
- | CRM | `Get CRM engagement record FE-<id> with all field values, comments, and audit history` |
32
- | ADO | `Get ADO work items for <project> updated between <start> and <end> with full discussion thread` |
22
+ These remain on their direct paths and are NOT governed by `workiq-only`:
33
23
 
34
- ## Pre-flight (every pull-* skill)
24
+ - **CRM (Dataverse)** — REST via `az account get-access-token --resource https://<env>.crm.dynamics.com` per `crm-bootstrap-discovery.instructions.md` + `pull-crm/SKILL.md`.
25
+ - **ADO** — REST via `az account get-access-token --resource 499b84ac-1321-427f-aa17-267ca6975798` per `ado-bootstrap-discovery.instructions.md` + `pull-ado/SKILL.md`.
35
26
 
36
- Before issuing the first WorkIQ query in a run:
27
+ ## Migration
37
28
 
38
- 1. `Get-Command workiq` (or the configured `cli_path`). If missing log `workiq-not-on-path` in `run-log.yml`, write a one-line evidence file pointing at `docs/getting-started/install-workiq.md`, and STOP this source.
39
- 2. Probe `workiq ask -q "ping"`. If EULA prompt → run `workiq accept-eula` once, retry. If auth-failed → log `workiq-auth-failed` and ask user to re-authenticate.
40
- 3. Only after a successful probe, proceed to per-source queries.
29
+ Every reference to `workiq-first.instructions.md` in skills / agents / docs should be updated to `workiq-only.instructions.md`. References to the old "Graph REST as last-resort" paragraph are invalid and MUST be removed.
41
30
 
42
- ## Graph REST when explicitly allowed
43
-
44
- Graph is allowed only as a non-blocking last resort, and only with:
45
- - An explicit `➖ partial via Graph REST` marker in the evidence file.
46
- - A `next_step` line telling the user to install/repair WorkIQ for full-fidelity capture next run.
47
- - Never as a silent default.
31
+ See `workiq-only.instructions.md` for: the canonical per-source WorkIQ prompts, the doubled-strict retry pattern, the user-paste fallback, the forbidden-paths list, and the coverage.md requirements.