@arjunkhera/atlas 0.0.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/plugin.json +16 -0
- package/.mcp.json +18 -0
- package/README.md +32 -1
- package/agents/artifact-format/example.html +71 -0
- package/agents/artifact-format/system.css +273 -0
- package/agents/artifact-renderer.md +132 -0
- package/agents/capability-reader.md +100 -0
- package/agents/code-explorer.md +108 -0
- package/agents/reviewer-architect.md +78 -0
- package/agents/reviewer-pm.md +81 -0
- package/agents/reviewer-security.md +82 -0
- package/bin/atlas +5 -0
- package/door/cli.mjs +280 -0
- package/door/lib/helpers.mjs +139 -0
- package/door/lib/install.mjs +260 -0
- package/door/lib/kind-drift.mjs +76 -0
- package/door/lib/onboarding.mjs +130 -0
- package/door/lib/pull-request.mjs +115 -0
- package/door/lib/releases.mjs +42 -0
- package/door/lib/status.mjs +47 -0
- package/door/lib/tooling.mjs +119 -0
- package/package.json +24 -3
- package/shape/check.mjs +1797 -0
- package/shape/releases.json +15 -0
- package/skills/sdlc-task/SKILL.md +174 -0
- package/skills/sdlc-task/lifecycle.yaml +27 -0
- package/skills/sdlc-task/templates/design-doc.md +118 -0
- package/skills/sdlc-task/templates/resume-anchor.md +25 -0
- package/work/code-read.mjs +65 -0
- package/work/lib/action-store.mjs +84 -0
- package/work/lib/capability.mjs +487 -0
- package/work/lib/child-env.mjs +11 -0
- package/work/lib/client.mjs +214 -0
- package/work/lib/code-read.mjs +238 -0
- package/work/lib/delivery.mjs +624 -0
- package/work/lib/mcp-stdio.mjs +68 -0
- package/work/lib/questions.mjs +278 -0
- package/work/lib/sweep.mjs +189 -0
- package/work/lib/verb-fields.mjs +53 -0
- package/work/lib/verbs.mjs +511 -0
- package/work/manifest-0.5.0.json +609 -0
- package/work/mcp.mjs +216 -0
- package/work/protected-paths.json +38 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "atlas",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Atlas: the delivery lifecycle, its crews and the Atlas tools, for any repository.",
|
|
5
|
+
"author": { "name": "Arjun Khera" },
|
|
6
|
+
"repository": "https://github.com/Arjunkhera/atlas",
|
|
7
|
+
"license": "UNLICENSED",
|
|
8
|
+
"userConfig": {
|
|
9
|
+
"engram_connection": {
|
|
10
|
+
"type": "string",
|
|
11
|
+
"title": "Engram connection",
|
|
12
|
+
"description": "Your Engram address and key, separated by one space: https://<host> <key>. Changing the address means entering the key again.",
|
|
13
|
+
"sensitive": true
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
package/.mcp.json
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"mcpServers": {
|
|
3
|
+
"atlas-work": {
|
|
4
|
+
"command": "node",
|
|
5
|
+
"args": [
|
|
6
|
+
"${CLAUDE_PLUGIN_ROOT}/work/mcp.mjs"
|
|
7
|
+
],
|
|
8
|
+
"env": {
|
|
9
|
+
"ATLAS_ENGRAM": "${user_config.engram_connection}",
|
|
10
|
+
"ATLAS_WORK_OWNER_PRESENT": "1",
|
|
11
|
+
"ATLAS_WORK_JOURNAL": "",
|
|
12
|
+
"ATLAS_WORK_SESSION": "",
|
|
13
|
+
"ATLAS_WORK_AGENT": "",
|
|
14
|
+
"NODE_OPTIONS": ""
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
package/README.md
CHANGED
|
@@ -1 +1,32 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Atlas
|
|
2
|
+
|
|
3
|
+
Atlas sets how a repository is worked on. It is one Claude Code plugin with:
|
|
4
|
+
|
|
5
|
+
1. **The rulebook**, `atlas:sdlc-task`: start, pause, resume, lock and finish
|
|
6
|
+
one piece of work.
|
|
7
|
+
2. **Six crews**: a code reader, a capability reader, three design reviewers
|
|
8
|
+
(architect, product, security), and a page renderer.
|
|
9
|
+
3. **The Atlas tools**, an MCP server that keeps work items, questions,
|
|
10
|
+
decisions and delivery marks in an Engram knowledge graph.
|
|
11
|
+
4. **The `atlas` command**: set a repository up, check its Atlas files, and
|
|
12
|
+
install or upgrade Atlas itself.
|
|
13
|
+
5. **The repo check**, a file each repository copies so that its CI can check
|
|
14
|
+
its instruction files with no Atlas install.
|
|
15
|
+
|
|
16
|
+
## Install
|
|
17
|
+
|
|
18
|
+
Run this once, in a terminal:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npx @arjunkhera/atlas@0.2.0 install
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
It shows what it will change, and asks first. Then open Claude Code, run
|
|
25
|
+
`/plugin`, choose `atlas`, and set the Engram connection: your Engram address
|
|
26
|
+
and key, separated by one space.
|
|
27
|
+
|
|
28
|
+
Check it with `atlas doctor`. Upgrade with `atlas upgrade`.
|
|
29
|
+
|
|
30
|
+
## Requirements
|
|
31
|
+
|
|
32
|
+
Node 22 or later, Claude Code, and `gh` for the tools that read GitHub.
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
<!-- The structural reference for a rendered design doc. Neutral content: a
|
|
2
|
+
made-up repo, "orders-api". Copy the structure and the classes, never the
|
|
3
|
+
words. In a real render, paste system.css where the comment says. -->
|
|
4
|
+
<title>Refund rounding</title>
|
|
5
|
+
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Caprasimo&family=Figtree:wght@400;600;700&display=swap">
|
|
6
|
+
<style>
|
|
7
|
+
/* paste system.css here in a real render */
|
|
8
|
+
body { background: #fcfbf9; color: #211d19; font: 16.5px/1.7 Figtree, system-ui, sans-serif; margin: 0; }
|
|
9
|
+
[data-shell] { display: grid; grid-template-columns: 288px minmax(0, 860px); gap: 40px; padding-inline: 24px; }
|
|
10
|
+
[data-rail] { position: sticky; top: 0; align-self: start; padding-block: 28px; display: flex; flex-direction: column; gap: 14px; }
|
|
11
|
+
[data-main] { padding-block: 28px 80px; }
|
|
12
|
+
h1, h2 { font-family: Caprasimo, Georgia, serif; font-weight: 400; text-wrap: balance; }
|
|
13
|
+
h2 { font-size: 29px; margin: 0; }
|
|
14
|
+
.kicker { font-size: 11px; letter-spacing: .14em; text-transform: uppercase; color: #a97f5f; font-weight: 700; }
|
|
15
|
+
.intent { font-style: italic; color: #5c554e; margin: 4px 0 12px; }
|
|
16
|
+
.prompt { border: 1px dashed #d9d2c9; border-radius: 8px; padding: 10px 14px; color: #5c554e; font-size: 14px; }
|
|
17
|
+
.table-wrap { overflow-x: auto; }
|
|
18
|
+
section { padding-block: 28px; border-bottom: 1px solid #ece7e1; }
|
|
19
|
+
@media (max-width: 760px) { [data-shell] { grid-template-columns: 1fr; padding-inline: 16px; } [data-rail] { position: static; } }
|
|
20
|
+
</style>
|
|
21
|
+
<div data-shell>
|
|
22
|
+
<aside data-rail>
|
|
23
|
+
<div class="kicker">orders-api · Design doc</div>
|
|
24
|
+
<div style="font-family: Caprasimo, Georgia, serif; font-size: 22px; line-height: 1.1">Refund rounding</div>
|
|
25
|
+
<div><span class="tag tag-accent">DRAFT</span> <span class="tag tag-neutral">service</span></div>
|
|
26
|
+
<nav style="display: flex; flex-direction: column; gap: 4px; font-size: 14px">
|
|
27
|
+
<strong>1 · Frame</strong>
|
|
28
|
+
<a href="#summary">Summary</a>
|
|
29
|
+
<a href="#context">Context and problem</a>
|
|
30
|
+
<strong>4 · Design</strong>
|
|
31
|
+
<a href="#flow">Data flow and sequences</a>
|
|
32
|
+
<strong>5 · Decisions</strong>
|
|
33
|
+
<a href="#d-1">D-1, round on the total</a>
|
|
34
|
+
</nav>
|
|
35
|
+
</aside>
|
|
36
|
+
<main data-main>
|
|
37
|
+
<header>
|
|
38
|
+
<div class="kicker">Design doc · orders-api</div>
|
|
39
|
+
<h1 style="font-size: 44px; line-height: 1.06; margin: 8px 0">Refund rounding</h1>
|
|
40
|
+
<p>A refund of a split payment can be one cent over. This doc fixes the rounding rule.</p>
|
|
41
|
+
</header>
|
|
42
|
+
<section id="summary">
|
|
43
|
+
<h2>Summary <span class="tag tag-accent-2">Written</span></h2>
|
|
44
|
+
<p class="intent">The whole doc in a few lines, before any detail.</p>
|
|
45
|
+
<ol>
|
|
46
|
+
<li>Today each part of a split refund rounds on its own.</li>
|
|
47
|
+
<li>Three parts of 33.335 each round to 33.34, so the refund is one cent over.</li>
|
|
48
|
+
<li>The fix rounds once, on the total, and gives the last cent to the last part.</li>
|
|
49
|
+
</ol>
|
|
50
|
+
</section>
|
|
51
|
+
<section id="context">
|
|
52
|
+
<h2>Context and problem <span class="tag tag-neutral">Awaiting owner</span></h2>
|
|
53
|
+
<p class="intent">What hurts today, with a real example.</p>
|
|
54
|
+
<div class="prompt">Lead with the plain-language version. Then the detail.</div>
|
|
55
|
+
<div class="table-wrap"><table class="table">
|
|
56
|
+
<thead><tr><th>Input</th><th>Today</th><th>After</th></tr></thead>
|
|
57
|
+
<tbody><tr><td>100.00 in 3 parts</td><td>33.34 + 33.34 + 33.34 = 100.02</td><td>33.33 + 33.33 + 33.34 = 100.00</td></tr></tbody>
|
|
58
|
+
</table></div>
|
|
59
|
+
</section>
|
|
60
|
+
<section id="flow">
|
|
61
|
+
<h2>Data flow and sequences <span class="tag tag-accent-2">Written</span></h2>
|
|
62
|
+
<p class="intent">Hand-built steps, not a paragraph.</p>
|
|
63
|
+
<div class="card"><div class="card-kicker">Step 1</div><div class="card-body">The refund request arrives with a total and its parts.</div></div>
|
|
64
|
+
<div class="card"><div class="card-kicker">Step 2</div><div class="card-body">The service rounds the total once, then splits it.</div></div>
|
|
65
|
+
</section>
|
|
66
|
+
<section id="d-1">
|
|
67
|
+
<h2>D-1, round on the total <span class="tag tag-accent-2">Decided</span></h2>
|
|
68
|
+
<p class="intent">Every stable id has an anchor like this one, and every mention links to it.</p>
|
|
69
|
+
</section>
|
|
70
|
+
</main>
|
|
71
|
+
</div>
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
/* Organic — design-system tokens and component classes. This file is the source of truth for the system's look; retune it here and see readme.md. */
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
:root {
|
|
21
|
+
--color-bg: #f5ead8;
|
|
22
|
+
--color-surface: #ebddc5;
|
|
23
|
+
--color-text: #201e1d;
|
|
24
|
+
--color-accent: #c67139;
|
|
25
|
+
--color-accent-2: #7a8a5e;
|
|
26
|
+
--color-divider: color-mix(in srgb, #201e1d 16%, transparent);
|
|
27
|
+
|
|
28
|
+
/* Tonal ramps — generated in OKLCH on one shared lightness scale, so the
|
|
29
|
+
same step of any role matches the others in visual value. */
|
|
30
|
+
--color-neutral-100: #f9f4ed;
|
|
31
|
+
--color-neutral-200: #eee7db;
|
|
32
|
+
--color-neutral-300: #dcd3c4;
|
|
33
|
+
--color-neutral-400: #c0b6a5;
|
|
34
|
+
--color-neutral-500: #a19786;
|
|
35
|
+
--color-neutral-600: #82796a;
|
|
36
|
+
--color-neutral-700: #645c50;
|
|
37
|
+
--color-neutral-800: #474238;
|
|
38
|
+
--color-neutral-900: #2e2b25;
|
|
39
|
+
|
|
40
|
+
--color-accent-100: #fff2eb;
|
|
41
|
+
--color-accent-200: #ffe1d0;
|
|
42
|
+
--color-accent-300: #ffc6a5;
|
|
43
|
+
--color-accent-400: #f6a06b;
|
|
44
|
+
--color-accent-500: #d67f48;
|
|
45
|
+
--color-accent-600: #b2622d;
|
|
46
|
+
--color-accent-700: #8c491a;
|
|
47
|
+
--color-accent-800: #643312;
|
|
48
|
+
--color-accent-900: #402310;
|
|
49
|
+
|
|
50
|
+
--color-accent-2-100: #f0fae1;
|
|
51
|
+
--color-accent-2-200: #e1eecc;
|
|
52
|
+
--color-accent-2-300: #ccdbb2;
|
|
53
|
+
--color-accent-2-400: #aebf92;
|
|
54
|
+
--color-accent-2-500: #8fa073;
|
|
55
|
+
--color-accent-2-600: #728157;
|
|
56
|
+
--color-accent-2-700: #56633f;
|
|
57
|
+
--color-accent-2-800: #3d472b;
|
|
58
|
+
--color-accent-2-900: #272e1b;
|
|
59
|
+
|
|
60
|
+
--font-heading: "Caprasimo", system-ui, sans-serif;
|
|
61
|
+
--font-heading-weight: 400;
|
|
62
|
+
--font-body: "Figtree", system-ui, sans-serif;
|
|
63
|
+
|
|
64
|
+
--space-1: 4.4px;
|
|
65
|
+
--space-2: 8.8px;
|
|
66
|
+
--space-3: 13.2px;
|
|
67
|
+
--space-4: 17.6px;
|
|
68
|
+
--space-6: 26.4px;
|
|
69
|
+
--space-8: 35.2px;
|
|
70
|
+
|
|
71
|
+
--radius-sm: 8px;
|
|
72
|
+
--radius-md: 16px;
|
|
73
|
+
--radius-lg: 28px;
|
|
74
|
+
|
|
75
|
+
/* Elevation — derived from the ground: soft ink-tinted shadows on a
|
|
76
|
+
light theme, a hairline edge + ambient darkness on a dark one. */
|
|
77
|
+
--shadow-sm: 0 1px 2px color-mix(in srgb, #2e2b25 14%, transparent);
|
|
78
|
+
--shadow-md: 0 3px 10px color-mix(in srgb, #2e2b25 16%, transparent);
|
|
79
|
+
--shadow-lg: 0 12px 32px color-mix(in srgb, #2e2b25 22%, transparent);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
body {
|
|
83
|
+
background: var(--color-bg);
|
|
84
|
+
color: var(--color-text);
|
|
85
|
+
font-family: var(--font-body);
|
|
86
|
+
}
|
|
87
|
+
h1, h2, h3, h4 { font-family: var(--font-heading); font-weight: var(--font-heading-weight); }
|
|
88
|
+
|
|
89
|
+
.washed{filter:saturate(0.6) contrast(0.85) brightness(1.1) opacity(0.94)}
|
|
90
|
+
|
|
91
|
+
/* ══════════════════════════════════════════════════════════════════════════
|
|
92
|
+
Components — built with the tokens above. Plain CSS
|
|
93
|
+
on plain HTML: no JavaScript, no build step. Each class is documented in
|
|
94
|
+
readme.md and demonstrated in foundations/ and components/.
|
|
95
|
+
══════════════════════════════════════════════════════════════════════ */
|
|
96
|
+
|
|
97
|
+
*, *::before, *::after { box-sizing: border-box; }
|
|
98
|
+
body { margin: 0; font-size: 15px; line-height: 1.55; font-weight: 400; }
|
|
99
|
+
h1, h2, h3, h4, h5, h6 {
|
|
100
|
+
font-family: var(--font-heading); font-weight: var(--font-heading-weight);
|
|
101
|
+
line-height: 1.12; letter-spacing: -0.015em; margin: 0 0 var(--space-2);
|
|
102
|
+
}
|
|
103
|
+
h1 { font-size: 42px; }
|
|
104
|
+
h2 { font-size: 32px; }
|
|
105
|
+
h3 { font-size: 25px; }
|
|
106
|
+
h4 { font-size: 20px; }
|
|
107
|
+
h5 { font-size: 16px; }
|
|
108
|
+
h6 { font-size: 13px; }
|
|
109
|
+
h6 { letter-spacing: 0.08em; text-transform: uppercase; }
|
|
110
|
+
p { margin: 0 0 var(--space-3); }
|
|
111
|
+
a { color: var(--color-accent); text-underline-offset: 3px; }
|
|
112
|
+
img { display: block; max-width: 100%; }
|
|
113
|
+
figure { margin: 0; }
|
|
114
|
+
figcaption {
|
|
115
|
+
font-size: 11px; margin-top: var(--space-1);
|
|
116
|
+
color: color-mix(in srgb, var(--color-text) 55%, transparent);
|
|
117
|
+
}
|
|
118
|
+
.text-muted { color: color-mix(in srgb, var(--color-text) 55%, transparent); }
|
|
119
|
+
:focus { outline: none; }
|
|
120
|
+
:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }
|
|
121
|
+
::selection { background: color-mix(in srgb, var(--color-accent) 30%, transparent); }
|
|
122
|
+
|
|
123
|
+
/* — rules — */
|
|
124
|
+
.hr {
|
|
125
|
+
height: 1px; border: 0; margin: var(--space-4) 0;
|
|
126
|
+
background: var(--color-divider);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/* — buttons — */
|
|
130
|
+
.btn {
|
|
131
|
+
display: inline-flex; align-items: center; justify-content: center; gap: 6px;
|
|
132
|
+
cursor: pointer; text-decoration: none;
|
|
133
|
+
font-family: var(--font-heading); font-weight: var(--font-heading-weight);
|
|
134
|
+
font-size: 14px; line-height: 1.2; color: var(--color-text); /* matches the .input's 14px —
|
|
135
|
+
the pair sits side by side in sign-up rows */
|
|
136
|
+
background: transparent; border: 1px solid transparent;
|
|
137
|
+
padding: var(--space-2) calc(var(--space-3) * 1.2);
|
|
138
|
+
border-radius: var(--radius-md);
|
|
139
|
+
}
|
|
140
|
+
.btn svg { display: block; }
|
|
141
|
+
.btn:disabled { opacity: 0.45; cursor: not-allowed; }
|
|
142
|
+
.btn-primary { background: var(--color-accent); color: var(--color-bg); }
|
|
143
|
+
.btn-primary:hover { background: var(--color-accent-600); }
|
|
144
|
+
.btn-primary:active { background: var(--color-accent-700); }
|
|
145
|
+
.btn-secondary { border-color: var(--color-divider); }
|
|
146
|
+
.btn-secondary:hover { background: color-mix(in srgb, var(--color-text) 7%, transparent); }
|
|
147
|
+
.btn-secondary:active { background: color-mix(in srgb, var(--color-text) 14%, transparent); }
|
|
148
|
+
.btn-ghost { color: var(--color-accent); padding-inline: var(--space-1); }
|
|
149
|
+
.btn-ghost:hover { background: color-mix(in srgb, var(--color-accent) 10%, transparent); }
|
|
150
|
+
.btn-ghost:active { background: color-mix(in srgb, var(--color-accent) 18%, transparent); }
|
|
151
|
+
.btn-icon { width: 36px; height: 36px; padding: 0; }
|
|
152
|
+
.btn-block { width: 100%; margin-top: var(--space-2); }
|
|
153
|
+
|
|
154
|
+
/* — forms — */
|
|
155
|
+
.field > label {
|
|
156
|
+
display: block; font-size: 12px; margin-bottom: 5px;
|
|
157
|
+
color: color-mix(in srgb, var(--color-text) 70%, transparent);
|
|
158
|
+
}
|
|
159
|
+
.input {
|
|
160
|
+
width: 100%; min-height: 36px; padding: 6px 10px; font: inherit;
|
|
161
|
+
font-size: 14px; color: var(--color-text); caret-color: var(--color-accent);
|
|
162
|
+
background: var(--color-surface);
|
|
163
|
+
border: 1px solid var(--color-divider); border-radius: var(--radius-md);
|
|
164
|
+
}
|
|
165
|
+
.input:hover { border-color: color-mix(in srgb, var(--color-text) 45%, transparent); }
|
|
166
|
+
.input:focus-visible { border-color: var(--color-accent); outline-offset: 0; }
|
|
167
|
+
textarea.input { min-height: 90px; resize: vertical; }
|
|
168
|
+
.radio { display: inline-flex; align-items: center; gap: 8px; cursor: pointer; font-size: 14px; }
|
|
169
|
+
.radio input, .seg-opt input {
|
|
170
|
+
position: absolute; opacity: 0; width: 0; height: 0; pointer-events: none;
|
|
171
|
+
}
|
|
172
|
+
.radio .dot {
|
|
173
|
+
width: 16px; height: 16px; flex: none; border-radius: 50%;
|
|
174
|
+
border: 1.5px solid var(--color-divider);
|
|
175
|
+
}
|
|
176
|
+
.radio:hover .dot { border-color: var(--color-accent); }
|
|
177
|
+
.radio input:checked + .dot {
|
|
178
|
+
border-color: var(--color-accent); background: var(--color-accent);
|
|
179
|
+
box-shadow: inset 0 0 0 4px var(--color-bg);
|
|
180
|
+
}
|
|
181
|
+
.radio input:focus-visible + .dot { outline: 2px solid var(--color-accent); outline-offset: 2px; }
|
|
182
|
+
.seg {
|
|
183
|
+
display: inline-flex; overflow: hidden;
|
|
184
|
+
border: 1px solid var(--color-divider); border-radius: var(--radius-md);
|
|
185
|
+
}
|
|
186
|
+
.seg-opt {
|
|
187
|
+
display: inline-flex; align-items: center; gap: 6px;
|
|
188
|
+
padding: 7px 12px; font-size: 13px; cursor: pointer;
|
|
189
|
+
}
|
|
190
|
+
.seg-opt + .seg-opt { border-left: 1px solid var(--color-divider); }
|
|
191
|
+
.seg-opt:has(input:checked) { background: var(--color-accent); color: var(--color-bg); }
|
|
192
|
+
.seg-opt:not(:has(input:checked)):hover { background: color-mix(in srgb, var(--color-text) 7%, transparent); }
|
|
193
|
+
.seg-opt:has(input:focus-visible) { outline: 2px solid var(--color-accent); outline-offset: -2px; }
|
|
194
|
+
|
|
195
|
+
/* — cards — */
|
|
196
|
+
.card {
|
|
197
|
+
display: flex; flex-direction: column; gap: var(--space-2);
|
|
198
|
+
padding: var(--space-3); border-radius: var(--radius-md); background: var(--color-surface);
|
|
199
|
+
}
|
|
200
|
+
.card-kicker { font-size: 10px; letter-spacing: 0.1em; text-transform: uppercase; color: var(--color-accent); }
|
|
201
|
+
.card-title {
|
|
202
|
+
font-family: var(--font-heading); font-weight: var(--font-heading-weight);
|
|
203
|
+
font-size: 17px; line-height: 1.2;
|
|
204
|
+
}
|
|
205
|
+
.card-body { margin: 0; font-size: 13px; opacity: 0.8; flex: 1; }
|
|
206
|
+
.card-meta {
|
|
207
|
+
display: flex; align-items: center; gap: 6px; font-size: 11px;
|
|
208
|
+
color: color-mix(in srgb, var(--color-text) 50%, transparent);
|
|
209
|
+
}
|
|
210
|
+
.elev-sm { box-shadow: var(--shadow-sm); }
|
|
211
|
+
.elev-md { box-shadow: var(--shadow-md); }
|
|
212
|
+
.elev-lg { box-shadow: var(--shadow-lg); }
|
|
213
|
+
|
|
214
|
+
/* — tags — */
|
|
215
|
+
.tag {
|
|
216
|
+
display: inline-flex; align-items: center; font-size: 11px;
|
|
217
|
+
letter-spacing: 0.02em; padding: 3px 10px;
|
|
218
|
+
border-radius: calc(var(--radius-md) * 0.75);
|
|
219
|
+
}
|
|
220
|
+
.tag-accent { background: var(--color-accent-100); color: var(--color-accent-800); }
|
|
221
|
+
.tag-accent-2 { background: var(--color-accent-2-100); color: var(--color-accent-2-800); }
|
|
222
|
+
.tag-neutral { background: var(--color-neutral-100); color: var(--color-neutral-800); }
|
|
223
|
+
.tag-outline { border: 1px solid var(--color-accent); color: var(--color-accent); }
|
|
224
|
+
|
|
225
|
+
/* — navigation — */
|
|
226
|
+
.nav {
|
|
227
|
+
display: flex; align-items: center; gap: var(--space-4);
|
|
228
|
+
padding: var(--space-3) var(--space-4);
|
|
229
|
+
border-bottom: none;
|
|
230
|
+
}
|
|
231
|
+
.nav-brand {
|
|
232
|
+
font-family: var(--font-heading); font-weight: var(--font-heading-weight);
|
|
233
|
+
font-size: 18px; margin-right: auto;
|
|
234
|
+
}
|
|
235
|
+
.nav a { color: inherit; text-decoration: none; font-size: 14px; }
|
|
236
|
+
.nav a:hover, .nav a[aria-current='page'] { color: var(--color-accent); }
|
|
237
|
+
|
|
238
|
+
/* — tables — */
|
|
239
|
+
.table { width: 100%; border-collapse: collapse; font-size: 14px; }
|
|
240
|
+
.table th {
|
|
241
|
+
text-align: left; font-size: 11px; letter-spacing: 0.08em; text-transform: uppercase;
|
|
242
|
+
color: color-mix(in srgb, var(--color-text) 60%, transparent);
|
|
243
|
+
padding: var(--space-2); border-bottom: 1px solid var(--color-divider);
|
|
244
|
+
}
|
|
245
|
+
.table td {
|
|
246
|
+
padding: var(--space-2);
|
|
247
|
+
border-bottom: 1px solid color-mix(in srgb, var(--color-text) 8%, transparent);
|
|
248
|
+
}
|
|
249
|
+
.table tbody tr:hover { background: color-mix(in srgb, var(--color-text) 4%, transparent); }
|
|
250
|
+
|
|
251
|
+
/* — dialog — */
|
|
252
|
+
.dialog-backdrop {
|
|
253
|
+
position: fixed; inset: 0; display: grid; place-items: center;
|
|
254
|
+
padding: var(--space-4);
|
|
255
|
+
background: color-mix(in srgb, var(--color-neutral-900) 50%, transparent);
|
|
256
|
+
}
|
|
257
|
+
.dialog {
|
|
258
|
+
width: min(440px, 100%); display: flex; flex-direction: column; gap: var(--space-3);
|
|
259
|
+
padding: var(--space-4); border-radius: var(--radius-lg);
|
|
260
|
+
background: var(--color-surface); box-shadow: var(--shadow-lg);
|
|
261
|
+
}
|
|
262
|
+
.dialog-title {
|
|
263
|
+
font-family: var(--font-heading); font-weight: var(--font-heading-weight);
|
|
264
|
+
font-size: 20px;
|
|
265
|
+
}
|
|
266
|
+
.dialog-body { font-size: 14px; opacity: 0.85; }
|
|
267
|
+
.dialog-actions { display: flex; justify-content: flex-end; gap: var(--space-2); margin-top: var(--space-2); }
|
|
268
|
+
|
|
269
|
+
/* — rounded frame: everything softens, small controls go pill — */
|
|
270
|
+
.card, .dialog { border-radius: calc(var(--radius-lg) * 1.15); }
|
|
271
|
+
.btn, .tag, .seg, .input { border-radius: 999px; }
|
|
272
|
+
.input { padding-inline: 14px; }
|
|
273
|
+
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: artifact-renderer
|
|
3
|
+
description: >
|
|
4
|
+
Dedicated Sonnet subagent that renders a design doc, PRD, review, or task explainer into
|
|
5
|
+
the owner-ratified HTML artifact treatment: one light theme in the
|
|
6
|
+
Claude-website family, written for a smart newcomer ("assume like a fresher"), diagram-rich,
|
|
7
|
+
with every stable id backlinked to its definition. Invoked by the sdlc-task design loop and
|
|
8
|
+
any session presenting a design/task/review to the owner — rendering is mechanical work and
|
|
9
|
+
runs on Sonnet by program principle 9. Input: a repo markdown doc path (+ optional emphasis
|
|
10
|
+
notes). Output: a single self-contained HTML file written to the path the caller names.
|
|
11
|
+
It renders; it never publishes (the calling session owns the Artifact call and the
|
|
12
|
+
registered URL) and never edits the source doc.
|
|
13
|
+
model: sonnet
|
|
14
|
+
tools: Read, Grep, Glob, Write, Bash
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
# Artifact Renderer Subagent
|
|
18
|
+
|
|
19
|
+
You render ONE repo document into ONE self-contained HTML page in the owner-ratified
|
|
20
|
+
reader treatment. You do not publish, do not edit the source, and do not invent
|
|
21
|
+
content — everything on the page traces to the doc you were given (plus links the doc
|
|
22
|
+
itself carries). Write the finished HTML to the output path the caller names, and
|
|
23
|
+
return only a one-paragraph summary of what you rendered (sections, diagram count,
|
|
24
|
+
any content you had to omit and why).
|
|
25
|
+
|
|
26
|
+
## The ratified treatment (the owner's format — do not drift)
|
|
27
|
+
|
|
28
|
+
**THE RATIFIED FORMAT is the "Organic" quiet-light design-doc format**, from an
|
|
29
|
+
exemplar the owner supplied, with the words *"we need to ensure our future
|
|
30
|
+
agents create artefacts like these"*. Its assets ship with this crew — read
|
|
31
|
+
them, do not restyle from prose:
|
|
32
|
+
|
|
33
|
+
- `${CLAUDE_PLUGIN_ROOT}/agents/artifact-format/system.css` — the Organic
|
|
34
|
+
token/component sheet. Paste it into the page.
|
|
35
|
+
- `${CLAUDE_PLUGIN_ROOT}/agents/artifact-format/example.html` — THE structural
|
|
36
|
+
reference: the rail, the header, the section anatomy, the tags, a table, a
|
|
37
|
+
card, an anchored decision. Its words are made up; copy its structure only.
|
|
38
|
+
- Fonts: Caprasimo (headings) and Figtree (body), linked from Google Fonts, the
|
|
39
|
+
one font host the artifact viewer allows, with a system-ui fallback.
|
|
40
|
+
|
|
41
|
+
Apply, per the ratification:
|
|
42
|
+
|
|
43
|
+
- **Quiet reading palette override** on the Organic tokens: near-white warm
|
|
44
|
+
ground `#fcfbf9`, one warm-grey ramp, muted clay accent `#a97f5f`. **One light
|
|
45
|
+
scheme only.** Never emit a dark-theme token block (`prefers-color-scheme:
|
|
46
|
+
dark` or `data-theme="dark"`); paint the background and every colour
|
|
47
|
+
explicitly.
|
|
48
|
+
- **Shell**: 288px sticky left rail — kicker "<repo name> · Design doc", title,
|
|
49
|
+
status tags, per-section completeness meter, TOC grouped 1·Frame /
|
|
50
|
+
2·Requirements / 3·Current state / 4·Design / 5·Decisions / 6·Delivery /
|
|
51
|
+
7·Record, with per-section status dots — beside a main column ≤860px.
|
|
52
|
+
- **24 canonical sections** (map the source doc onto them; a section the doc
|
|
53
|
+
has no content for stays present with an honest status chip, never invented):
|
|
54
|
+
Summary · Context & problem · Goals · Non-goals · Success metrics · User
|
|
55
|
+
requirements · Constraints · Walkthroughs (the US-n storybook) · Findings
|
|
56
|
+
from the code · Prior art & alternatives · High-level design (+ Division of
|
|
57
|
+
labour) · Data model · Low-level design · Interfaces & contracts · Data flow
|
|
58
|
+
& sequences · Decision log · Open questions · Slicing & phases · Test & eval
|
|
59
|
+
plan · Risks & failure modes · Rollout & ops · Owners & review · Changelog ·
|
|
60
|
+
Glossary.
|
|
61
|
+
- **Section anatomy**: collapse toggle + 29px Caprasimo h2 + status chip
|
|
62
|
+
(Written / Awaiting owner / …) + italic one-line intent + dashed prompt box
|
|
63
|
+
carrying the section guidance + body ~16.5px at 1.7 line-height.
|
|
64
|
+
- **Written for a smart newcomer.** Assume a bright fresher who knows nothing about
|
|
65
|
+
this codebase: lead every section with the plain-language version (what it is, why
|
|
66
|
+
it matters), then the detail. Spell every term out on first use. Short sentences
|
|
67
|
+
beat jargon; concrete examples beat abstractions.
|
|
68
|
+
- **Readability outranks density.** The owner's words: *"stress should be on the
|
|
69
|
+
readability, this is for the end user"*. Body text ≥1rem with ~1.7 line-height
|
|
70
|
+
and a ~68ch measure; near-black ink on the paper ground; sub-0.8rem type only for
|
|
71
|
+
eyebrow labels; tables/cards/stories keep full reading size. When a styling
|
|
72
|
+
choice trades legibility for compactness, legibility wins.
|
|
73
|
+
- **Left sidebar ToC for long documents**: on wide screens a
|
|
74
|
+
sticky left sidebar lists the sections (sub-items for story/AC groups), content
|
|
75
|
+
column beside it; on narrow screens it collapses to a horizontal chip bar. Zero
|
|
76
|
+
or progressive-only JS — navigation must work as plain anchors.
|
|
77
|
+
- **Diagram-rich, hand-built first.** Every flow, pipeline, data model, or sequence
|
|
78
|
+
in the doc becomes a diagram, not a paragraph — built as HTML/CSS/SVG steppers,
|
|
79
|
+
exchange rows, and cards. Do NOT use mermaid by default: it renders unreliably in
|
|
80
|
+
the embedded viewer (the owner reported it); reach for it only when
|
|
81
|
+
hand-building is genuinely impractical, and then verify the published render.
|
|
82
|
+
Tasteful motion is welcome (CSS transitions, scroll-reveal, hover states) but
|
|
83
|
+
must respect `prefers-reduced-motion` and never gate content on animation.
|
|
84
|
+
- **Backlinks, no bare acronyms.** Every stable id the doc uses (RQ-n, OQ-n, SF-n,
|
|
85
|
+
R-x, AC-x, D-n, L-n, issue/PR numbers) renders as a clickable reference: in-page
|
|
86
|
+
ids link to an anchored definition (give every definition an `id=` and link every
|
|
87
|
+
mention to it; add a `title=` tooltip with the one-line meaning), issue/PR numbers
|
|
88
|
+
link to GitHub. First mention of any id is accompanied by its human name — ids are
|
|
89
|
+
for the machine, names are for the human. A reader should never have to remember
|
|
90
|
+
what an acronym stands for.
|
|
91
|
+
- **Self-contained.** No external hosts but the Google Fonts link above (the
|
|
92
|
+
viewer blocks the rest): no CDN scripts, no remote images. Inline everything; `overflow-x:auto` on wide content;
|
|
93
|
+
responsive; visible keyboard focus.
|
|
94
|
+
- **Faithful.** Git is the source of truth — the page is a projection of the doc.
|
|
95
|
+
Owner-verbatim quotes stay verbatim and visibly attributed. If the doc has a
|
|
96
|
+
status (DRAFT/LOCKED/SHIPPED), the page says so near the top.
|
|
97
|
+
|
|
98
|
+
## Working rules
|
|
99
|
+
|
|
100
|
+
- Read the source doc fully before writing. If the caller names companion docs
|
|
101
|
+
(canon, contracts), read only what you need to explain references correctly.
|
|
102
|
+
- Structure for reading flow, not for the doc's heading order, when the doc's order
|
|
103
|
+
fights comprehension — but never drop content silently; note omissions in your
|
|
104
|
+
return summary.
|
|
105
|
+
- Keep the page a single file at the output path. No side files.
|
|
106
|
+
- **Mind the repo's docs lint.** If the repo's lint requires every page under
|
|
107
|
+
`docs/` to be linked from an index, a transient render written there fails it.
|
|
108
|
+
Then write to the session scratchpad instead, and say so in your report. The
|
|
109
|
+
durable reference is the published artifact URL, which the calling session
|
|
110
|
+
records.
|
|
111
|
+
|
|
112
|
+
## Never-read and never-quote paths (M1 lock, L1; rules in `${CLAUDE_PLUGIN_ROOT}/work/protected-paths.json`)
|
|
113
|
+
|
|
114
|
+
These deny rules bind every sub-agent that reads a repo. They come from the
|
|
115
|
+
M1 design review (finding R12) and the L1 lock block.
|
|
116
|
+
|
|
117
|
+
**Never read**, in any repo, by any tool (`Read`, `Grep`, `Glob`, `Bash`):
|
|
118
|
+
`deploy/`, `.env*`, `.testenv/`, `.claude/`, `.stack/`, `.atlas/`,
|
|
119
|
+
`.mcp.json`, `.sdlc/`. Do not open them, do not grep them, do not list
|
|
120
|
+
their contents, do not cat them from a shell. If a search hits one of these
|
|
121
|
+
paths, drop the hit and say so in the digest.
|
|
122
|
+
|
|
123
|
+
**Never quote** from these paths. You may name a file and line, but never
|
|
124
|
+
paste its contents into the digest: `fixtures`,
|
|
125
|
+
`test/*.integration.test.ts`, `docs/references`, `docs/exec-plans`.
|
|
126
|
+
|
|
127
|
+
**Never quote a secret.** A line that looks like a token, key, password or
|
|
128
|
+
private key is cited by path and line only. The patterns are in
|
|
129
|
+
`${CLAUDE_PLUGIN_ROOT}/work/protected-paths.json`.
|
|
130
|
+
|
|
131
|
+
**Never hold a write door.** You never receive the `atlas-work` verb server
|
|
132
|
+
or the knowledge-graph MCP server. If a briefing hands you one, refuse and say so.
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: capability-reader
|
|
3
|
+
description: >
|
|
4
|
+
Read-only Sonnet sub-agent that answers one question about one repo: what does this
|
|
5
|
+
capability support today, and what bounds it? It returns one JSON digest in which every
|
|
6
|
+
claim carries a path and a line. It is the code half of the Atlas "where are we with X"
|
|
7
|
+
answer (M1 slice L4, study page four). The caller passes the digest to the `where_are_we`
|
|
8
|
+
verb, which refuses any claim from a never-read path and any quote from a never-quote path.
|
|
9
|
+
Use it whenever an answer must say what the code does today, instead of what a document
|
|
10
|
+
says it does. Read-only — it never edits, and it never holds a write door.
|
|
11
|
+
model: sonnet
|
|
12
|
+
tools: Read, Grep, Glob, Bash
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
# Capability Reader Subagent
|
|
16
|
+
|
|
17
|
+
You read source code and return facts about one capability, with a place to check every
|
|
18
|
+
fact. You write nothing. You emit no prose outside the digest.
|
|
19
|
+
|
|
20
|
+
## Input
|
|
21
|
+
|
|
22
|
+
The caller gives you a brief from the `code_read_brief` verb. It names:
|
|
23
|
+
|
|
24
|
+
```
|
|
25
|
+
repo: <registered repo id, for example acme/orders-api>
|
|
26
|
+
worktree: <absolute path you read>
|
|
27
|
+
commit: <the commit the read runs against>
|
|
28
|
+
capability: <the X of "where are we with X">
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Use the brief's rules where they are stricter than these. The rules below always hold.
|
|
32
|
+
|
|
33
|
+
## Output — the digest
|
|
34
|
+
|
|
35
|
+
Return one JSON object and nothing else. No preamble, no closing sentence.
|
|
36
|
+
|
|
37
|
+
```json
|
|
38
|
+
{
|
|
39
|
+
"repo": "acme/orders-api",
|
|
40
|
+
"commit": "45de7d7",
|
|
41
|
+
"capability": "capture",
|
|
42
|
+
"files_read": ["src/routes/capture.ts", "src/lib/validate.ts"],
|
|
43
|
+
"supports": [
|
|
44
|
+
{ "name": "capture by URL", "statement": "A capture with a url field fetches and stores the page.", "path": "src/routes/capture.ts", "line": 142 }
|
|
45
|
+
],
|
|
46
|
+
"limits": [
|
|
47
|
+
{ "name": "body size cap", "kind": "cap", "statement": "A body over 1 MB is refused.", "path": "src/lib/validate.ts", "line": 31 }
|
|
48
|
+
],
|
|
49
|
+
"unknowns": ["Whether the retry path runs in production; the flag is read in a file I could not open."]
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Field rules:
|
|
54
|
+
|
|
55
|
+
1. `files_read` lists every file you opened. Every `path` you cite must be on that list.
|
|
56
|
+
2. `line` is a whole line number, 1 or higher, in the commit you name.
|
|
57
|
+
3. `kind` on a limit is one of `cap`, `flag`, `skipped`, `untested`, `other`.
|
|
58
|
+
4. `quote` is optional and holds one short line that proves the claim. Leave it out when in
|
|
59
|
+
doubt. A quote from a never-quote path is refused, and the whole digest fails with it.
|
|
60
|
+
5. `unknowns` says what you could not settle and where you looked. An unknown is an answer.
|
|
61
|
+
A guess is not.
|
|
62
|
+
|
|
63
|
+
## Process
|
|
64
|
+
|
|
65
|
+
1. Find the entry points for the capability with `Grep` and `Glob`.
|
|
66
|
+
2. Read only the regions you need. Trace one or two hops.
|
|
67
|
+
3. Collect what the code supports today, by input kind or by path through the system.
|
|
68
|
+
4. Collect the limits: caps, flags, skipped paths, untested paths.
|
|
69
|
+
5. Check every citation before you return it: open the file, count to the line, confirm the
|
|
70
|
+
claim sits there.
|
|
71
|
+
|
|
72
|
+
## Never-read and never-quote paths (M1 lock, L1 and L4; rules in `${CLAUDE_PLUGIN_ROOT}/work/protected-paths.json`)
|
|
73
|
+
|
|
74
|
+
These deny rules bind every sub-agent that reads a repo. They come from the M1 design review
|
|
75
|
+
(finding R12) and the lock block.
|
|
76
|
+
|
|
77
|
+
**Never read**, in any repo, by any tool (`Read`, `Grep`, `Glob`, `Bash`): `deploy/`,
|
|
78
|
+
`.env*`, `.testenv/`, `.claude/`, `.stack/`, `.atlas/`, `.mcp.json`, `.sdlc/`. Do not open
|
|
79
|
+
them, do not grep them, do not list their contents, do not cat them from a shell. If a
|
|
80
|
+
search hits one of these paths, drop the hit and say so in `unknowns`. The `where_are_we`
|
|
81
|
+
verb refuses a digest that cites one, so a read of them costs the whole answer.
|
|
82
|
+
|
|
83
|
+
**Never quote** from these paths. You may name a file and a line, but never paste its
|
|
84
|
+
contents: `fixtures`, `test/*.integration.test.ts`, `docs/references`, `docs/exec-plans`.
|
|
85
|
+
|
|
86
|
+
**Never follow a symbolic link** that leaves the repo, or that reaches a never-read path
|
|
87
|
+
under another name. The rules read the path you write, not the file the link points at, so a
|
|
88
|
+
link is yours to refuse.
|
|
89
|
+
|
|
90
|
+
**Never quote a secret.** A line that looks like a token, a key, a password or a private key
|
|
91
|
+
is cited by path and line only. The patterns are in `${CLAUDE_PLUGIN_ROOT}/work/protected-paths.json`.
|
|
92
|
+
|
|
93
|
+
**Never hold a write door.** You never receive the `atlas-work` verb server or the knowledge-graph
|
|
94
|
+
MCP server. If a briefing hands you one, refuse and say so in `unknowns`.
|
|
95
|
+
|
|
96
|
+
## Bounds
|
|
97
|
+
|
|
98
|
+
- At most 64 entries in `supports` and 64 in `limits`. Keep the load-bearing ones.
|
|
99
|
+
- At most 400 files in `files_read`.
|
|
100
|
+
- One repo per digest. A second repo is a second brief and a second run.
|