kushi-agents 6.1.2 → 6.2.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.
- package/package.json +1 -1
- package/plugin/instructions/agentskills-compliance.instructions.md +144 -0
- package/plugin/instructions/dashboard-artifact.instructions.md +132 -0
- package/plugin/instructions/guided-tour.instructions.md +100 -0
- package/plugin/instructions/karpathy-state-layout.instructions.md +124 -0
- package/plugin/instructions/schema-evolve.instructions.md +73 -0
- package/plugin/instructions/skill-authoring.instructions.md +147 -0
- package/plugin/instructions/skill-evals.instructions.md +130 -0
- package/plugin/runners/bootstrap.mjs +55 -22
- package/plugin/runners/lib/runlog.mjs +153 -6
- package/plugin/runners/migrate-to-v550.mjs +192 -0
- package/plugin/runners/pull-email.mjs +194 -3
- package/plugin/runners/pull-meetings.mjs +207 -4
- package/plugin/runners/pull-onenote.mjs +239 -3
- package/plugin/runners/pull-sharepoint.mjs +284 -3
- package/plugin/runners/pull-state.mjs +297 -0
- package/plugin/runners/pull-teams.mjs +170 -3
- package/plugin/runners/refresh.mjs +9 -1
- package/plugin/runners/test/fixtures/email-abn-amro.json +13 -0
- package/plugin/runners/test/fixtures/email-novel-error.json +9 -0
- package/plugin/runners/test/fixtures/meetings-abn-amro.json +10 -0
- package/plugin/runners/test/fixtures/meetings-body-unavailable.json +10 -0
- package/plugin/runners/test/fixtures/onenote-abn-amro.json +30 -0
- package/plugin/runners/test/fixtures/onenote-partial.json +21 -0
- package/plugin/runners/test/fixtures/refresh-dir/email.json +7 -4
- package/plugin/runners/test/fixtures/refresh-dir/teams.json +6 -4
- package/plugin/runners/test/fixtures/sharepoint-abn-amro.json +12 -0
- package/plugin/runners/test/fixtures/teams-abn-amro.json +11 -0
- package/plugin/runners/test/integration/migrate-to-v550.integration.test.mjs +138 -0
- package/plugin/runners/test/integration/pull-email.integration.test.mjs +149 -0
- package/plugin/runners/test/integration/pull-meetings.integration.test.mjs +92 -0
- package/plugin/runners/test/integration/pull-onenote.integration.test.mjs +86 -0
- package/plugin/runners/test/integration/pull-sharepoint.integration.test.mjs +93 -0
- package/plugin/runners/test/integration/pull-teams.integration.test.mjs +91 -0
- package/plugin/runners/test/unit/runlog.test.mjs +1 -1
- package/plugin/skills/build-state/SKILL.md +195 -0
- package/plugin/skills/build-state/evals/evals.json +31 -0
- package/plugin/skills/dashboard/SKILL.md +132 -0
- package/plugin/skills/dashboard/evals/evals.json +33 -0
- package/plugin/skills/lint-state/.created-by-skill-creator +0 -0
- package/plugin/skills/lint-state/SKILL.md +98 -0
- package/plugin/skills/lint-state/evals/evals.json +34 -0
- package/plugin/skills/lint-state/lint.ps1 +218 -0
- package/plugin/skills/promote/.created-by-skill-creator +1 -0
- package/plugin/skills/promote/SKILL.md +125 -0
- package/plugin/skills/promote/evals/evals.json +35 -0
- package/plugin/skills/schema-evolve/.created-by-skill-creator +0 -0
- package/plugin/skills/schema-evolve/SKILL.md +106 -0
- package/plugin/skills/schema-evolve/evals/evals.json +37 -0
- package/plugin/skills/skill-checker/SKILL.md +136 -0
- package/plugin/skills/skill-checker/check-skill.ps1 +416 -0
- package/plugin/skills/skill-checker/evals/evals.json +41 -0
- package/plugin/skills/skill-creator/SKILL.md +134 -0
- package/plugin/skills/skill-creator/evals/evals.json +40 -0
- package/plugin/skills/skill-creator/generate-eval-review.ps1 +101 -0
- package/plugin/skills/skill-creator/optimize-description.ps1 +87 -0
- package/plugin/skills/skill-creator/scaffold.ps1 +180 -0
- package/plugin/skills/skill-creator/templates/evals-starter.template.json +27 -0
- package/plugin/skills/skill-creator/templates/gotchas-stub.template.md +9 -0
- package/plugin/skills/skill-creator/templates/skill-skeleton.template.md +28 -0
- package/plugin/skills/teach/.created-by-skill-creator +0 -0
- package/plugin/skills/teach/SKILL.md +79 -0
- package/plugin/skills/teach/evals/evals.json +59 -0
- package/plugin/skills/tour/SKILL.md +85 -0
- package/plugin/skills/tour/build-tour.ps1 +185 -0
- package/plugin/skills/tour/evals/evals.json +33 -0
- package/plugin/templates/state/00_overview.template.md +44 -0
- package/plugin/templates/state/01_decisions.template.md +41 -0
- package/plugin/templates/state/02_stakeholders.template.md +48 -0
- package/plugin/templates/state/03_architecture-and-solution.template.md +56 -0
- package/plugin/templates/state/04_workshops-and-key-meetings.template.md +43 -0
- package/plugin/templates/state/05_action-items.template.md +29 -0
- package/plugin/templates/state/06_risks-and-issues.template.md +43 -0
- package/plugin/templates/state/07_timeline-and-milestones.template.md +45 -0
- package/plugin/templates/state/08_artifacts-and-deliverables.template.md +55 -0
- package/plugin/templates/state/09_open-questions.template.md +62 -0
- package/plugin/templates/state/AGENTS.template.md +33 -0
- package/plugin/templates/state/CLAUDE.template.md +33 -0
- package/plugin/templates/state/README.md +41 -0
- package/plugin/templates/state/answers.README.md +7 -0
- package/plugin/templates/state/hot.template.md +12 -0
- package/plugin/templates/state/index.template.md +41 -0
- package/plugin/templates/state/log.template.md +14 -0
- package/plugin/templates/state/page.template.md +22 -0
- package/plugin/templates/state/review-queue.template.md +10 -0
- package/plugin/runners/test/integration/csc-pull.integration.test.mjs +0 -160
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# Open Questions & Low-Fidelity Items — {{project_name}}
|
|
2
|
+
|
|
3
|
+
> **Purpose.** Living list of things we don't yet know, are unsure about, or have only partial / second-hand info on. Each item gets resolved → moves to **Resolved** section with the answer + source. Never delete — the history is the audit trail.
|
|
4
|
+
|
|
5
|
+
**As of:** {{as_of_date}}
|
|
6
|
+
**Maintained by:** project-evidence skill (auto-updated each run; humans may add / edit freely)
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## Conventions
|
|
11
|
+
|
|
12
|
+
- **ID:** `Q-NNN` (monotonic, never reused)
|
|
13
|
+
- **Status:** `🔴 Open` · `🟡 Partial` (some info, more needed) · `🟢 Resolved` · `⚫ Stale` (no longer relevant — leave with reason)
|
|
14
|
+
- **Fidelity:** `Low` (rumor / inferred / single second-hand source) · `Medium` (one direct source, unconfirmed) · `High` (confirmed from authoritative source — at which point it usually moves to a State file and Q is Resolved)
|
|
15
|
+
- **Category:** `People` · `Scope` · `Timeline` · `Architecture` · `Decision` · `Risk` · `Process` · `Funding` · `Data` · `Other`
|
|
16
|
+
- **Needed By:** date or milestone the answer is needed for (blank = nice-to-know)
|
|
17
|
+
- **Source:** evidence file or person where the question originated
|
|
18
|
+
- **Resolution:** when status flips to 🟢, fill answer + source + date; the resolved item also gets folded into the right State file (00–08) and that destination is recorded in **Folded Into**
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## 🔴 Open / 🟡 Partial
|
|
23
|
+
|
|
24
|
+
| ID | Status | Fidelity | Category | Question / Concern | Needed By | Asked Of | Source | Notes |
|
|
25
|
+
|---|---|---|---|---|---|---|---|---|
|
|
26
|
+
| Q-001 | 🔴 Open | Low | _example_ | _What is the customer's preferred go-live date?_ | _next steering_ | _Acct team_ | _Evidence/ushak/Teams-Chats/2026-04-27_ | _Mentioned in passing, no commitment_ |
|
|
27
|
+
|
|
28
|
+
<!-- Add new rows above this line. Keep newest at top within each status. -->
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## 🟢 Resolved
|
|
33
|
+
|
|
34
|
+
| ID | Resolved On | Question | Answer | Source of Answer | Folded Into |
|
|
35
|
+
|---|---|---|---|---|---|
|
|
36
|
+
| _(none yet)_ | | | | | |
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## ⚫ Stale / No Longer Relevant
|
|
41
|
+
|
|
42
|
+
| ID | Marked Stale On | Question | Reason |
|
|
43
|
+
|---|---|---|---|
|
|
44
|
+
| _(none yet)_ | | | |
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## How items get added
|
|
49
|
+
|
|
50
|
+
1. **Auto** — during a weekly run, the skill flags anything where evidence is conflicting, second-hand, or implies a follow-up question. Each becomes a new `Q-NNN` row with Fidelity=Low or Medium.
|
|
51
|
+
2. **Manual** — anyone can add a row. Use next free `Q-NNN`.
|
|
52
|
+
3. **From action items** — if an `AI-NNN` blocks on a question, mirror it here and cross-reference.
|
|
53
|
+
|
|
54
|
+
## How items get resolved
|
|
55
|
+
|
|
56
|
+
1. When evidence comes in (a meeting transcript, a CRM/ADO update, an email reply) the skill updates the row's Fidelity → Medium/High and may flip Status → 🟢.
|
|
57
|
+
2. On resolution, the answer is also written into the appropriate State file (00–08), and **Folded Into** points to it.
|
|
58
|
+
3. The row stays here forever as audit trail.
|
|
59
|
+
|
|
60
|
+
## How items go stale
|
|
61
|
+
|
|
62
|
+
If the question stops mattering (scope cut, customer dropped the topic, decision overtaken), flip to ⚫ with reason. Do not delete.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# AGENTS.md — kushi project agent doc
|
|
2
|
+
|
|
3
|
+
> _Mirror of `CLAUDE.md`. Written by `build-state` from `plugin/templates/state/AGENTS.template.md`. Preserved across runs if user-edited._
|
|
4
|
+
|
|
5
|
+
This is a **kushi**-managed project. Everything authoritative about the project lives under:
|
|
6
|
+
|
|
7
|
+
- `Evidence/<alias>/<source>/weekly/<YYYY-MM-DD>_<source>-csc.md` — per-week, per-source, per-contributor Comprehensive Structured Capture (CSC) blocks.
|
|
8
|
+
- `Evidence/<alias>/<source>/_index/entities.yml` — per-contributor entity index (canonical entity-id, latest CSC file, last_touched).
|
|
9
|
+
- `Evidence/_graph/project-graph.json` — cross-source entity graph (nodes + edges with citations).
|
|
10
|
+
- `State/` — synthesized wiki pages. v5 pages have `kushi_state_page: true` in front-matter; legacy v4.x State files live alongside.
|
|
11
|
+
|
|
12
|
+
## Reading rules for AI agents
|
|
13
|
+
|
|
14
|
+
1. **Cite every claim.** Every assertion about this project MUST carry an inline citation of the form `[source: <alias>/<source>/weekly/<file>#<entity-anchor> · <iso-ts>]`. If you cannot cite, do not claim.
|
|
15
|
+
2. **Use `[[wikilinks]]`.** When referring to a State page, use `[[slug]]` — slug = lowercase-kebab-case of the page title. The wikilink resolves to `State/<category>/<slug>.md`. Categories: people, opportunities, adoworkitems, decisions, risks, customerasks, meetings, artifacts.
|
|
16
|
+
3. **Graph-first for cross-source questions.** If the question spans sources ("what ADO items did the May 7 meeting decide?", "who owns the action items from this opp?"), consult `Evidence/_graph/project-graph.json` first to find connected entities, THEN read the cited weekly files for the body.
|
|
17
|
+
4. **Never invent IDs.** Canonical entity-id formats are defined in `plugin/instructions/weekly-csc.instructions.md` (email://, teams://, meetings://, onenote://, sharepoint://, crm://, ado://). The graph never invents IDs; neither should you.
|
|
18
|
+
5. **Open the dashboard for visual orientation.** `<project>/dashboard.html` is a single self-contained HTML file. Open in any browser; click a node to surface its cited CSC blocks.
|
|
19
|
+
6. **Start with the tour.** `State/tour.md` is the auto-generated week-in-review walkthrough. Top-N entities by recency × cross-reference count.
|
|
20
|
+
|
|
21
|
+
## Writing rules for AI agents
|
|
22
|
+
|
|
23
|
+
- **Do NOT modify `Evidence/`.** That folder is owned by the `pull-*` skills.
|
|
24
|
+
- **Do NOT modify `State/index.md`, `State/log.md`, `State/tour.md`, or `State/<category>/*.md` pages with `kushi_state_page: true`.** Those are owned by `build-state` + `tour` and regenerated each run.
|
|
25
|
+
- Legacy State files (`State/00_overview.md`, `State/05_action-items.md`, etc., without the `kushi_state_page` flag) ARE user-editable when the project profile is `standard` — `build-state` only touches them on `full` profile.
|
|
26
|
+
|
|
27
|
+
## Related kushi doctrines
|
|
28
|
+
|
|
29
|
+
- `plugin/instructions/entity-graph.instructions.md`
|
|
30
|
+
- `plugin/instructions/karpathy-state-layout.instructions.md`
|
|
31
|
+
- `plugin/instructions/weekly-csc.instructions.md`
|
|
32
|
+
- `plugin/instructions/comprehensive-structured-capture.instructions.md`
|
|
33
|
+
- `plugin/instructions/citation-ledger.instructions.md`
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# CLAUDE.md — kushi project agent doc
|
|
2
|
+
|
|
3
|
+
> _Mirror of `AGENTS.md`. Written by `build-state` from `plugin/templates/state/CLAUDE.template.md`. Preserved across runs if user-edited._
|
|
4
|
+
|
|
5
|
+
This is a **kushi**-managed project. Everything authoritative about the project lives under:
|
|
6
|
+
|
|
7
|
+
- `Evidence/<alias>/<source>/weekly/<YYYY-MM-DD>_<source>-csc.md` — per-week, per-source, per-contributor Comprehensive Structured Capture (CSC) blocks.
|
|
8
|
+
- `Evidence/<alias>/<source>/_index/entities.yml` — per-contributor entity index (canonical entity-id, latest CSC file, last_touched).
|
|
9
|
+
- `Evidence/_graph/project-graph.json` — cross-source entity graph (nodes + edges with citations).
|
|
10
|
+
- `State/` — synthesized wiki pages. v5 pages have `kushi_state_page: true` in front-matter; legacy v4.x State files live alongside.
|
|
11
|
+
|
|
12
|
+
## Reading rules for AI agents
|
|
13
|
+
|
|
14
|
+
1. **Cite every claim.** Every assertion about this project MUST carry an inline citation of the form `[source: <alias>/<source>/weekly/<file>#<entity-anchor> · <iso-ts>]`. If you cannot cite, do not claim.
|
|
15
|
+
2. **Use `[[wikilinks]]`.** When referring to a State page, use `[[slug]]` — slug = lowercase-kebab-case of the page title. The wikilink resolves to `State/<category>/<slug>.md`. Categories: people, opportunities, adoworkitems, decisions, risks, customerasks, meetings, artifacts.
|
|
16
|
+
3. **Graph-first for cross-source questions.** If the question spans sources ("what ADO items did the May 7 meeting decide?", "who owns the action items from this opp?"), consult `Evidence/_graph/project-graph.json` first to find connected entities, THEN read the cited weekly files for the body.
|
|
17
|
+
4. **Never invent IDs.** Canonical entity-id formats are defined in `plugin/instructions/weekly-csc.instructions.md` (email://, teams://, meetings://, onenote://, sharepoint://, crm://, ado://). The graph never invents IDs; neither should you.
|
|
18
|
+
5. **Open the dashboard for visual orientation.** `<project>/dashboard.html` is a single self-contained HTML file. Open in any browser; click a node to surface its cited CSC blocks.
|
|
19
|
+
6. **Start with the tour.** `State/tour.md` is the auto-generated week-in-review walkthrough. Top-N entities by recency × cross-reference count.
|
|
20
|
+
|
|
21
|
+
## Writing rules for AI agents
|
|
22
|
+
|
|
23
|
+
- **Do NOT modify `Evidence/`.** That folder is owned by the `pull-*` skills.
|
|
24
|
+
- **Do NOT modify `State/index.md`, `State/log.md`, `State/tour.md`, or `State/<category>/*.md` pages with `kushi_state_page: true`.** Those are owned by `build-state` + `tour` and regenerated each run.
|
|
25
|
+
- Legacy State files (`State/00_overview.md`, `State/05_action-items.md`, etc., without the `kushi_state_page` flag) ARE user-editable when the project profile is `standard` — `build-state` only touches them on `full` profile.
|
|
26
|
+
|
|
27
|
+
## Related kushi doctrines
|
|
28
|
+
|
|
29
|
+
- `plugin/instructions/entity-graph.instructions.md`
|
|
30
|
+
- `plugin/instructions/karpathy-state-layout.instructions.md`
|
|
31
|
+
- `plugin/instructions/weekly-csc.instructions.md`
|
|
32
|
+
- `plugin/instructions/comprehensive-structured-capture.instructions.md`
|
|
33
|
+
- `plugin/instructions/citation-ledger.instructions.md`
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Contoso — Current State
|
|
2
|
+
|
|
3
|
+
**As of:** 2026-05-06
|
|
4
|
+
**Status:** Pre-engagement / fit-assessment phase
|
|
5
|
+
**Source:** Consolidated from `Evidence\<contributor>\*` summaries through week of 2026-04-27. Latest evidence wins on conflicts.
|
|
6
|
+
|
|
7
|
+
This folder is **outcome-based**, not source-based. Each file answers a single question about the project's current truth. The per-source weekly summaries under `Evidence\` remain the audit trail.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Files in this folder
|
|
12
|
+
|
|
13
|
+
| File | Answers |
|
|
14
|
+
|------|---------|
|
|
15
|
+
| `00_overview.md` | What is this engagement? Where does it stand right now? |
|
|
16
|
+
| `01_decisions.md` | What has been decided (and what was superseded)? |
|
|
17
|
+
| `02_stakeholders.md` | Who is involved? Roles, accountability, contact. |
|
|
18
|
+
| `03_architecture-and-solution.md` | What is being built / proposed? Use cases, components, dependencies. |
|
|
19
|
+
| `04_workshops-and-key-meetings.md` | What significant meetings/workshops happened or are planned? |
|
|
20
|
+
| `05_action-items.md` | What's owed, by whom, by when — open items only. |
|
|
21
|
+
| `06_risks-and-issues.md` | What could derail this, and what's the mitigation? |
|
|
22
|
+
| `07_timeline-and-milestones.md` | What's the trajectory — past, present, planned? |
|
|
23
|
+
| `08_artifacts-and-deliverables.md` | What concrete artifacts exist (decks, docs, recordings, code)? |
|
|
24
|
+
| `09_open-questions.md` | What don't we know yet, what's low-fidelity, and what's been answered? Living tracker — items move from 🔴 Open → 🟡 Partial → 🟢 Resolved (never deleted). |
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## Conventions
|
|
29
|
+
|
|
30
|
+
- **Latest evidence wins** on conflicts. Each fact carries `[as of YYYY-MM-DD, source: <alias>/<source>/<file>]`.
|
|
31
|
+
- A **Supersedes:** line preserves the prior value when a fact changes (e.g., owner change), so history isn't lost.
|
|
32
|
+
- A short `## Conflicts` section appears wherever contributors disagree.
|
|
33
|
+
- Files are **regenerated on each refresh** from the latest weekly summaries — do not hand-edit; edit the source summary instead.
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## How to refresh
|
|
38
|
+
|
|
39
|
+
1. Ensure all contributors' weekly summaries under `Evidence\<alias>\` are up to date.
|
|
40
|
+
2. Run the consolidation/state-refresh step. This re-reads every weekly summary, sorts facts by their evidence date, and emits these `State\*.md` files.
|
|
41
|
+
3. The run-log (`Evidence\run-log.md`) records when State was last refreshed and from what cutoff.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# State/answers/
|
|
2
|
+
|
|
3
|
+
This folder contains filed-back Q&A answers from `ask-project --file-back`.
|
|
4
|
+
|
|
5
|
+
Each file is named `YYYY-MM-DD_<slug>.md` and contains the question, answer, and source citations.
|
|
6
|
+
|
|
7
|
+
These are durable knowledge artifacts — they persist across refreshes and serve as a queryable FAQ for the project.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
---
|
|
2
|
+
kushi_state_hot: true
|
|
3
|
+
generated_at: "{{generated_at}}"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Hot — {{project}}
|
|
7
|
+
|
|
8
|
+
> _Auto-generated. Entities touched in the last 7 days, ranked by recency. Content between fences is regenerated on every build-state run._
|
|
9
|
+
|
|
10
|
+
<!-- kushi:auto:start section="hot-entities" -->
|
|
11
|
+
{{hot_entities}}
|
|
12
|
+
<!-- kushi:auto:end section="hot-entities" -->
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
---
|
|
2
|
+
kushi_state_index: true
|
|
3
|
+
generated_at: "{{generated_at}}"
|
|
4
|
+
generated_by_alias: "{{alias}}"
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# State Index — {{project}}
|
|
8
|
+
|
|
9
|
+
> _Auto-regenerated by `build-state` on every run. Lists every v5 State page (those with `kushi_state_page: true` in front-matter). Legacy v4.x State files (00–08 + 09_open-questions) live alongside and are not enumerated here._
|
|
10
|
+
|
|
11
|
+
## People
|
|
12
|
+
|
|
13
|
+
{{people_links}}
|
|
14
|
+
|
|
15
|
+
## Opportunities
|
|
16
|
+
|
|
17
|
+
{{opportunities_links}}
|
|
18
|
+
|
|
19
|
+
## ADO Work Items
|
|
20
|
+
|
|
21
|
+
{{adoworkitems_links}}
|
|
22
|
+
|
|
23
|
+
## Decisions
|
|
24
|
+
|
|
25
|
+
{{decisions_links}}
|
|
26
|
+
|
|
27
|
+
## Risks
|
|
28
|
+
|
|
29
|
+
{{risks_links}}
|
|
30
|
+
|
|
31
|
+
## Customer Asks
|
|
32
|
+
|
|
33
|
+
{{customerasks_links}}
|
|
34
|
+
|
|
35
|
+
## Meetings
|
|
36
|
+
|
|
37
|
+
{{meetings_links}}
|
|
38
|
+
|
|
39
|
+
## Artifacts
|
|
40
|
+
|
|
41
|
+
{{artifacts_links}}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
---
|
|
2
|
+
kushi_state_log: true
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# State Log — {{project}}
|
|
6
|
+
|
|
7
|
+
> _Chronological refresh log. One entry per `bootstrap-project` or `refresh-project` run. Appended (never rewritten) by `build-state`._
|
|
8
|
+
|
|
9
|
+
## {{first_entry_timestamp}} · {{first_entry_alias}} · {{first_entry_mode}}
|
|
10
|
+
|
|
11
|
+
- **Sources pulled:** {{first_entry_sources}}
|
|
12
|
+
- **Entities added:** {{first_entry_added}}
|
|
13
|
+
- **Entities updated:** {{first_entry_updated}}
|
|
14
|
+
- **Link-entities edges added:** {{first_entry_edges_added}}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
---
|
|
2
|
+
kushi_state_page: true
|
|
3
|
+
category: "{{category}}"
|
|
4
|
+
entity_ids: {{entity_ids_yaml}}
|
|
5
|
+
related: {{related_yaml}}
|
|
6
|
+
last_synthesized_iso: "{{last_synthesized_iso}}"
|
|
7
|
+
synthesized_by_alias: "{{alias}}"
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# {{title}}
|
|
11
|
+
|
|
12
|
+
## Summary
|
|
13
|
+
|
|
14
|
+
{{summary}}
|
|
15
|
+
|
|
16
|
+
## Cross-references
|
|
17
|
+
|
|
18
|
+
{{related_bullets}}
|
|
19
|
+
|
|
20
|
+
## Evidence
|
|
21
|
+
|
|
22
|
+
{{evidence_bullets}}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
---
|
|
2
|
+
kushi_state_review_queue: true
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Review Queue
|
|
6
|
+
|
|
7
|
+
> _Open contradictions requiring human review. Updated by build-state when contradictions are detected. Cleared when resolved (auto or manual)._
|
|
8
|
+
|
|
9
|
+
| Entity | Property | Old value | New value | Flagged | Sources |
|
|
10
|
+
|---|---|---|---|---|---|
|
|
@@ -1,160 +0,0 @@
|
|
|
1
|
-
// plugin/runners/test/integration/csc-pull.integration.test.mjs
|
|
2
|
-
//
|
|
3
|
-
// Integration tests for the WorkIQ-only CSC pull pipeline (kushi v6.1.0+).
|
|
4
|
-
// One table-driven suite covers all 5 user-scoped sources
|
|
5
|
-
// (email, teams, meetings, onenote, sharepoint) — they share lib/csc-pull.mjs,
|
|
6
|
-
// so a single contract test fixture set proves them all.
|
|
7
|
-
//
|
|
8
|
-
// Fixture shape (WorkIQ stdout, NOT Graph JSON):
|
|
9
|
-
// { "stdout": "> [block: csc]\n> entity_id: ...", "stderr": "", "exitCode": 0 }
|
|
10
|
-
|
|
11
|
-
import { test, beforeEach, afterEach } from 'node:test';
|
|
12
|
-
import assert from 'node:assert/strict';
|
|
13
|
-
import { promises as fs } from 'node:fs';
|
|
14
|
-
import path from 'node:path';
|
|
15
|
-
import os from 'node:os';
|
|
16
|
-
import { spawnSync } from 'node:child_process';
|
|
17
|
-
import YAML from 'yaml';
|
|
18
|
-
import { fileURLToPath } from 'node:url';
|
|
19
|
-
|
|
20
|
-
const HERE = path.dirname(fileURLToPath(import.meta.url));
|
|
21
|
-
const REPO_ROOT = path.resolve(HERE, '..', '..', '..', '..');
|
|
22
|
-
const FIXTURE_DIR = path.join(HERE, '..', 'fixtures');
|
|
23
|
-
|
|
24
|
-
const RUNNERS = {
|
|
25
|
-
email: path.join(REPO_ROOT, 'plugin', 'runners', 'pull-email.mjs'),
|
|
26
|
-
teams: path.join(REPO_ROOT, 'plugin', 'runners', 'pull-teams.mjs'),
|
|
27
|
-
meetings: path.join(REPO_ROOT, 'plugin', 'runners', 'pull-meetings.mjs'),
|
|
28
|
-
onenote: path.join(REPO_ROOT, 'plugin', 'runners', 'pull-onenote.mjs'),
|
|
29
|
-
sharepoint: path.join(REPO_ROOT, 'plugin', 'runners', 'pull-sharepoint.mjs'),
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
const ENTITIES = {
|
|
33
|
-
email: 'Inbox/102. Test Project',
|
|
34
|
-
teams: '19:abc123@thread.v2',
|
|
35
|
-
meetings: 'https://teams.microsoft.com/l/meetup-join/abc',
|
|
36
|
-
onenote: 'sectionFileId-deadbeef',
|
|
37
|
-
sharepoint: 'https://contoso.sharepoint.com/sites/test',
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
const WEEK = '2026-05-25';
|
|
41
|
-
|
|
42
|
-
let projectRoot;
|
|
43
|
-
beforeEach(async () => {
|
|
44
|
-
projectRoot = await fs.mkdtemp(path.join(os.tmpdir(), 'kushi-csc-int-'));
|
|
45
|
-
await fs.mkdir(path.join(projectRoot, 'Evidence', 'ushak'), { recursive: true });
|
|
46
|
-
});
|
|
47
|
-
afterEach(async () => { await fs.rm(projectRoot, { recursive: true, force: true }); });
|
|
48
|
-
|
|
49
|
-
function runRunner(source, fixtureName, extra = []) {
|
|
50
|
-
const fixture = path.join(FIXTURE_DIR, fixtureName);
|
|
51
|
-
return spawnSync(process.execPath, [RUNNERS[source],
|
|
52
|
-
'--project', projectRoot, '--alias', 'ushak',
|
|
53
|
-
'--entity', ENTITIES[source],
|
|
54
|
-
'--week', WEEK, '--fixture', fixture,
|
|
55
|
-
...extra,
|
|
56
|
-
], { encoding: 'utf8' });
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
for (const source of Object.keys(RUNNERS)) {
|
|
60
|
-
test(`[${source}] captured: writes weekly CSC + index + raw + ledger`, async () => {
|
|
61
|
-
const res = runRunner(source, 'csc-captured.json');
|
|
62
|
-
assert.equal(res.status, 0, `stderr: ${res.stderr}`);
|
|
63
|
-
const result = JSON.parse(res.stdout.trim().split('\n').pop());
|
|
64
|
-
assert.equal(result.status, 'captured');
|
|
65
|
-
assert.equal(result.items_pulled, 2);
|
|
66
|
-
assert.equal(result.source, source);
|
|
67
|
-
|
|
68
|
-
const sourceDir = path.join(projectRoot, 'Evidence', 'ushak', source);
|
|
69
|
-
const weeklyFile = path.join(sourceDir, 'weekly', `${WEEK}_${source}-csc.md`);
|
|
70
|
-
const md = await fs.readFile(weeklyFile, 'utf8');
|
|
71
|
-
assert.match(md, /Kickoff agenda/);
|
|
72
|
-
assert.match(md, /Architecture review notes/);
|
|
73
|
-
assert.match(md, new RegExp(`# ${source.toUpperCase()} CSC`));
|
|
74
|
-
|
|
75
|
-
const idx = YAML.parse(await fs.readFile(path.join(sourceDir, '_index', 'entities.yml'), 'utf8'));
|
|
76
|
-
assert.equal(idx.entities.length, 2);
|
|
77
|
-
assert.ok(idx.entities.every(e => e.id.startsWith(`${source}://`)));
|
|
78
|
-
assert.ok(idx.entities.every(e => e.weeks_touched.includes(WEEK)));
|
|
79
|
-
|
|
80
|
-
const ledger = YAML.parse(await fs.readFile(path.join(projectRoot, 'Evidence', 'ushak', '_ledger.yml'), 'utf8'));
|
|
81
|
-
const cell = ledger.entries[`${source}::${ENTITIES[source]}::${WEEK}`];
|
|
82
|
-
assert.ok(cell);
|
|
83
|
-
assert.equal(cell.last_status, 'captured');
|
|
84
|
-
assert.equal(cell.items_pulled, 2);
|
|
85
|
-
|
|
86
|
-
const rawFiles = await fs.readdir(path.join(sourceDir, '_raw'));
|
|
87
|
-
assert.equal(rawFiles.length, 1);
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
test(`[${source}] no-activity: empty stdout → status no-activity, no weekly file`, async () => {
|
|
91
|
-
const res = runRunner(source, 'csc-empty.json');
|
|
92
|
-
assert.equal(res.status, 0);
|
|
93
|
-
const result = JSON.parse(res.stdout.trim().split('\n').pop());
|
|
94
|
-
assert.equal(result.status, 'no-activity');
|
|
95
|
-
assert.equal(result.items_pulled, 0);
|
|
96
|
-
let exists = true;
|
|
97
|
-
try { await fs.access(path.join(projectRoot, 'Evidence', 'ushak', source, 'weekly', `${WEEK}_${source}-csc.md`)); }
|
|
98
|
-
catch { exists = false; }
|
|
99
|
-
assert.equal(exists, false);
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
test(`[${source}] throttled: deferred + no learning candidate`, async () => {
|
|
103
|
-
const res = runRunner(source, 'csc-throttled.json');
|
|
104
|
-
assert.equal(res.status, 0);
|
|
105
|
-
const result = JSON.parse(res.stdout.trim().split('\n').pop());
|
|
106
|
-
assert.equal(result.status, 'deferred');
|
|
107
|
-
assert.match(result.errors[0].signature, /throttled/);
|
|
108
|
-
let learningExists = true;
|
|
109
|
-
try { await fs.access(path.join(projectRoot, 'Evidence', '_learnings-candidates')); }
|
|
110
|
-
catch { learningExists = false; }
|
|
111
|
-
assert.equal(learningExists, false, 'throttled is retryable; should NOT emit learning candidate');
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
test(`[${source}] novel error: failed + learning candidate`, async () => {
|
|
115
|
-
const res = runRunner(source, 'csc-novel-error.json');
|
|
116
|
-
assert.equal(res.status, 0);
|
|
117
|
-
const result = JSON.parse(res.stdout.trim().split('\n').pop());
|
|
118
|
-
assert.equal(result.status, 'failed');
|
|
119
|
-
const candDir = path.join(projectRoot, 'Evidence', '_learnings-candidates');
|
|
120
|
-
const entries = await fs.readdir(candDir);
|
|
121
|
-
const md = entries.filter(f => f.endsWith('.md'));
|
|
122
|
-
assert.equal(md.length, 1, `expected 1 candidate, got: ${entries.join(', ')}`);
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
test(`[${source}] citation tokens / placeholders are filtered → no-activity`, async () => {
|
|
126
|
-
const res = runRunner(source, 'csc-citation-tokens.json');
|
|
127
|
-
assert.equal(res.status, 0);
|
|
128
|
-
const result = JSON.parse(res.stdout.trim().split('\n').pop());
|
|
129
|
-
assert.equal(result.status, 'no-activity', `bogus turn1searchN / <value> blocks must be dropped`);
|
|
130
|
-
});
|
|
131
|
-
|
|
132
|
-
test(`[${source}] dry-run: no files written, ledger empty`, async () => {
|
|
133
|
-
const res = runRunner(source, 'csc-captured.json', ['--dry-run']);
|
|
134
|
-
assert.equal(res.status, 0);
|
|
135
|
-
const result = JSON.parse(res.stdout.trim().split('\n').pop());
|
|
136
|
-
assert.deepEqual(result.files_written, []);
|
|
137
|
-
let ledgerExists = true;
|
|
138
|
-
try { await fs.access(path.join(projectRoot, 'Evidence', 'ushak', '_ledger.yml')); }
|
|
139
|
-
catch { ledgerExists = false; }
|
|
140
|
-
assert.equal(ledgerExists, false);
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
test(`[${source}] missing --entity exits 2`, () => {
|
|
144
|
-
const res = spawnSync(process.execPath, [RUNNERS[source],
|
|
145
|
-
'--project', projectRoot, '--alias', 'ushak',
|
|
146
|
-
'--fixture', path.join(FIXTURE_DIR, 'csc-captured.json'),
|
|
147
|
-
], { encoding: 'utf8' });
|
|
148
|
-
assert.equal(res.status, 2);
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
test(`[${source}] idempotent: re-running same fixture is a no-op rewrite`, async () => {
|
|
152
|
-
const r1 = runRunner(source, 'csc-captured.json');
|
|
153
|
-
assert.equal(r1.status, 0);
|
|
154
|
-
const r2 = runRunner(source, 'csc-captured.json');
|
|
155
|
-
assert.equal(r2.status, 0);
|
|
156
|
-
const idx = YAML.parse(await fs.readFile(path.join(projectRoot, 'Evidence', 'ushak', source, '_index', 'entities.yml'), 'utf8'));
|
|
157
|
-
assert.equal(idx.entities.length, 2, 'rerun must not duplicate entities');
|
|
158
|
-
assert.equal(idx.entities[0].weeks_touched.length, 1, 'rerun same week must not duplicate weeks_touched');
|
|
159
|
-
});
|
|
160
|
-
}
|