arkaos 2.25.0 → 2.28.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. package/VERSION +1 -1
  2. package/arka/skills/bootstrap-agent/SKILL.md +76 -0
  3. package/arka/skills/design-ops/SKILL.md +68 -0
  4. package/arka/skills/design-ops/scripts/extract-colors.py +86 -0
  5. package/arka/skills/design-ops/scripts/shadcn-tokens.py +59 -0
  6. package/arka/skills/design-ops/scripts/wcag-contrast.py +92 -0
  7. package/arka/skills/research/SKILL.md +117 -0
  8. package/config/constitution.yaml +4 -0
  9. package/config/hooks/post-tool-use.sh +17 -0
  10. package/config/hooks/user-prompt-submit.sh +16 -0
  11. package/core/agents/__pycache__/loader.cpython-313.pyc +0 -0
  12. package/core/agents/__pycache__/schema.cpython-313.pyc +0 -0
  13. package/core/agents/loader.py +4 -1
  14. package/core/agents/schema.py +29 -0
  15. package/core/cognition/__pycache__/retrieval.cpython-313.pyc +0 -0
  16. package/core/cognition/capture/__pycache__/collector.cpython-313.pyc +0 -0
  17. package/core/cognition/retrieval.py +383 -0
  18. package/core/cognition/scheduler/__pycache__/daemon.cpython-313.pyc +0 -0
  19. package/core/obsidian/__pycache__/writer.cpython-313.pyc +0 -0
  20. package/core/runtime/__pycache__/path_resolver.cpython-313.pyc +0 -0
  21. package/departments/brand/agents/design-ops/design-ops-lead.yaml +78 -0
  22. package/departments/brand/agents/design-ops/extraction-script-writer.yaml +74 -0
  23. package/departments/brand/agents/design-ops/shadcn-padronizer.yaml +76 -0
  24. package/departments/brand/agents/design-ops/wcag-auditor.yaml +76 -0
  25. package/departments/dev/skills/mcp/SKILL.md +16 -0
  26. package/package.json +1 -1
  27. package/pyproject.toml +1 -1
