crewly 1.8.4 → 1.8.6
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/config/roles/_common/wiki-instructions.md +33 -0
- package/config/roles/orchestrator/prompt.md +66 -4
- package/config/roles/team-leader/prompt.md +38 -0
- package/config/skills/agent/core/wiki-query/SKILL.md +66 -0
- package/config/skills/agent/core/wiki-query/execute.sh +107 -0
- package/config/skills/orchestrator/wiki-bookkeep/SKILL.md +71 -0
- package/config/skills/orchestrator/wiki-bookkeep/execute.sh +72 -0
- package/config/skills/orchestrator/wiki-ingest/SKILL.md +63 -0
- package/config/skills/orchestrator/wiki-ingest/execute.sh +113 -0
- package/config/skills/orchestrator/wiki-process-queue/SKILL.md +71 -0
- package/config/skills/orchestrator/wiki-process-queue/execute.sh +93 -0
- package/config/skills/orchestrator/wiki-queue-add/SKILL.md +89 -0
- package/config/skills/orchestrator/wiki-queue-add/execute.sh +115 -0
- package/dist/backend/backend/src/controllers/chat/chat.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/chat/chat.controller.js +20 -0
- package/dist/backend/backend/src/controllers/chat/chat.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/slack/slack.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/slack/slack.controller.js +15 -0
- package/dist/backend/backend/src/controllers/slack/slack.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/wiki/wiki.controller.d.ts +134 -0
- package/dist/backend/backend/src/controllers/wiki/wiki.controller.d.ts.map +1 -0
- package/dist/backend/backend/src/controllers/wiki/wiki.controller.js +718 -0
- package/dist/backend/backend/src/controllers/wiki/wiki.controller.js.map +1 -0
- package/dist/backend/backend/src/controllers/wiki/wiki.routes.d.ts +23 -0
- package/dist/backend/backend/src/controllers/wiki/wiki.routes.d.ts.map +1 -0
- package/dist/backend/backend/src/controllers/wiki/wiki.routes.js +43 -0
- package/dist/backend/backend/src/controllers/wiki/wiki.routes.js.map +1 -0
- package/dist/backend/backend/src/index.d.ts.map +1 -1
- package/dist/backend/backend/src/index.js +65 -0
- package/dist/backend/backend/src/index.js.map +1 -1
- package/dist/backend/backend/src/routes/api.routes.d.ts.map +1 -1
- package/dist/backend/backend/src/routes/api.routes.js +4 -0
- package/dist/backend/backend/src/routes/api.routes.js.map +1 -1
- package/dist/backend/backend/src/services/orc/orc-delivery-enforcer.service.d.ts +142 -0
- package/dist/backend/backend/src/services/orc/orc-delivery-enforcer.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/orc/orc-delivery-enforcer.service.js +265 -0
- package/dist/backend/backend/src/services/orc/orc-delivery-enforcer.service.js.map +1 -0
- package/dist/backend/backend/src/services/session/pty/pty-session.d.ts +28 -0
- package/dist/backend/backend/src/services/session/pty/pty-session.d.ts.map +1 -1
- package/dist/backend/backend/src/services/session/pty/pty-session.js +162 -4
- package/dist/backend/backend/src/services/session/pty/pty-session.js.map +1 -1
- package/dist/backend/backend/src/services/wiki/referenced-by.resolver.d.ts +69 -0
- package/dist/backend/backend/src/services/wiki/referenced-by.resolver.d.ts.map +1 -0
- package/dist/backend/backend/src/services/wiki/referenced-by.resolver.js +174 -0
- package/dist/backend/backend/src/services/wiki/referenced-by.resolver.js.map +1 -0
- package/dist/backend/backend/src/services/wiki/schema-loader.service.d.ts +57 -0
- package/dist/backend/backend/src/services/wiki/schema-loader.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/wiki/schema-loader.service.js +183 -0
- package/dist/backend/backend/src/services/wiki/schema-loader.service.js.map +1 -0
- package/dist/backend/backend/src/services/wiki/wiki-bookkeep-trigger.service.d.ts +86 -0
- package/dist/backend/backend/src/services/wiki/wiki-bookkeep-trigger.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/wiki/wiki-bookkeep-trigger.service.js +187 -0
- package/dist/backend/backend/src/services/wiki/wiki-bookkeep-trigger.service.js.map +1 -0
- package/dist/backend/backend/src/services/wiki/wiki-bookkeep.service.d.ts +116 -0
- package/dist/backend/backend/src/services/wiki/wiki-bookkeep.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/wiki/wiki-bookkeep.service.js +299 -0
- package/dist/backend/backend/src/services/wiki/wiki-bookkeep.service.js.map +1 -0
- package/dist/backend/backend/src/services/wiki/wiki-chat-subscriber.service.d.ts +74 -0
- package/dist/backend/backend/src/services/wiki/wiki-chat-subscriber.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/wiki/wiki-chat-subscriber.service.js +154 -0
- package/dist/backend/backend/src/services/wiki/wiki-chat-subscriber.service.js.map +1 -0
- package/dist/backend/backend/src/services/wiki/wiki-ingest.service.d.ts +100 -0
- package/dist/backend/backend/src/services/wiki/wiki-ingest.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/wiki/wiki-ingest.service.js +212 -0
- package/dist/backend/backend/src/services/wiki/wiki-ingest.service.js.map +1 -0
- package/dist/backend/backend/src/services/wiki/wiki-process.service.d.ts +84 -0
- package/dist/backend/backend/src/services/wiki/wiki-process.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/wiki/wiki-process.service.js +138 -0
- package/dist/backend/backend/src/services/wiki/wiki-process.service.js.map +1 -0
- package/dist/backend/backend/src/services/wiki/wiki-query.service.d.ts +115 -0
- package/dist/backend/backend/src/services/wiki/wiki-query.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/wiki/wiki-query.service.js +291 -0
- package/dist/backend/backend/src/services/wiki/wiki-query.service.js.map +1 -0
- package/dist/backend/backend/src/services/wiki/wiki-queue.service.d.ts +115 -0
- package/dist/backend/backend/src/services/wiki/wiki-queue.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/wiki/wiki-queue.service.js +261 -0
- package/dist/backend/backend/src/services/wiki/wiki-queue.service.js.map +1 -0
- package/dist/backend/backend/src/services/wiki/wiki.types.d.ts +84 -0
- package/dist/backend/backend/src/services/wiki/wiki.types.d.ts.map +1 -0
- package/dist/backend/backend/src/services/wiki/wiki.types.js +10 -0
- package/dist/backend/backend/src/services/wiki/wiki.types.js.map +1 -0
- package/frontend/dist/assets/{index-b279da34.js → index-cc115bb4.js} +246 -246
- package/frontend/dist/assets/{index-c07e04c0.css → index-db3f5041.css} +1 -1
- package/frontend/dist/index.html +2 -2
- package/package.json +1 -1
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
## LLM-Wiki — Queue Worth-Saving Content (per-turn discipline)
|
|
2
|
+
|
|
3
|
+
The Crewly LLM-wiki captures **only what agents judge worth remembering**. There is NO automatic capture — you are the gate.
|
|
4
|
+
|
|
5
|
+
**Before yielding the turn**, scan your conversation (what you sent, what teammates sent you) and ask:
|
|
6
|
+
|
|
7
|
+
- Did a **decision** get made? (pricing, scope, sequencing, hire, deprecation, scheduling)
|
|
8
|
+
- Did a **fact** about a person, customer, partner, or competitor surface that future-you / the team needs?
|
|
9
|
+
- Did a **pattern, gotcha, or learning** get exposed that the team should not re-discover?
|
|
10
|
+
- Did Steve / a TL / another agent **lock** something previously fluid?
|
|
11
|
+
|
|
12
|
+
If YES, before yielding, call `config/skills/orchestrator/wiki-queue-add/execute.sh`:
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
--vault <path> # project: <project>/.crewly/wiki; team: ~/.crewly/teams/<id>/wiki; global: ~/.crewly/global-wiki
|
|
16
|
+
--content "<the fact / decision / learning text>"
|
|
17
|
+
--reason "<one sentence: WHY this is wiki-worthy>" # required — empty reason is rejected
|
|
18
|
+
--source-ref "<chat msg id | slack thread | WI id | file path>"
|
|
19
|
+
--source-type user_chat | slack_message | spec_file | pr_merge | record_learning | task_verified
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
**DO NOT queue:**
|
|
23
|
+
- Routine status checks (`standup`, `?`, `ok`, `got it`)
|
|
24
|
+
- Implementation details already in code / PR / spec
|
|
25
|
+
- Conversation pleasantries
|
|
26
|
+
- Anything already in the wiki (call `wiki-query` first if unsure)
|
|
27
|
+
- Items where you can't articulate a non-trivial `--reason`
|
|
28
|
+
|
|
29
|
+
**One queue call per worth-saving event.** Don't batch unrelated facts.
|
|
30
|
+
|
|
31
|
+
The item lands in the queue with `status: pending`. Later — either when you're idle, OR when a `[BOOKKEEP]` message arrives — drain the queue with `wiki-process-queue`: claim an item, read the vault context, let your LLM pick a target folder (no preset taxonomy beyond the frozen ones), call `wiki-ingest`, then POST `/queue/<id>/process` to commit. If after reading the context you decide the item isn't actually worth saving, POST `/queue/<id>/skip` with a `skipReason`.
|
|
32
|
+
|
|
33
|
+
**Bookkeep cadence:** when you receive `[BOOKKEEP] vault=…`, run `wiki-bookkeep` for that vault. The report surfaces duplicate clusters and consolidation candidates — use your LLM to merge them.
|
|
@@ -522,11 +522,73 @@ bash {{ORCHESTRATOR_SKILLS_PATH}}/reply-slack/execute.sh '{"channelId":"D0AC7NF5
|
|
|
522
522
|
|
|
523
523
|
Before yielding the turn:
|
|
524
524
|
1. Did I receive any `[CHAT:slack-...]` messages this turn?
|
|
525
|
-
2.
|
|
526
|
-
3.
|
|
527
|
-
4. If the
|
|
525
|
+
2. **Did I receive any `[DELIVER_REQUIRED]` messages this turn?** (System reminder that a worker agent posted `[DONE]` to a slack thread the user is waiting on, and I haven't yet forwarded the deliverable. See the dedicated section below.)
|
|
526
|
+
3. For EACH such message, did I make at least one Bash call to `reply-slack/execute.sh`?
|
|
527
|
+
4. If no, the response was NOT delivered — `[NOTIFY]` alone is not sufficient.
|
|
528
|
+
5. If the answer to (3) is "no," call `reply-slack` now BEFORE yielding the turn.
|
|
528
529
|
|
|
529
|
-
This is a hard pre-yield check. Do not yield if any Slack message is unanswered.
|
|
530
|
+
This is a hard pre-yield check. Do not yield if any Slack message or `[DELIVER_REQUIRED]` is unanswered.
|
|
531
|
+
|
|
532
|
+
## Handling `[DELIVER_REQUIRED]` Messages — MANDATORY
|
|
533
|
+
|
|
534
|
+
The system delivers `[DELIVER_REQUIRED]` to your inbox when a worker agent has posted `[DONE]` / `[COMPLETED]` / `[DELIVERED]` to a Slack thread the user originated, AND you haven't yet forwarded the deliverable via `reply-slack`. This catches the 2026-05-23 failure mode where you internally narrate "pipeline closed" but never actually call `reply-slack`, leaving the user in silence.
|
|
535
|
+
|
|
536
|
+
Shape:
|
|
537
|
+
```
|
|
538
|
+
[DELIVER_REQUIRED] Steve is waiting on a deliverable in Slack thread <conversationId>.
|
|
539
|
+
|
|
540
|
+
Agent `<sender>` posted [DONE] <N> min ago with this content (preview):
|
|
541
|
+
> <first ~200 chars of the agent's [DONE] message>
|
|
542
|
+
|
|
543
|
+
Action required: call reply-slack now with the deliverable. Treat this
|
|
544
|
+
the same as a [CHAT:slack-...] message — do NOT yield the turn until
|
|
545
|
+
the reply lands on the thread. ...
|
|
546
|
+
```
|
|
547
|
+
|
|
548
|
+
**Action protocol** (in order, no exceptions):
|
|
549
|
+
|
|
550
|
+
1. **Look up the actual deliverable.** The `[DONE]` preview is truncated — the full content is in the agent's session output (use `get-agent-logs` if needed) and likely also persisted to a spec / findings file inside `.crewly/`. Read it.
|
|
551
|
+
2. **Decide if it's the FINAL deliverable for the user request OR a Phase-N intermediate.**
|
|
552
|
+
- **Final**: call `reply-slack` with a Steve-facing summary (Owner-Facing Communication Standard — no internal session names, no jargon). Include any links / file paths Steve needs.
|
|
553
|
+
- **Intermediate (Phase 1 of 2, etc.)**: still call `reply-slack` — Steve gets a "Phase 1 done, Phase 2 starting, revised ETA" update. Then continue the pipeline. The enforcer will keep tracking until the FINAL phase delivers.
|
|
554
|
+
3. **One `reply-slack` call clears the reminder** (the system marks the thread as delivered on successful `/api/slack/send`). If you ignore the `[DELIVER_REQUIRED]`, you'll get escalating reminders at 3 / 10 / 30 min, then a final "budget exhausted — giving up" log entry, and Steve is permanently silent.
|
|
555
|
+
|
|
556
|
+
**Hard rule:** if there is a `[DELIVER_REQUIRED]` in your inbox at end-of-turn AND no matching `reply-slack` call was made this turn, you are LITERALLY incomplete. Make the call before yielding. No mental-model substitution — the actual skill call must happen.
|
|
557
|
+
|
|
558
|
+
## LLM-Wiki — Queue Worth-Saving Content (MANDATORY per-turn discipline)
|
|
559
|
+
|
|
560
|
+
The wiki captures **only what agents judge worth remembering**. There is
|
|
561
|
+
NO automatic chat-to-vault pipeline anymore (keyword heuristics were
|
|
562
|
+
removed 2026-05-22). You are the gate.
|
|
563
|
+
|
|
564
|
+
**Before yielding the turn**, scan the messages you sent or received and ask:
|
|
565
|
+
|
|
566
|
+
- Did a **decision** get made? (pricing, scope, sequencing, hire, deprecation, scheduling)
|
|
567
|
+
- Did a **fact** about a person, customer, partner, or competitor surface that future-me will need?
|
|
568
|
+
- Did a **pattern, gotcha, or learning** get exposed that the team should not re-discover?
|
|
569
|
+
- Did Steve / a TL **lock** something previously fluid?
|
|
570
|
+
|
|
571
|
+
If YES, before you yield, call `config/skills/orchestrator/wiki-queue-add/execute.sh` with:
|
|
572
|
+
- `--vault` → the project vault (`<project-root>/.crewly/wiki`) for project-scoped
|
|
573
|
+
content; the team vault (`~/.crewly/teams/<team-id>/wiki`) for cross-project
|
|
574
|
+
team norms; `~/.crewly/global-wiki` for cross-project synthesis.
|
|
575
|
+
- `--content` → the actual fact / decision / learning text (keep it terse but complete).
|
|
576
|
+
- `--reason` → one sentence justifying why this is wiki-worthy. **Required**. The reason is the audit trail and helps the processor decide where it lands. Refusal to write a reason = refusal to queue.
|
|
577
|
+
- `--source-ref` → stable reference (slack msg id, chat id, WI id, file path).
|
|
578
|
+
- `--source-type` → `user_chat` (default), `slack_message`, `spec_file`, `pr_merge`, `record_learning`, `task_verified`.
|
|
579
|
+
|
|
580
|
+
**DO NOT queue:**
|
|
581
|
+
- Routine status checks ("standup", "?", "ok", "got it")
|
|
582
|
+
- Implementation details already captured in code / PR / spec files
|
|
583
|
+
- Conversation pleasantries
|
|
584
|
+
- Content already in the wiki (call `wiki-query` first if unsure)
|
|
585
|
+
- Items where you can't articulate a non-trivial `--reason`
|
|
586
|
+
|
|
587
|
+
**One queue call per worth-saving event.** Don't batch unrelated facts into a single item — the processor needs to classify each one. If a turn produced 3 distinct worth-saving facts, make 3 queue-add calls.
|
|
588
|
+
|
|
589
|
+
After queueing, continue the turn normally. A separate `wiki-process-queue` run (batch, run periodically by you OR when bookkeep fires) classifies queued items, picks the target page (`llm-curated/customers/<name>.md`, `llm-curated/decisions/<slug>.md`, etc. — the LLM decides; no preset taxonomy beyond the frozen folders), and calls `wiki-ingest` to write.
|
|
590
|
+
|
|
591
|
+
**Bookkeep cadence:** when you receive a `[BOOKKEEP] vault=…` message OR when you notice the vault has accumulated many new pages since your last pass, run `wiki-bookkeep` to dedupe, consolidate, and prune. (Bookkeep skill ships separately; until it does, the WI brief will spell out the consolidation rules.)
|
|
530
592
|
|
|
531
593
|
## Handling `[ESCALATION]` Messages — MANDATORY
|
|
532
594
|
|
|
@@ -284,3 +284,41 @@ You are failing the task if you:
|
|
|
284
284
|
- Stop after partial progress without assigning next action.
|
|
285
285
|
- Delegate without checking completion.
|
|
286
286
|
- Produce status updates but no artifact, code, decision, or verified result.
|
|
287
|
+
|
|
288
|
+
## LLM-Wiki — Queue Worth-Saving Content (MANDATORY per-turn discipline)
|
|
289
|
+
|
|
290
|
+
TLs are the last filter before content reaches the wiki. ORC operates cross-team; YOU operate inside one team and see worker conversations + verify outputs. That makes you the right agent to capture team-scoped patterns, decisions, and norms.
|
|
291
|
+
|
|
292
|
+
**Before yielding the turn**, scan messages from your workers + the user and ask:
|
|
293
|
+
|
|
294
|
+
- Did a **team decision** get locked? (architecture, SOP change, hiring/handoff, policy)
|
|
295
|
+
- Did a **worker surface a gotcha / pattern** worth sharing across the team?
|
|
296
|
+
- Did a **person fact** appear (customer, partner, candidate) that the team needs to remember?
|
|
297
|
+
- Did a **verification reveal something subtle** about how the system actually works?
|
|
298
|
+
|
|
299
|
+
If YES, call `config/skills/orchestrator/wiki-queue-add/execute.sh`:
|
|
300
|
+
|
|
301
|
+
```bash
|
|
302
|
+
--vault ~/.crewly/teams/<your-team-id>/wiki # team vault for team-scoped
|
|
303
|
+
<project>/.crewly/wiki # project vault for project-scoped
|
|
304
|
+
--content "<the captured fact / decision / pattern>"
|
|
305
|
+
--reason "<one sentence: WHY future-team needs this>" # required
|
|
306
|
+
--source-ref "<WI id | chat msg id | spec path>"
|
|
307
|
+
--source-type record_learning | task_verified | spec_file | user_chat | slack_message
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
**DO NOT queue:**
|
|
311
|
+
- Routine status updates ("done", "in progress", "blocked-pending-X")
|
|
312
|
+
- Implementation details captured in the code/PR — link the PR, don't paraphrase
|
|
313
|
+
- Anything already in the wiki — call `wiki-query` first if unsure
|
|
314
|
+
- Items where you can't articulate why this matters in one sentence
|
|
315
|
+
|
|
316
|
+
**One queue call per worth-saving event.** If a verification turn produces 3 distinct learnings, that's 3 queue-add calls.
|
|
317
|
+
|
|
318
|
+
**Drain the queue** when idle OR when `[BOOKKEEP] vault=…` arrives:
|
|
319
|
+
1. `wiki-process-queue --claimed-by <your-session>` → claims item + returns vault context.
|
|
320
|
+
2. Your LLM picks a target page under `llm-curated/` — invent sub-folder names; **NO preset taxonomy**.
|
|
321
|
+
3. `wiki-ingest --target <relative-path>` to write.
|
|
322
|
+
4. POST `/api/wiki/queue/<id>/process` to commit, OR `/queue/<id>/skip` if you decide it's actually a duplicate after seeing context.
|
|
323
|
+
|
|
324
|
+
Frozen folders (`memory/`, `sop/`, `team-norm/`, `sop-overrides/`) are OFF-LIMITS — ingest will reject with 422.
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Wiki Query
|
|
3
|
+
description: Read a project/team/global vault and return the system-context payload your runtime feeds to the LLM for synthesis. Single-vault scope (Phase 1).
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
category: knowledge
|
|
6
|
+
skillType: claude-skill
|
|
7
|
+
assignableRoles:
|
|
8
|
+
- developer
|
|
9
|
+
- qa
|
|
10
|
+
- tpm
|
|
11
|
+
- designer
|
|
12
|
+
- frontend-developer
|
|
13
|
+
- backend-developer
|
|
14
|
+
- fullstack-dev
|
|
15
|
+
- qa-engineer
|
|
16
|
+
- product-manager
|
|
17
|
+
- architect
|
|
18
|
+
- generalist
|
|
19
|
+
- team-leader
|
|
20
|
+
- researcher
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
# Wiki Query
|
|
24
|
+
|
|
25
|
+
Read a vault (`<project>/.crewly/wiki/`, `~/.crewly/teams/<id>/wiki/`, or `~/.crewly/global-wiki/`) and get back the structured context the caller's LLM uses for synthesis.
|
|
26
|
+
|
|
27
|
+
Per Atlas v2.1 §3, this skill **does not call an LLM itself**. It emits the LLM-agnostic system-context (vault SCHEMA, recent log entries, candidate pages by keyword overlap). The caller's runtime concatenates this with the per-LLM task-instruction prompt at `prompts/<runtime>.md` and makes the LLM call locally.
|
|
28
|
+
|
|
29
|
+
## When to use
|
|
30
|
+
|
|
31
|
+
- ORC assembling cross-team context for a planning turn.
|
|
32
|
+
- TL pulling the team's last 20 decisions for a sprint review.
|
|
33
|
+
- A worker checking "did we already record an opinion on X?" before writing one.
|
|
34
|
+
|
|
35
|
+
## Inputs
|
|
36
|
+
|
|
37
|
+
| Flag | Required | Description |
|
|
38
|
+
|---|---|---|
|
|
39
|
+
| `--vault <path>` | yes | Absolute path to a vault root (must contain `SCHEMA.md`). |
|
|
40
|
+
| `--query <text>` | yes | Natural-language question. Used for keyword-overlap candidate ranking. |
|
|
41
|
+
| `--top-k <n>` | no | How many candidate pages to return (default 5). |
|
|
42
|
+
| `--recent-log <n>` | no | How many tail log entries to include (default 20). |
|
|
43
|
+
| `--json <obj>` | alt | Pass all fields as JSON. |
|
|
44
|
+
|
|
45
|
+
## Output
|
|
46
|
+
|
|
47
|
+
JSON with `success`, `result.context`. The context has:
|
|
48
|
+
|
|
49
|
+
- `vault` — scope, id, absolute path
|
|
50
|
+
- `schemaSummary` — frozen folders, llm-curated layout, write_policy
|
|
51
|
+
- `recentLog` — last N entries (most-recent first), with timestamp / sourceType / caller / body
|
|
52
|
+
- `candidatePages` — top-K pages by keyword overlap with `query`
|
|
53
|
+
- `callerNotes` — synthesis hints the LLM should honor (e.g. refuse writes into frozen paths)
|
|
54
|
+
|
|
55
|
+
## Example
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
bash execute.sh \
|
|
59
|
+
--vault ~/Desktop/projects/crewly-projects/crewly/.crewly/wiki \
|
|
60
|
+
--query "what did we decide about Crewly Pro pricing in May"
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Failure modes
|
|
64
|
+
|
|
65
|
+
- `400 invalid_input` — missing vault/query or bad topK
|
|
66
|
+
- `404 schema_missing` — vault has no SCHEMA.md
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# wiki-query — fetch a vault's system-context payload for LLM synthesis.
|
|
3
|
+
#
|
|
4
|
+
# Per Atlas v2.1 §3: this skill emits ONLY the system-context (LLM-agnostic).
|
|
5
|
+
# The caller's runtime concatenates this with its per-LLM task-instruction
|
|
6
|
+
# at prompts/<runtime>.md before making the LLM call. The skill itself
|
|
7
|
+
# never curls an LLM endpoint.
|
|
8
|
+
#
|
|
9
|
+
# Usage:
|
|
10
|
+
# bash execute.sh --vault /path/to/vault --query "what did we decide about pricing"
|
|
11
|
+
# bash execute.sh --vault /path/to/vault --query "..." --top-k 10
|
|
12
|
+
# bash execute.sh --json '{"vaultPath":"/path","query":"...","topK":5}'
|
|
13
|
+
# cat input.json | bash execute.sh
|
|
14
|
+
set -euo pipefail
|
|
15
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
16
|
+
source "${SCRIPT_DIR}/../../_common/lib.sh"
|
|
17
|
+
|
|
18
|
+
INPUT_JSON=""
|
|
19
|
+
VAULT_PATH=""
|
|
20
|
+
QUERY=""
|
|
21
|
+
TOP_K=""
|
|
22
|
+
RECENT_LOG=""
|
|
23
|
+
|
|
24
|
+
# Detect legacy JSON positional arg
|
|
25
|
+
if [[ $# -gt 0 && ${1:0:1} == '{' ]]; then
|
|
26
|
+
INPUT_JSON="$1"
|
|
27
|
+
shift || true
|
|
28
|
+
fi
|
|
29
|
+
|
|
30
|
+
while [[ $# -gt 0 ]]; do
|
|
31
|
+
case "$1" in
|
|
32
|
+
--vault|-v)
|
|
33
|
+
VAULT_PATH="$2"
|
|
34
|
+
shift 2
|
|
35
|
+
;;
|
|
36
|
+
--query|-q)
|
|
37
|
+
QUERY="$2"
|
|
38
|
+
shift 2
|
|
39
|
+
;;
|
|
40
|
+
--top-k|-k)
|
|
41
|
+
TOP_K="$2"
|
|
42
|
+
shift 2
|
|
43
|
+
;;
|
|
44
|
+
--recent-log|-r)
|
|
45
|
+
RECENT_LOG="$2"
|
|
46
|
+
shift 2
|
|
47
|
+
;;
|
|
48
|
+
--json|-j)
|
|
49
|
+
INPUT_JSON="$2"
|
|
50
|
+
shift 2
|
|
51
|
+
;;
|
|
52
|
+
--help|-h)
|
|
53
|
+
cat <<EOF
|
|
54
|
+
Usage:
|
|
55
|
+
execute.sh --vault <vault-dir> --query "<question>" [--top-k 5] [--recent-log 20]
|
|
56
|
+
execute.sh --json '{"vaultPath":"...","query":"...","topK":5,"recentLogEntries":20}'
|
|
57
|
+
|
|
58
|
+
Outputs JSON system-context for the caller's LLM. Skill makes no LLM calls itself.
|
|
59
|
+
EOF
|
|
60
|
+
exit 0
|
|
61
|
+
;;
|
|
62
|
+
--)
|
|
63
|
+
shift
|
|
64
|
+
break
|
|
65
|
+
;;
|
|
66
|
+
*)
|
|
67
|
+
if [[ -z "$INPUT_JSON" && ${1:0:1} == '{' ]]; then
|
|
68
|
+
INPUT_JSON="$1"
|
|
69
|
+
shift
|
|
70
|
+
else
|
|
71
|
+
error_exit "Unknown argument: $1"
|
|
72
|
+
fi
|
|
73
|
+
;;
|
|
74
|
+
esac
|
|
75
|
+
done
|
|
76
|
+
|
|
77
|
+
# Read JSON from stdin if no other input
|
|
78
|
+
if [ -z "$INPUT_JSON" ] && [ -z "$QUERY" ] && [ ! -t 0 ]; then
|
|
79
|
+
STDIN_DATA="$(cat)"
|
|
80
|
+
if [[ ${STDIN_DATA:0:1} == '{' ]]; then
|
|
81
|
+
INPUT_JSON="$STDIN_DATA"
|
|
82
|
+
else
|
|
83
|
+
QUERY="$STDIN_DATA"
|
|
84
|
+
fi
|
|
85
|
+
fi
|
|
86
|
+
|
|
87
|
+
# Parse JSON if supplied
|
|
88
|
+
if [ -n "$INPUT_JSON" ]; then
|
|
89
|
+
INPUT=$(read_json_input "$INPUT_JSON")
|
|
90
|
+
[ -z "$VAULT_PATH" ] && VAULT_PATH=$(printf '%s' "$INPUT" | jq -r '.vaultPath // empty')
|
|
91
|
+
[ -z "$QUERY" ] && QUERY=$(printf '%s' "$INPUT" | jq -r '.query // empty')
|
|
92
|
+
[ -z "$TOP_K" ] && TOP_K=$(printf '%s' "$INPUT" | jq -r '.topK // empty')
|
|
93
|
+
[ -z "$RECENT_LOG" ] && RECENT_LOG=$(printf '%s' "$INPUT" | jq -r '.recentLogEntries // empty')
|
|
94
|
+
fi
|
|
95
|
+
|
|
96
|
+
require_param "vaultPath (--vault)" "$VAULT_PATH"
|
|
97
|
+
require_param "query (--query)" "$QUERY"
|
|
98
|
+
|
|
99
|
+
# Build body with env-var passthrough so jq escapes safely.
|
|
100
|
+
export _WQ_VAULT="$VAULT_PATH"
|
|
101
|
+
export _WQ_QUERY="$QUERY"
|
|
102
|
+
BODY=$(jq -n '{vaultPath: env._WQ_VAULT, query: env._WQ_QUERY}')
|
|
103
|
+
[ -n "$TOP_K" ] && BODY=$(echo "$BODY" | jq --argjson k "$TOP_K" '. + {topK: $k}')
|
|
104
|
+
[ -n "$RECENT_LOG" ] && BODY=$(echo "$BODY" | jq --argjson n "$RECENT_LOG" '. + {recentLogEntries: $n}')
|
|
105
|
+
unset _WQ_VAULT _WQ_QUERY
|
|
106
|
+
|
|
107
|
+
api_call POST "/wiki/query" "$BODY"
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Wiki Bookkeep
|
|
3
|
+
description: Vault health report — md counts, duplicate clusters, queue snapshot, consolidation recommendations. Returns signals; your LLM decides what to merge or archive.
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
category: knowledge
|
|
6
|
+
skillType: claude-skill
|
|
7
|
+
assignableRoles:
|
|
8
|
+
- orchestrator
|
|
9
|
+
- team-leader
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# Wiki Bookkeep
|
|
13
|
+
|
|
14
|
+
Periodic vault health check. Returns a structured report (md counts, recent activity, duplicate clusters by filename similarity, stale-page count, queue snapshot, recommendations). **The skill does not write to the vault.** Your LLM reads the report and decides next actions.
|
|
15
|
+
|
|
16
|
+
## When to use
|
|
17
|
+
|
|
18
|
+
- When `wiki-process-queue` returns `no_pending_items` — quiet moment, good for housekeeping.
|
|
19
|
+
- When the report's `shouldFire` was `true` on the last run (you owe the vault a consolidation pass).
|
|
20
|
+
- When you receive a `[BOOKKEEP] vault=…` message (a future cron + threshold trigger will deliver these).
|
|
21
|
+
|
|
22
|
+
## Inputs
|
|
23
|
+
|
|
24
|
+
| Flag | Required | Default | Description |
|
|
25
|
+
|---|---|---|---|
|
|
26
|
+
| `--vault <path>` | yes | — | Absolute vault path. |
|
|
27
|
+
| `--window-days <n>` | no | 7 | "Recent activity" window for `recentMdCount`. |
|
|
28
|
+
| `--threshold <n>` | no | 10 | `shouldFire` triggers when `recentMdCount >= threshold` OR there are duplicate clusters. |
|
|
29
|
+
|
|
30
|
+
## What you do with the report
|
|
31
|
+
|
|
32
|
+
1. **Drain pending queue first** — if `queue.pending > 0`, run `wiki-process-queue` until empty before doing anything else.
|
|
33
|
+
2. **Consolidate duplicate clusters** — for each cluster in `duplicateCandidates`, read the member pages, ask your LLM whether they should merge, and if yes:
|
|
34
|
+
- Call `wiki-ingest` with a consolidated body that supersedes the originals (preserve the most-load-bearing info, deduplicate restated facts).
|
|
35
|
+
- Note: page DELETION is not in Phase 1 — surface "these N old pages can be archived" in your reply for human review.
|
|
36
|
+
3. **Hot-folder rollups** — if `countsByFolder` shows >20 pages in one bucket without a recent index page, generate one. Pattern: `llm-curated/<folder>/index.md` linking + summarizing each page.
|
|
37
|
+
4. **Stale-page flag** — if `staleCount > 0`, mention to the user — they decide which to keep.
|
|
38
|
+
|
|
39
|
+
## Output
|
|
40
|
+
|
|
41
|
+
```json
|
|
42
|
+
{
|
|
43
|
+
"success": true,
|
|
44
|
+
"report": {
|
|
45
|
+
"vault": {"scope": "project", "id": "crewly", "path": "..."},
|
|
46
|
+
"generatedAt": "2026-05-23T03:00:00Z",
|
|
47
|
+
"windowDays": 7,
|
|
48
|
+
"threshold": 10,
|
|
49
|
+
"shouldFire": true,
|
|
50
|
+
"totalMdCount": 47,
|
|
51
|
+
"recentMdCount": 12,
|
|
52
|
+
"countsByFolder": {"llm-curated/decisions": 8, "llm-curated/customers": 3, ...},
|
|
53
|
+
"duplicateCandidates": [
|
|
54
|
+
{"basis": "llm-curated/customers/anthropic-pricing", "pages": ["...-v1.md", "...-v2.md"]}
|
|
55
|
+
],
|
|
56
|
+
"staleCount": 4,
|
|
57
|
+
"queue": {"pending": 2, "claimed": 0, "processed": 11, "skipped": 1, "total": 14},
|
|
58
|
+
"recommendations": [
|
|
59
|
+
"Window has 12 new md(s) — at or above threshold (10). Consider a consolidation pass.",
|
|
60
|
+
"1 likely-duplicate cluster(s) detected. ...",
|
|
61
|
+
...
|
|
62
|
+
]
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Failure modes
|
|
68
|
+
|
|
69
|
+
- `404 vault_missing` — the vault directory does not exist.
|
|
70
|
+
- `404 schema_missing` — vault has no SCHEMA.md.
|
|
71
|
+
- `400 invalid_input` — vaultPath not absolute / windowDays or threshold non-positive.
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# wiki-bookkeep — vault health report + consolidation signals.
|
|
3
|
+
#
|
|
4
|
+
# Use this skill periodically (or when the queue stats / md-count
|
|
5
|
+
# threshold says "fire"). The skill returns a JSON report:
|
|
6
|
+
# - total / recent md counts
|
|
7
|
+
# - per-folder bucket counts
|
|
8
|
+
# - likely-duplicate clusters (filename Jaccard)
|
|
9
|
+
# - stale-page count (90+ days untouched)
|
|
10
|
+
# - queue snapshot (pending/claimed/processed/skipped)
|
|
11
|
+
# - recommendations
|
|
12
|
+
#
|
|
13
|
+
# This skill does NOT write to the vault. After reading the report,
|
|
14
|
+
# YOUR runtime decides which clusters to merge (call wiki-ingest with
|
|
15
|
+
# a consolidated body) and which pages to archive (out of Phase 1
|
|
16
|
+
# scope — flag in chat for now).
|
|
17
|
+
#
|
|
18
|
+
# Usage:
|
|
19
|
+
# bash execute.sh --vault /path
|
|
20
|
+
# bash execute.sh --vault /path --window-days 14 --threshold 10
|
|
21
|
+
set -euo pipefail
|
|
22
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
23
|
+
source "${SCRIPT_DIR}/../../_common/lib.sh"
|
|
24
|
+
|
|
25
|
+
INPUT_JSON=""
|
|
26
|
+
VAULT_PATH=""
|
|
27
|
+
WINDOW=""
|
|
28
|
+
THRESHOLD=""
|
|
29
|
+
|
|
30
|
+
if [[ $# -gt 0 && ${1:0:1} == '{' ]]; then
|
|
31
|
+
INPUT_JSON="$1"; shift || true
|
|
32
|
+
fi
|
|
33
|
+
|
|
34
|
+
while [[ $# -gt 0 ]]; do
|
|
35
|
+
case "$1" in
|
|
36
|
+
--vault|-v) VAULT_PATH="$2"; shift 2 ;;
|
|
37
|
+
--window-days|-d) WINDOW="$2"; shift 2 ;;
|
|
38
|
+
--threshold|-t) THRESHOLD="$2"; shift 2 ;;
|
|
39
|
+
--json|-j) INPUT_JSON="$2"; shift 2 ;;
|
|
40
|
+
--help|-h)
|
|
41
|
+
cat <<EOF
|
|
42
|
+
Usage:
|
|
43
|
+
execute.sh --vault <path> [--window-days 7] [--threshold 10]
|
|
44
|
+
|
|
45
|
+
Returns a JSON bookkeeping report with should-fire signal, recent activity,
|
|
46
|
+
duplicate clusters, queue snapshot, and recommendations. The skill makes
|
|
47
|
+
no LLM calls; you decide next actions based on the report.
|
|
48
|
+
EOF
|
|
49
|
+
exit 0 ;;
|
|
50
|
+
--) shift; break ;;
|
|
51
|
+
*)
|
|
52
|
+
if [[ -z "$INPUT_JSON" && ${1:0:1} == '{' ]]; then INPUT_JSON="$1"; shift
|
|
53
|
+
else error_exit "Unknown argument: $1"; fi ;;
|
|
54
|
+
esac
|
|
55
|
+
done
|
|
56
|
+
|
|
57
|
+
if [ -n "$INPUT_JSON" ]; then
|
|
58
|
+
INPUT=$(read_json_input "$INPUT_JSON")
|
|
59
|
+
[ -z "$VAULT_PATH" ] && VAULT_PATH=$(printf '%s' "$INPUT" | jq -r '.vaultPath // empty')
|
|
60
|
+
[ -z "$WINDOW" ] && WINDOW=$(printf '%s' "$INPUT" | jq -r '.windowDays // empty')
|
|
61
|
+
[ -z "$THRESHOLD" ] && THRESHOLD=$(printf '%s' "$INPUT" | jq -r '.threshold // empty')
|
|
62
|
+
fi
|
|
63
|
+
|
|
64
|
+
require_param "vaultPath (--vault)" "$VAULT_PATH"
|
|
65
|
+
|
|
66
|
+
export _WB_V="$VAULT_PATH"
|
|
67
|
+
BODY=$(jq -n '{vaultPath: env._WB_V}')
|
|
68
|
+
[ -n "$WINDOW" ] && BODY=$(echo "$BODY" | jq --argjson w "$WINDOW" '. + {windowDays: $w}')
|
|
69
|
+
[ -n "$THRESHOLD" ] && BODY=$(echo "$BODY" | jq --argjson t "$THRESHOLD" '. + {threshold: $t}')
|
|
70
|
+
unset _WB_V
|
|
71
|
+
|
|
72
|
+
api_call POST "/wiki/bookkeep" "$BODY"
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Wiki Ingest
|
|
3
|
+
description: Append a source (spec / decision / chat / pr / learning) into a vault's llm-curated/ tree. Refuses writes into frozen paths.
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
category: knowledge
|
|
6
|
+
skillType: claude-skill
|
|
7
|
+
assignableRoles:
|
|
8
|
+
- orchestrator
|
|
9
|
+
- team-leader
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# Wiki Ingest
|
|
13
|
+
|
|
14
|
+
Append a source to a vault's `llm-curated/log.md` (default) or to a dedicated page under `llm-curated/` (via `--target`). Per Atlas v2.1 §2 + §3.
|
|
15
|
+
|
|
16
|
+
The chat subscriber **already** auto-ingests every user→ORC chat message; this skill is for explicit manual ingest:
|
|
17
|
+
|
|
18
|
+
- TL promoting a decision to `llm-curated/decisions/<date>-<slug>.md`
|
|
19
|
+
- ORC archiving a synthesis memo into `~/.crewly/global-wiki/llm-curated/`
|
|
20
|
+
- A worker filing a `record-learning`-style pattern page
|
|
21
|
+
|
|
22
|
+
## Inputs
|
|
23
|
+
|
|
24
|
+
| Flag | Required | Description |
|
|
25
|
+
|---|---|---|
|
|
26
|
+
| `--vault <path>` | yes | Absolute vault root (must contain `SCHEMA.md`). |
|
|
27
|
+
| `--source-type <t>` | yes | One of: `user_chat`, `slack_message`, `spec_file`, `pr_merge`, `record_learning`, `task_verified`. |
|
|
28
|
+
| `--source-ref <ref>` | yes | Stable reference for audit (URL, file path, message id, …). |
|
|
29
|
+
| `--source-body <text>` | yes | Body content to ingest. |
|
|
30
|
+
| `--caller <sess>` | no | Session/user that authored the source (defaults to source-ref). |
|
|
31
|
+
| `--target <relpath>` | no | Override the default `llm-curated/log.md`. Must NOT be inside a frozen folder. |
|
|
32
|
+
|
|
33
|
+
## Output
|
|
34
|
+
|
|
35
|
+
```json
|
|
36
|
+
{
|
|
37
|
+
"success": true,
|
|
38
|
+
"result": {
|
|
39
|
+
"ok": true,
|
|
40
|
+
"pagesWritten": ["llm-curated/log.md"],
|
|
41
|
+
"logEntry": "## [ISO] sourceType | caller ...",
|
|
42
|
+
"frozenPathsTouched": []
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Failure modes
|
|
48
|
+
|
|
49
|
+
- `422 frozen_path` — target lives under a `hardcoded:` (frozen) folder. The `outcome.frozenFolders` field lists every frozen path in the vault.
|
|
50
|
+
- `404 schema_missing` — vault has no `SCHEMA.md`.
|
|
51
|
+
- `400 invalid_input | empty_body` — missing/invalid args.
|
|
52
|
+
|
|
53
|
+
## Example: ingest a TL-promoted decision
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
bash execute.sh \
|
|
57
|
+
--vault ~/.crewly/teams/ad923b66-19dd-4d73-9c92-dc1107d37501/wiki \
|
|
58
|
+
--source-type user_chat \
|
|
59
|
+
--source-ref slack://thread/D0ABC/1779363330.313849 \
|
|
60
|
+
--source-body "Pricing locked at \$999 setup + \$799/month." \
|
|
61
|
+
--caller user/steve \
|
|
62
|
+
--target llm-curated/decisions/2026-05-22-crewly-pro-pricing.md
|
|
63
|
+
```
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# wiki-ingest — append a source into a vault's llm-curated/log.md.
|
|
3
|
+
#
|
|
4
|
+
# Phase A scope (Atlas v2.1 §4 + §4.5): rules-only routing — the caller
|
|
5
|
+
# decides which vault. The chat subscriber already auto-ingests every
|
|
6
|
+
# user→ORC message; this skill is for MANUAL ingest (specs, decisions,
|
|
7
|
+
# LLM-promoted content, etc.) where you want explicit control.
|
|
8
|
+
#
|
|
9
|
+
# Refuses writes into frozen paths (memory/, sop-overrides/, sop/,
|
|
10
|
+
# team-norm/). Only llm-curated/ is restructure-eligible.
|
|
11
|
+
#
|
|
12
|
+
# Usage:
|
|
13
|
+
# bash execute.sh --vault /path --source-type spec_file --source-ref /path/to/spec.md --source-body "..."
|
|
14
|
+
# bash execute.sh --vault /path --source-type user_chat --source-ref msg-1 --source-body "..." --caller user/steve
|
|
15
|
+
# bash execute.sh --vault /path --target llm-curated/decisions/2026-05-22-pricing.md --source-type user_chat --source-ref s1 --source-body "..."
|
|
16
|
+
# bash execute.sh --json '{"vaultPath":"...","sourceType":"...","sourceRef":"...","sourceBody":"..."}'
|
|
17
|
+
set -euo pipefail
|
|
18
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
19
|
+
source "${SCRIPT_DIR}/../../_common/lib.sh"
|
|
20
|
+
|
|
21
|
+
INPUT_JSON=""
|
|
22
|
+
VAULT_PATH=""
|
|
23
|
+
SOURCE_TYPE=""
|
|
24
|
+
SOURCE_REF=""
|
|
25
|
+
SOURCE_BODY=""
|
|
26
|
+
CALLER=""
|
|
27
|
+
TARGET=""
|
|
28
|
+
|
|
29
|
+
if [[ $# -gt 0 && ${1:0:1} == '{' ]]; then
|
|
30
|
+
INPUT_JSON="$1"
|
|
31
|
+
shift || true
|
|
32
|
+
fi
|
|
33
|
+
|
|
34
|
+
while [[ $# -gt 0 ]]; do
|
|
35
|
+
case "$1" in
|
|
36
|
+
--vault|-v)
|
|
37
|
+
VAULT_PATH="$2"; shift 2 ;;
|
|
38
|
+
--source-type|-t)
|
|
39
|
+
SOURCE_TYPE="$2"; shift 2 ;;
|
|
40
|
+
--source-ref|-r)
|
|
41
|
+
SOURCE_REF="$2"; shift 2 ;;
|
|
42
|
+
--source-body|-b)
|
|
43
|
+
SOURCE_BODY="$2"; shift 2 ;;
|
|
44
|
+
--caller|-c)
|
|
45
|
+
CALLER="$2"; shift 2 ;;
|
|
46
|
+
--target)
|
|
47
|
+
TARGET="$2"; shift 2 ;;
|
|
48
|
+
--json|-j)
|
|
49
|
+
INPUT_JSON="$2"; shift 2 ;;
|
|
50
|
+
--help|-h)
|
|
51
|
+
cat <<EOF
|
|
52
|
+
Usage:
|
|
53
|
+
execute.sh --vault <vault> --source-type <type> --source-ref <ref> --source-body <body> [--caller <sess>] [--target <relpath>]
|
|
54
|
+
execute.sh --json '{"vaultPath":"...","sourceType":"...","sourceRef":"...","sourceBody":"...","callerSession":"...","targetRelativePath":"..."}'
|
|
55
|
+
|
|
56
|
+
sourceType MUST be one of:
|
|
57
|
+
user_chat | slack_message | spec_file | pr_merge | record_learning | task_verified
|
|
58
|
+
|
|
59
|
+
Default target is "llm-curated/log.md". Override with --target for a dedicated page (must NOT be inside a frozen folder).
|
|
60
|
+
EOF
|
|
61
|
+
exit 0 ;;
|
|
62
|
+
--)
|
|
63
|
+
shift; break ;;
|
|
64
|
+
*)
|
|
65
|
+
if [[ -z "$INPUT_JSON" && ${1:0:1} == '{' ]]; then
|
|
66
|
+
INPUT_JSON="$1"; shift
|
|
67
|
+
else
|
|
68
|
+
error_exit "Unknown argument: $1"
|
|
69
|
+
fi ;;
|
|
70
|
+
esac
|
|
71
|
+
done
|
|
72
|
+
|
|
73
|
+
# stdin JSON fallback
|
|
74
|
+
if [ -z "$INPUT_JSON" ] && [ -z "$SOURCE_BODY" ] && [ ! -t 0 ]; then
|
|
75
|
+
STDIN_DATA="$(cat)"
|
|
76
|
+
if [[ ${STDIN_DATA:0:1} == '{' ]]; then
|
|
77
|
+
INPUT_JSON="$STDIN_DATA"
|
|
78
|
+
else
|
|
79
|
+
SOURCE_BODY="$STDIN_DATA"
|
|
80
|
+
fi
|
|
81
|
+
fi
|
|
82
|
+
|
|
83
|
+
if [ -n "$INPUT_JSON" ]; then
|
|
84
|
+
INPUT=$(read_json_input "$INPUT_JSON")
|
|
85
|
+
[ -z "$VAULT_PATH" ] && VAULT_PATH=$(printf '%s' "$INPUT" | jq -r '.vaultPath // empty')
|
|
86
|
+
[ -z "$SOURCE_TYPE" ] && SOURCE_TYPE=$(printf '%s' "$INPUT" | jq -r '.sourceType // empty')
|
|
87
|
+
[ -z "$SOURCE_REF" ] && SOURCE_REF=$(printf '%s' "$INPUT" | jq -r '.sourceRef // empty')
|
|
88
|
+
[ -z "$SOURCE_BODY" ] && SOURCE_BODY=$(printf '%s' "$INPUT" | jq -r '.sourceBody // empty')
|
|
89
|
+
[ -z "$CALLER" ] && CALLER=$(printf '%s' "$INPUT" | jq -r '.callerSession // empty')
|
|
90
|
+
[ -z "$TARGET" ] && TARGET=$(printf '%s' "$INPUT" | jq -r '.targetRelativePath // empty')
|
|
91
|
+
fi
|
|
92
|
+
|
|
93
|
+
require_param "vaultPath (--vault)" "$VAULT_PATH"
|
|
94
|
+
require_param "sourceType (--source-type)" "$SOURCE_TYPE"
|
|
95
|
+
require_param "sourceRef (--source-ref)" "$SOURCE_REF"
|
|
96
|
+
require_param "sourceBody (--source-body)" "$SOURCE_BODY"
|
|
97
|
+
|
|
98
|
+
# Build body via env vars (safe escaping).
|
|
99
|
+
export _WI_VAULT="$VAULT_PATH"
|
|
100
|
+
export _WI_TYPE="$SOURCE_TYPE"
|
|
101
|
+
export _WI_REF="$SOURCE_REF"
|
|
102
|
+
export _WI_BODY="$SOURCE_BODY"
|
|
103
|
+
BODY=$(jq -n '{
|
|
104
|
+
vaultPath: env._WI_VAULT,
|
|
105
|
+
sourceType: env._WI_TYPE,
|
|
106
|
+
sourceRef: env._WI_REF,
|
|
107
|
+
sourceBody: env._WI_BODY
|
|
108
|
+
}')
|
|
109
|
+
[ -n "$CALLER" ] && { export _WI_CALLER="$CALLER"; BODY=$(echo "$BODY" | jq '. + {callerSession: env._WI_CALLER}'); unset _WI_CALLER; }
|
|
110
|
+
[ -n "$TARGET" ] && { export _WI_TARGET="$TARGET"; BODY=$(echo "$BODY" | jq '. + {targetRelativePath: env._WI_TARGET}'); unset _WI_TARGET; }
|
|
111
|
+
unset _WI_VAULT _WI_TYPE _WI_REF _WI_BODY
|
|
112
|
+
|
|
113
|
+
api_call POST "/wiki/ingest" "$BODY"
|