kushi-agents 5.6.4 → 5.7.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 (48) hide show
  1. package/package.json +1 -1
  2. package/plugin/instructions/bootstrap-status-format.instructions.md +151 -151
  3. package/plugin/instructions/customer-hint-discovery.instructions.md +131 -131
  4. package/plugin/instructions/deferred-retry-on-workiq-fail.instructions.md +155 -155
  5. package/plugin/instructions/evidence-layout-canonical.instructions.md +123 -123
  6. package/plugin/instructions/karpathy-state-layout.instructions.md +124 -124
  7. package/plugin/instructions/living-wiki.instructions.md +88 -88
  8. package/plugin/instructions/log-format.instructions.md +78 -78
  9. package/plugin/instructions/no-hallucinated-success.instructions.md +45 -0
  10. package/plugin/instructions/onedrive-pin-policy.instructions.md +132 -132
  11. package/plugin/instructions/tracking.instructions.md +165 -165
  12. package/plugin/instructions/weekly-csc.instructions.md +335 -335
  13. package/plugin/learnings/crm.md +96 -96
  14. package/plugin/learnings/cross-cutting.md +127 -76
  15. package/plugin/learnings/meetings.md +30 -30
  16. package/plugin/learnings/onenote.md +200 -200
  17. package/plugin/plugin.json +1 -0
  18. package/plugin/reference-packs/fde/report-doctrine.md +189 -189
  19. package/plugin/runners/discover.mjs +286 -0
  20. package/plugin/runners/package.json +11 -11
  21. package/plugin/runners/test/unit/discover.test.mjs +130 -0
  22. package/plugin/skills/apply-ado-update/SKILL.md +135 -135
  23. package/plugin/skills/ask-project/evals/evals.json +34 -34
  24. package/plugin/skills/bootstrap-project/SKILL.md +4 -2
  25. package/plugin/skills/consolidate-evidence/SKILL.md +10 -10
  26. package/plugin/skills/discover-project/SKILL.md +56 -0
  27. package/plugin/skills/discover-project/evals/evals.json +46 -0
  28. package/plugin/skills/pull-onenote/write-snapshot.mjs +272 -272
  29. package/plugin/skills/refresh-project/SKILL.md +1 -0
  30. package/plugin/skills/setup/references/onedrive-pin-sync.md +60 -60
  31. package/plugin/templates/init/external-links.template.txt +30 -30
  32. package/plugin/templates/snapshot/meeting-verbatim.template.md +104 -104
  33. package/plugin/templates/state/00_overview.template.md +44 -44
  34. package/plugin/templates/state/01_decisions.template.md +41 -41
  35. package/plugin/templates/state/02_stakeholders.template.md +48 -48
  36. package/plugin/templates/state/03_architecture-and-solution.template.md +56 -56
  37. package/plugin/templates/state/04_workshops-and-key-meetings.template.md +43 -43
  38. package/plugin/templates/state/05_action-items.template.md +29 -29
  39. package/plugin/templates/state/06_risks-and-issues.template.md +43 -43
  40. package/plugin/templates/state/07_timeline-and-milestones.template.md +45 -45
  41. package/plugin/templates/state/08_artifacts-and-deliverables.template.md +55 -55
  42. package/plugin/templates/state/09_open-questions.template.md +62 -62
  43. package/plugin/templates/weekly/run-log.template.md +88 -88
  44. package/src/bootstrap-dryrun.integration.test.mjs +235 -235
  45. package/src/detect-vertex-repo.test.mjs +128 -128
  46. package/src/emit-vertex.e2e.test.mjs +308 -308
  47. package/src/install-runner-deps.mjs +57 -57
  48. package/src/vertex-validate.test.mjs +142 -142
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kushi-agents",
3
- "version": "5.6.4",
3
+ "version": "5.7.0",
4
4
  "description": "Install Kushi — multi-source project evidence agent with Comprehensive Structured Capture (CSC) into weekly-only files across Email, Teams, OneNote, Loop, SharePoint, Meetings, CRM, ADO. Meetings retain a sibling verbatim/ audit folder. WorkIQ-only for M365 sources (Graph / m365_* FORBIDDEN as fallbacks; user-paste is first-class). Host-agnostic.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,151 +1,151 @@