package/VERSION CHANGED
@@ -1 +1 @@
1
- 2.25.0
1
+ 2.28.0
@@ -0,0 +1,76 @@
1
+ ---
2
+ name: arka-bootstrap-agent
3
+ description: >
4
+ Formalises the "agents set up agents" pattern surfaced in the 2026-05-13
5
+ Nick Saraev × Greg Isenberg podcast on the Orgo agent business. When the
6
+ user asks to spin up a new specialist or an integration that requires
7
+ research-heavy setup, this skill orchestrates The Forge to dispatch
8
+ research subagents (Perplexity / Exa / Context7 / Firecrawl / XMCP),
9
+ synthesises the findings, and produces a ready-to-use agent YAML or
10
+ installation guide.
11
+ allowed-tools: [Agent, Read, Write, Bash]
12
+ ---
13
+
14
+ # /arka bootstrap-agent — agents that set up agents
15
+
16
+ > Pattern source: Nick Saraev (Orgo) interview, 2026-05-13. ArkaOS already
17
+ > has The Forge for complexity-based planning; this skill is the explicit
18
+ > entry point users invoke when they want a new specialist or a setup
19
+ > playbook rather than a feature.
20
+
21
+ ## Subcommands
22
+
23
+ | Command | What it does |
24
+ | --- | --- |
25
+ | `/arka bootstrap-agent specialist <slug>` | Generates a new Tier 2 agent YAML for a domain you describe. Dispatches research subagents to gather domain frameworks, conventions, and common pitfalls. Produces `departments/<dept>/agents/<slug>.yaml` with full 4-framework DNA. |
26
+ | `/arka bootstrap-agent integration <tool>` | Installation playbook for an external tool (e.g. Hermes, Composio, Agent Mail). Researches official docs + community recipes, outputs a step-by-step setup guide and any required MCP config. |
27
+ | `/arka bootstrap-agent persona <name>` | Builds an AI persona profile (DISC + Enneagram + OCEAN + MBTI) from learned content. Delegates to `/kb` (Clara) for source ingestion. |
28
+
29
+ ## How it works
30
+
31
+ ```
32
+ User: /arka bootstrap-agent specialist "design-tokens-engineer"
33
+
34
+
35
+ 1. The Forge classifies request complexity (usually "medium" — single
36
+ specialist, multiple research dimensions).
37
+ 2. Spawns 3-5 research subagents in parallel:
38
+ - Perplexity MCP → real-time framework discovery
39
+ - Exa AI → semantic search for prior art
40
+ - Context7 → official documentation pulls
41
+ - Firecrawl → scrape competitor / canonical sources
42
+ - XMCP → Twitter / X conversations for community wisdom
43
+ 3. Critic synthesis: a Tier 0 reviewer collapses overlap, surfaces
44
+ contradictions, prioritises by source weight.
45
+ 4. Generates the deliverable (YAML / playbook / persona) and saves to
46
+ the canonical path.
47
+ 5. Quality Gate (Marta + Eduardo + Francisca) approves before output
48
+ reaches the user.
49
+ ```
50
+
51
+ ## Why this exists
52
+
53
+ Per the Orgo interview, the recurring pattern in successful one-person
54
+ agent businesses is "use agents to set up agents". ArkaOS already had
55
+ the primitives — The Forge for planning, the Agent tool for subagent
56
+ dispatch, KB-first research — but no single entry point that made the
57
+ pattern *the* way to add capability. This skill is that entry.
58
+
59
+ ## Boundaries
60
+
61
+ - This skill **generates**. It does not modify production code.
62
+ - The generated YAML lands in `departments/<dept>/agents/` for review;
63
+ it is **not** auto-registered until the user commits and the next
64
+ loader pass picks it up.
65
+ - Personas built via this skill go through `/kb` for the actual
66
+ content ingestion (YouTube / PDFs / articles). This skill orchestrates,
67
+ it does not bypass the knowledge pipeline.
68
+
69
+ ## Cross-references
70
+
71
+ - Source pattern: 2026-05-13 Orgo podcast (Nick Saraev × Greg Isenberg)
72
+ - Related: `/arka forge` (planning engine, lower level)
73
+ - Related: `/kb persona` (content-driven persona builder)
74
+ - Related: `/arka research` (the same research-fan-out pattern for
75
+ one-off knowledge tasks rather than agent generation)
76
+ - Memory: [[project_next_level_conclave]]
@@ -0,0 +1,68 @@
1
+ ---
2
+ name: arka-design-ops
3
+ description: >
4
+ Brand Design Ops sub-squad orchestrator. Routes design-system extraction,
5
+ WCAG audit, and shadcn padronisation work to Iris (lead) + Nia
6
+ (extraction) + Oren (WCAG) + Leo (shadcn). Inspired by the AIOX Squad
7
+ → Sub-Squad pattern documented in the 2026-04-30 KB live and unblocked
8
+ for ArkaOS by the v2.27.0 Conclave roadmap.
9
+ allowed-tools: [Read, Write, Bash, Edit]
10
+ ---
11
+
12
+ # /brand design-ops — Design Ops sub-squad
13
+
14
+ > Sub-squad of `/brand` (Valentina). Operational specialists for the
15
+ > production rails of design systems: tokens, audits, components.
16
+
17
+ ## Squad
18
+
19
+ | Agent | Role | Tier | Owns |
20
+ | --- | --- | --- | --- |
21
+ | **Iris** (`design-ops-lead`) | Lead | 1 | governance, escalation to Valentina |
22
+ | **Nia** (`extraction-script-writer`) | Specialist | 2 | reverse-engineer tokens from sites / figma |
23
+ | **Oren** (`wcag-auditor`) | Specialist | 2 | WCAG 2.2 AA conformance + reports |
24
+ | **Leo** (`shadcn-padronizer`) | Specialist | 2 | shadcn/ui canonical components |
25
+
26
+ ## Subcommands
27
+
28
+ | Command | Owner | What it does |
29
+ | --- | --- | --- |
30
+ | `/brand design-ops extract <url>` | Nia | Extract color, typography, spacing tokens from a live URL or figma file. Writes JSON to `~/.arkaos/design-ops/<slug>/tokens.json`. |
31
+ | `/brand design-ops wcag <url\|path>` | Oren | Run WCAG 2.2 AA audit. Outputs issue table (severity / criterion / location / fix) + conformance score. |
32
+ | `/brand design-ops shadcn <component>` | Leo | Generate or refactor a component to the shadcn/ui canonical form (CVA variants, Radix primitives, theme tokens). |
33
+ | `/brand design-ops audit <project>` | Iris | Orchestrate full audit: tokens drift, WCAG conformance, component-library variance. Produces a single report. |
34
+
35
+ ## Scripts (under `scripts/`)
36
+
37
+ The scripts library is intentionally small at v2.27.0 — three reference
38
+ implementations to anchor the pattern. Nia / Oren / Leo extend it as
39
+ ArkaOS evolves; AIOX's reference set is ~30 scripts and ArkaOS will
40
+ catch up incrementally.
41
+
42
+ | Script | Owner | Input | Output |
43
+ | --- | --- | --- | --- |
44
+ | `scripts/extract-colors.py` | Nia | URL or local HTML | `colors.json` (DTCG-compliant token list) |
45
+ | `scripts/wcag-contrast.py` | Oren | hex pairs OR CSS file | Issue list with contrast ratios + AA / AAA verdict |
46
+ | `scripts/shadcn-tokens.py` | Leo | tokens.json | shadcn CSS variables block + Tailwind config snippet |
47
+
48
+ Run any script with `python3 scripts/<name>.py --help` for usage.
49
+
50
+ ## Output
51
+
52
+ All design-ops output writes to:
53
+ - `~/.arkaos/design-ops/<slug>/` — generated artefacts (JSON, CSS, reports)
54
+ - `${VAULT_PATH}/Projects/Design Ops/<slug>.md` — human-readable summary (Obsidian)
55
+
56
+ ## Boundaries
57
+
58
+ - Strategy and visual direction stay with **Valentina** (`/brand`).
59
+ - Iris escalates anything that requires brand-level taste calls.
60
+ - Design-ops never opens PRs or pushes code; it produces specs, tokens,
61
+ audits. Implementation goes back to `/dev` via Paulo.
62
+
63
+ ## Cross-references
64
+
65
+ - Pattern source: KB note `🧠 Knowledge Base/Frameworks/AIOX Squads` (2026-04-30 live)
66
+ - ADR: this skill is the v2.27.0 Conclave instantiation of the sub-squad pattern
67
+ - Parent: `/brand` (Valentina)
68
+ - Stack origin: v2.27.0 (PR5 of 6 from the 2026-05-13 Conclave roadmap)
@@ -0,0 +1,86 @@
1
+ #!/usr/bin/env python3
2
+ """Extract colour tokens from CSS / HTML / JSON (Nia's reference script).
3
+
4
+ Scans the input for hex colours and named CSS variables, normalises to
5
+ lower-case 6-digit hex, deduplicates, and emits a DTCG-compliant
6
+ ``colors.json`` token list.
7
+
8
+ Usage:
9
+ python3 extract-colors.py path/to/styles.css
10
+ python3 extract-colors.py --stdin < styles.css
11
+ cat styles.css | python3 extract-colors.py --stdin
12
+ """
13
+
14
+ from __future__ import annotations
15
+
16
+ import argparse
17
+ import json
18
+ import re
19
+ import sys
20
+ from pathlib import Path
21
+
22
+ HEX = re.compile(r"#([0-9a-fA-F]{3,8})\b")
23
+ RGB = re.compile(r"rgb(?:a)?\((\d+)\s*,\s*(\d+)\s*,\s*(\d+)")
24
+
25
+
26
+ def normalise(hex_value: str) -> str | None:
27
+ h = hex_value.lower()
28
+ if len(h) == 3:
29
+ h = "".join(c * 2 for c in h)
30
+ elif len(h) == 4:
31
+ h = "".join(c * 2 for c in h[:3])
32
+ elif len(h) == 8:
33
+ h = h[:6]
34
+ if len(h) != 6:
35
+ return None
36
+ return f"#{h}"
37
+
38
+
39
+ def rgb_to_hex(r: int, g: int, b: int) -> str:
40
+ return f"#{r:02x}{g:02x}{b:02x}"
41
+
42
+
43
+ def extract(text: str) -> list[str]:
44
+ seen: set[str] = set()
45
+ out: list[str] = []
46
+ for m in HEX.finditer(text):
47
+ norm = normalise(m.group(1))
48
+ if norm and norm not in seen:
49
+ seen.add(norm)
50
+ out.append(norm)
51
+ for r, g, b in RGB.findall(text):
52
+ norm = rgb_to_hex(int(r), int(g), int(b))
53
+ if norm not in seen:
54
+ seen.add(norm)
55
+ out.append(norm)
56
+ return out
57
+
58
+
59
+ def to_dtcg(colors: list[str]) -> dict:
60
+ tokens = {}
61
+ for i, c in enumerate(colors):
62
+ slug = f"color-{i:03d}"
63
+ tokens[slug] = {"$value": c, "$type": "color"}
64
+ return {"$schema": "https://design-tokens.org/draft", "colors": tokens}
65
+
66
+
67
+ def main(argv: list[str]) -> int:
68
+ parser = argparse.ArgumentParser(description=__doc__)
69
+ parser.add_argument("source", nargs="?", help="path to CSS / HTML file")
70
+ parser.add_argument("--stdin", action="store_true", help="read from stdin")
71
+ args = parser.parse_args(argv)
72
+
73
+ if args.stdin or args.source == "-":
74
+ text = sys.stdin.read()
75
+ elif args.source:
76
+ text = Path(args.source).read_text(encoding="utf-8")
77
+ else:
78
+ parser.error("provide a source path or use --stdin")
79
+
80
+ colors = extract(text)
81
+ print(json.dumps(to_dtcg(colors), indent=2))
82
+ return 0
83
+
84
+
85
+ if __name__ == "__main__":
86
+ sys.exit(main(sys.argv[1:]))
@@ -0,0 +1,59 @@
1
+ #!/usr/bin/env python3
2
+ """Convert DTCG colour tokens into shadcn/ui CSS variables (Leo's script).
3
+
4
+ Reads a DTCG-style ``colors.json`` (as produced by ``extract-colors.py``)
5
+ and emits the canonical shadcn/ui CSS variable block plus a matching
6
+ ``tailwind.config.js`` ``theme.extend.colors`` snippet.
7
+
8
+ Usage:
9
+ python3 shadcn-tokens.py colors.json
10
+ python3 shadcn-tokens.py colors.json --prefix brand-
11
+ """
12
+
13
+ from __future__ import annotations
14
+
15
+ import argparse
16
+ import json
17
+ import sys
18
+ from pathlib import Path
19
+
20
+
21
+ def to_css_var(slug: str, value: str, prefix: str) -> str:
22
+ return f" --{prefix}{slug}: {value};"
23
+
24
+
25
+ def to_tailwind_entry(slug: str, prefix: str) -> str:
26
+ key = slug.replace("color-", "")
27
+ return f' "{prefix}{slug}": "var(--{prefix}{slug})",'
28
+
29
+
30
+ def main(argv: list[str]) -> int:
31
+ parser = argparse.ArgumentParser(description=__doc__)
32
+ parser.add_argument("source", help="path to DTCG colors.json")
33
+ parser.add_argument("--prefix", default="", help="CSS variable prefix (e.g. 'brand-')")
34
+ args = parser.parse_args(argv)
35
+
36
+ data = json.loads(Path(args.source).read_text(encoding="utf-8"))
37
+ tokens = data.get("colors", {})
38
+ if not tokens:
39
+ print("no colours found in source", file=sys.stderr)
40
+ return 1
41
+
42
+ css_vars = [to_css_var(slug, t["$value"], args.prefix) for slug, t in tokens.items()]
43
+ tailwind = [to_tailwind_entry(slug, args.prefix) for slug in tokens]
44
+
45
+ print(":root {")
46
+ print("\n".join(css_vars))
47
+ print("}\n")
48
+
49
+ print("// tailwind.config.js — theme.extend.colors")
50
+ print("{")
51
+ print(' theme: { extend: { colors: {')
52
+ print("\n".join(tailwind))
53
+ print(" } } }")
54
+ print("}")
55
+ return 0
56
+
57
+
58
+ if __name__ == "__main__":
59
+ sys.exit(main(sys.argv[1:]))
@@ -0,0 +1,92 @@
1
+ #!/usr/bin/env python3
2
+ """WCAG 2.2 contrast ratio checker (Oren's reference script).
3
+
4
+ Compares foreground / background colours and reports whether the pair
5
+ passes WCAG 2.2 Level AA (4.5 : 1 normal text, 3 : 1 large text and UI
6
+ components) and AAA (7 : 1 normal, 4.5 : 1 large).
7
+
8
+ Usage:
9
+ python3 wcag-contrast.py "#1a1a1a" "#ffffff"
10
+ python3 wcag-contrast.py --json "#0f172a" "#ffffff" "#3b82f6" "#ffffff"
11
+
12
+ Outputs a single-line verdict or, with --json, a structured report.
13
+ """
14
+
15
+ from __future__ import annotations
16
+
17
+ import argparse
18
+ import json
19
+ import sys
20
+
21
+
22
+ def relative_luminance(rgb: tuple[int, int, int]) -> float:
23
+ """WCAG relative luminance formula."""
24
+ def channel(c: int) -> float:
25
+ s = c / 255
26
+ return s / 12.92 if s <= 0.03928 else ((s + 0.055) / 1.055) ** 2.4
27
+
28
+ r, g, b = (channel(c) for c in rgb)
29
+ return 0.2126 * r + 0.7152 * g + 0.0722 * b
30
+
31
+
32
+ def contrast_ratio(fg: tuple[int, int, int], bg: tuple[int, int, int]) -> float:
33
+ lf, lb = relative_luminance(fg), relative_luminance(bg)
34
+ lighter, darker = max(lf, lb), min(lf, lb)
35
+ return (lighter + 0.05) / (darker + 0.05)
36
+
37
+
38
+ def hex_to_rgb(hex_color: str) -> tuple[int, int, int]:
39
+ s = hex_color.lstrip("#")
40
+ if len(s) == 3:
41
+ s = "".join(c * 2 for c in s)
42
+ if len(s) != 6:
43
+ raise ValueError(f"Invalid hex colour: {hex_color}")
44
+ return int(s[0:2], 16), int(s[2:4], 16), int(s[4:6], 16)
45
+
46
+
47
+ def verdict(ratio: float) -> dict[str, bool]:
48
+ return {
49
+ "AA_normal": ratio >= 4.5,
50
+ "AA_large": ratio >= 3.0,
51
+ "AAA_normal": ratio >= 7.0,
52
+ "AAA_large": ratio >= 4.5,
53
+ }
54
+
55
+
56
+ def check_pair(fg_hex: str, bg_hex: str) -> dict[str, object]:
57
+ fg = hex_to_rgb(fg_hex)
58
+ bg = hex_to_rgb(bg_hex)
59
+ ratio = round(contrast_ratio(fg, bg), 2)
60
+ return {
61
+ "fg": fg_hex,
62
+ "bg": bg_hex,
63
+ "ratio": ratio,
64
+ **verdict(ratio),
65
+ }
66
+
67
+
68
+ def main(argv: list[str]) -> int:
69
+ parser = argparse.ArgumentParser(description=__doc__)
70
+ parser.add_argument("colors", nargs="*", help="alternating fg bg pairs")
71
+ parser.add_argument("--json", action="store_true", help="emit JSON report")
72
+ args = parser.parse_args(argv)
73
+
74
+ if len(args.colors) < 2 or len(args.colors) % 2 != 0:
75
+ parser.error("provide pairs of hex colours: <fg> <bg> [<fg> <bg> ...]")
76
+
77
+ pairs = list(zip(args.colors[::2], args.colors[1::2]))
78
+ results = [check_pair(fg, bg) for fg, bg in pairs]
79
+
80
+ if args.json:
81
+ print(json.dumps({"results": results}, indent=2))
82
+ return 0
83
+
84
+ for r in results:
85
+ flags = [k for k, v in r.items() if k.startswith("AA") and v]
86
+ flag_str = "+".join(flags) if flags else "FAILS_ALL"
87
+ print(f"{r['fg']} on {r['bg']}: {r['ratio']}:1 → {flag_str}")
88
+ return 0
89
+
90
+
91
+ if __name__ == "__main__":
92
+ sys.exit(main(sys.argv[1:]))
@@ -0,0 +1,117 @@
1
+ ---
2
+ name: arka-research
3
+ description: >
4
+ Fan-out research workflow. Spawns 5 parallel subagents — Perplexity,
5
+ Exa AI, Context7, Firecrawl, XMCP — synthesises their findings into
6
+ a single report, and writes a Knowledge Base note to the Obsidian
7
+ vault. Inspired by the multi-source research pattern surfaced in the
8
+ 2026-05-13 Orgo podcast (Nick Saraev): "I tell Claude Code, hey,
9
+ spawn five sub-agents — one for Perplexity, one for Exa, one for
10
+ Context7, one for Firecrawl, one for XMCP — and we get best practices."
11
+ allowed-tools: [Agent, Read, Write, mcp__obsidian__search_notes]
12
+ ---
13
+
14
+ # /arka research — one prompt, five parallel sources
15
+
16
+ > Companion to `/arka bootstrap-agent`. Where bootstrap-agent generates
17
+ > capability, this skill generates *knowledge*.
18
+
19
+ ## Usage
20
+
21
+ ```
22
+ /arka research <topic>
23
+ ```
24
+
25
+ `<topic>` is a free-form research question. Examples:
26
+
27
+ - `/arka research "Hermes agent setup with Telegram gateway"`
28
+ - `/arka research "Mistral Medium 3.5 cost vs Sonnet 4.6"`
29
+ - `/arka research "AIOX Squad de Saúde framework"`
30
+
31
+ ## Sources fanned out
32
+
33
+ | Subagent | MCP / tool | Strength |
34
+ | --- | --- | --- |
35
+ | Perplexity | `mcp__perplexity__ask` | Real-time web with citations |
36
+ | Exa AI | `mcp__exa__search` | Semantic vector search across the web |
37
+ | Context7 | `mcp__context7__query-docs` | Up-to-date official library docs |
38
+ | Firecrawl | `mcp__firecrawl__firecrawl_scrape` | Site-specific deep scraping |
39
+ | XMCP | `mcp__x__search` | X / Twitter conversations and threads |
40
+
41
+ If any MCP is not registered in `.mcp.json`, that subagent is skipped
42
+ with a `[arka:source-skipped]` note in the report. KB-first protocol
43
+ still applies — Obsidian search runs before any external call.
44
+
45
+ ## Workflow
46
+
47
+ ```
48
+ 1. KB-first: search Obsidian vault for prior notes on the topic.
49
+ If high-confidence matches exist, the report cites them first
50
+ and asks the user whether external research is still needed.
51
+
52
+ 2. Fan out 5 subagents in parallel via the Agent tool. Each gets
53
+ the same topic, returns a focused short brief (≤500 words).
54
+
55
+ 3. Critic synthesis (Tier 0 reviewer, opus): collapses overlap,
56
+ surfaces contradictions, ranks sources by weight (official docs >
57
+ recent community threads > older articles).
58
+
59
+ 4. Synthesis report saved to:
60
+ ${VAULT_PATH}/Knowledge Base/Research/<YYYY-MM-DD>-<slug>.md
61
+ with full citations and a "where to go next" section.
62
+
63
+ 5. Returns a compact summary to the user (the full report links to
64
+ the Obsidian note).
65
+ ```
66
+
67
+ ## Output shape
68
+
69
+ ```markdown
70
+ ---
71
+ title: <topic>
72
+ date: <YYYY-MM-DD>
73
+ sources: [perplexity, exa, context7, firecrawl, xmcp]
74
+ status: synthesised
75
+ tags: [research, <topic-tag>]
76
+ ---
77
+
78
+ # <Topic>
79
+
80
+ ## TL;DR
81
+ <3-bullet summary>
82
+
83
+ ## Findings by source
84
+ ### Perplexity
85
+ ...
86
+ ### Exa AI
87
+ ...
88
+ (etc.)
89
+
90
+ ## Synthesis
91
+ <contradictions resolved, ranked by source weight>
92
+
93
+ ## Next steps
94
+ <2-3 follow-up questions or actions>
95
+ ```
96
+
97
+ ## Cost & budget
98
+
99
+ This is a heavy operation — 5 parallel LLM calls plus a synthesis call.
100
+ A typical run consumes 3-8k tokens. The `/arka costs` skill tracks the
101
+ spend and the `[arka:warn]` token-hygiene hook flags excessive use.
102
+
103
+ ## Boundaries
104
+
105
+ - Read-only: this skill never modifies code or configuration. It only
106
+ writes to the Obsidian Knowledge Base.
107
+ - KB-first: always check the vault first. Many topics already have
108
+ notes from prior Dreaming / Research sessions.
109
+ - No external research without the user asking — agents do not
110
+ proactively fan out unless `/arka research` is invoked.
111
+
112
+ ## Cross-references
113
+
114
+ - Source pattern: 2026-05-13 Orgo podcast
115
+ - Related: `/arka forge` (planning, not research)
116
+ - Related: `/kb research` (Clara, knowledge management)
117
+ - Related: `/arka bootstrap-agent` (capability-from-research)
@@ -135,6 +135,10 @@ enforcement_levels:
135
135
  rule: "All ecosystem skills must follow the standard 7-phase workflow defined in config/standards/ecosystem-workflow.md"
