arkaos 2.22.1 → 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.
- package/README.md +105 -9
- package/VERSION +1 -1
- package/arka/SKILL.md +1 -0
- package/arka/skills/bootstrap-agent/SKILL.md +76 -0
- package/arka/skills/comfyui/SKILL.md +2 -2
- package/arka/skills/comfyui/references/workflows.md +6 -6
- package/arka/skills/costs/SKILL.md +11 -0
- package/arka/skills/design-ops/SKILL.md +68 -0
- package/arka/skills/design-ops/scripts/extract-colors.py +86 -0
- package/arka/skills/design-ops/scripts/shadcn-tokens.py +59 -0
- package/arka/skills/design-ops/scripts/wcag-contrast.py +92 -0
- package/arka/skills/research/SKILL.md +117 -0
- package/config/cognition/prompts/dreaming.md +3 -3
- package/config/cognition/prompts/research.md +4 -4
- package/config/constitution.yaml +4 -0
- package/config/hooks/post-tool-use.sh +17 -0
- package/config/hooks/user-prompt-submit.sh +22 -1
- package/core/agents/__pycache__/loader.cpython-313.pyc +0 -0
- package/core/agents/__pycache__/schema.cpython-313.pyc +0 -0
- package/core/agents/loader.py +4 -1
- package/core/agents/schema.py +29 -0
- package/core/cognition/__pycache__/auto_documentor.cpython-313.pyc +0 -0
- package/core/cognition/__pycache__/retrieval.cpython-313.pyc +0 -0
- package/core/cognition/capture/__pycache__/collector.cpython-313.pyc +0 -0
- package/core/cognition/capture/collector.py +10 -3
- package/core/cognition/retrieval.py +383 -0
- package/core/cognition/scheduler/__pycache__/daemon.cpython-313.pyc +0 -0
- package/core/cognition/scheduler/daemon.py +5 -0
- package/core/jobs/__pycache__/auto_doc_worker.cpython-313.pyc +0 -0
- package/core/obsidian/__pycache__/writer.cpython-313.pyc +0 -0
- package/core/obsidian/writer.py +5 -4
- package/core/runtime/__pycache__/base.cpython-313.pyc +0 -0
- package/core/runtime/__pycache__/claude_code.cpython-313.pyc +0 -0
- package/core/runtime/__pycache__/codex_cli.cpython-313.pyc +0 -0
- package/core/runtime/__pycache__/gemini_cli.cpython-313.pyc +0 -0
- package/core/runtime/__pycache__/llm_provider.cpython-313.pyc +0 -0
- package/core/runtime/__pycache__/path_resolver.cpython-313.pyc +0 -0
- package/core/runtime/path_resolver.py +202 -0
- package/core/shared/__pycache__/__init__.cpython-313.pyc +0 -0
- package/core/shared/__pycache__/safe_session_id.cpython-313.pyc +0 -0
- package/core/specs/SPEC-installer-cross-os.md +227 -0
- package/core/specs/SPEC-paths-portability.md +209 -0
- package/core/synapse/__pycache__/kb_cache.cpython-313.pyc +0 -0
- package/core/synapse/__pycache__/layers.cpython-313.pyc +0 -0
- package/core/workflow/__pycache__/flow_enforcer.cpython-313.pyc +0 -0
- package/core/workflow/__pycache__/marker_cache.cpython-313.pyc +0 -0
- package/core/workflow/__pycache__/research_gate.cpython-313.pyc +0 -0
- package/departments/brand/agents/design-ops/design-ops-lead.yaml +78 -0
- package/departments/brand/agents/design-ops/extraction-script-writer.yaml +74 -0
- package/departments/brand/agents/design-ops/shadcn-padronizer.yaml +76 -0
- package/departments/brand/agents/design-ops/wcag-auditor.yaml +76 -0
- package/departments/dev/skills/mcp/SKILL.md +16 -0
- package/departments/dev/skills/scaffold/SKILL.md +4 -4
- package/departments/kb/skills/knowledge/SKILL.md +1 -1
- package/departments/ops/skills/operations/SKILL.md +1 -1
- package/installer/cli.js +2 -1
- package/installer/doctor.js +48 -0
- package/installer/index.js +26 -1
- package/installer/migrate-user-data.js +17 -1
- package/installer/migrations/v3_path_schema.js +109 -0
- package/installer/package-manager.js +191 -0
- package/installer/path-resolver.js +124 -0
- package/installer/system-tools.js +243 -0
- package/installer/update.js +24 -3
- package/knowledge/obsidian-config.json +1 -1
- package/package.json +1 -1
- package/pyproject.toml +1 -1
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
npx arkaos install
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
[](https://www.npmjs.com/package/arkaos) [](LICENSE) [](https://www.npmjs.com/package/arkaos) [](LICENSE) []()
|
|
12
12
|
|
|
13
13
|
---
|
|
14
14
|
|
|
@@ -228,6 +228,84 @@ arkaos scheduler logs # View logs
|
|
|
228
228
|
|
|
229
229
|
---
|
|
230
230
|
|
|
231
|
+
## Intelligence Loop (v2.21.0+)
|
|
232
|
+
|
|
233
|
+
Three-layer system that makes ArkaOS consult its brain before going external, and write every session's learnings back to the vault automatically. The system compounds daily — tomorrow's ArkaOS is smarter than today's.
|
|
234
|
+
|
|
235
|
+
### Synapse L2.5 — KB Context Injection (v2.21.0)
|
|
236
|
+
|
|
237
|
+
On every user prompt, ArkaOS runs semantic search against the Obsidian vault and injects the top relevant notes (with wikilinks and excerpts) as context **before the model starts planning**. The agent sees what the vault already knows, naturally — no hard gate, no friction.
|
|
238
|
+
|
|
239
|
+
- Top 3–5 notes by similarity
|
|
240
|
+
- Jaccard fallback when vector store absent
|
|
241
|
+
- Feature flag `synapse.l25KbContext` default `true`
|
|
242
|
+
- Kill switch `ARKA_BYPASS_L25=1`
|
|
243
|
+
|
|
244
|
+
### Research Gate — Natural Nudge (v2.21.0)
|
|
245
|
+
|
|
246
|
+
When an agent tries `Context7`, `WebSearch`, `WebFetch`, or `Firecrawl` without consulting Obsidian first:
|
|
247
|
+
|
|
248
|
+
- **First attempt** → natural PT-PT nudge listing top 3 vault hits. Allows the call.
|
|
249
|
+
- **Second attempt in same turn** → deny. The nudge wasn't enough.
|
|
250
|
+
|
|
251
|
+
Feature flag `hooks.kbFirst` default `false` in v2.21.0 — dormant until operator flips. Kill switch `ARKA_BYPASS_KB_FIRST=1` (audited).
|
|
252
|
+
|
|
253
|
+
### Auto-Documentor + Cataloger + Relator (v2.21.0)
|
|
254
|
+
|
|
255
|
+
After every approved session, an async worker writes the learnings back to the vault:
|
|
256
|
+
|
|
257
|
+
1. **Extract** — parses the transcript for sources consulted, decisions made, deliverables produced
|
|
258
|
+
2. **Classify** — cataloger chooses the right taxonomic home (code pattern, persona, client strategy, marketing test, ADR, research finding, framework, or session fallback)
|
|
259
|
+
3. **Write** — creates the note at the correct vault path with frontmatter + tags
|
|
260
|
+
4. **Relate** — relator finds semantically similar existing notes, creates bidirectional `[[wikilinks]]`, updates MOCs
|
|
261
|
+
|
|
262
|
+
The vault becomes a relational graph that grows with every session.
|
|
263
|
+
|
|
264
|
+
### LLM Agnostic Auto-Documentor (v2.22.0)
|
|
265
|
+
|
|
266
|
+
The synthesis LLM call is runtime-agnostic. **Zero model hardcoding.** Whatever runtime you have configured decides the model:
|
|
267
|
+
|
|
268
|
+
| Provider | Default | Model decided by |
|
|
269
|
+
|---|---|---|
|
|
270
|
+
| `subagent` | ✅ | Active runtime's headless CLI (`claude -p`, `gemini -p …`) |
|
|
271
|
+
| `anthropic-direct` | — | `ANTHROPIC_MODEL` env var; no code default |
|
|
272
|
+
| `stub` | tests | Template fallback |
|
|
273
|
+
|
|
274
|
+
Fallback chain `subagent → anthropic-direct → stub` never raises. Prompt caching ON by default (5-min TTL `cache_control: ephemeral` on system block).
|
|
275
|
+
|
|
276
|
+
### Budget Telemetry + `/arka costs` (v2.22.0)
|
|
277
|
+
|
|
278
|
+
Every LLM call appends to `~/.arkaos/telemetry/llm-cost.jsonl` with tokens, cache hits, and estimated cost. Per [ADR-011](docs/adr/), this is **visibility only — never blocks**.
|
|
279
|
+
|
|
280
|
+
```bash
|
|
281
|
+
/arka costs # today (default)
|
|
282
|
+
/arka costs week # last 7 days
|
|
283
|
+
/arka costs month # last 30 days
|
|
284
|
+
/arka costs sessions # top 10 expensive sessions
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
Soft advisory when a single session exceeds $5 equivalent. No hard caps.
|
|
288
|
+
|
|
289
|
+
### Flow Marker v2 (v2.21.0)
|
|
290
|
+
|
|
291
|
+
The constitutional 13-phase flow enforcement (binding in v2.20) got a turn-scoped marker cache, eliminating the cross-turn false positives that triggered on subagent dispatch and short user continuations. ADR-compliant: cache accelerates ALLOW decisions only; the transcript remains authoritative for DENY.
|
|
292
|
+
|
|
293
|
+
### Polish & Consolidation (v2.22.1)
|
|
294
|
+
|
|
295
|
+
- `core/shared/safe_session_id.py` — single source of truth for the path-traversal / injection allowlist, deduped across 6 modules (100% coverage, 33 security-contract tests)
|
|
296
|
+
- Gemini CLI headless live (`gemini -p "…" --output-format json`)
|
|
297
|
+
- `_MAX_FALLBACK_NOTES = 2000` bound on Synapse L2.5 degraded-mode scan
|
|
298
|
+
- Auto-documentor coverage lifted 93% → 98%
|
|
299
|
+
- Template synthesiser now mirrors LLM prompt structure (Key Facts → Decisions → Sources)
|
|
300
|
+
|
|
301
|
+
### ADRs
|
|
302
|
+
|
|
303
|
+
- [`2026-04-20-flow-marker-v2.md`](docs/adr/2026-04-20-flow-marker-v2.md) — turn-scoped cache amendment
|
|
304
|
+
- [`2026-04-20-kb-first-intelligence.md`](docs/adr/2026-04-20-kb-first-intelligence.md) — Synapse L2.5 + gate + auto-documentor
|
|
305
|
+
- [`2026-04-20-llm-agnostic.md`](docs/adr/2026-04-20-llm-agnostic.md) — runtime-agnostic LLM wiring
|
|
306
|
+
|
|
307
|
+
---
|
|
308
|
+
|
|
231
309
|
## Ecosystem Management
|
|
232
310
|
|
|
233
311
|
ArkaOS manages client projects as **ecosystems** — groups of related projects with dedicated squads.
|
|
@@ -370,21 +448,39 @@ Full documentation is available on the **[GitHub Wiki](https://github.com/andrea
|
|
|
370
448
|
|
|
371
449
|
## CLI Reference
|
|
372
450
|
|
|
451
|
+
**Installer (terminal):**
|
|
452
|
+
|
|
373
453
|
```bash
|
|
374
|
-
npx arkaos install
|
|
375
|
-
npx arkaos update
|
|
376
|
-
npx arkaos migrate
|
|
377
|
-
npx arkaos doctor
|
|
378
|
-
npx arkaos dashboard
|
|
379
|
-
npx arkaos keys
|
|
380
|
-
npx arkaos uninstall
|
|
454
|
+
npx arkaos install # Fresh install (auto-detects runtime)
|
|
455
|
+
npx arkaos@latest update # Update core + hooks to latest version
|
|
456
|
+
npx arkaos migrate # Migrate from v1
|
|
457
|
+
npx arkaos doctor # Health check
|
|
458
|
+
npx arkaos dashboard # Start monitoring dashboard
|
|
459
|
+
npx arkaos keys # Manage API keys
|
|
460
|
+
npx arkaos uninstall # Remove ArkaOS
|
|
381
461
|
```
|
|
382
462
|
|
|
463
|
+
**In-session commands (inside Claude Code / Codex / Gemini / Cursor):**
|
|
464
|
+
|
|
465
|
+
```
|
|
466
|
+
/arka update # Sync all project configs after core update
|
|
467
|
+
/arka status # System health + LLM costs (24h)
|
|
468
|
+
/arka costs [today|week|month|all|sessions] # LLM cost visibility
|
|
469
|
+
/arka index # (Re)index Obsidian vault into vector store
|
|
470
|
+
/arka search <query> # Semantic search in knowledge base
|
|
471
|
+
/arka standup # Daily standup (projects, blockers, updates)
|
|
472
|
+
/arka onboard <path> # Onboard an existing project
|
|
473
|
+
/arka conclave # Personal AI advisory board
|
|
474
|
+
/do <description> # Universal routing — natural language to department
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
Department commands: `/dev`, `/mkt`, `/brand`, `/fin`, `/strat`, `/ecom`, `/kb`, `/ops`, `/pm`, `/saas`, `/landing`, `/content`, `/community`, `/sales`, `/lead`, `/org`.
|
|
478
|
+
|
|
383
479
|
---
|
|
384
480
|
|
|
385
481
|
## Contributing
|
|
386
482
|
|
|
387
|
-
See [CONTRIBUTING.md](.github/CONTRIBUTING.md). PRs welcome — all changes require passing the full test suite (
|
|
483
|
+
See [CONTRIBUTING.md](.github/CONTRIBUTING.md). PRs welcome — all changes require passing the full test suite (3,025 tests) and Quality Gate review.
|
|
388
484
|
|
|
389
485
|
## License
|
|
390
486
|
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
2.
|
|
1
|
+
2.28.0
|
package/arka/SKILL.md
CHANGED
|
@@ -122,6 +122,7 @@ violation (squad-routing, arka-supremacy, spec-driven, mandatory-qa).
|
|
|
122
122
|
| `/arka search <query>` | Semantic search in knowledge base |
|
|
123
123
|
| `/arka keys` | Manage API keys (OpenAI, Google, fal.ai) |
|
|
124
124
|
| `/arka personas` | Manage AI personas (create, clone to agent) |
|
|
125
|
+
| `/arka resume <PR_URL>` | Re-enter the Claude Code session that produced a PR (GitHub / GitLab / Bitbucket). Wraps the native `/resume` from Claude Code 2.1.122+. Useful with `arka-spec` and `arka-release` archaeology. |
|
|
125
126
|
| `/do <description>` | Universal routing — natural language to department command |
|
|
126
127
|
|
|
127
128
|
## Universal Orchestrator (/do)
|
|
@@ -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]]
|
|
@@ -19,8 +19,8 @@ Full-spectrum AI media production platform. From ComfyUI node engineering to Hol
|
|
|
19
19
|
|
|
20
20
|
| Project | Type | Stack | Path |
|
|
21
21
|
|---------|------|-------|------|
|
|
22
|
-
| **purz-comfyui-workflows** | Workflow Collection | ComfyUI JSON (7 workflows, 110+ nodes) |
|
|
23
|
-
| **lora_tester** | CLI Tool + Gallery | Python 3.8+ (stdlib) + Vanilla HTML/JS |
|
|
22
|
+
| **purz-comfyui-workflows** | Workflow Collection | ComfyUI JSON (7 workflows, 110+ nodes) | `${ARKA_OS_REPOS}/purz-comfyui-workflows` |
|
|
23
|
+
| **lora_tester** | CLI Tool + Gallery | Python 3.8+ (stdlib) + Vanilla HTML/JS | `${ARKA_OS_REPOS}/lora_tester` |
|
|
24
24
|
|
|
25
25
|
## Squads
|
|
26
26
|
|
|
@@ -7,8 +7,8 @@ Referenced from SKILL.md. Read only when needed.
|
|
|
7
7
|
For EVERY `/comfyui` request, follow this workflow:
|
|
8
8
|
|
|
9
9
|
### Phase 1 — Context Loading
|
|
10
|
-
1. Read ComfyUI skill reference:
|
|
11
|
-
2. Check available workflows: `ls /
|
|
10
|
+
1. Read ComfyUI skill reference: `${ARKA_OS_REPOS}/lora_tester/.claude/skills/comfy_local/skill.md`
|
|
11
|
+
2. Check available workflows: `ls ${ARKA_OS_REPOS}/purz-comfyui-workflows/`
|
|
12
12
|
3. Check ComfyUI server: `curl -s http://localhost:8188/system_stats 2>/dev/null`
|
|
13
13
|
4. Load project context for affected repos
|
|
14
14
|
5. Identify which squad(s) the request needs
|
|
@@ -320,8 +320,8 @@ while pending:
|
|
|
320
320
|
curl -s http://localhost:8188/system_stats 2>/dev/null
|
|
321
321
|
|
|
322
322
|
# Project status
|
|
323
|
-
cd /
|
|
324
|
-
cd /
|
|
323
|
+
cd ${ARKA_OS_REPOS}/purz-comfyui-workflows && git log --oneline -5
|
|
324
|
+
cd ${ARKA_OS_REPOS}/lora_tester && git log --oneline -5
|
|
325
325
|
```
|
|
326
326
|
|
|
327
327
|
Present as:
|
|
@@ -403,10 +403,10 @@ When Iris (Node Researcher) investigates custom nodes:
|
|
|
403
403
|
|
|
404
404
|
## Obsidian Output
|
|
405
405
|
|
|
406
|
-
All documentation:
|
|
406
|
+
All documentation: `${VAULT_PATH}/Projects/ComfyUI/`
|
|
407
407
|
|
|
408
408
|
```
|
|
409
|
-
|
|
409
|
+
Projects/ComfyUI/
|
|
410
410
|
├── Home.md <- Ecosystem overview
|
|
411
411
|
├── Workflows/
|
|
412
412
|
│ ├── LTX-2 T2V.md
|
|
@@ -55,6 +55,17 @@ Source:
|
|
|
55
55
|
One JSONL line per LLM call, written by every provider adapter.
|
|
56
56
|
Malformed lines are skipped and counted, never raised.
|
|
57
57
|
|
|
58
|
+
## Cost-tuning levers
|
|
59
|
+
|
|
60
|
+
Outside this skill's scope but worth surfacing alongside the summary:
|
|
61
|
+
|
|
62
|
+
| Lever | Where | Effect |
|
|
63
|
+
| --- | --- | --- |
|
|
64
|
+
| `ARKAOS_LLM_PROVIDER` | env | Switch between Anthropic, OpenAI, Gemini adapters per the multi-LLM router. |
|
|
65
|
+
| `ANTHROPIC_BEDROCK_SERVICE_TIER` | env (Claude Code 2.1.122+) | `default` / `flex` / `priority`. Only relevant when routing through AWS Bedrock — `flex` cuts cost ~50 % on non-urgent workloads at the price of higher tail latency. |
|
|
66
|
+
| Agent `model:` field | `departments/*/agents/*.yaml` | Per-agent override per the model-routing matrix in CLAUDE.md. Mechanical roles default to haiku, C-suite to opus. |
|
|
67
|
+
| Quality Gate model | constitution rule (NON-NEGOTIABLE) | Marta / Eduardo / Francisca always run on opus regardless of the cost ceiling. |
|
|
68
|
+
|
|
58
69
|
## Non-negotiables
|
|
59
70
|
|
|
60
71
|
1. Read-only. This skill never edits state.
|
|
@@ -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:]))
|