1
- ---
2
- applyTo: "**"
3
- excludeAgent: "code-review"
4
- ---
5
-
6
- # Bootstrap Status Artifact — Format Contract
7
-
8
- When `bootstrap-project` (or any full refresh / retry workflow) finishes a project run, it MUST write `<project>/Evidence/<alias>/bootstrap-status.md` using the format below. This file is the **per-user fast orientation artifact** for the project — what was bootstrapped, what durable context now exists, what stage the engagement is in, what gaps remain. It is NOT a transcript of the run.
9
-
10
- > **v5.4.4+ — per-user path.** The bootstrap-status artifact is **per-user authored** under `Evidence/<alias>/bootstrap-status.md` per `multi-user-shared-files.instructions.md` § "Per-user authored files". A cross-contributor rollup lives at `<project>/_Consolidated/bootstrap-status.md`, written deterministically by `consolidate-evidence` (Step 5). The pre-v5.4.4 root-level `<project>/bootstrap-status.md` is owned by `consolidate-evidence` only; writers MUST NOT touch it. Legacy projects are auto-migrated by `migrate-per-user-files`.
11
-
12
- > **v4.4.2 contracts** — every `Status` cell in this artifact MUST come from the closed taxonomy in `status-taxonomy.instructions.md`. Direct-path failures that were recovered by a documented fallback MUST be rendered as `completed-via-fallback` per `fallback-status-reporting.instructions.md`, not `failed` / `blocked`. The pre-v4.4.2 ad-hoc strings (`populated`, `unsynced`, `degraded`, `partial-cap`, etc.) are mapped onto the taxonomy in `status-taxonomy.instructions.md §1`.
13
-
14
- ## Required section order
15
-
16
- ```
17
- # Bootstrap Status
18
-
19
- - Bootstrap Date: YYYY-MM-DD HH:MM TZ
20
- - Project: <name>
21
- - Customer Hint: <token used to resolve>
22
- - Mode: bootstrap | refresh | retry | force
23
- - Lookback Window: <days>
24
-
25
- ## Preflight Checks
26
-
27
- | Check | Status | Notes |
28
- |---|---|---|
29
- | `.kushi/config/shared/integrations.yml` filled | resolved \| blocked-auth \| missing | ... |
30
- | `.kushi/config/shared/integrations.yml` filled | ... | ... |
31
- | `<project>/integrations.yml` boundaries present | ... | ... |
32
- | `az` CLI tenant matches | cli-available \| blocked-auth | ... |
33
-
34
- ## Context Artifact Status
35
-
36
- | Artifact | Status | Notes |
37
- |---|---|---|
38
- | `crm/snapshot/<entity>/<id>.md` | populated \| unsynced \| degraded \| partial-template | <annotation count> |
39
- | `ado/snapshot/engagement-<id>.md` | populated \| ado-not-complete | <tree size> |
40
- | `ado/snapshot/items/*.md` | populated \| skipped \| ado-not-complete | <N items> |
41
- | `onenote/snapshot/<section>/*.md` | populated \| degraded | <pages enumerated/failed> |
42
- | `email/_index/<week>_message-index.md` | populated \| degraded-list-only \| throttled-tooManyRequests | <N enumerated> |
43
- | `email/stream/<week>_email-stream.md` | populated \| degraded-list-only | <N threads> |
44
- | `teams/...` | ... | ... |
45
-
46
- ## Current Bootstrap Outcome
47
-
48
- - One-line current state per source.
49
- - CRM stage: <plain-language interpretation of statuscode> (`internal-only` per `evidence-confidence-ladder`).
50
- - ADO linkage: pinned engagement <id> | pending pick from N candidates | `ado-not-complete`.
51
- - Notable gaps: ...
52
-
53
- ## Access Limitations
54
-
55
- | System | Status | Reason | Workaround |
56
- |---|---|---|---|
57
- | ADO | resolved | — | — |
58
- | CRM | blocked-auth | tenant mismatch | `az login --tenant <id>` |
59
- | Email | throttled-tooManyRequests | WorkIQ rate-limited | retry next refresh |
60
-
61
- ## Deferred Retries (kushi v4.4.1+, per `deferred-retry-on-workiq-fail.instructions.md`)
62
-
63
- Omit this section entirely if `<project>/Evidence/<alias>/_deferred-retries/` is empty across all contributors.
64
-
65
- | Source | Target | Attempts | Marker | First seen | Discovered by |
66
- |---|---|---|---|---|---|
67
- | meetings | "JD FDE Intake" 2026-05-13 | 1 | `Evidence/ushak/_deferred-retries/2026-05-20-1230_meetings_empty.yml` | 2026-05-20 | ushak |
68
- | onenote | "Architecture overview" | 2 | `Evidence/ushak/_deferred-retries/2026-05-19-0810_onenote_throttled.yml` | 2026-05-19 | ushak |
69
-
70
- Markers older than 5 attempts auto-promote to `OPEN-QUESTIONS-DRAFT.md`. The next `refresh` drains the queue (Step 2a in `refresh-project/SKILL.md`) — do NOT manually retry by calling `m365_get_*` / Graph; those are forbidden per `workiq-only.instructions.md`.
71
-
72
- ## Bootstrap Status
73
-
74
- ONE final line, normalized:
75
- - `bootstrap-complete`
76
- - `bootstrap-complete-with-coverage-gaps`
77
- - `bootstrap-blocked — <primary reason>`
78
- - `refresh-complete`
79
- - `refresh-complete-with-coverage-gaps`
80
- ```
81
-
82
- ## Normalized status vocabulary
83
-
84
- Use these exact strings everywhere (table cells, run-log, narrative):
85
-
86
- - `resolved` — check passed
87
- - `cli-available` — required CLI is installed and authenticated
88
- - `blocked-auth` — auth missing/failed
89
- - `partial-template` — file exists but only template scaffolding written
90
- - `unsynced` — file does not contain real data yet
91
- - `populated` — file contains real fetched data
92
- - `degraded` / `degraded-list-only` — partial fetch (e.g. email body-unavailable for some messages)
93
- - `throttled-tooManyRequests` — source rate-limited
94
- - `ado-not-complete` — engagement record not found yet OR ADO linkage missing
95
- - `completed-with-coverage-gaps` — final outcome with explicit gaps recorded
96
-
97
- ## Multi-contributor safety (kushi v5.4.4+)
98
-
99
- Per `multi-user-shared-files.instructions.md`, this file is **per-user authored** at `<project>/Evidence/<alias>/bootstrap-status.md` and the consolidated cross-contributor view lives at `<project>/_Consolidated/bootstrap-status.md` (written by `consolidate-evidence` Step 5):
100
-
101
- 1. **Writers target the per-user path only.** Every `bootstrap-project` / `refresh-project` run writes its own `Evidence/<alias>/bootstrap-status.md`. There is no read-modify-write contention — each alias owns its file.
102
- 2. **No `Contributors who have bootstrapped this project` section on the per-user file.** That section is reconstructed in the `_Consolidated/bootstrap-status.md` rollup, which lists every contributor with their per-user file's `Last Run` / `Mode` / `Outcome`.
103
- 3. **Conflict-copies on the per-user file are extremely rare** (only the owning alias writes it). If they do appear, the alias's next bootstrap absorbs them and deletes them per the universal merge rules.
104
- 4. **The final one-line status** on the per-user file is for the most recent run by that alias only.
105
-
106
- ### Required `## Run summary` section on the per-user file
107
-
108
- Append immediately after `## Bootstrap Status`:
109
-
110
- ```
111
- ## Run summary
112
-
113
- | Alias | Display Name | Last Run | Mode | Outcome |
114
- |---|---|---|---|---|
115
- | ushak | Usha Kandregula | 2026-05-27 09:42 EDT | bootstrap | bootstrap-complete-with-coverage-gaps |
116
- ```
117
-
118
- `consolidate-evidence` Step 5 reads every `Evidence/<alias>/bootstrap-status.md`, harvests its `## Run summary` row, and emits a merged `## Contributors who have bootstrapped this project` table into `_Consolidated/bootstrap-status.md`.
119
-
120
- ## Sections to AVOID in bootstrap-status
121
-
122
- Do NOT keep these in `bootstrap-status.md` (they belong elsewhere or become stale):
123
-
124
- - `Fallback Inputs Used` → run-log only
125
- - `Evidence & Current Context` → State files
126
- - `FDE Fitness Assessment` → State/00_overview.md
127
- - `Source Coverage` → already covered by Access Limitations
128
- - `Recommended Actions` → State/05_action-items.md or Open Questions/
129
- - long historical retry logs → run-log only
130
-
131
- ## Stable-summary test
132
-
133
- When deciding whether a detail belongs in `bootstrap-status.md`, ask: **"Does this help a future reader understand the current durable project state?"** If it's mainly describing how this one run unfolded, push it to `update-status.md` (per-run history) or the run-log instead.
134
-
135
- ## ADO-not-complete note
136
-
137
- When a bootstrap cannot resolve the ADO Engagement WI, include in `## Current Bootstrap Outcome`:
138
-
139
- > ADO context sync pending: engagement record not found yet; bootstrap is usable with CRM/transcript context and should be revisited after ADO engagement creation or when the candidate WI is pinned to `integrations.yml#ado.engagement_id`.
140
-
141
- And reflect `ado-not-complete` in the relevant Context Artifact Status rows.
142
-
143
- ## Relationship to other artifacts
144
-
145
- - Detailed CRM content → `crm-context/record-profile.md` + `crm/snapshot/`
146
- - Detailed ADO tree → `ado/snapshot/tree.md` + per-item files
147
- - Detailed transcripts → `meeting-transcripts/index.md`
148
- - Per-run history → `update-status.md` (project-local)
149
- - Cross-source synthesis → `State/`
150
-
151
- `bootstrap-status.md` summarizes; it never duplicates these artifacts.
1
+ ---
2
+ applyTo: "**"
3
+ excludeAgent: "code-review"
4
+ ---
5
+
6
+ # Bootstrap Status Artifact — Format Contract
7
+
8
+ When `bootstrap-project` (or any full refresh / retry workflow) finishes a project run, it MUST write `<project>/Evidence/<alias>/bootstrap-status.md` using the format below. This file is the **per-user fast orientation artifact** for the project — what was bootstrapped, what durable context now exists, what stage the engagement is in, what gaps remain. It is NOT a transcript of the run.
9
+
10
+ > **v5.4.4+ — per-user path.** The bootstrap-status artifact is **per-user authored** under `Evidence/<alias>/bootstrap-status.md` per `multi-user-shared-files.instructions.md` § "Per-user authored files". A cross-contributor rollup lives at `<project>/_Consolidated/bootstrap-status.md`, written deterministically by `consolidate-evidence` (Step 5). The pre-v5.4.4 root-level `<project>/bootstrap-status.md` is owned by `consolidate-evidence` only; writers MUST NOT touch it. Legacy projects are auto-migrated by `migrate-per-user-files`.
11
+
12
+ > **v4.4.2 contracts** — every `Status` cell in this artifact MUST come from the closed taxonomy in `status-taxonomy.instructions.md`. Direct-path failures that were recovered by a documented fallback MUST be rendered as `completed-via-fallback` per `fallback-status-reporting.instructions.md`, not `failed` / `blocked`. The pre-v4.4.2 ad-hoc strings (`populated`, `unsynced`, `degraded`, `partial-cap`, etc.) are mapped onto the taxonomy in `status-taxonomy.instructions.md §1`.
13
+
14
+ ## Required section order
15
+
16
+ ```
17
+ # Bootstrap Status
18
+
19
+ - Bootstrap Date: YYYY-MM-DD HH:MM TZ
20
+ - Project: <name>
21
+ - Customer Hint: <token used to resolve>
22
+ - Mode: bootstrap | refresh | retry | force
23
+ - Lookback Window: <days>
24
+
25
+ ## Preflight Checks
26
+
27
+ | Check | Status | Notes |
28
+ |---|---|---|
29
+ | `.kushi/config/shared/integrations.yml` filled | resolved \| blocked-auth \| missing | ... |
30
+ | `.kushi/config/shared/integrations.yml` filled | ... | ... |
31
+ | `<project>/integrations.yml` boundaries present | ... | ... |
32
+ | `az` CLI tenant matches | cli-available \| blocked-auth | ... |
33
+
34
+ ## Context Artifact Status
35
+
36
+ | Artifact | Status | Notes |
37
+ |---|---|---|
38
+ | `crm/snapshot/<entity>/<id>.md` | populated \| unsynced \| degraded \| partial-template | <annotation count> |
39
+ | `ado/snapshot/engagement-<id>.md` | populated \| ado-not-complete | <tree size> |
40
+ | `ado/snapshot/items/*.md` | populated \| skipped \| ado-not-complete | <N items> |
41
+ | `onenote/snapshot/<section>/*.md` | populated \| degraded | <pages enumerated/failed> |
42
+ | `email/_index/<week>_message-index.md` | populated \| degraded-list-only \| throttled-tooManyRequests | <N enumerated> |
43
+ | `email/stream/<week>_email-stream.md` | populated \| degraded-list-only | <N threads> |
44
+ | `teams/...` | ... | ... |
45
+
46
+ ## Current Bootstrap Outcome
47
+
48
+ - One-line current state per source.
49
+ - CRM stage: <plain-language interpretation of statuscode> (`internal-only` per `evidence-confidence-ladder`).
50
+ - ADO linkage: pinned engagement <id> | pending pick from N candidates | `ado-not-complete`.
51
+ - Notable gaps: ...
52
+
53
+ ## Access Limitations
54
+
55
+ | System | Status | Reason | Workaround |
56
+ |---|---|---|---|
57
+ | ADO | resolved | — | — |
58
+ | CRM | blocked-auth | tenant mismatch | `az login --tenant <id>` |
59
+ | Email | throttled-tooManyRequests | WorkIQ rate-limited | retry next refresh |
60
+
61
+ ## Deferred Retries (kushi v4.4.1+, per `deferred-retry-on-workiq-fail.instructions.md`)
62
+
63
+ Omit this section entirely if `<project>/Evidence/<alias>/_deferred-retries/` is empty across all contributors.
64
+
65
+ | Source | Target | Attempts | Marker | First seen | Discovered by |
66
+ |---|---|---|---|---|---|
67
+ | meetings | "JD FDE Intake" 2026-05-13 | 1 | `Evidence/ushak/_deferred-retries/2026-05-20-1230_meetings_empty.yml` | 2026-05-20 | ushak |
68
+ | onenote | "Architecture overview" | 2 | `Evidence/ushak/_deferred-retries/2026-05-19-0810_onenote_throttled.yml` | 2026-05-19 | ushak |
69
+
70
+ Markers older than 5 attempts auto-promote to `OPEN-QUESTIONS-DRAFT.md`. The next `refresh` drains the queue (Step 2a in `refresh-project/SKILL.md`) — do NOT manually retry by calling `m365_get_*` / Graph; those are forbidden per `workiq-only.instructions.md`.
71
+
72
+ ## Bootstrap Status
73
+
74
+ ONE final line, normalized:
75
+ - `bootstrap-complete`
76
+ - `bootstrap-complete-with-coverage-gaps`
77
+ - `bootstrap-blocked — <primary reason>`
78
+ - `refresh-complete`
79
+ - `refresh-complete-with-coverage-gaps`
80
+ ```
81
+
82
+ ## Normalized status vocabulary
83
+
84
+ Use these exact strings everywhere (table cells, run-log, narrative):
85
+
86
+ - `resolved` — check passed
87
+ - `cli-available` — required CLI is installed and authenticated
88
+ - `blocked-auth` — auth missing/failed
89
+ - `partial-template` — file exists but only template scaffolding written
90
+ - `unsynced` — file does not contain real data yet
91
+ - `populated` — file contains real fetched data
92
+ - `degraded` / `degraded-list-only` — partial fetch (e.g. email body-unavailable for some messages)
93
+ - `throttled-tooManyRequests` — source rate-limited
94
+ - `ado-not-complete` — engagement record not found yet OR ADO linkage missing
95
+ - `completed-with-coverage-gaps` — final outcome with explicit gaps recorded
96
+
97
+ ## Multi-contributor safety (kushi v5.4.4+)
98
+
99
+ Per `multi-user-shared-files.instructions.md`, this file is **per-user authored** at `<project>/Evidence/<alias>/bootstrap-status.md` and the consolidated cross-contributor view lives at `<project>/_Consolidated/bootstrap-status.md` (written by `consolidate-evidence` Step 5):
100
+
101
+ 1. **Writers target the per-user path only.** Every `bootstrap-project` / `refresh-project` run writes its own `Evidence/<alias>/bootstrap-status.md`. There is no read-modify-write contention — each alias owns its file.
102
+ 2. **No `Contributors who have bootstrapped this project` section on the per-user file.** That section is reconstructed in the `_Consolidated/bootstrap-status.md` rollup, which lists every contributor with their per-user file's `Last Run` / `Mode` / `Outcome`.
103
+ 3. **Conflict-copies on the per-user file are extremely rare** (only the owning alias writes it). If they do appear, the alias's next bootstrap absorbs them and deletes them per the universal merge rules.
104
+ 4. **The final one-line status** on the per-user file is for the most recent run by that alias only.
105
+
106
+ ### Required `## Run summary` section on the per-user file
107
+
108
+ Append immediately after `## Bootstrap Status`:
109
+
110
+ ```
111
+ ## Run summary
112
+
113
+ | Alias | Display Name | Last Run | Mode | Outcome |
114
+ |---|---|---|---|---|
115
+ | ushak | Usha Kandregula | 2026-05-27 09:42 EDT | bootstrap | bootstrap-complete-with-coverage-gaps |
116
+ ```
117
+
118
+ `consolidate-evidence` Step 5 reads every `Evidence/<alias>/bootstrap-status.md`, harvests its `## Run summary` row, and emits a merged `## Contributors who have bootstrapped this project` table into `_Consolidated/bootstrap-status.md`.
119
+
120
+ ## Sections to AVOID in bootstrap-status
121
+
122
+ Do NOT keep these in `bootstrap-status.md` (they belong elsewhere or become stale):
123
+
124
+ - `Fallback Inputs Used` → run-log only
125
+ - `Evidence & Current Context` → State files
126
+ - `FDE Fitness Assessment` → State/00_overview.md
127
+ - `Source Coverage` → already covered by Access Limitations
128
+ - `Recommended Actions` → State/05_action-items.md or Open Questions/
129
+ - long historical retry logs → run-log only
130
+
131
+ ## Stable-summary test
132
+
133
+ When deciding whether a detail belongs in `bootstrap-status.md`, ask: **"Does this help a future reader understand the current durable project state?"** If it's mainly describing how this one run unfolded, push it to `update-status.md` (per-run history) or the run-log instead.
134
+
135
+ ## ADO-not-complete note
136
+
137
+ When a bootstrap cannot resolve the ADO Engagement WI, include in `## Current Bootstrap Outcome`:
138
+
139
+ > ADO context sync pending: engagement record not found yet; bootstrap is usable with CRM/transcript context and should be revisited after ADO engagement creation or when the candidate WI is pinned to `integrations.yml#ado.engagement_id`.
140
+
141
+ And reflect `ado-not-complete` in the relevant Context Artifact Status rows.
142
+
143
+ ## Relationship to other artifacts
144
+
145
+ - Detailed CRM content → `crm-context/record-profile.md` + `crm/snapshot/`
146
+ - Detailed ADO tree → `ado/snapshot/tree.md` + per-item files
147
+ - Detailed transcripts → `meeting-transcripts/index.md`
148
+ - Per-run history → `update-status.md` (project-local)
149
+ - Cross-source synthesis → `State/`
150
+
151
+ `bootstrap-status.md` summarizes; it never duplicates these artifacts.
@@ -1,131 +1,131 @@
1
- ---
2
- applyTo: "**/skills/bootstrap-project/**, **/skills/pull-email/**, **/skills/pull-teams/**, **/skills/pull-meetings/**, **/skills/pull-sharepoint/**, **/skills/refresh-project/**"
3
- description: "Customer-hint discovery sweep — bootstrap MUST attempt WorkIQ-driven discovery for every source whose boundary is empty before declaring blocked-config. Mirrors crm-bootstrap-discovery + loop-bootstrap-discovery pattern. Kushi v4.8.0+."
4
- ---
5
-
6
- # Customer-hint discovery sweep (HARD RULE — kushi v4.8.0+)
7
-
8
- ## The defect this rule exists to prevent
9
-
10
- Bootstrap runs that scaffold an empty `<project>/integrations.yml#boundaries.*` and immediately declare every source `blocked-config` — without ever asking WorkIQ "who/what mentions this customer?". The result: a fresh project bootstrap finishes with 0 evidence pulled, the user is told to hand-populate mailboxes / chat IDs / channel IDs / meeting join URLs / SharePoint sites, and the entire value proposition of "bootstrap a project from a customer hint" collapses to a config form. Discovered 2026-05-26 on the Northwind bootstrap — every source row read `blocked-config` despite extensive Northwind email / Teams / meeting history in the tenant.
11
-
12
- ## The rule
13
-
14
- Before `bootstrap-project` (or `refresh-project` on a first pull) is allowed to write `last_status: blocked-config` for **email, teams, meetings, or sharepoint**, the per-source customer-hint discovery sweep defined in the matching doctrine MUST be attempted with the customer hint + lookback window:
15
-
16
- | Source | Doctrine file (mandatory) |
17
- |---|---|
18
- | email | `email-bootstrap-discovery.instructions.md` |
19
- | teams | `teams-bootstrap-discovery.instructions.md` |
20
- | meetings | `meetings-bootstrap-discovery.instructions.md` |
21
- | sharepoint | `sharepoint-bootstrap-discovery.instructions.md` |
22
- | onenote | `bootstrap-project/SKILL.md#step-4a` (already shipped v4.7.x — display-name driven) |
23
- | loop | `loop-bootstrap-discovery.instructions.md` (already shipped v4.6.0) |
24
- | crm | `crm-bootstrap-discovery.instructions.md` (already shipped v3.11.0) |
25
- | ado | `ado-bootstrap-discovery.instructions.md` |
26
-
27
- `blocked-config` is ONLY legitimate when:
28
-
29
- 1. **The sweep ran** and returned 0 candidates → status is `unresolved` (sweep succeeded but no hits), not `blocked-config`. Use `discovery-empty` annotation in the per-source notes.
30
- 2. **The sweep COULD not run** because a prerequisite is genuinely missing (e.g. CRM/ADO need `<workspace>/.kushi/config/shared/integrations.yml` populated, SharePoint local-folder enumeration needs a local OneDrive sync path the customer hint cannot infer). In that case, `blocked-config` is correct, and the per-source `next_step` MUST cite the specific missing config field.
31
-
32
- Any other path that writes `blocked-config` without attempting the sweep is a **defect**.
33
-
34
- ## Required inputs
35
-
36
- - `<customer-hint>` — verbatim string the user provided at bootstrap invocation (e.g. `Northwind`). Captured by `bootstrap-project` Step 0/1 and persisted to `<project>/bootstrap-status.md` under `Customer Hint:`. Used VERBATIM in v4.8.0 — no fuzzy expansion (deferred to v4.9.0).
37
- - `<lookback-days>` — defaults to **90** for discovery (longer than the 30-day pull window so historical chats / series still surface). Configurable via `<workspace>/.kushi/config/user/m365-mutable.json#bootstrap.discoveryLookbackDays`.
38
- - `<project>` — engagement name (already resolved).
39
- - `<alias>` — current contributor.
40
-
41
- ## Required outputs
42
-
43
- For each source whose sweep runs:
44
-
45
- 1. **Append discovered IDs / URLs / paths to `<engagement-root>/<project>/integrations.yml#boundaries.<source>.<key>`** as plain strings (existing pull-* skills consume strings — do NOT change the array element type). Idempotent: deduplicate by exact-string equality.
46
-
47
- 2. **Write a sidecar discovery record to `<engagement-root>/<project>/Evidence/<alias>/_discovery/<YYYY-MM-DD>_<source>_discovery.yml`** with the per-row metadata (`discovered_by`, `discovered_at`, `needs_review`, `query`, `request_id`, `confidence`). The sidecar lives **inside the contributor's alias folder** because discovery results are inherently per-identity (each contributor sees a different mailbox / chat / meeting set). Schema:
48
-
49
- ```yaml
50
- source: email | teams | meetings | sharepoint
51
- project: <project>
52
- customer_hint: '<hint>'
53
- lookback_days: 90
54
- discovered_at: '<ISO-8601>'
55
- discovered_by: <alias>
56
- query: '<exact WorkIQ prompt>'
57
- workiq_request_id: '<request-id from response>'
58
- total_candidates_found: <N>
59
- candidates_persisted: <M> # ≤ 10 after cap
60
- candidates_deferred: <N - M> # written to OPEN-QUESTIONS-DRAFT.md
61
- results:
62
- - value: '<string written to boundary>'
63
- label: '<human-readable label>'
64
- confidence: high | medium | low
65
- needs_review: true
66
- ```
67
-
68
- 3. **If `total_candidates_found > 10`**, persist the top 10 by recency to the boundary and append the remaining N–10 to `<project>/OPEN-QUESTIONS-DRAFT.md` under `## Discovery sweep — candidates over cap` with one row per candidate.
69
-
70
- 4. **Add a `## Discovery Sweep Results` section to `<project>/bootstrap-status.md`** after `## Context Artifact Status`. Table shape:
71
-
72
- ```
73
- ## Discovery Sweep Results
74
-
75
- | Source | Hint | Query attempted | Candidates found | Persisted | Deferred | Discovered by |
76
- |---|---|---|---|---|---|---|
77
- | email | Northwind | "In my Inbox..." | 7 | 7 | 0 | ushak |
78
- | teams | Northwind | "In my Teams chats..." | 14 | 10 | 4 | ushak |
79
- | meetings | Northwind | "In my calendar..." | 3 | 3 | 0 | ushak |
80
- | sharepoint | Northwind | "In my SharePoint sites..." | 0 | 0 | 0 | ushak |
81
- ```
82
-
83
- ## Behavior matrix (per source)
84
-
85
- | Sweep result | `boundaries.<source>.<key>` written? | `last_status` | `retry_signal` | Open Questions written? |
86
- |---|---|---|---|---|
87
- | 0 candidates | no | `unresolved` (annotated `discovery-empty`) | `user-action` | yes — "Discovery sweep for `<source>` returned 0 hits for `<hint>`; widen hint or seed `boundaries.<source>.<key>` manually" |
88
- | 1–10 candidates | yes (all) | `completed-with-coverage-gaps` (because rows are `needs_review`) | `watch` | only if any row low-confidence |
89
- | > 10 candidates | yes (top 10 by recency) | `completed-with-coverage-gaps` | `watch` | yes — "Discovery sweep returned >10 candidates; review the deferred list" |
90
- | **WorkIQ punted — no surface for this source** (sharepoint sites, teams channels — v4.8.1 empirical) | no | `unresolved` (annotated `discovery-empty-no-workiq-surface`) | `user-action` | yes — cite that this source has no known WorkIQ discovery surface and direct the user to manual configuration (the per-source doctrine has the exact wording) |
91
- | Sweep query failed (WorkIQ error / classified per `fallback-status-reporting.instructions.md`) | no | `deferred` (write marker per `deferred-retry-on-workiq-fail.instructions.md`) | `retry` | no — next refresh will drain |
92
- | Prerequisite genuinely missing (e.g. CRM shared config empty) | no | `blocked-config` | `user-action` | yes — cite specific missing field |
93
-
94
- ## Multi-contributor safety
95
-
96
- When the boundary already has rows from another alias (or sibling `Evidence/<other-alias>/_discovery/` folders already have entries):
97
-
98
- 1. **Append-only** — the new alias's sweep adds rows that are not already present (dedupe by exact-string equality on the boundary value). Never remove or rewrite another alias's row.
99
- 2. **Sidecar files are per-contributor-folder-per-source-per-date** — each contributor writes only into their own `Evidence/<alias>/_discovery/` folder. Filenames are NOT suffixed with `-<alias>` (folder already namespaces the owner). On the same day, contributors `ushak` and `stand` produce `Evidence/ushak/_discovery/2026-05-26_email_discovery.yml` and `Evidence/stand/_discovery/2026-05-26_email_discovery.yml` respectively — no collision possible. Bootstrap-status's Discovery Sweep Results table shows one row per source × alias.
100
- 3. **`Discovered by` column in bootstrap-status's per-source Context Artifact Status row** cites the most recent discovering alias. Preserve other aliases' rows in `## Contributors who have bootstrapped this project` per `multi-user-shared-files.instructions.md`.
101
- 4. **NEVER write to another contributor's `Evidence/<other-alias>/_discovery/` folder.** Reading other aliases' discovery sidecars (e.g. to merge already-confirmed candidates into the shared boundary) is allowed and expected; writing into them is forbidden.
102
-
103
- ## Rerun behavior
104
-
105
- When the user re-runs bootstrap on a project that already has populated boundaries:
106
-
107
- | Boundary state | Sweep behavior |
108
- |---|---|
109
- | Empty | Run sweep (full discovery). |
110
- | Has rows, none `needs_review: true` (all confirmed) | **Skip sweep.** Boundary is gospel — do not re-discover. |
111
- | Has rows, some `needs_review: true` (sidecar shows confidence < high) | Run sweep. Merge new candidates by ID. Promote previously-discovered candidates from `needs_review: true` → `false` only if user has manually confirmed (i.e. removed the `needs_review` flag from the sidecar). |
112
- | User passes `--force-rediscover` | Run sweep regardless of state. Merge new candidates; never delete user-confirmed rows. |
113
-
114
- ## Forbidden behaviors
115
-
116
- 1. **Declaring `blocked-config` without running the sweep first** for email/teams/meetings/sharepoint — see "The defect" above. CRM/ADO have their own mandates in `crm-bootstrap-discovery` / `ado-bootstrap-discovery`.
117
- 2. **Auto-narrowing the customer hint** ("Northwind" → "Northwind Healthcare Inc"). Use the hint verbatim. Smart-expansion is v4.9.0.
118
- 3. **Discovering across all sources in one mega-query.** Each source has its own narrow WorkIQ prompt (see per-source doctrines). Mega-queries punt to Graph and return empty.
119
- 4. **Inferring local OneDrive sync paths from the hint** for SharePoint `local_folders[]`. Discovery populates `site_urls[]` only.
120
- 5. **Calling Graph / `m365_*` directly for discovery.** Per `workiq-only.instructions.md` the four sources covered here use WorkIQ exclusively. The only allowed `m365_*` exceptions remain `m365_list_chat_messages` (parallel structured dump per pull-teams) and the per-source carve-outs already named in their pull-* SKILLs.
121
-
122
- ## References
123
-
124
- - `crm-bootstrap-discovery.instructions.md` — the original "must-attempt-before-declaring-disabled" doctrine; this file mirrors its pattern for the WorkIQ-driven sources.
125
- - `loop-bootstrap-discovery.instructions.md` — Loop-specific discovery + registry shape.
126
- - `scope-boundaries.instructions.md` — the broader partial-determinism contract; this doctrine is the discovery-time enabler that makes boundaries achievable.
127
- - `workiq-only.instructions.md` — what discovery is NOT allowed to call (Graph, m365_* for content).
128
- - `status-taxonomy.instructions.md` — the closed-set status vocabulary; `unresolved` + `discovery-empty` annotation vs. `blocked-config`.
129
- - `fallback-status-reporting.instructions.md` — how to classify WorkIQ punts during the sweep.
130
- - `multi-user-shared-files.instructions.md` — append-only rules for the boundary file.
131
- - `bootstrap-status-format.instructions.md` — where `## Discovery Sweep Results` slots in the report.
1
+ ---
2
+ applyTo: "**/skills/bootstrap-project/**, **/skills/pull-email/**, **/skills/pull-teams/**, **/skills/pull-meetings/**, **/skills/pull-sharepoint/**, **/skills/refresh-project/**"
3
+ description: "Customer-hint discovery sweep — bootstrap MUST attempt WorkIQ-driven discovery for every source whose boundary is empty before declaring blocked-config. Mirrors crm-bootstrap-discovery + loop-bootstrap-discovery pattern. Kushi v4.8.0+."
4
+ ---
5
+
6
+ # Customer-hint discovery sweep (HARD RULE — kushi v4.8.0+)
7
+
8
+ ## The defect this rule exists to prevent
9
+
10
+ Bootstrap runs that scaffold an empty `<project>/integrations.yml#boundaries.*` and immediately declare every source `blocked-config` — without ever asking WorkIQ "who/what mentions this customer?". The result: a fresh project bootstrap finishes with 0 evidence pulled, the user is told to hand-populate mailboxes / chat IDs / channel IDs / meeting join URLs / SharePoint sites, and the entire value proposition of "bootstrap a project from a customer hint" collapses to a config form. Discovered 2026-05-26 on the Northwind bootstrap — every source row read `blocked-config` despite extensive Northwind email / Teams / meeting history in the tenant.
11
+
12
+ ## The rule
13
+
14
+ Before `bootstrap-project` (or `refresh-project` on a first pull) is allowed to write `last_status: blocked-config` for **email, teams, meetings, or sharepoint**, the per-source customer-hint discovery sweep defined in the matching doctrine MUST be attempted with the customer hint + lookback window:
15
+
16
+ | Source | Doctrine file (mandatory) |
17
+ |---|---|
18
+ | email | `email-bootstrap-discovery.instructions.md` |
19
+ | teams | `teams-bootstrap-discovery.instructions.md` |
20
+ | meetings | `meetings-bootstrap-discovery.instructions.md` |
21
+ | sharepoint | `sharepoint-bootstrap-discovery.instructions.md` |
22
+ | onenote | `bootstrap-project/SKILL.md#step-4a` (already shipped v4.7.x — display-name driven) |
23
+ | loop | `loop-bootstrap-discovery.instructions.md` (already shipped v4.6.0) |
24
+ | crm | `crm-bootstrap-discovery.instructions.md` (already shipped v3.11.0) |
25
+ | ado | `ado-bootstrap-discovery.instructions.md` |
26
+
27
+ `blocked-config` is ONLY legitimate when:
28
+
29
+ 1. **The sweep ran** and returned 0 candidates → status is `unresolved` (sweep succeeded but no hits), not `blocked-config`. Use `discovery-empty` annotation in the per-source notes.
30
+ 2. **The sweep COULD not run** because a prerequisite is genuinely missing (e.g. CRM/ADO need `<workspace>/.kushi/config/shared/integrations.yml` populated, SharePoint local-folder enumeration needs a local OneDrive sync path the customer hint cannot infer). In that case, `blocked-config` is correct, and the per-source `next_step` MUST cite the specific missing config field.
31
+
32
+ Any other path that writes `blocked-config` without attempting the sweep is a **defect**.
33
+
34
+ ## Required inputs
35
+
36
+ - `<customer-hint>` — verbatim string the user provided at bootstrap invocation (e.g. `Northwind`). Captured by `bootstrap-project` Step 0/1 and persisted to `<project>/bootstrap-status.md` under `Customer Hint:`. Used VERBATIM in v4.8.0 — no fuzzy expansion (deferred to v4.9.0).
37
+ - `<lookback-days>` — defaults to **90** for discovery (longer than the 30-day pull window so historical chats / series still surface). Configurable via `<workspace>/.kushi/config/user/m365-mutable.json#bootstrap.discoveryLookbackDays`.
38
+ - `<project>` — engagement name (already resolved).
39
+ - `<alias>` — current contributor.
40
+
41
+ ## Required outputs
42
+
43
+ For each source whose sweep runs:
44
+
45
+ 1. **Append discovered IDs / URLs / paths to `<engagement-root>/<project>/integrations.yml#boundaries.<source>.<key>`** as plain strings (existing pull-* skills consume strings — do NOT change the array element type). Idempotent: deduplicate by exact-string equality.
46
+
47
+ 2. **Write a sidecar discovery record to `<engagement-root>/<project>/Evidence/<alias>/_discovery/<YYYY-MM-DD>_<source>_discovery.yml`** with the per-row metadata (`discovered_by`, `discovered_at`, `needs_review`, `query`, `request_id`, `confidence`). The sidecar lives **inside the contributor's alias folder** because discovery results are inherently per-identity (each contributor sees a different mailbox / chat / meeting set). Schema:
48
+
49
+ ```yaml
50
+ source: email | teams | meetings | sharepoint
51
+ project: <project>
52
+ customer_hint: '<hint>'
53
+ lookback_days: 90
54
+ discovered_at: '<ISO-8601>'
55
+ discovered_by: <alias>
56
+ query: '<exact WorkIQ prompt>'
57
+ workiq_request_id: '<request-id from response>'
58
+ total_candidates_found: <N>
59
+ candidates_persisted: <M> # ≤ 10 after cap
60
+ candidates_deferred: <N - M> # written to OPEN-QUESTIONS-DRAFT.md
61
+ results:
62
+ - value: '<string written to boundary>'
63
+ label: '<human-readable label>'
64
+ confidence: high | medium | low
65
+ needs_review: true
66
+ ```
67
+
68
+ 3. **If `total_candidates_found > 10`**, persist the top 10 by recency to the boundary and append the remaining N–10 to `<project>/OPEN-QUESTIONS-DRAFT.md` under `## Discovery sweep — candidates over cap` with one row per candidate.
69
+
70
+ 4. **Add a `## Discovery Sweep Results` section to `<project>/bootstrap-status.md`** after `## Context Artifact Status`. Table shape:
71
+
72
+ ```
73
+ ## Discovery Sweep Results
74
+
75
+ | Source | Hint | Query attempted | Candidates found | Persisted | Deferred | Discovered by |
76
+ |---|---|---|---|---|---|---|
77
+ | email | Northwind | "In my Inbox..." | 7 | 7 | 0 | ushak |
78
+ | teams | Northwind | "In my Teams chats..." | 14 | 10 | 4 | ushak |
79
+ | meetings | Northwind | "In my calendar..." | 3 | 3 | 0 | ushak |
80
+ | sharepoint | Northwind | "In my SharePoint sites..." | 0 | 0 | 0 | ushak |
81
+ ```
82
+
83
+ ## Behavior matrix (per source)
84
+
85
+ | Sweep result | `boundaries.<source>.<key>` written? | `last_status` | `retry_signal` | Open Questions written? |
86
+ |---|---|---|---|---|
87
+ | 0 candidates | no | `unresolved` (annotated `discovery-empty`) | `user-action` | yes — "Discovery sweep for `<source>` returned 0 hits for `<hint>`; widen hint or seed `boundaries.<source>.<key>` manually" |
88
+ | 1–10 candidates | yes (all) | `completed-with-coverage-gaps` (because rows are `needs_review`) | `watch` | only if any row low-confidence |
89
+ | > 10 candidates | yes (top 10 by recency) | `completed-with-coverage-gaps` | `watch` | yes — "Discovery sweep returned >10 candidates; review the deferred list" |
90
+ | **WorkIQ punted — no surface for this source** (sharepoint sites, teams channels — v4.8.1 empirical) | no | `unresolved` (annotated `discovery-empty-no-workiq-surface`) | `user-action` | yes — cite that this source has no known WorkIQ discovery surface and direct the user to manual configuration (the per-source doctrine has the exact wording) |
91
+ | Sweep query failed (WorkIQ error / classified per `fallback-status-reporting.instructions.md`) | no | `deferred` (write marker per `deferred-retry-on-workiq-fail.instructions.md`) | `retry` | no — next refresh will drain |
92
+ | Prerequisite genuinely missing (e.g. CRM shared config empty) | no | `blocked-config` | `user-action` | yes — cite specific missing field |
93
+
94
+ ## Multi-contributor safety
95
+
96
+ When the boundary already has rows from another alias (or sibling `Evidence/<other-alias>/_discovery/` folders already have entries):
97
+
98
+ 1. **Append-only** — the new alias's sweep adds rows that are not already present (dedupe by exact-string equality on the boundary value). Never remove or rewrite another alias's row.
99
+ 2. **Sidecar files are per-contributor-folder-per-source-per-date** — each contributor writes only into their own `Evidence/<alias>/_discovery/` folder. Filenames are NOT suffixed with `-<alias>` (folder already namespaces the owner). On the same day, contributors `ushak` and `stand` produce `Evidence/ushak/_discovery/2026-05-26_email_discovery.yml` and `Evidence/stand/_discovery/2026-05-26_email_discovery.yml` respectively — no collision possible. Bootstrap-status's Discovery Sweep Results table shows one row per source × alias.
100
+ 3. **`Discovered by` column in bootstrap-status's per-source Context Artifact Status row** cites the most recent discovering alias. Preserve other aliases' rows in `## Contributors who have bootstrapped this project` per `multi-user-shared-files.instructions.md`.
101
+ 4. **NEVER write to another contributor's `Evidence/<other-alias>/_discovery/` folder.** Reading other aliases' discovery sidecars (e.g. to merge already-confirmed candidates into the shared boundary) is allowed and expected; writing into them is forbidden.
102
+
103
+ ## Rerun behavior
104
+
105
+ When the user re-runs bootstrap on a project that already has populated boundaries:
106
+
107
+ | Boundary state | Sweep behavior |
108
+ |---|---|
109
+ | Empty | Run sweep (full discovery). |
110
+ | Has rows, none `needs_review: true` (all confirmed) | **Skip sweep.** Boundary is gospel — do not re-discover. |
111
+ | Has rows, some `needs_review: true` (sidecar shows confidence < high) | Run sweep. Merge new candidates by ID. Promote previously-discovered candidates from `needs_review: true` → `false` only if user has manually confirmed (i.e. removed the `needs_review` flag from the sidecar). |
112
+ | User passes `--force-rediscover` | Run sweep regardless of state. Merge new candidates; never delete user-confirmed rows. |
113
+
114
+ ## Forbidden behaviors
115
+
116
+ 1. **Declaring `blocked-config` without running the sweep first** for email/teams/meetings/sharepoint — see "The defect" above. CRM/ADO have their own mandates in `crm-bootstrap-discovery` / `ado-bootstrap-discovery`.
117
+ 2. **Auto-narrowing the customer hint** ("Northwind" → "Northwind Healthcare Inc"). Use the hint verbatim. Smart-expansion is v4.9.0.
118
+ 3. **Discovering across all sources in one mega-query.** Each source has its own narrow WorkIQ prompt (see per-source doctrines). Mega-queries punt to Graph and return empty.
119
+ 4. **Inferring local OneDrive sync paths from the hint** for SharePoint `local_folders[]`. Discovery populates `site_urls[]` only.
120
+ 5. **Calling Graph / `m365_*` directly for discovery.** Per `workiq-only.instructions.md` the four sources covered here use WorkIQ exclusively. The only allowed `m365_*` exceptions remain `m365_list_chat_messages` (parallel structured dump per pull-teams) and the per-source carve-outs already named in their pull-* SKILLs.
121
+
122
+ ## References
123
+
124
+ - `crm-bootstrap-discovery.instructions.md` — the original "must-attempt-before-declaring-disabled" doctrine; this file mirrors its pattern for the WorkIQ-driven sources.
125
+ - `loop-bootstrap-discovery.instructions.md` — Loop-specific discovery + registry shape.
126
+ - `scope-boundaries.instructions.md` — the broader partial-determinism contract; this doctrine is the discovery-time enabler that makes boundaries achievable.
127
+ - `workiq-only.instructions.md` — what discovery is NOT allowed to call (Graph, m365_* for content).
128
+ - `status-taxonomy.instructions.md` — the closed-set status vocabulary; `unresolved` + `discovery-empty` annotation vs. `blocked-config`.
129
+ - `fallback-status-reporting.instructions.md` — how to classify WorkIQ punts during the sweep.
130
+ - `multi-user-shared-files.instructions.md` — append-only rules for the boundary file.
131
+ - `bootstrap-status-format.instructions.md` — where `## Discovery Sweep Results` slots in the report.