136
136
  enforcement: "Ecosystem SKILL.md files must reference or implement all 7 phases"
137
137
 
138
+ - id: sub-squad-hierarchy
139
+ rule: "Agents in a sub-squad MUST declare parent_squad (department slug) and sub_squad_role. Sub-squads inherit the parent department's authority chain; their lead escalates to the department squad lead, not directly to Tier 0."
140
+ enforcement: "Agent loader validates parent_squad + sub_squad_role coherence (sub_squad_role requires parent_squad). PR5 v2.27.0 introduced the pattern; AIOX Squad → Sub-Squad → Skills/Scripts is the reference architecture."
141
+
138
142
  - id: forge-persistence
139
143
  rule: "All forge plans (approved and rejected) must be persisted to Obsidian"
140
144
  enforcement: "persistence.py exports on status change; audit detects missing exports"
@@ -391,6 +391,23 @@ if not match and all_deliverables:
391
391
  fi
392
392
  fi
393
393
 
394
+ # ─── Cognitive layer capture (PR4 v2.26.0 hooks-as-retrieval) ────────────
395
+ # Backgrounded so the hook returns immediately. The retrieval helper has
396
+ # its own internal time caps (ripgrep ≤ 1s, Python fallback capped at 500
397
+ # files) so a runaway extract can never block the next user prompt. We
398
+ # disown so the child cannot zombie if the hook process exits first.
399
+ if [ -n "$SESSION_ID_PTU" ] && [ -n "$TOOL_OUTPUT" ]; then
400
+ _ARKAOS_REPO=$(cat "$HOME/.arkaos/.repo-path" 2>/dev/null || echo "")
401
+ if [ -n "$_ARKAOS_REPO" ] && [ -d "$_ARKAOS_REPO" ]; then
402
+ (
403
+ PYTHONPATH="$_ARKAOS_REPO" python3 -m core.cognition.retrieval capture "$SESSION_ID_PTU" <<EOF >/dev/null 2>&1
404
+ $TOOL_OUTPUT
405
+ EOF
406
+ ) &
407
+ disown 2>/dev/null || true
408
+ fi
409
+ fi
410
+
394
411
  # ─── Log Metrics ─────────────────────────────────────────────────────────
