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,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.
@@ -0,0 +1,193 @@
1
+ ---
2
+ applyTo: "**"
3
+ description: "WorkIQ is the canonical path for ALL M365 evidence. Graph REST and m365_get_* host tools are explicitly FORBIDDEN as fallbacks in this workspace because they fail unpredictably (Tool execution failed, 401, 415, throttling). Codifies the exact WorkIQ prompts that are known to work, so skills do not re-discover them every run."
4
+ ---
5
+
6
+ # WorkIQ is the ONLY M365 path (HARD RULE, kushi v3.11.0+)
7
+
8
+ ## Why this supersedes `workiq-first`
9
+
10
+ `workiq-first.instructions.md` (v3.7.0) named WorkIQ as preferred but allowed Graph REST / `m365_get_*` host tools as a "last-resort partial". In practice (observed continuously in this workspace 2026-05-13 through 2026-05-18), **the Graph / m365 host tools fail almost every time** with `Tool execution failed`, `401`, `415`, throttling, or returning empty payloads even when content exists. Meanwhile WorkIQ returns full transcripts, full OneNote page bodies, full chat threads, and full email bodies on the first try.
11
+
12
+ Continuing to attempt Graph / m365_get_* in the cascade:
13
+ - wastes a turn
14
+ - produces a defect-looking trail in coverage.md ("step 1 failed, step 2 failed…")
15
+ - causes the agent to "figure out" the right WorkIQ prompt on every run
16
+ - risks the agent giving up after the Graph failures instead of trying WorkIQ at all
17
+
18
+ This rule replaces the cascade with: **WorkIQ first AND only. If WorkIQ fails, ask the user to paste.** Graph / m365_get_* are **forbidden** from kushi pull-* skills.
19
+
20
+ ## Scope of this rule
21
+
22
+ Applies to ALL evidence retrieval from these M365 sources:
23
+
24
+ - Meeting transcripts
25
+ - Meeting facilitator / Copilot recap notes
26
+ - Teams chats and channel messages
27
+ - OneNote pages (bodies)
28
+ - Email bodies and attachments
29
+ - SharePoint file contents (when text extraction is needed)
30
+ - Calendar events (when not already known by id)
31
+
32
+ **Out of scope** (these are NOT WorkIQ — they remain on their direct paths):
33
+
34
+ - **CRM (Dataverse)**: REST via `az account get-access-token --resource https://iscrm.crm.dynamics.com` per `crm-bootstrap-discovery.instructions.md` and `pull-crm/SKILL.md`. WorkIQ does NOT replace Dataverse REST for CRM because WorkIQ summarizes fields and may miss annotations.
35
+ - **ADO**: REST via `az account get-access-token --resource 499b84ac-1321-427f-aa17-267ca6975798` per `ado-bootstrap-discovery.instructions.md` and `pull-ado/SKILL.md`. WorkIQ does NOT replace ADO REST for ADO because WorkIQ summarizes discussion threads.
36
+ - **Raw chat-message metadata** (when you need the chat-id, member list, or raw JSON for an artifact dump): `m365_list_chat_messages` is **allowed** as a structured-data dump alongside the WorkIQ pull. It is NOT a fallback — it is a separate artifact (`chat-messages.json`) that captures the structured form. WorkIQ captures the human-readable thread.
37
+
38
+ ## The doctrine
39
+
40
+ For every M365 source in scope:
41
+
42
+ 1. **WorkIQ FIRST and ONLY.** Issue the canonical query from the table below.
43
+ 2. **If WorkIQ returns insufficient content** (empty, truncated, or only a summary when the query asked for verbatim): retry ONCE with the doubled-strict prompt from the same row.
44
+ 3. **If WorkIQ still fails or is unavailable**: ask the user to paste the data verbatim. This is a first-class evidence path, not a degradation.
45
+ 4. **DO NOT attempt** `m365_get_transcript`, `m365_get_facilitator_notes`, `m365_list_meetings`, `m365_list_events`, `m365_search_files` (for content), `m365_download_file` (for transcript/notes), or any Graph REST URL for the in-scope sources above. These are FORBIDDEN. Calling them is a defect; coverage.md must NOT show them in the attempt trail.
46
+ 5. **Allowed alongside WorkIQ** (structured-data dumps only): `m365_list_chat_messages` for chat-id'd threads → `chat-messages.json`. These run in parallel with the WorkIQ pull, not as a substitute.
47
+
48
+ ## Canonical WorkIQ commands (CODIFIED — do not re-discover)
49
+
50
+ The CLI is at `C:\Users\ushak\.copilot\bin\workiq.cmd` (resolved from `<USER_HOME>/.copilot/project-evidence.yml workiq.cli_path`; fall back to PATH).
51
+
52
+ Invocation shape:
53
+
54
+ ```powershell
55
+ & "<workiq.cli_path>" ask -q "<prompt>" 2>&1 | Out-File "<temp-dump>" -Encoding utf8
56
+ # Then post-process: strip leading "request-id:" lines, keep transcript body.
57
+ ```
58
+
59
+ ### Meeting transcript (FULL VERBATIM)
60
+
61
+ ```text
62
+ 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.
63
+ ```
64
+
65
+ Doubled-strict retry (if first returns a summary):
66
+
67
+ ```text
68
+ Return the COMPLETE, RAW transcript of meeting "<subject>" on <YYYY-MM-DD>. I need every speaker turn in order. Do NOT summarize. Do NOT paraphrase. Do NOT skip any segments. Output as plain text with speaker name colon turn-text per line.
69
+ ```
70
+
71
+ Known-good evidence: JD FDE Intake (2026-05-13) → 8.4KB plain-text transcript with 5+ speakers, first try, request-id `54d9c6bc-6e56-43b6-9eb7-ac23e86e2cc0`, kushi v3.11.0 2026-05-18.
72
+
73
+ ### Meeting Copilot recap / facilitator notes
74
+
75
+ ```text
76
+ 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.
77
+ ```
78
+
79
+ ### Teams chat thread (HUMAN-READABLE)
80
+
81
+ ```text
82
+ Show the full message-by-message reproduction of the Teams chat titled "<topic>" between <YYYY-MM-DD> and <YYYY-MM-DD>. Include sender, ISO timestamp, and full message body for every message. Do not skip, do not summarize.
83
+ ```
84
+
85
+ (Run `m365_list_chat_messages(chatId)` in parallel for the structured JSON dump.)
86
+
87
+ ### OneNote section / page
88
+
89
+ **Three-tier output (CRITICAL — picked the wrong tier = wrong fidelity):**
90
+
91
+ WorkIQ returns OneNote content in three distinct tiers. Each tier is a different prompt. Asking the wrong prompt for the wrong tier wastes the call AND makes the skill think OneNote is broken.
92
+
93
+ | Tier | What WorkIQ returns | Bulk? | Use for |
94
+ |---|---|---|---|
95
+ | **A. Enumeration** | titles + `wdpartid` + `wdsectionfileid` + last-modified + author + deep-link per page | YES — all pages, one call | bootstrap discovery; mutable hints |
96
+ | **B. Search snippet** | ~500-char Graph-search snippet per page (verbatim from search index) | YES — all pages, one call | quick coverage scan; NOT verbatim body substitute |
97
+ | **C. Full verbatim body** | full page text, every paragraph, every table | **NO — ONE page per call**; bulk request is refused with `combined content size … exceeds the maximum response payload that Copilot can safely render in-chat` (HCA evidence 2026-05-13 request-id `fdbf3290-649d-4066-84ea-ceab678697ed`) | snapshot/ verbatim per `pull-onenote` |
98
+
99
+ **DO NOT** ask WorkIQ for "all pages' full bodies in one call." That's the defect signature — it silently degrades to tier A+B and the skill thinks verbatim is unavailable.
100
+
101
+ **Tier A — Enumeration prompt:**
102
+
103
+ ```text
104
+ Search Microsoft 365 OneNote for sections matching the name "<name>". For each match return: section display name, wdsectionfileid, wdsectiongroupid, wdsectiononenoteguid, parentReferenceId (notebook), sourceDoc URL. Flat table, no commentary, no truncation.
105
+ ```
106
+
107
+ **Tier A — Per-section page index prompt (after section is resolved):**
108
+
109
+ ```text
110
+ List EVERY page in OneNote section "<section>.one" (wdsectionfileid <id>). For each page return: title, wdpartid, lastModifiedDateTime, lastModifiedBy, and a deep-link URL. Flat table only, no commentary, no truncation, no summary.
111
+ ```
112
+
113
+ **Tier B — Search snippets prompt:**
114
+
115
+ ```text
116
+ Search OneNote for pages associated with section "<section>.one" (sourceDoc <guid>). For each page return: page title and the exact visible snippet text returned by search (verbatim, not summarized, not rewritten).
117
+ ```
118
+
119
+ **Tier C — Single-page full body prompt (ONE page per call):**
120
+
121
+ ```text
122
+ Get the FULL verbatim body of OneNote page "<title>" (wdpartid <id>) in section "<section>.one". Return every paragraph, every heading, every embedded table, in order, no summarization, no truncation. If you cannot return the full body, say "body-unavailable" exactly and nothing else.
123
+ ```
124
+
125
+ **Per `pull-onenote` v2.9.0+**: Playwright browser-scrape is the PRIMARY path for tier-C bulk capture (16/16 HCA pages tested 2026-05-14) because WorkIQ tier C is one-page-per-call and rate-prone. WorkIQ tier C remains the fallback when the Playwright auth profile expires. Browser-scrape is NOT a Graph call — it's UI automation against OneNote-for-Web — and is therefore compatible with this workiq-only rule.
126
+
127
+ Discovery variant (used at bootstrap to resolve `wdsectionfileid`):
128
+
129
+ ```text
130
+ Search Microsoft 365 OneNote for sections matching the name "<name>". For each match return: section display name, wdsectionfileid, wdsectiongroupid, wdsectiononenoteguid, parentReferenceId (notebook), sourceDoc URL. Flat table, no commentary, no truncation.
131
+ ```
132
+
133
+ ### Email bodies
134
+
135
+ ```text
136
+ Find emails about "<project>" in folder "<folder>" between <YYYY-MM-DD> and <YYYY-MM-DD>. For each email return: sender, recipients, subject, full body verbatim, and reply chain. Do not summarize, do not truncate.
137
+ ```
138
+
139
+ ### SharePoint file content (text-extracted)
140
+
141
+ ```text
142
+ List SharePoint files for "<project>" modified between <YYYY-MM-DD> and <YYYY-MM-DD>. For each file return: file name, URL, author, last-modified, and the full text content (paragraphs and tables) verbatim. Do not summarize.
143
+ ```
144
+
145
+ ### Calendar / online meetings discovery (when joinUrl is unknown)
146
+
147
+ ```text
148
+ List my Teams meetings between <YYYY-MM-DD> and <YYYY-MM-DD> where the subject contains "<token>". Return subject, date, start time, organizer, joinUrl, and Teams chat id.
149
+ ```
150
+
151
+ ## Pre-flight (every M365 pull-* skill)
152
+
153
+ Before the first WorkIQ query in a run:
154
+
155
+ 1. Resolve CLI path: `<USER_HOME>/.copilot/project-evidence.yml workiq.cli_path` OR `Get-Command workiq`. If missing → log `workiq-not-on-path`, write evidence file pointing at install docs, STOP this source.
156
+ 2. Probe with `workiq ask -q "ping"`. If EULA prompt → `workiq accept-eula` once, retry.
157
+ 3. Capture `--version` once into run-log for audit.
158
+
159
+ ## Coverage.md requirements
160
+
161
+ For every WorkIQ-sourced artifact, coverage.md MUST include:
162
+
163
+ ```
164
+ - Source: WorkIQ (workiq.cmd ask)
165
+ - Query: "<exact prompt>"
166
+ - Request-id: <from workiq stderr>
167
+ - Result: SUCCESS | EMPTY | SUMMARY-ONLY (after doubled-strict retry)
168
+ - Artifact: <relative path>, <bytes>
169
+ - Fidelity: full-verbatim | speaker-turns-plain-text | summary-only-warning
170
+ ```
171
+
172
+ If `Result: SUMMARY-ONLY` after doubled-strict retry: the artifact is acceptable but MUST carry the WARNING header per the artifact-class doctrine (e.g. `transcript-source.md` for meetings). It is NOT a substitute for full-verbatim and the source is flagged in run-log.
173
+
174
+ ## Anti-patterns (defects)
175
+
176
+ 1. **Calling `m365_get_transcript`, `m365_get_facilitator_notes`, `m365_list_meetings`, `m365_list_events` from a kushi pull-* skill.** FORBIDDEN. These tools have a near-100% failure rate in this workspace. Use WorkIQ.
177
+ 2. **Using Graph REST URLs directly** (e.g. `https://graph.microsoft.com/v1.0/me/onlineMeetings/...`) from a kushi pull-* skill. FORBIDDEN for the in-scope M365 sources. Use WorkIQ.
178
+ 3. **Re-discovering the right WorkIQ prompt every run.** FORBIDDEN. Use the codified prompts from the table above. If a new source variant is needed, add a row to the table, do not improvise.
179
+ 4. **Stopping after one weak WorkIQ result.** WorkIQ's first response can be a summary; the doubled-strict retry is REQUIRED before falling back to user-paste.
180
+ 5. **Treating user-paste as an error.** It is a first-class evidence path. Coverage.md should label it `Source: User paste on <ISO>` and the artifact stands.
181
+ 6. **Mixing Graph fallbacks with WorkIQ in coverage.md.** If a skill's coverage trail shows `m365_get_transcript: failed` followed by `WorkIQ: success`, the skill is using the old `workiq-first` cascade. Remove the forbidden step.
182
+
183
+ ## Migration note
184
+
185
+ `workiq-first.instructions.md` (v3.7.0) is **deprecated as of kushi v3.11.0** for M365 sources. It remains valid only for the parts that talk about "ask user to paste" as a first-class path. All kushi pull-* skills that pull M365 content (`pull-meetings`, `pull-teams`, `pull-onenote`, `pull-email`, `pull-sharepoint`) must cite `workiq-only.instructions.md` in their front contracts blockquote from v2.x onward. The Graph-fallback paragraph in workiq-first is OVERRIDDEN by this rule.
186
+
187
+ ## Cross-references
188
+
189
+ - `plugin/instructions/meetings-verbatim-required.instructions.md` — transcript artifact classification (transcript.txt is the WorkIQ-derived tier for plain-text speaker turns).
190
+ - `plugin/instructions/crm-bootstrap-discovery.instructions.md` — CRM is OUT of WorkIQ scope; it uses Dataverse REST.
191
+ - `plugin/instructions/ado-bootstrap-discovery.instructions.md` — ADO is OUT of WorkIQ scope; it uses ADO REST.
192
+ - `plugin/instructions/scope-boundaries.instructions.md` — every pull-* still respects integrations.yml#boundaries.
193
+ - `plugin/instructions/evidence-thoroughness.instructions.md` — verbatim is the bar; this rule operationalizes how to hit it.
@@ -0,0 +1,50 @@
1
+ # Learnings register
2
+
3
+ Per-source register of API quirks, fixes, and workarounds discovered during real kushi runs.
4
+
5
+ Governed by [`../instructions/capture-learnings.instructions.md`](../instructions/capture-learnings.instructions.md). Every `pull-*` skill MUST read its register at preflight and append new entries the moment a fix lands mid-run.
6
+
7
+ ## Files
8
+
9
+ | File | Owner skill | Scope |
10
+ |---|---|---|
11
+ | [`ado.md`](./ado.md) | `pull-ado` | Azure DevOps REST + WIQL quirks. |
12
+ | [`crm.md`](./crm.md) | `pull-crm` | Dataverse REST, OData expand quirks, env overrides. |
13
+ | [`email.md`](./email.md) | `pull-email` | Outlook / Graph mail quirks. |
14
+ | [`teams.md`](./teams.md) | `pull-teams` | Teams chat / channel message quirks. |
15
+ | [`meetings.md`](./meetings.md) | `pull-meetings` | Calendar / transcript / online meeting quirks. |
16
+ | [`onenote.md`](./onenote.md) | `pull-onenote` | OneNote page / section quirks. |
17
+ | [`sharepoint.md`](./sharepoint.md) | `pull-sharepoint` | SharePoint / OneDrive file enumeration quirks. |
18
+ | [`cross-cutting.md`](./cross-cutting.md) | (any) | Auth, encoding, PowerShell, host-tool quirks that span sources. |
19
+
20
+ ## How to add an entry
21
+
22
+ 1. The moment a fix or workaround lands during a run, prepend a new entry to the matching file.
23
+ 2. Use the standard format (newest on top):
24
+
25
+ ```markdown
26
+ ### YYYY-MM-DD — short title
27
+
28
+ **Symptom**: ...
29
+
30
+ **Root cause**: ...
31
+
32
+ **Fix / workaround**: ...
33
+
34
+ **Doctrine impact**: ... (or "register-only — TODO promote on next sighting")
35
+
36
+ **Discovered during**: project / skill
37
+ ```
38
+
39
+ 3. If the fix also changes how the skill should always behave, edit the SKILL.md or related instructions file in the **same commit**.
40
+ 4. Never delete entries. To supersede, add a one-liner at the bottom of the old entry: `→ superseded by YYYY-MM-DD entry above`.
41
+
42
+ ## Promotion rules
43
+
44
+ After two sightings of the same learning across projects/runs, **promote** the rule from register to first-class doctrine (SKILL.md or a new `*.instructions.md`). Leave a breadcrumb in the register entry:
45
+
46
+ ```
47
+ → promoted to plugin/instructions/<file>.md on YYYY-MM-DD
48
+ ```
49
+
50
+ Pre-promotion (one sighting) clutters the SKILL.md with one-offs. Wait for the second.
@@ -0,0 +1,45 @@
1
+ # Learnings — Azure DevOps (`pull-ado`)
2
+
3
+ Newest on top. Format defined in [`README.md`](./README.md).
4
+
5
+ ---
6
+
7
+ ### 2026-05-13 — `$top=500` exceeds permissible range on workItems updates endpoint
8
+
9
+ **Symptom**: `GET wit/workItems/{id}/updates?$top=500&api-version=7.1` returns `VS402337: The value provided for the query string parameter '$top' is outside the permissible range.` Result: 0 updates fetched, revision-history section is empty.
10
+
11
+ **Root cause**: ADO REST `$top` max on `/updates` is **200**, not 500 like some sibling endpoints.
12
+
13
+ **Fix / workaround**: Use `$top=200`. If a WI has >200 revisions, paginate with `$skip` or omit `$top` and let the server default apply.
14
+
15
+ **Doctrine impact**: `plugin/skills/pull-ado/SKILL.md` — added explicit `$top=200` to the per-WI pull pseudocode (v3.7.6).
16
+
17
+ **Discovered during**: `HCA / pull-ado` — engagement-96944 + child 96571 both got 0 updates on first pull.
18
+
19
+ ---
20
+
21
+ ### 2026-05-13 — `[Custom.ISCRMRequestId]` field does not exist in IS Engagements WIQL schema
22
+
23
+ **Symptom**: `WIQL` query with `[Custom.ISCRMRequestId] = 'FE-2026-001458'` returns `TF51005: The query references a field that does not exist.`
24
+
25
+ **Root cause**: Earlier doctrine assumed a custom field named `ISCRMRequestId` existed on Engagement WIs to cross-link to CRM. The field was never created in the IS Engagements project schema. The actual link is via title/tags scan.
26
+
27
+ **Fix / workaround**: Drop the `[Custom.ISCRMRequestId]` clause from any WIQL probe. Use the title-substring + Tags scan path instead, then disambiguate by customer name in the title.
28
+
29
+ **Doctrine impact**: `plugin/skills/pull-ado/SKILL.md` — removed the custom-field clause from the resolution-order template (v3.7.6).
30
+
31
+ **Discovered during**: `HCA / pull-ado`.
32
+
33
+ ---
34
+
35
+ ### 2026-05-13 — PowerShell `${id}` interpolation required when next char is `?` or `/`
36
+
37
+ **Symptom**: `Invoke-RestMethod -Uri "$base/workItems/$id?api-version=7.1"` fails because PowerShell parses `$id?` as a single variable and looks for `id?` (which doesn't exist), so the URL becomes malformed.
38
+
39
+ **Root cause**: PowerShell variable name parsing greedy-extends until a non-identifier char. `?` and `/` are valid identifier chars in some contexts.
40
+
41
+ **Fix / workaround**: Always wrap WI-ID interpolation as `${id}` when followed by `?`, `/`, `:`, or `(` — e.g. `"$base/workItems/${id}?api-version=7.1"`.
42
+
43
+ **Doctrine impact**: register-only — TODO promote to a `powershell-quirks.instructions.md` if it bites a second time.
44
+
45
+ **Discovered during**: `HCA / pull-ado` per-WI pull script.