kushi-agents 4.4.0 → 4.4.3
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.
- package/bin/cli.mjs +2 -4
- package/package.json +1 -1
- package/plugin/agents/kushi.agent.md +5 -1
- package/plugin/instructions/ado-engagement-tree.instructions.md +1 -1
- package/plugin/instructions/az-auth-conditional.instructions.md +2 -2
- package/plugin/instructions/azure-auth-patterns.instructions.md +6 -6
- package/plugin/instructions/bootstrap-status-format.instructions.md +15 -2
- package/plugin/instructions/cleanup-on-resolution.instructions.md +1 -1
- package/plugin/instructions/communication-guidelines.instructions.md +79 -0
- package/plugin/instructions/crm-bootstrap-discovery.instructions.md +1 -1
- package/plugin/instructions/deferred-retry-on-workiq-fail.instructions.md +155 -0
- package/plugin/instructions/engagement-root-resolution.instructions.md +13 -10
- package/plugin/instructions/evidence-layout-canonical.instructions.md +2 -2
- package/plugin/instructions/fallback-status-reporting.instructions.md +104 -0
- package/plugin/instructions/fde-grounding.instructions.md +146 -0
- package/plugin/instructions/identity-resolution.instructions.md +15 -8
- package/plugin/instructions/m365-id-registry.instructions.md +1 -1
- package/plugin/instructions/scope-boundaries.instructions.md +4 -4
- package/plugin/instructions/status-taxonomy.instructions.md +118 -0
- package/plugin/instructions/workiq-only.instructions.md +4 -2
- package/plugin/lib/Get-KushiConfig.ps1 +112 -7
- package/plugin/prompts/bootstrap.prompt.md +64 -49
- package/plugin/skills/apply-ado-update/SKILL.md +2 -2
- package/plugin/skills/bootstrap-project/SKILL.md +10 -10
- package/plugin/skills/propose-ado-update/SKILL.md +3 -3
- package/plugin/skills/pull-ado/SKILL.md +27 -13
- package/plugin/skills/pull-crm/SKILL.md +20 -9
- package/plugin/skills/pull-email/SKILL.md +2 -2
- package/plugin/skills/pull-meetings/SKILL.md +1 -1
- package/plugin/skills/pull-onenote/scripts/recapture-section-url.mjs +2 -1
- package/plugin/skills/pull-onenote/write-snapshot.mjs +2 -1
- package/plugin/skills/pull-sharepoint/SKILL.md +1 -1
- package/plugin/skills/pull-teams/SKILL.md +1 -1
- package/plugin/skills/refresh-project/SKILL.md +21 -1
- package/plugin/skills/self-check/run.ps1 +24 -1
- package/plugin/templates/ado-update/integrations-ado-writes.example.yml +1 -1
- package/plugin/templates/init/integrations.template.yml +32 -19
- package/plugin/templates/init/m365-auth.template.json +5 -5
- package/plugin/templates/init/project-integrations.template.yml +2 -2
- package/plugin/templates/snapshot/onenote-page.template.md +3 -3
- package/src/config-loader.mjs +92 -5
- package/src/main.mjs +2 -30
- package/plugin/templates/init/ado-config.template.yml +0 -21
- package/plugin/templates/init/crm-config.template.yml +0 -16
- package/src/prompt.mjs +0 -42
package/bin/cli.mjs
CHANGED
|
@@ -23,10 +23,9 @@ if (args.includes('--help') || args.includes('-h')) {
|
|
|
23
23
|
--profile full Standard + report packs (FDE weekly/customer/handoff).
|
|
24
24
|
|
|
25
25
|
Options:
|
|
26
|
-
--dest <path> Override destination (relative for vscode, absolute for clawpilot)
|
|
27
26
|
--force Overwrite existing destination without asking
|
|
28
|
-
--yes, -y
|
|
29
|
-
|
|
27
|
+
--yes, -y Skip the project-root check (useful for scripted or
|
|
28
|
+
agent-driven installs)
|
|
30
29
|
--no-settings Skip .vscode/settings.json update (vscode target only)
|
|
31
30
|
--no-instructions Skip .github/copilot-instructions.md merge (vscode target only)
|
|
32
31
|
|
|
@@ -62,7 +61,6 @@ if (args.includes('--clawpilot')) {
|
|
|
62
61
|
}
|
|
63
62
|
|
|
64
63
|
const options = {
|
|
65
|
-
dest: getFlag('--dest'),
|
|
66
64
|
force: args.includes('--force'),
|
|
67
65
|
yes: args.includes('--yes') || args.includes('-y'),
|
|
68
66
|
noSettings: args.includes('--no-settings'),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kushi-agents",
|
|
3
|
-
"version": "4.4.
|
|
3
|
+
"version": "4.4.3",
|
|
4
4
|
"description": "Install Kushi — multi-source project evidence agent with snapshot+stream capture across Email, Teams, OneNote, SharePoint, Meetings, CRM, ADO. WorkIQ-only for M365 sources (Graph / m365_* FORBIDDEN as fallbacks; user-paste is first-class). Host-agnostic.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -75,6 +75,10 @@ See `instructions/snapshot-vs-stream.instructions.md` for the full rule.
|
|
|
75
75
|
- **Auth pre-flight, retry, error logging** (mandatory before every external call) — `instructions/auth-and-retry.instructions.md`
|
|
76
76
|
- **Citation Ledger** (every assertion cites source) — `instructions/citation-ledger.instructions.md`
|
|
77
77
|
- **Answer-from-Evidence** (read-only Q&A doctrine for `ask-project`) — `instructions/answer-from-evidence.instructions.md`
|
|
78
|
+
- **Status taxonomy** (closed-set Status / Retry-Signal vocabulary for every artifact) — `instructions/status-taxonomy.instructions.md`
|
|
79
|
+
- **Fallback status reporting** (direct-path failure recovered by fallback → `completed-via-fallback`) — `instructions/fallback-status-reporting.instructions.md`
|
|
80
|
+
- **FDE grounding** (always-on FDE doctrine via `reference-packs/fde/`) — `instructions/fde-grounding.instructions.md`
|
|
81
|
+
- **Communication guidelines** (chat-reply tone; scoped to user-facing replies, NOT artifacts) — `instructions/communication-guidelines.instructions.md`
|
|
78
82
|
- **NEVER reach out** — Kushi never sends outbound messages without explicit user approval in the current turn. Park recommendations in `State/09_open-questions.md` under `## ✋ Pending Outbound`.
|
|
79
83
|
|
|
80
84
|
## Routing
|
|
@@ -100,7 +104,7 @@ When a user message arrives:
|
|
|
100
104
|
```
|
|
101
105
|
<workspace>/.kushi/config/user/project-evidence.yml ← personal: alias, engagement_root, active_projects (seeded by installer; never overwritten)
|
|
102
106
|
<workspace>/.kushi/config/shared/integrations.yml ← optional global CRM/ADO defaults (seeded by installer; never overwritten)
|
|
103
|
-
<
|
|
107
|
+
<workspace>/.kushi/config/ ← per-machine, per-user M365 config + per-project shared ADO/CRM connection (v4.4.0+, replaces legacy `<engagement-root>/.project-evidence/`)
|
|
104
108
|
m365/m365-auth.json
|
|
105
109
|
m365/m365-mutable.json
|
|
106
110
|
crm/config.yml
|
|
@@ -49,7 +49,7 @@ After the Engagement WI ID is resolved:
|
|
|
49
49
|
|
|
50
50
|
## Source files
|
|
51
51
|
|
|
52
|
-
- `<
|
|
52
|
+
- `<workspace>/.kushi/config/shared/integrations.yml` — connection: `tenantId`, `organization`, `defaultProject`, `apiVersion`, `azDevOpsResourceId`.
|
|
53
53
|
- `<engagement-root>/<project>/integrations.yml#ado` — per-project: `engagement_id`, `queryId`, `area_paths`, `iteration_paths`.
|
|
54
54
|
- `<engagement-root>/<project>/integrations.yml#boundaries.ado` — required scope (`area_paths` + optional `work_item_ids`).
|
|
55
55
|
|
|
@@ -10,8 +10,8 @@ The skill calls `az account get-access-token` only when CRM (Dataverse) or ADO a
|
|
|
10
10
|
## Decision logic
|
|
11
11
|
|
|
12
12
|
```
|
|
13
|
-
crm_enabled = Test-Path <
|
|
14
|
-
ado_enabled = Test-Path <
|
|
13
|
+
crm_enabled = Test-Path <workspace>/.kushi/config/shared/integrations.yml
|
|
14
|
+
ado_enabled = Test-Path <workspace>/.kushi/config/shared/integrations.yml
|
|
15
15
|
|
|
16
16
|
if (NOT crm_enabled AND NOT ado_enabled):
|
|
17
17
|
Skip az check entirely. Display "az sign-in skipped (no CRM/ADO configured)".
|
|
@@ -39,7 +39,7 @@ Acquire each token **once per run** (per `auth-and-retry.instructions.md §2`).
|
|
|
39
39
|
### 2.1 CRM / Dataverse
|
|
40
40
|
|
|
41
41
|
```powershell
|
|
42
|
-
$crmConfig = Get-Content "$
|
|
42
|
+
$crmConfig = (Get-Content "$workspace\.kushi\config\shared\integrations.yml" -Raw | ConvertFrom-Yaml).crm # v4.4.0+ — was <engagement-root>\.project-evidence\crm\config.yml
|
|
43
43
|
$tenant = $crmConfig.tenantId
|
|
44
44
|
$crmBaseUrl = $crmConfig.baseUrl
|
|
45
45
|
$crmToken = (az account get-access-token --tenant $tenant --resource $crmBaseUrl --query accessToken -o tsv --only-show-errors 2>&1).Trim()
|
|
@@ -60,7 +60,7 @@ $crmHeaders = @{
|
|
|
60
60
|
ADO's resource is the constant `499b84ac-1321-427f-aa17-267ca6975798` (Visual Studio Team Services). Read it from config — never hardcode:
|
|
61
61
|
|
|
62
62
|
```powershell
|
|
63
|
-
$adoConfig = Get-Content "$
|
|
63
|
+
$adoConfig = (Get-Content "$workspace\.kushi\config\shared\integrations.yml" -Raw | ConvertFrom-Yaml).ado # v4.4.0+ — was <engagement-root>\.project-evidence\ado\config.yml
|
|
64
64
|
$tenant = $adoConfig.tenantId
|
|
65
65
|
$adoRes = $adoConfig.resource # 499b84ac-1321-427f-aa17-267ca6975798
|
|
66
66
|
$adoToken = (az account get-access-token --tenant $tenant --resource $adoRes --query accessToken -o tsv --only-show-errors 2>&1).Trim()
|
|
@@ -127,7 +127,7 @@ Allowed tenants are config-driven, not hardcoded. Validate before the first ADO
|
|
|
127
127
|
|
|
128
128
|
```powershell
|
|
129
129
|
# $account from Section 1
|
|
130
|
-
$adoConfig = Get-Content "$
|
|
130
|
+
$adoConfig = (Get-Content "$workspace\.kushi\config\shared\integrations.yml" -Raw | ConvertFrom-Yaml).ado # v4.4.0+
|
|
131
131
|
$allowedTenants = @($adoConfig.allowedTenantIds)
|
|
132
132
|
$currentTenant = $account.tenantId
|
|
133
133
|
if ($allowedTenants.Count -gt 0 -and $allowedTenants -notcontains $currentTenant) {
|
|
@@ -224,9 +224,9 @@ Maintained alongside `auth-and-retry §3` (canonical) — quick lookup:
|
|
|
224
224
|
|
|
225
225
|
| Service | Config file (engagement-scoped) |
|
|
226
226
|
|---------|---------------------------------|
|
|
227
|
-
| Dynamics 365 / CRM | `<
|
|
228
|
-
| Azure DevOps | `<
|
|
229
|
-
| Microsoft Graph / M365 / OneNote | `<
|
|
227
|
+
| Dynamics 365 / CRM | `<workspace>/.kushi/config/shared/integrations.yml` |
|
|
228
|
+
| Azure DevOps | `<workspace>/.kushi/config/shared/integrations.yml` |
|
|
229
|
+
| Microsoft Graph / M365 / OneNote | `<workspace>/.kushi/config/user/m365-mutable.json` + `<workspace>/.kushi/config/user/m365-auth.json` |
|
|
230
230
|
| WorkIQ CLI path | `<workspace>/.kushi/config/user/project-evidence.yml` (workspace-scoped) |
|
|
231
231
|
| Global integrations (optional) | `<workspace>/.kushi/config/shared/integrations.yml` |
|
|
232
232
|
|
|
@@ -7,6 +7,8 @@ excludeAgent: "code-review"
|
|
|
7
7
|
|
|
8
8
|
When `bootstrap-project` (or any full refresh / retry workflow) finishes a project run, it MUST write `<project>/bootstrap-status.md` using the format below. This file is the **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
9
|
|
|
10
|
+
> **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`.
|
|
11
|
+
|
|
10
12
|
## Required section order
|
|
11
13
|
|
|
12
14
|
```
|
|
@@ -22,8 +24,8 @@ When `bootstrap-project` (or any full refresh / retry workflow) finishes a proje
|
|
|
22
24
|
|
|
23
25
|
| Check | Status | Notes |
|
|
24
26
|
|---|---|---|
|
|
25
|
-
| `.
|
|
26
|
-
| `.
|
|
27
|
+
| `.kushi/config/shared/integrations.yml` filled | resolved \| blocked-auth \| missing | ... |
|
|
28
|
+
| `.kushi/config/shared/integrations.yml` filled | ... | ... |
|
|
27
29
|
| `<project>/integrations.yml` boundaries present | ... | ... |
|
|
28
30
|
| `az` CLI tenant matches | cli-available \| blocked-auth | ... |
|
|
29
31
|
|
|
@@ -54,6 +56,17 @@ When `bootstrap-project` (or any full refresh / retry workflow) finishes a proje
|
|
|
54
56
|
| CRM | blocked-auth | tenant mismatch | `az login --tenant <id>` |
|
|
55
57
|
| Email | throttled-tooManyRequests | WorkIQ rate-limited | retry next refresh |
|
|
56
58
|
|
|
59
|
+
## Deferred Retries (kushi v4.4.1+, per `deferred-retry-on-workiq-fail.instructions.md`)
|
|
60
|
+
|
|
61
|
+
Omit this section entirely if `<project>/Evidence/<alias>/_deferred-retries/` is empty across all contributors.
|
|
62
|
+
|
|
63
|
+
| Source | Target | Attempts | Marker | First seen | Discovered by |
|
|
64
|
+
|---|---|---|---|---|---|
|
|
65
|
+
| meetings | "JD FDE Intake" 2026-05-13 | 1 | `Evidence/ushak/_deferred-retries/2026-05-20-1230_meetings_empty.yml` | 2026-05-20 | ushak |
|
|
66
|
+
| onenote | "Architecture overview" | 2 | `Evidence/ushak/_deferred-retries/2026-05-19-0810_onenote_throttled.yml` | 2026-05-19 | ushak |
|
|
67
|
+
|
|
68
|
+
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`.
|
|
69
|
+
|
|
57
70
|
## Bootstrap Status
|
|
58
71
|
|
|
59
72
|
ONE final line, normalized:
|
|
@@ -28,7 +28,7 @@ When a resolution succeeds, in the same turn, prune:
|
|
|
28
28
|
- Remove inline comments like `# TODO: find this`, `# could not resolve as of YYYY-MM-DD`.
|
|
29
29
|
- Keep `pinned_on` + `pinned_by` (those are durable provenance).
|
|
30
30
|
|
|
31
|
-
### `<
|
|
31
|
+
### `<workspace>/.kushi/config/user/m365-mutable.json`
|
|
32
32
|
- Remove entries under `m365Mutable.unresolved.<project>.<source>` if the same key was just resolved into `m365Mutable.knownSections.<project>.<source>`.
|
|
33
33
|
- Replace any `confidence: 'low'` entry with the new `confidence: 'high'` entry on resolution; do not keep both.
|
|
34
34
|
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
---
|
|
2
|
+
applyTo: "**"
|
|
3
|
+
excludeAgent: "code-review"
|
|
4
|
+
description: "How kushi talks to the user in chat — coach-like thinking, colleague-like speaking, options not directives. Scoped to user-facing chat replies and ask-project answer prose; does NOT override evidence-thoroughness / verbatim-by-default for artifacts."
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Communication Guidelines — User-Facing Chat
|
|
8
|
+
|
|
9
|
+
This rule shapes how kushi **talks to the user in chat**: how it acknowledges asks, surfaces findings, offers next steps, and runs interactive flows (`ask-project`, `fde-intake` interview, refresh confirmations, candidate-pick prompts).
|
|
10
|
+
|
|
11
|
+
**Scope boundary (important):** this rule applies to the **chat-reply prose** and to the **interactive Q&A surface of `ask-project`**. It does NOT govern Evidence/, State/, or Reports/ artifact content. Inside artifacts, `evidence-thoroughness.instructions.md` and `verbatim-by-default.instructions.md` rule — write the long, complete, comprehensive narrative the doctrine demands. The "avoid 'comprehensive' / 'thorough'" line below applies only to the conversational replies, not to artifacts where those words are accurate.
|
|
12
|
+
|
|
13
|
+
## THINK (internally) — like a coach
|
|
14
|
+
|
|
15
|
+
- What questions would surface insights here?
|
|
16
|
+
- What patterns am I seeing in the user's project / corpus?
|
|
17
|
+
- What doctrine guidance (boundaries, confidence ladder, FDE fitness) would help them?
|
|
18
|
+
- Where might they get stuck or miss something — empty boundary, stale CRM field, missing OneNote section pin?
|
|
19
|
+
|
|
20
|
+
## SPEAK (externally in chat) — like a helpful colleague
|
|
21
|
+
|
|
22
|
+
- Share thinking briefly: "I'm noticing the CRM field flipped 2026-03-26 but the latest customer transcript is from 2026-03-23 — that's still `internal-only`, not `confirmed`."
|
|
23
|
+
- Offer concrete observations: "The fitness scorecard has 3 criteria at risk; funding clarity is the dominant gap."
|
|
24
|
+
- Give helpful context: "Per FDE doctrine, ECIF status flips are aspirational until deal-desk approves — want me to flag this as an Open Question?"
|
|
25
|
+
- Keep it conversational and human, 2–3 sentences at a time. Reserve depth for the artifact.
|
|
26
|
+
- When citing evidence in chat, use the short kushi citation form: `[source: <relative-path> · <date>]` — full ledgers belong in the artifact, not the chat.
|
|
27
|
+
|
|
28
|
+
## EMPOWER (always) — offer choices
|
|
29
|
+
|
|
30
|
+
- End replies with options, not directives.
|
|
31
|
+
- "Does that resonate? Want to explore funding gaps next, or move on to the stage-readiness check?"
|
|
32
|
+
- "Make sense? Should I deepen the risks section, or run a refresh on email first?"
|
|
33
|
+
- "Two candidates matched the project token. Want me to show both, or do you have a preference?"
|
|
34
|
+
|
|
35
|
+
When the user is making a discrete choice (2–5 options) prefer surfacing it as a structured question rather than burying it in prose. The host UI may render structured asks better.
|
|
36
|
+
|
|
37
|
+
## AVOID in chat (not in artifacts)
|
|
38
|
+
|
|
39
|
+
- Do NOT say "Comprehensive", "Thorough", "Exhaustive", "In-depth", "Complete picture" in conversational replies — these set expectations a single chat turn cannot meet AND can mask the underlying source coverage. Save those words for artifact descriptions, where they are evidence-backed.
|
|
40
|
+
- Do NOT pile on hyphens / colons / em-dashes in chat suggestions — keep replies conversational.
|
|
41
|
+
- Do NOT give a single closed answer when multiple valid paths exist — surface the options.
|
|
42
|
+
- Do NOT paraphrase a `communicated` decision as `final`, or an `internal-only` field as `confirmed`. Use the ladder labels (per `evidence-confidence-ladder.instructions.md`) in chat too, not just in artifacts.
|
|
43
|
+
- Do NOT skip the source basis when surfacing a finding in chat. Even a one-line citation is enough — `[source: Evidence/<alias>/crm/snapshot/.../<id>.md · 2026-05-13]`.
|
|
44
|
+
|
|
45
|
+
## When the user asks a project question (ask-project surface)
|
|
46
|
+
|
|
47
|
+
`ask-project` is the highest-touch chat surface kushi has. Apply this rule rigorously there:
|
|
48
|
+
|
|
49
|
+
1. Always read evidence first (per `answer-from-evidence.instructions.md`); never answer FDE-shaped questions from priors.
|
|
50
|
+
2. Lead the answer with the most-recent dated source that bears on the question (per `fde-grounding.instructions.md` recency precedence).
|
|
51
|
+
3. Carry inline citations for every assertion (per `citation-ledger.instructions.md`).
|
|
52
|
+
4. Footer the answer with a Source basis line + the Status taxonomy value (`completed-via-fallback`, `completed-with-coverage-gaps`, etc.) so the user knows the coverage shape — per `status-taxonomy.instructions.md` + `fallback-status-reporting.instructions.md`.
|
|
53
|
+
5. End with one offered next step ("Want me to refresh this slice?", "Should I open this as an Open Question?", "Want the long-shape report?") — empower, don't direct.
|
|
54
|
+
|
|
55
|
+
## Confirmation flows (refresh, retry, candidate-pick)
|
|
56
|
+
|
|
57
|
+
When kushi is about to do something with side effects (run a refresh, drain deferred retries, pick a candidate, apply an ADO update):
|
|
58
|
+
|
|
59
|
+
- Surface what kushi is about to do, in one sentence, before doing it.
|
|
60
|
+
- Show the inputs and the scope (boundary, window, target file paths).
|
|
61
|
+
- Offer the user a clear choice (proceed / change scope / cancel).
|
|
62
|
+
- For outbound communications (CRM notes, ADO comments, emails) — per the workspace privacy rules, ALWAYS preview the message + recipient and wait for explicit confirmation before sending. Never auto-send.
|
|
63
|
+
|
|
64
|
+
## What this rule does NOT apply to
|
|
65
|
+
|
|
66
|
+
- `Evidence/<alias>/<source>/{snapshot,stream}/` artifact bodies — use full verbatim depth per `verbatim-by-default.instructions.md`.
|
|
67
|
+
- `State/` rollups — use the section headings and depth per `evidence-thoroughness.instructions.md`.
|
|
68
|
+
- `Reports/fde-<shape>-<date>.md` — follow the per-shape template from `reference-packs/fde/report-doctrine.md`.
|
|
69
|
+
- Run-log / refresh-report tables — use the normalized Status taxonomy; "comprehensive" is fine in artifact summaries when supported by source coverage.
|
|
70
|
+
|
|
71
|
+
## References
|
|
72
|
+
|
|
73
|
+
- `tracking.instructions.md` — what kushi writes about itself (journal, separate from artifacts).
|
|
74
|
+
- `answer-from-evidence.instructions.md` — `ask-project` retrieval contract.
|
|
75
|
+
- `citation-ledger.instructions.md` — citation format.
|
|
76
|
+
- `evidence-confidence-ladder.instructions.md` — `internal-only | communicated | confirmed`.
|
|
77
|
+
- `fallback-status-reporting.instructions.md` — Source basis in chat answers.
|
|
78
|
+
- `status-taxonomy.instructions.md` — closed-set Status vocabulary.
|
|
79
|
+
- `fde-grounding.instructions.md` — recency precedence + FDE doctrine framing in chat.
|
|
@@ -21,7 +21,7 @@ Any other path that writes `disabled: true` is a defect. The correct fallback fo
|
|
|
21
21
|
|
|
22
22
|
```powershell
|
|
23
23
|
# 1. Acquire Dataverse token (per pull-crm Step Auth)
|
|
24
|
-
$config = Get-Content "<
|
|
24
|
+
$config = Get-Content "<workspace>/.kushi/config/shared/integrations.yml" | ConvertFrom-Yaml
|
|
25
25
|
$token = (az account get-access-token --tenant $config.tenant_id --resource $config.base_url --query accessToken -o tsv --only-show-errors).Trim()
|
|
26
26
|
$headers = @{
|
|
27
27
|
Authorization = "Bearer $token"
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
---
|
|
2
|
+
applyTo: "**"
|
|
3
|
+
description: "When WorkIQ fails (and the doubled-strict retry also fails), Kushi MUST NOT fall back to Graph / m365_get_* / Dataverse REST as a workaround. Instead, write a deferred-retry marker, surface it in the run report, and continue. The next refresh drains the queue. This is the v4.4.1 hard rule that closes the last Graph-fallback escape hatch."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Deferred-Retry on WorkIQ Failure (HARD RULE, kushi v4.4.1+)
|
|
7
|
+
|
|
8
|
+
## Why this exists
|
|
9
|
+
|
|
10
|
+
`workiq-only.instructions.md` (v3.11.0+) forbade Graph / `m365_get_*` as a **first-class fallback**. But the doctrine's step 3 still said *"ask the user to paste"* — which in practice agents interpreted as:
|
|
11
|
+
|
|
12
|
+
1. *"WorkIQ failed → block the entire run and wait for the human."* (bootstrap stops mid-flight, evidence for OTHER sources is lost)
|
|
13
|
+
2. *"WorkIQ failed → silently try `m365_get_*` since it's right there in the tool list."* (the very anti-pattern workiq-only was meant to kill)
|
|
14
|
+
3. *"WorkIQ failed → skip the source, no record."* (next refresh never retries; the gap is permanent)
|
|
15
|
+
|
|
16
|
+
All three are defects. This rule replaces them with a deterministic, auditable, **non-blocking** flow.
|
|
17
|
+
|
|
18
|
+
## The rule (HARD)
|
|
19
|
+
|
|
20
|
+
When a WorkIQ call fails (auth error, empty after doubled-strict retry, throttled, CLI error, or any non-success), Kushi MUST:
|
|
21
|
+
|
|
22
|
+
1. **NOT call Graph, `m365_get_*`, or any other M365 host tool as a fallback.** No exceptions. Even if the tool is right there and looks like it would work. The doctrine in `workiq-only.instructions.md` is absolute.
|
|
23
|
+
2. **Write a deferred-retry marker** (see schema below).
|
|
24
|
+
3. **Surface a one-liner** in coverage.md, the per-user run report, and the project's `bootstrap-status.md` `## Deferred Retries` section.
|
|
25
|
+
4. **Continue the run** for all other sources. Never block the orchestrator on a single source's failure.
|
|
26
|
+
5. **Inform the user** at end-of-run with the count of deferred items and the path to the queue directory.
|
|
27
|
+
|
|
28
|
+
The next `refresh-project` run drains the queue first (Step 2a). On success, the marker is deleted. On repeated failure, the marker's `attempts` counter increments and the user is re-informed.
|
|
29
|
+
|
|
30
|
+
## Marker file location
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
<engagement-root>/<project>/Evidence/<alias>/_deferred-retries/<YYYY-MM-DD-HHmm>_<source>_<short-reason>.yml
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
- Per-contributor (`<alias>`) — never shared, so multi-user safety is moot.
|
|
37
|
+
- Sortable by filename (chronological).
|
|
38
|
+
- One marker per failed call. Do NOT batch — granular markers make retry deterministic.
|
|
39
|
+
|
|
40
|
+
## Marker schema
|
|
41
|
+
|
|
42
|
+
```yaml
|
|
43
|
+
# Deferred-retry marker — auto-generated. Do NOT hand-edit.
|
|
44
|
+
# Drained by refresh-project Step 2a. Deleted on retry success.
|
|
45
|
+
schema_version: 1
|
|
46
|
+
source: meetings # one of: email, teams, meetings, onenote, sharepoint, crm, ado, misc, identity
|
|
47
|
+
project: HCA
|
|
48
|
+
alias: ushak
|
|
49
|
+
created_at: 2026-05-20T12:30:00Z
|
|
50
|
+
attempts: 1
|
|
51
|
+
last_attempt_at: 2026-05-20T12:30:00Z
|
|
52
|
+
window: { from: '2026-04-20', to: '2026-05-20' }
|
|
53
|
+
target:
|
|
54
|
+
# source-specific identifying fields — exactly what the retry needs to re-issue the call
|
|
55
|
+
subject: "JD FDE Intake"
|
|
56
|
+
date: "2026-05-13"
|
|
57
|
+
workiq:
|
|
58
|
+
command: 'workiq ask -q "Find the Teams meeting titled \"JD FDE Intake\" that occurred on 2026-05-13..."'
|
|
59
|
+
request_id: '54d9c6bc-6e56-43b6-9eb7-ac23e86e2cc0' # if WorkIQ returned one before failing
|
|
60
|
+
error_class: 'empty-after-doubled-strict' # auth-error | empty | empty-after-doubled-strict | throttled | cli-error | timeout
|
|
61
|
+
error_message: 'WorkIQ returned a summary only after both prompts.'
|
|
62
|
+
user_message: |
|
|
63
|
+
Could not retrieve the full verbatim transcript of "JD FDE Intake" (2026-05-13) via WorkIQ.
|
|
64
|
+
The next refresh will retry automatically. To populate now, paste the transcript into
|
|
65
|
+
Evidence/ushak/meetings/snapshot/2026-05-13_jd-fde-intake_transcript.md and mark this marker
|
|
66
|
+
resolved by deleting the file.
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Producer contract (every pull-* skill + identity-resolution)
|
|
70
|
+
|
|
71
|
+
Before considering a source "failed and skipped", the skill MUST:
|
|
72
|
+
|
|
73
|
+
1. Call WorkIQ once with the canonical prompt from `workiq-only.instructions.md`.
|
|
74
|
+
2. On weak result, call the doubled-strict retry prompt from the same table.
|
|
75
|
+
3. If both fail:
|
|
76
|
+
- Write the marker per the schema above.
|
|
77
|
+
- Add a row to coverage.md: `Source: WorkIQ → DEFERRED (marker: <relative-path>)`.
|
|
78
|
+
- Continue the run. Do NOT throw. Do NOT call any other M365 tool.
|
|
79
|
+
|
|
80
|
+
Pseudocode (PowerShell shape):
|
|
81
|
+
|
|
82
|
+
```powershell
|
|
83
|
+
$result = Invoke-WorkIQ -Query $canonical
|
|
84
|
+
if (-not (Test-Sufficient $result)) {
|
|
85
|
+
$result = Invoke-WorkIQ -Query $doubledStrict
|
|
86
|
+
}
|
|
87
|
+
if (-not (Test-Sufficient $result)) {
|
|
88
|
+
Write-DeferredRetryMarker -Source $src -Target $target -Window $win -Workiq $workiqMeta
|
|
89
|
+
Add-CoverageRow -Source 'WorkIQ' -Status 'DEFERRED' -MarkerPath $markerPath
|
|
90
|
+
return # CONTINUE the orchestrator with the next source. NEVER call m365_get_*.
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Consumer contract (refresh-project)
|
|
95
|
+
|
|
96
|
+
`refresh-project` SKILL Step 2a (NEW, REQUIRED) runs **before** the per-source dispatch loop:
|
|
97
|
+
|
|
98
|
+
```
|
|
99
|
+
For each <alias>/_deferred-retries/*.yml in chronological order:
|
|
100
|
+
- Load marker
|
|
101
|
+
- Re-issue the canonical WorkIQ query with original window + target
|
|
102
|
+
- If success → write artifact to its canonical Evidence/ path, delete marker, log "drained" in refresh report
|
|
103
|
+
- If failure → increment attempts, update last_attempt_at, leave marker in place, log "still-deferred"
|
|
104
|
+
After drain → run normal Step 2 per-source dispatch
|
|
105
|
+
After Step 2 → report drain results in the run report's `## Deferred-retry drain` section
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
If `attempts` reaches 5, do NOT keep silently retrying. Promote to a project-level Open Question:
|
|
109
|
+
|
|
110
|
+
```
|
|
111
|
+
- [ ] DEFERRED-RETRY (5 attempts): <source> for <target>. See <marker-path>. Manual intervention required (paste verbatim, or remove the marker if no longer needed).
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## bootstrap-status.md integration
|
|
115
|
+
|
|
116
|
+
`bootstrap-status-format.instructions.md` mandates a `## Deferred Retries` section. Format:
|
|
117
|
+
|
|
118
|
+
```
|
|
119
|
+
## Deferred Retries
|
|
120
|
+
|
|
121
|
+
| Source | Target | Attempts | Marker | First seen |
|
|
122
|
+
|---|---|---|---|---|
|
|
123
|
+
| meetings | JD FDE Intake 2026-05-13 | 1 | Evidence/ushak/_deferred-retries/2026-05-20-1230_meetings_empty.yml | 2026-05-20 |
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Section is omitted entirely when no markers exist.
|
|
127
|
+
|
|
128
|
+
## What "informing the user" looks like
|
|
129
|
+
|
|
130
|
+
At end-of-run summary (every `pull-*`, `bootstrap-project`, `refresh-project`):
|
|
131
|
+
|
|
132
|
+
```
|
|
133
|
+
⚠ Deferred retries this run: 2 (will retry on next `refresh <project>`)
|
|
134
|
+
- meetings/JD FDE Intake 2026-05-13 → Evidence/ushak/_deferred-retries/2026-05-20-1230_meetings_empty.yml
|
|
135
|
+
- onenote/Architecture overview → Evidence/ushak/_deferred-retries/2026-05-20-1231_onenote_throttled.yml
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
Never silent. Never collapsed. The user sees exactly which calls deferred and where to find the markers.
|
|
139
|
+
|
|
140
|
+
## Anti-patterns (defects)
|
|
141
|
+
|
|
142
|
+
1. **Calling `m365_get_*` / Graph REST after a WorkIQ failure.** FORBIDDEN. Even "just to check if it works." Even "as a last resort." Write the marker; move on.
|
|
143
|
+
2. **Throwing / blocking the orchestrator on a single source's WorkIQ failure.** FORBIDDEN. Bootstrap and refresh dispatch every enabled source; a single failure must not stop the others.
|
|
144
|
+
3. **Silently skipping a source with no marker.** FORBIDDEN. If WorkIQ failed and you did NOT write a marker, the user has no signal and `refresh` will never retry. Always mark.
|
|
145
|
+
4. **Asking the user to paste mid-run as the primary recovery.** Pasting is a manual override the user MAY do later (by populating the artifact directly and deleting the marker). It is NOT the agent's recovery flow. The agent's recovery flow is: mark + continue + inform.
|
|
146
|
+
5. **Promoting markers to OPEN-QUESTIONS-DRAFT.md before 5 attempts.** Too noisy. Let refresh drain naturally.
|
|
147
|
+
6. **Storing markers outside `Evidence/<alias>/_deferred-retries/`.** Wrong location = the drainer can't find them. Wrong scope = breaks multi-user (markers are per-contributor by design).
|
|
148
|
+
|
|
149
|
+
## Cross-references
|
|
150
|
+
|
|
151
|
+
- `workiq-only.instructions.md` — WorkIQ is the only path. This file defines what happens when that path fails.
|
|
152
|
+
- `identity-resolution.instructions.md` — "Failure modes" table now cites this rule.
|
|
153
|
+
- `bootstrap-status-format.instructions.md` — `## Deferred Retries` section contract.
|
|
154
|
+
- `multi-user-shared-files.instructions.md` — `_deferred-retries/` is per-contributor (under `Evidence/<alias>/`) so multi-user collision doctrine does not apply.
|
|
155
|
+
- `verbatim-by-default.instructions.md` — deferring is NOT a silent skip. A marker IS the audit trail.
|
|
@@ -15,20 +15,23 @@ Resolve `<engagement-root>` in this order — first match wins:
|
|
|
15
15
|
2. **`customer_workspace/FDEDocs/`** — if the user's workspace has this symlink, follow it. Common in FDE-style installs.
|
|
16
16
|
3. **Ask the user** once and persist the answer to `<workspace>/.kushi/config/user/project-evidence.yml engagement_root`.
|
|
17
17
|
|
|
18
|
-
## Live config location
|
|
18
|
+
## Live config location (v4.4.0+)
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
Live filled configs live under the workspace (where `.kushi/` is), NOT under the engagement root:
|
|
21
21
|
|
|
22
22
|
```
|
|
23
|
-
<
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
23
|
+
<workspace>/.kushi/config/
|
|
24
|
+
user/ ← per-contributor (gitignored)
|
|
25
|
+
project-evidence.yml identity, engagement_root, workiq cli path
|
|
26
|
+
m365-auth.json tenant + default notebook + mailbox folders + SP root
|
|
27
|
+
m365-mutable.json discovered IDs (knownSections.<projectKey>)
|
|
28
|
+
shared/ ← team-owned (safe to commit)
|
|
29
|
+
integrations.yml ADO + CRM connection blocks (per project)
|
|
29
30
|
```
|
|
30
31
|
|
|
31
|
-
|
|
32
|
+
The legacy location `<engagement-root>/.project-evidence/` is no longer used as of kushi v4.4.0. Existing installs are migrated on first run of v4.4.0+. The new layout is host-agnostic: workspace is always where `.kushi/` lives (vscode target: project root; clawpilot target: any `cwd` where the user invokes Kushi).
|
|
33
|
+
|
|
34
|
+
`<engagement-root>` is still where per-project Evidence/, State/, and `<project>/integrations.yml` (per-project boundaries) live.
|
|
32
35
|
|
|
33
36
|
## Project resolution
|
|
34
37
|
|
|
@@ -42,7 +45,7 @@ Once `<engagement-root>` is known, individual projects are subfolders:
|
|
|
42
45
|
|
|
43
46
|
Project name resolution (always fuzzy):
|
|
44
47
|
|
|
45
|
-
1. Match against keys in `<
|
|
48
|
+
1. Match against keys in `<workspace>/.kushi/config/user/m365-mutable.json m365Mutable.knownSections`.
|
|
46
49
|
2. Match against `active_projects:` in `<workspace>/.kushi/config/user/project-evidence.yml`.
|
|
47
50
|
3. Match against actual subfolder names under `<engagement-root>`.
|
|
48
51
|
|
|
@@ -85,7 +85,7 @@ Anything outside these paths is invisible to them — by design. The path IS the
|
|
|
85
85
|
|
|
86
86
|
`plugin/skills/self-check/run.ps1` -Deep MUST detect any `<project>/<sibling>/` folder under engagement roots where:
|
|
87
87
|
|
|
88
|
-
- `<sibling>` is not in the allow-list `@('Evidence','State','Reports','.kushi','.kushi-reference','.
|
|
88
|
+
- `<sibling>` is not in the allow-list `@('Evidence','State','Reports','.kushi','.kushi-reference','.vscode')`, AND
|
|
89
89
|
- `<sibling>` contains markdown files matching the per-source patterns (`*-summary.md`, `*-stream.md`, `*-context*`, `current-state.md`, `index.md`, etc.).
|
|
90
90
|
|
|
91
91
|
When detected → emit a D14 finding with the canonical replacement path from Rule 2.
|
|
@@ -105,7 +105,7 @@ Together they guarantee that two contributors running the same verb on the same
|
|
|
105
105
|
|
|
106
106
|
- `snapshot-vs-stream.instructions.md` — the two shapes inside each `<source>/` folder.
|
|
107
107
|
- `scope-boundaries.instructions.md` — what each source is allowed to query (orthogonal: scope vs path).
|
|
108
|
-
- `side-by-side-config.instructions.md` — config files (mutable hints, integrations.yml)
|
|
108
|
+
- `side-by-side-config.instructions.md` — config files (mutable hints, integrations.yml) live under `<workspace>/.kushi/config/` (v4.4.0+, was `<engagement-root>/.project-evidence/`).
|
|
109
109
|
- `run-reports.instructions.md` — every layout-migration MUST appear in the refresh report.
|
|
110
110
|
- `cleanup-on-resolution.instructions.md` — once a legacy folder is migrated, all stale references in older summaries/notes get rewritten in the same turn.
|
|
111
111
|
- `bootstrap-project/SKILL.md` — creates the canonical tree on first run.
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
---
|
|
2
|
+
applyTo: "**"
|
|
3
|
+
description: "When a fallback path recovers the needed evidence or output, report the overall task as completed-via-fallback — not failed. Distinguish direct-path status from overall-task status everywhere status is rendered (bootstrap-status.md, run-log.yml, refresh reports, ask-project answers)."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Fallback Status Reporting (HARD RULE)
|
|
7
|
+
|
|
8
|
+
When a project workflow uses a fallback path successfully, report the **overall task** as completed via fallback — never as failed. This is the rule that prevents a successful refresh from being mis-summarized as a broken one because one direct path (Graph, REST, default config) did not work.
|
|
9
|
+
|
|
10
|
+
## Scope
|
|
11
|
+
|
|
12
|
+
This applies to every kushi workflow that can produce a usable result through more than one path:
|
|
13
|
+
|
|
14
|
+
- `bootstrap-project`, `refresh-project`, `aggregate-project`, `consolidate-evidence`
|
|
15
|
+
- every `pull-*` skill (email, teams, meetings, onenote, sharepoint, crm, ado, misc)
|
|
16
|
+
- `build-state`, `project-status`, `fde-report`, `fde-triage`, `fde-intake`
|
|
17
|
+
- `ask-project` (when the answer is assembled from evidence retrieved via a fallback)
|
|
18
|
+
- the deferred-retry drainer in `refresh-project` Step 2a (per `deferred-retry-on-workiq-fail.instructions.md`)
|
|
19
|
+
|
|
20
|
+
Concrete fallback patterns kushi runs into:
|
|
21
|
+
|
|
22
|
+
- direct OneNote Graph retrieval fails → Playwright/WorkIQ recovers the pages
|
|
23
|
+
- direct CRM query shape fails (e.g. `new_companyname` 400) → resolution-order step 2 (account lookup) finds the record
|
|
24
|
+
- transcript pull is incomplete from one path → evidence reconstructed from the meeting chat per `auth-and-retry §5`
|
|
25
|
+
- global `<workspace>/.kushi/config/shared/integrations.yml` is empty → per-project `sources.crm.environment_url_override` / `sources.ado.engagement_id` satisfies the effective-config preflight (per `scope-boundaries.instructions.md` Rule 3 v3.7.6+)
|
|
26
|
+
- WorkIQ throttled → narrower query (`one_sectionFileId` instead of section-name search) returns the same pages
|
|
27
|
+
- chat thread WorkIQ-empty after doubled-strict retry → `m365_list_chat_messages` parallel structured-data dump still provides the JSON record (NOT a substitute for the WorkIQ artifact, but coverage is partial-via-fallback rather than failed)
|
|
28
|
+
|
|
29
|
+
## Required behavior
|
|
30
|
+
|
|
31
|
+
1. **Distinguish two statuses, always.** Every place a status is rendered (bootstrap-status.md, refresh report, run-log.yml, ask-project answer footer) MUST separate:
|
|
32
|
+
- **Direct-path status** — what the preferred path did (e.g. `direct path failed`, `graph-401`, `workiq-empty-after-retry`, `crm-config-global-missing`).
|
|
33
|
+
- **Overall-task status** — what the task delivered (e.g. `completed`, `completed-via-fallback`, `completed-with-coverage-gaps`, `partial`, `failed`).
|
|
34
|
+
2. **Mark the overall task `completed-via-fallback` (or `resolved-via-fallback`) when the fallback recovered the needed result.** Do not write `failed` or `blocked` for the overall task when usable evidence was actually produced.
|
|
35
|
+
3. **If the fallback result is partial rather than complete, say so explicitly** with one of:
|
|
36
|
+
- `completed-via-fallback (partial)` — fallback ran but only covered part of the requested scope (e.g. transcript reconstructed from chat instead of true transcript).
|
|
37
|
+
- `completed-with-coverage-gaps` — task wrote usable evidence but specific known gaps remain (cite the gaps).
|
|
38
|
+
4. **Only mark the overall task `failed` (or `unresolved`) when BOTH the primary path AND every fallback failed** to recover any usable result.
|
|
39
|
+
5. **Record both statuses in source coverage**. In `run-log.yml#sources.<source>` and in `bootstrap-status.md`'s Context Artifact Status table:
|
|
40
|
+
- the primary-path status (e.g. `direct path failed`, `graph-401`)
|
|
41
|
+
- the fallback-path status (e.g. `fallback completed`, `reconstructed from chat`, `effective-config from project override`)
|
|
42
|
+
6. **In bootstrap / refresh / status artifacts, prefer this wording**:
|
|
43
|
+
- `OneNote context recovery completed via WorkIQ fallback`
|
|
44
|
+
- `CRM resolution completed via per-project environment_url_override`
|
|
45
|
+
- `ADO preflight completed via per-project engagement_id pin (global ado: block was empty)`
|
|
46
|
+
- `Transcript coverage completed via chat reconstruction (no Teams transcription)`
|
|
47
|
+
- `Email refresh completed via failed-fetch register retry (transient m365_get_email 0-segment parse bug)`
|
|
48
|
+
|
|
49
|
+
## Interaction with existing kushi doctrine
|
|
50
|
+
|
|
51
|
+
This rule is the **summary-time companion** to:
|
|
52
|
+
|
|
53
|
+
- `auth-and-retry.instructions.md §4` — defines per-source `last_status: ok | partial | failed | skipped-auth`. This file extends that vocabulary with `completed-via-fallback` and clarifies that **a fallback success must roll up to `ok` or `partial`, never `failed`** at the source level when usable evidence was written.
|
|
54
|
+
- `deferred-retry-on-workiq-fail.instructions.md` — the deferred-retry queue is a fallback mechanism. A drained marker (next refresh recovered the call) is `resolved-via-fallback`, not `recovered after failure`.
|
|
55
|
+
- `evidence-confidence-ladder.instructions.md` — orthogonal: confidence is about evidence kind (`internal-only | communicated | confirmed`); this rule is about run outcome. A `completed-via-fallback` run can still produce `internal-only` evidence, and vice versa.
|
|
56
|
+
- `scope-boundaries.instructions.md` — the per-project override / global default resolution is a documented fallback path; effective-config success is `completed`, not `completed-via-fallback`, because the schema explicitly allows either layer. Reserve `completed-via-fallback` for runtime path switches, not config-layer resolution.
|
|
57
|
+
|
|
58
|
+
## Anti-patterns (defects)
|
|
59
|
+
|
|
60
|
+
1. **Overall task `failed` when evidence was written.** If `pull-crm` resolved the record via account-lookup (resolution step 2) and wrote the snapshot file, `sources.crm.last_status` is `ok`, not `failed`. The direct-title-match attempt status goes into `errors[]` with `action_taken: fell-back-to-account-lookup`.
|
|
61
|
+
2. **Hiding the direct-path failure when fallback succeeded.** Do not omit the original failure from `errors[]` just because the fallback worked. The audit trail matters; future runs and learnings depend on it.
|
|
62
|
+
3. **Conflating `completed-via-fallback` with `partial`.** They are different: `partial` = task delivered less than requested scope; `completed-via-fallback` = task delivered the requested scope but via the alternate path. Use `completed-via-fallback (partial)` when both apply.
|
|
63
|
+
4. **Writing `blocked: missing X` when X was satisfied via an override.** The HCA bootstrap (2026-05-20) mis-reported CRM/ADO/Teams as `blocked: missing shared connection values` even though per-project `integrations.yml` had `environment_url_override`, `engagement_id`, and `chat_ids` fully pinned. The correct status was `completed via per-project effective-config`. Always check the effective-config result, not just the global-config layer.
|
|
64
|
+
|
|
65
|
+
## Render examples
|
|
66
|
+
|
|
67
|
+
In `bootstrap-status.md#Access Limitations`:
|
|
68
|
+
|
|
69
|
+
```
|
|
70
|
+
| System | Status | Reason | Workaround |
|
|
71
|
+
|---|---|---|---|
|
|
72
|
+
| CRM | completed-via-fallback | global crm: block empty; resolved via project environment_url_override | none — recommend filling global for tenant-wide default |
|
|
73
|
+
| OneNote | completed-via-fallback (partial) | Graph 401 on 3 pages; recovered via WorkIQ tier-C with page-body-unavailable on 2 of those | deferred-retry markers written for 2; will drain on next refresh |
|
|
74
|
+
| Teams | completed | direct path via WorkIQ + m365_list_chat_messages parallel dump | n/a |
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
In `run-log.yml`:
|
|
78
|
+
|
|
79
|
+
```yaml
|
|
80
|
+
sources:
|
|
81
|
+
crm:
|
|
82
|
+
last_status: ok
|
|
83
|
+
last_path: 'project-override' # NEW field — which layer / path delivered the result
|
|
84
|
+
errors:
|
|
85
|
+
- phase: preflight
|
|
86
|
+
path: global-config
|
|
87
|
+
signature: crm-config-global-empty
|
|
88
|
+
action_taken: fell-back-to-project-override
|
|
89
|
+
next_step: 'Optional — fill <workspace>/.kushi/config/shared/integrations.yml#crm for tenant-wide default'
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
In `ask-project` answer footers:
|
|
93
|
+
|
|
94
|
+
```
|
|
95
|
+
Source basis: completed-via-fallback (3 of 18 OneNote pages reconstructed from WorkIQ tier-C; others direct from cached snapshot).
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## References
|
|
99
|
+
|
|
100
|
+
- `auth-and-retry.instructions.md` — error-log schema + per-source `last_status` values.
|
|
101
|
+
- `deferred-retry-on-workiq-fail.instructions.md` — deferred-retry queue (a fallback mechanism that drains on next refresh).
|
|
102
|
+
- `bootstrap-status-format.instructions.md` — where the Context Artifact Status + Access Limitations + Current Bootstrap Outcome tables live.
|
|
103
|
+
- `status-taxonomy.instructions.md` — the unified vocabulary of Status + Retry-Signal values.
|
|
104
|
+
- `scope-boundaries.instructions.md` — effective-config rule (Rule 3).
|