395
412
  _DURATION_MS=$(_hook_ms)
396
413
  METRICS_FILE="$HOME/.arkaos/hook-metrics.json"
@@ -356,9 +356,25 @@ sequential-validation, full-visibility, arka-supremacy."
356
356
  fi
357
357
  fi
358
358
 
359
+ # ─── Cognitive context injection (PR4 v2.26.0 hooks-as-retrieval) ───────
360
+ # Read the context cache populated by the previous PostToolUse turn and
361
+ # inject any KB hits as an `[arka:context]` advisory. The Python helper
362
+ # has internal TTL filtering (10 min) and returns empty when there is no
363
+ # fresh cache, so this stays a no-op until the cognitive layer has data
364
+ # to share.
365
+ _ARKA_CONTEXT_HITS=""
366
+ if [ -n "$SESSION_ID" ]; then
367
+ _ARKAOS_REPO=$(cat "$HOME/.arkaos/.repo-path" 2>/dev/null || echo "")
368
+ if [ -n "$_ARKAOS_REPO" ] && [ -d "$_ARKAOS_REPO" ]; then
369
+ _ARKA_CONTEXT_HITS=$(PYTHONPATH="$_ARKAOS_REPO" python3 -m core.cognition.retrieval inject "$SESSION_ID" 2>/dev/null)
370
+ fi
371
+ fi
372
+
359
373
  # ─── Output ──────────────────────────────────────────────────────────────
360
374
  _OUT_CONTEXT="${_ARKA_GREETING:-}${_SYNC_NOTICE:-}${_ROUTE_REMINDER}${_WORKFLOW_DIRECTIVE} $python_result"
361
375
  [ -n "$_HYGIENE" ] && _OUT_CONTEXT="$_OUT_CONTEXT $_HYGIENE"
376
+ [ -n "$_ARKA_CONTEXT_HITS" ] && _OUT_CONTEXT="$_OUT_CONTEXT
377
+ $_ARKA_CONTEXT_HITS"
362
378
  # Escape for JSON
363
379
  _OUT_JSON=$(python3 -c "import json,sys; print(json.dumps(sys.stdin.read()))" <<< "$_OUT_CONTEXT" 2>/dev/null)
364
380
  if [ -n "$_OUT_JSON" ]; then
@@ -60,7 +60,10 @@ def load_all_agents(
60
60
  for agents_dir in search_dirs:
61
61
  if not agents_dir.is_dir():
62
62
  continue
63
- for yaml_file in sorted(agents_dir.glob("*.yaml")):
63
+ # Recursive rglob picks up sub-squad subdirectories (e.g.
64
+ # departments/brand/agents/design-ops/*.yaml) per the v2.27.0
65
+ # Sub-Squad pattern. Sorted output keeps load order stable.
66
+ for yaml_file in sorted(agents_dir.rglob("*.yaml")):
64
67
  try:
65
68
  agent = load_agent(yaml_file)
66
69
  agents.append(agent)
@@ -273,6 +273,35 @@ class Agent(BaseModel):
273
273
  description="Claude model override for dispatch. Falls back to tier default when None.",
274
274
  )
275
275
 
276
+ parent_squad: Optional[str] = Field(
277
+ default=None,
278
+ description=(
279
+ "Slug of the parent squad when this agent belongs to a sub-squad. "
280
+ "Sub-squads are operational specialisations inside a department "
281
+ "(e.g. brand → design-ops). Optional and backwards-compatible: "
282
+ "agents without a parent_squad belong directly to their department."
283
+ ),
284
+ )
285
+
286
+ sub_squad_role: Optional[str] = Field(
287
+ default=None,
288
+ description=(
289
+ "Role within the sub-squad when parent_squad is set "
290
+ "(e.g. 'lead', 'extraction-script-writer', 'wcag-auditor'). "
291
+ "Inspired by the AIOX Squad → Sub-Squad pattern (KB note "
292
+ "AIOX Squads, April 30 2026 live)."
293
+ ),
294
+ )
295
+
296
+ @model_validator(mode="after")
297
+ def validate_sub_squad_coherence(self) -> "Agent":
298
+ """sub_squad_role only makes sense when parent_squad is set."""
299
+ if self.sub_squad_role and not self.parent_squad:
300
+ raise ValueError(
301
+ "sub_squad_role requires parent_squad to be set"
302
+ )
303
+ return self
304
+
276
305
  @model_validator(mode="after")
277
306
  def auto_fill_memory_path(self) -> "Agent":
278
307
  if not self.memory_path: