@arjunkhera/atlas 0.2.3 → 0.3.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 +1 -1
- package/README.md +14 -8
- package/agents/artifact-renderer.md +6 -1
- package/agents/capability-reader.md +1 -1
- package/agents/code-explorer.md +1 -1
- package/agents/reviewer-architect.md +1 -1
- package/agents/reviewer-pm.md +1 -1
- package/agents/reviewer-security.md +1 -1
- package/agents/verifier.md +97 -0
- package/door/cli.mjs +33 -108
- package/door/lib/kind-drift.mjs +16 -6
- package/door/lib/privacy.mjs +61 -0
- package/door/lib/pull-request.mjs +55 -56
- package/door/lib/ste-words.json +51 -0
- package/door/lib/ste.mjs +199 -0
- package/door/lib/tooling.mjs +2 -2
- package/package.json +1 -1
- package/shape/check.mjs +33 -33
- package/shape/releases.json +5 -0
- package/skills/feedback/SKILL.md +39 -0
- package/skills/lead/SKILL.md +103 -0
- package/skills/learnings/SKILL.md +48 -0
- package/skills/repo-skills/SKILL.md +64 -0
- package/skills/sdlc-task/SKILL.md +54 -67
- package/skills/sdlc-task/lifecycle.yaml +5 -3
- package/skills/sdlc-task/templates/design-doc.md +22 -17
- package/work/lib/delivery.mjs +12 -6
- package/work/lib/verb-fields.mjs +31 -0
- package/work/lib/verbs.mjs +16 -15
- package/work/{manifest-0.5.0.json → manifest-0.6.0.json} +9 -3
- package/work/mcp.mjs +5 -4
- package/work/protected-paths.json +4 -2
- package/door/lib/helpers.mjs +0 -139
- package/door/lib/onboarding.mjs +0 -130
package/shape/check.mjs
CHANGED
|
@@ -29,12 +29,12 @@ export const sha256 = (text) => createHash('sha256').update(String(text ?? ''),
|
|
|
29
29
|
// The version of this check, as a whole number. It moves only when this file's
|
|
30
30
|
// own code changes, never with the Atlas package version (row F11, amendment
|
|
31
31
|
// A1.9). A release of Atlas that leaves the check alone leaves every repo's copy
|
|
32
|
-
// current, so the
|
|
32
|
+
// current, so the no-loss rule's check-file case does not fire on every release.
|
|
33
33
|
//
|
|
34
34
|
// Whether a copy is current or behind is not decided here. CI has no package
|
|
35
35
|
// and no network. The session verb decides it, from the release list that
|
|
36
36
|
// ships beside this file in the package, shape/releases.json.
|
|
37
|
-
export const CHECK_VERSION =
|
|
37
|
+
export const CHECK_VERSION = 3;
|
|
38
38
|
|
|
39
39
|
// ---------------------------------------------------------------------------
|
|
40
40
|
// The spec. One object per version. The check reads a version it has here and
|
|
@@ -614,7 +614,7 @@ export const WORKFLOW_TEMPLATE = `# The Atlas repo shape check, in this repo's o
|
|
|
614
614
|
#
|
|
615
615
|
# It reports in the docs lane. It never fails a code merge.
|
|
616
616
|
#
|
|
617
|
-
# The second checkout is the
|
|
617
|
+
# The second checkout is the no-loss rule's base tree. The check scores the base
|
|
618
618
|
# commit and the head commit side by side, and it goes red when a part the base
|
|
619
619
|
# already had is taken away. The base tree lands in ${BASE_DIR}, whose name
|
|
620
620
|
# starts with a dot, so no scanner walks into it. If that checkout fails there
|
|
@@ -637,7 +637,7 @@ jobs:
|
|
|
637
637
|
steps:
|
|
638
638
|
# actions/checkout v4.3.1
|
|
639
639
|
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262
|
|
640
|
-
- name: the base commit, for the
|
|
640
|
+
- name: the base commit, for the no-loss rule
|
|
641
641
|
uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262
|
|
642
642
|
continue-on-error: true
|
|
643
643
|
with:
|
|
@@ -1191,24 +1191,24 @@ function workflowStructure(document) {
|
|
|
1191
1191
|
return out;
|
|
1192
1192
|
}
|
|
1193
1193
|
|
|
1194
|
-
// The
|
|
1194
|
+
// The no-loss rule's own two inputs, from slice L2 stage two.
|
|
1195
1195
|
//
|
|
1196
1196
|
// Without them the check still runs, still prints a report, and still goes
|
|
1197
|
-
// green — and the
|
|
1197
|
+
// green — and the no-loss rule never runs at all. That is the same class of hole
|
|
1198
1198
|
// the batch 16 reviewer found nine ways (finding S2-1): a workflow that
|
|
1199
1199
|
// silences the job while the part still reads "filled". Deleting two flags
|
|
1200
1200
|
// is the cheapest version of it, so the scanner reads the flags, not just
|
|
1201
1201
|
// the path.
|
|
1202
1202
|
for (const flag of ['--base', '--base-sha']) {
|
|
1203
1203
|
if (!new RegExp(`${flag}(?:[ \t=]|$)`, 'm').test(found.runs)) {
|
|
1204
|
-
out.push(`the check step does not pass ${flag}, so the
|
|
1204
|
+
out.push(`the check step does not pass ${flag}, so the no-loss rule never runs and a pull request can take a part away with the job still green`);
|
|
1205
1205
|
}
|
|
1206
1206
|
}
|
|
1207
1207
|
// And the tree it compares against has to be fetched by something.
|
|
1208
1208
|
const fetchesBase = Object.values(jobs).some((job) => (Array.isArray(job?.steps) ? job.steps : [])
|
|
1209
1209
|
.some((step) => typeof step?.uses === 'string' && step.uses.startsWith('actions/checkout') && step?.with?.path === BASE_DIR));
|
|
1210
1210
|
if (!fetchesBase) {
|
|
1211
|
-
out.push(`no step checks the base commit out into ${BASE_DIR}, so the
|
|
1211
|
+
out.push(`no step checks the base commit out into ${BASE_DIR}, so the no-loss rule has no tree to compare against`);
|
|
1212
1212
|
}
|
|
1213
1213
|
|
|
1214
1214
|
// A condition switches the step, or its whole job, off. Same effect as a
|
|
@@ -1216,7 +1216,7 @@ function workflowStructure(document) {
|
|
|
1216
1216
|
if (found.step.if !== undefined) out.push('the workflow puts an if: on the check step; the step must always run');
|
|
1217
1217
|
if (found.job.if !== undefined) out.push("the workflow puts an if: on the check's job; the job must always run");
|
|
1218
1218
|
// Two more ways to make a red check look green. Neither is in the frozen
|
|
1219
|
-
// list. Both defeat the same purpose, and stage two's
|
|
1219
|
+
// list. Both defeat the same purpose, and stage two's no-loss rule needs a red job
|
|
1220
1220
|
// to mean something, so the check names them (reviewer of batch 16, S2-1).
|
|
1221
1221
|
if (found.step['continue-on-error'] === true || found.job['continue-on-error'] === true) {
|
|
1222
1222
|
out.push('the workflow sets continue-on-error on the check; a failed check would not turn the job red');
|
|
@@ -1259,7 +1259,7 @@ function checkWorkflow(context, part) {
|
|
|
1259
1259
|
// works for any copy; importing it would only work for this one.
|
|
1260
1260
|
//
|
|
1261
1261
|
// A copy from before row F11 carries no CHECK_VERSION. When it declares a spec,
|
|
1262
|
-
// it still reads as the Atlas check, so the
|
|
1262
|
+
// it still reads as the Atlas check, so the no-loss rule can score a base tree that
|
|
1263
1263
|
// holds an old copy.
|
|
1264
1264
|
export function checkStamps(text) {
|
|
1265
1265
|
const check = /^export const CHECK_VERSION = (\d+);/m.exec(text ?? '');
|
|
@@ -1386,7 +1386,7 @@ export function readFacts(root) {
|
|
|
1386
1386
|
} catch (error) { return { facts: null, error: `atlas.yaml cannot be read: ${error.message}` }; }
|
|
1387
1387
|
}
|
|
1388
1388
|
|
|
1389
|
-
// `scoreAs` is the
|
|
1389
|
+
// `scoreAs` is the no-loss rule's one lever. It replaces the kind and the spec this
|
|
1390
1390
|
// tree declares with the ones handed in, so two trees are scored by the same
|
|
1391
1391
|
// yardstick. Without it the base's `kind: service` and the head's
|
|
1392
1392
|
// `kind: library` would be two different spec tables, and the comparison would
|
|
@@ -1456,17 +1456,17 @@ export function counts(files) {
|
|
|
1456
1456
|
}
|
|
1457
1457
|
|
|
1458
1458
|
// ---------------------------------------------------------------------------
|
|
1459
|
-
// The
|
|
1459
|
+
// The no-loss rule. Milestone M2, slice L2 stage two.
|
|
1460
1460
|
//
|
|
1461
1461
|
// What it is. A pull request may not take away an instruction-class part that
|
|
1462
1462
|
// the base commit already had. Nothing else. It is never red on debt that was
|
|
1463
1463
|
// there before, and it is red on the pull request that made things worse.
|
|
1464
1464
|
//
|
|
1465
|
-
// Why a
|
|
1465
|
+
// Why a no-loss rule and not a level. Turning `fail-on` up to `required` goes red on
|
|
1466
1466
|
// the day it is switched on, for parts a later slice builds. The first repo it
|
|
1467
1467
|
// ran on had seven required parts not filled, four of them a later slice's
|
|
1468
1468
|
// work. A level
|
|
1469
|
-
// asks the repository to be finished. A
|
|
1469
|
+
// asks the repository to be finished. A no-loss rule asks it not to go backwards.
|
|
1470
1470
|
//
|
|
1471
1471
|
// Why per part and never a count. A count is defeated two ways. Empty one part,
|
|
1472
1472
|
// fill another, and the total does not move. Or change one line: `atlas.yaml`
|
|
@@ -1485,9 +1485,9 @@ export function counts(files) {
|
|
|
1485
1485
|
// Where it lives. Here. The repository still carries two files and only two.
|
|
1486
1486
|
// ---------------------------------------------------------------------------
|
|
1487
1487
|
|
|
1488
|
-
// The five cases where the
|
|
1488
|
+
// The five cases where the no-loss rule reports and does not gate. Each is named in
|
|
1489
1489
|
// the report, so a reader never has to guess why the job stayed green.
|
|
1490
|
-
export const
|
|
1490
|
+
export const NO_LOSS_CASES = Object.freeze(['check-file', 'workflow', 'kind', 'spec', 'base-tree']);
|
|
1491
1491
|
|
|
1492
1492
|
const fileHash = (root, path) => { const text = readText(root, path); return text === null ? null : sha256(text); };
|
|
1493
1493
|
|
|
@@ -1517,7 +1517,7 @@ const partIndex = (report) => {
|
|
|
1517
1517
|
return map;
|
|
1518
1518
|
};
|
|
1519
1519
|
|
|
1520
|
-
export function
|
|
1520
|
+
export function noLoss({ headRoot, baseRoot, baseSha = null, repoId = null, secretPatterns: patterns = secretPatterns() }) {
|
|
1521
1521
|
const out = {
|
|
1522
1522
|
ran: true,
|
|
1523
1523
|
gates: true,
|
|
@@ -1639,15 +1639,15 @@ export function toText(report) {
|
|
|
1639
1639
|
lines.push(` ${row.exists ? '+' : '-'} ${row.path} <- ${row.pointed_at_by.join(', ') || 'the entry map only'}${row.exempt ? ' [exempt]' : ''}`);
|
|
1640
1640
|
if (row.exempt_note) lines.push(` - ${row.exempt_note}`);
|
|
1641
1641
|
}
|
|
1642
|
-
if (report.
|
|
1642
|
+
if (report.noLoss) lines.push('', ...noLossLines(report.noLoss));
|
|
1643
1643
|
return `${lines.join('\n')}\n`;
|
|
1644
1644
|
}
|
|
1645
1645
|
|
|
1646
|
-
// The
|
|
1646
|
+
// The no-loss rule, in the CI log. It says which tree it compared against, what it
|
|
1647
1647
|
// compared, and either the parts that went backwards or the case that made it
|
|
1648
1648
|
// report instead of gate.
|
|
1649
|
-
export function
|
|
1650
|
-
const out = ['
|
|
1649
|
+
export function noLossLines(state) {
|
|
1650
|
+
const out = ['No-loss rule: instruction-class parts, base to head.'];
|
|
1651
1651
|
// The sha this check READ from the base tree, never the one it was handed.
|
|
1652
1652
|
// Printing the promise would assert a commit nothing verified.
|
|
1653
1653
|
const read = state.base_head ? state.base_head.slice(0, 12) : 'a commit the tree does not name';
|
|
@@ -1662,7 +1662,7 @@ export function ratchetLines(state) {
|
|
|
1662
1662
|
}
|
|
1663
1663
|
if (!state.regressions.length && state.base_facts) out.push(' no instruction-class part went backwards');
|
|
1664
1664
|
if (!state.gates) {
|
|
1665
|
-
out.push(' this
|
|
1665
|
+
out.push(' this no-loss rule reports and does not gate on this pull request');
|
|
1666
1666
|
// The loudest line in the report, and the one a reader must not miss. The
|
|
1667
1667
|
// frozen text excuses these five cases because a person merges every file
|
|
1668
1668
|
// that causes one. That is a compensating control, not an absence of
|
|
@@ -1696,9 +1696,9 @@ export function toMarkdown(report) {
|
|
|
1696
1696
|
}
|
|
1697
1697
|
out.push('');
|
|
1698
1698
|
}
|
|
1699
|
-
if (report.
|
|
1700
|
-
out.push('###
|
|
1701
|
-
for (const line of
|
|
1699
|
+
if (report.noLoss) {
|
|
1700
|
+
out.push('### The no-loss rule', '');
|
|
1701
|
+
for (const line of noLossLines(report.noLoss).slice(1)) out.push(`- ${line.trim()}`);
|
|
1702
1702
|
out.push('');
|
|
1703
1703
|
}
|
|
1704
1704
|
return `${out.join('\n')}\n`;
|
|
@@ -1710,11 +1710,11 @@ export function toMarkdown(report) {
|
|
|
1710
1710
|
// count. It keeps its three levels and it stays a report line at the shipped
|
|
1711
1711
|
// level.
|
|
1712
1712
|
//
|
|
1713
|
-
// The
|
|
1713
|
+
// The no-loss rule answers "did this pull request take something away?" It is the
|
|
1714
1714
|
// one that can be true on a repository with debt, so it is checked first.
|
|
1715
1715
|
export function verdict(report, failOn) {
|
|
1716
1716
|
if (report.errors.length) return { green: false, why: `the check hit ${report.errors.length} error(s)` };
|
|
1717
|
-
const state = report.
|
|
1717
|
+
const state = report.noLoss;
|
|
1718
1718
|
if (state?.gates && state.regressions.length) {
|
|
1719
1719
|
return { green: false, why: `${state.regressions.length} instruction-class part(s) went backwards against the base: ${state.regressions.map((row) => row.label).join(', ')}` };
|
|
1720
1720
|
}
|
|
@@ -1723,8 +1723,8 @@ export function verdict(report, failOn) {
|
|
|
1723
1723
|
const excused = state && !state.gates && state.regressions.length
|
|
1724
1724
|
? ` — WARNING: ${state.regressions.length} part(s) went backwards and were NOT gated; a person merges this one`
|
|
1725
1725
|
: '';
|
|
1726
|
-
const
|
|
1727
|
-
return { green: true, why: `${report.counts.required_not_filled} required file(s) are not filled; fail-on is "${failOn}"${
|
|
1726
|
+
const noLossWhy = state ? (state.gates ? '; no instruction-class part went backwards' : `; the no-loss rule reported and did not gate (${state.report_only.map((row) => row.case).join(', ')})${excused}`) : '';
|
|
1727
|
+
return { green: true, why: `${report.counts.required_not_filled} required file(s) are not filled; fail-on is "${failOn}"${noLossWhy}` };
|
|
1728
1728
|
}
|
|
1729
1729
|
|
|
1730
1730
|
// ---------------------------------------------------------------------------
|
|
@@ -1744,7 +1744,7 @@ export function parseArguments(argv) {
|
|
|
1744
1744
|
else if (flag === '--json') out.json = resolve(next());
|
|
1745
1745
|
else if (flag === '--summary') out.summary = resolve(next());
|
|
1746
1746
|
else if (flag === '--quiet') out.quiet = true;
|
|
1747
|
-
// The
|
|
1747
|
+
// The no-loss rule's two inputs. `--base` is the directory the workflow checked
|
|
1748
1748
|
// the base commit out into. `--base-sha` is the pull request's base.sha, so
|
|
1749
1749
|
// the check can say the tree it reads is the tree it was promised.
|
|
1750
1750
|
else if (flag === '--base') out.base = resolve(next());
|
|
@@ -1763,10 +1763,10 @@ export function run(argv, env = process.env) {
|
|
|
1763
1763
|
const patterns = secretPatterns();
|
|
1764
1764
|
const report = scan({ root: options.root, repoId, extractors: EXTRACTORS, secretPatterns: patterns });
|
|
1765
1765
|
// No `--base` means no pull request to measure: a push build, or a run by
|
|
1766
|
-
// hand. The
|
|
1766
|
+
// hand. The no-loss rule then does not run at all, and the report says nothing
|
|
1767
1767
|
// about it rather than claiming a pass.
|
|
1768
|
-
report.
|
|
1769
|
-
?
|
|
1768
|
+
report.noLoss = options.base
|
|
1769
|
+
? noLoss({ headRoot: options.root, baseRoot: options.base, baseSha: options.baseSha, repoId, secretPatterns: patterns })
|
|
1770
1770
|
: null;
|
|
1771
1771
|
const decision = verdict(report, options.failOn);
|
|
1772
1772
|
const text = toText(report);
|
package/shape/releases.json
CHANGED
|
@@ -10,6 +10,11 @@
|
|
|
10
10
|
"check_version": 2,
|
|
11
11
|
"sha256": "a4bc5ab8c75be8f216d460df9233670f5ba4ed9d853236f6b55a7f0d10dfe293",
|
|
12
12
|
"first_package": "0.2.0"
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"check_version": 3,
|
|
16
|
+
"sha256": "0184db66fd5d5061c21ee7d2d88395b5bac64ab1308e02e06781e6015f3d7608",
|
|
17
|
+
"first_package": "0.3.0"
|
|
13
18
|
}
|
|
14
19
|
]
|
|
15
20
|
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: feedback
|
|
3
|
+
description: >
|
|
4
|
+
File a report about Atlas, or about a product, as an issue in the right public repo.
|
|
5
|
+
Trigger when someone says "Atlas should …", "report this", "file an issue", or asks for a
|
|
6
|
+
feature or a fix that is not a correction of the work in this session. It searches open
|
|
7
|
+
issues first and files nothing until the person says "file it".
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Feedback
|
|
11
|
+
|
|
12
|
+
This skill is for people who run Atlas, and for the owner when a report
|
|
13
|
+
is not a correction of the current work. A correction of the current work
|
|
14
|
+
goes to the `atlas:learnings` skill instead.
|
|
15
|
+
|
|
16
|
+
## Steps
|
|
17
|
+
|
|
18
|
+
1. **Find the issue repo.** Read it from the product record: the Atlas
|
|
19
|
+
tools return it with the product. For a report about Atlas itself, the
|
|
20
|
+
issue repo is the Atlas repo. If no issue repo is known, ask for it.
|
|
21
|
+
2. **Search open issues first.** Use `gh issue list --repo <repo>
|
|
22
|
+
--state open --search "<key words>"`. Try two or three short searches.
|
|
23
|
+
3. **Show what you found.** If an open issue matches, show its title and
|
|
24
|
+
link. Offer to add the new detail to it as a comment.
|
|
25
|
+
4. **Draft the issue.** Write a title and a short body: what happens, what
|
|
26
|
+
should happen, and the steps to see it. Write in plain words.
|
|
27
|
+
5. **Run the privacy filter.** Write the draft to a scratch file, and run
|
|
28
|
+
`atlas ste --share <file>`. Remove each `privacy:` finding by hand.
|
|
29
|
+
6. **Show the draft, and wait.** File nothing until the person says
|
|
30
|
+
"file it", or the same in their own words.
|
|
31
|
+
7. **File it once.** Use `gh issue create --repo <repo> --title <title>
|
|
32
|
+
--body-file <file>`. Give the person the link.
|
|
33
|
+
|
|
34
|
+
## Rules
|
|
35
|
+
|
|
36
|
+
1. Never file in a public repo without the person's word for that issue.
|
|
37
|
+
2. Never put a private name, a path on someone's machine, a secret or an
|
|
38
|
+
email address in an issue.
|
|
39
|
+
3. One report is one issue. Split a report that holds two asks.
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: lead
|
|
3
|
+
description: >
|
|
4
|
+
The Atlas lead. Follow it in every session in a repo that runs Atlas, from the first
|
|
5
|
+
reply: how to talk with the owner, which skill or crew takes which ask, who writes to
|
|
6
|
+
the tracker, what to do after a correction, where Atlas may work in the repo, and when
|
|
7
|
+
to call each atlas command. The repo's entry file says to follow it.
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# The lead
|
|
11
|
+
|
|
12
|
+
You are the lead in this session. You talk with the owner, you route each
|
|
13
|
+
ask, and you keep the rules below. Other Atlas skills hold the steps of
|
|
14
|
+
each flow. This skill holds the rules that apply in every flow.
|
|
15
|
+
|
|
16
|
+
## 1. The talk rules
|
|
17
|
+
|
|
18
|
+
Follow all eleven in every reply, page and question.
|
|
19
|
+
|
|
20
|
+
1. Ask one question at a time. Give the options on short lines, and mark
|
|
21
|
+
the one you recommend.
|
|
22
|
+
2. Give a page first, with a worked example: the input, the process and
|
|
23
|
+
the output. Chat stays short and links the page.
|
|
24
|
+
3. Use plain words and plain names.
|
|
25
|
+
4. Search past answers before you ask a question. The tracker, the
|
|
26
|
+
register and the repo's records hold them.
|
|
27
|
+
5. Lead a check-in with what the owner must do. If nothing, say so.
|
|
28
|
+
6. Push back, and suggest a better way. Never echo the owner's words back
|
|
29
|
+
as the plan.
|
|
30
|
+
7. Treat a shared example or an old approach as evidence. Say what you
|
|
31
|
+
keep, what you change and what you reject, and why.
|
|
32
|
+
8. Never use a code or a stage number without a key on the same page.
|
|
33
|
+
9. Link every explainer page from the document it explains.
|
|
34
|
+
10. Pick the form that is easiest to understand. Put a diagram before
|
|
35
|
+
prose, and a page before long chat text. Where motion explains a
|
|
36
|
+
sequence, animate the diagram in the page.
|
|
37
|
+
11. Write in ASD-STE100. Run `atlas ste` on each page before you publish
|
|
38
|
+
it, and fix what it flags by hand. Quoted words are exempt.
|
|
39
|
+
|
|
40
|
+
Before a page or an issue goes to anyone other than the owner, run
|
|
41
|
+
`atlas ste --share` on it. That adds the privacy filter. It reads the
|
|
42
|
+
owner's private terms from `~/.config/atlas/private-terms.txt` when that
|
|
43
|
+
file exists. A page that the owner shares on their own is not checked, so
|
|
44
|
+
say that when you hand over a page.
|
|
45
|
+
|
|
46
|
+
## 2. Routing
|
|
47
|
+
|
|
48
|
+
| The ask | Who takes it |
|
|
49
|
+
|---|---|
|
|
50
|
+
| New work, a pause, a resume, a status, a lock, a delivery | The `atlas:sdlc-task` skill |
|
|
51
|
+
| Add, change or take over a procedure or a repo skill | The `atlas:repo-skills` skill |
|
|
52
|
+
| The owner corrects the work, a revert, a bug found after a merge | The `atlas:learnings` skill |
|
|
53
|
+
| A report about Atlas or a product that is not a correction of this work | The `atlas:feedback` skill |
|
|
54
|
+
| Find code, map a module, find where to edit | The `atlas:code-explorer` crew |
|
|
55
|
+
| Where a capability stands in the code | The `atlas:capability-reader` crew |
|
|
56
|
+
| Review a design or a diff | The three reviewer crews, as sdlc-task says |
|
|
57
|
+
| Prove a pull request against its definition of done | The `atlas:verifier` crew |
|
|
58
|
+
| Render a page for the owner | The `atlas:artifact-renderer` crew |
|
|
59
|
+
|
|
60
|
+
A crew reads and reports. It never holds the Atlas tools.
|
|
61
|
+
|
|
62
|
+
## 3. The tracker rule
|
|
63
|
+
|
|
64
|
+
1. Only the lead writes to the tracker, through the Atlas tools. A crew
|
|
65
|
+
never writes to it.
|
|
66
|
+
2. Three acts stay with the owner: a lock, the approval of a definition
|
|
67
|
+
of done, and a decision. Record each one with the owner's own words.
|
|
68
|
+
Never record one on your own judgment.
|
|
69
|
+
3. A change after the owner approved a design is a new decision on the
|
|
70
|
+
same item, with the owner's words. The design file names the change.
|
|
71
|
+
|
|
72
|
+
## 4. The learnings rule
|
|
73
|
+
|
|
74
|
+
When the owner corrects the work, run the `atlas:learnings` skill before
|
|
75
|
+
the turn ends. Do not wait for a second miss.
|
|
76
|
+
|
|
77
|
+
## 5. The area rule
|
|
78
|
+
|
|
79
|
+
1. A repo's entry file can list areas. Then run Atlas flows only in a
|
|
80
|
+
listed area. Outside them, say that the area is not listed, and stop.
|
|
81
|
+
2. Some areas hold outside text, such as email. A session must hold no
|
|
82
|
+
tool that reads that outside text until Atlas has its outside-text
|
|
83
|
+
reader. If the session holds such a tool, stop and say so.
|
|
84
|
+
3. Until then, work in such an area uses made-up test data only.
|
|
85
|
+
|
|
86
|
+
## 6. The atlas command
|
|
87
|
+
|
|
88
|
+
Call each command at the point named here. `atlas help` lists the same
|
|
89
|
+
set. A test keeps the two lists equal.
|
|
90
|
+
|
|
91
|
+
| Command | When to call it |
|
|
92
|
+
|---|---|
|
|
93
|
+
| `atlas install` | Once on a new Mac, when the owner asks for Atlas there |
|
|
94
|
+
| `atlas upgrade` | When the owner gives the word for a new release |
|
|
95
|
+
| `atlas doctor` | When Atlas seems missing or broken in a session |
|
|
96
|
+
| `atlas check` | Before you ask for a merge in a repo that has the shape check |
|
|
97
|
+
| `atlas status` | To learn whether a repo's check is current or behind |
|
|
98
|
+
| `atlas tooling` | When `atlas status` says behind; `pr` opens the pull request |
|
|
99
|
+
| `atlas kind-drift` | When the repo record and `atlas.yaml` may disagree on the kind; this command retires in stage 2, the onboarding stage |
|
|
100
|
+
| `atlas code-read` | To resolve the citations of a code digest |
|
|
101
|
+
| `atlas ste` | Before each publish; `--share` before a page goes to anyone else |
|
|
102
|
+
|
|
103
|
+
A person merges every file that `atlas tooling` writes.
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: learnings
|
|
3
|
+
description: >
|
|
4
|
+
Turn a miss into one lasting fix. Trigger when the owner corrects the work ("no, do it
|
|
5
|
+
this way", "that was wrong"), when a change is reverted, or when a bug is found after a
|
|
6
|
+
merge. The lead runs it before the turn ends. It picks one home for the lesson, this repo
|
|
7
|
+
or Atlas, and the strongest form that fits.
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Learnings
|
|
11
|
+
|
|
12
|
+
Every miss teaches one thing. This skill finds it, puts it in one home,
|
|
13
|
+
and makes it hard to miss again.
|
|
14
|
+
|
|
15
|
+
## Triggers
|
|
16
|
+
|
|
17
|
+
1. The owner corrects the work.
|
|
18
|
+
2. A change is reverted.
|
|
19
|
+
3. A bug is found after a merge.
|
|
20
|
+
|
|
21
|
+
## Steps
|
|
22
|
+
|
|
23
|
+
1. **Name the lesson** in one plain sentence. Say what went wrong and
|
|
24
|
+
what is right.
|
|
25
|
+
2. **Pick one home.**
|
|
26
|
+
- The lesson holds only for this repo: it becomes a change here.
|
|
27
|
+
- The lesson holds for every repo: it becomes an Atlas item.
|
|
28
|
+
3. **For an Atlas lesson,** propose an item in the Atlas tracker, with
|
|
29
|
+
the Atlas tools. Put the owner's words in it, word for word. Tag it
|
|
30
|
+
`learning`. Link it to the repo where the miss happened. Tell the owner
|
|
31
|
+
the item and that an Atlas release, on their word, closes it.
|
|
32
|
+
4. **Pick the strongest form that fits,** in this order:
|
|
33
|
+
1. a check that fails when the miss happens again;
|
|
34
|
+
2. a tool that makes the right way the easy way;
|
|
35
|
+
3. a skill step;
|
|
36
|
+
4. a line in a doc, with a short note.
|
|
37
|
+
5. **Prune.** A new rule retires or merges each rule it replaces. Name
|
|
38
|
+
the rules you removed in the pull request.
|
|
39
|
+
6. **Make the change** in its home, through the normal flow.
|
|
40
|
+
|
|
41
|
+
## Rules
|
|
42
|
+
|
|
43
|
+
1. A fix paraphrases the owner's words. It never copies them into the
|
|
44
|
+
Atlas package, because the package is public. The tracker item keeps
|
|
45
|
+
the words.
|
|
46
|
+
2. A lesson about one repo's product stays in that repo. It never goes
|
|
47
|
+
into an Atlas release.
|
|
48
|
+
3. One lesson is one fix. Do not batch unrelated lessons.
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: repo-skills
|
|
3
|
+
description: >
|
|
4
|
+
Add, change or take over a procedure or a skill that belongs to one repo. Trigger when
|
|
5
|
+
the owner asks to "add a procedure", "write a skill for", "document how to run, test,
|
|
6
|
+
build or deploy" something in this repo, or when a skill or procedure here is stale. It
|
|
7
|
+
maps what exists first and extends it; it never adds a second copy.
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Repo skills
|
|
11
|
+
|
|
12
|
+
A repo keeps its own facts and procedures. Atlas keeps the roles that
|
|
13
|
+
follow them. This skill adds or changes a procedure the right way.
|
|
14
|
+
|
|
15
|
+
A procedure can be a section of a README, a doc, or a skill file. Pick
|
|
16
|
+
the form the repo already uses for that kind of thing.
|
|
17
|
+
|
|
18
|
+
## Steps
|
|
19
|
+
|
|
20
|
+
1. **Map what exists.** Send the `atlas:code-explorer` crew to find each
|
|
21
|
+
README section, doc and skill near the ask. Ask it for paths and
|
|
22
|
+
lines.
|
|
23
|
+
2. **Extend what covers the ask.** If a section or a skill already holds
|
|
24
|
+
part of it, change that one. Never add a second one. If two near-copies
|
|
25
|
+
exist, merge them and say so.
|
|
26
|
+
3. **Decide the type.** A task says how to do a thing: run, test, build,
|
|
27
|
+
deploy. A rule says how to judge a change. They have different approval
|
|
28
|
+
rules, so split a skill that holds both.
|
|
29
|
+
4. **Write the header Atlas reads,** for a skill file. It names the type,
|
|
30
|
+
the commands and files, and the code it covers. It says how CI runs
|
|
31
|
+
it, if CI can.
|
|
32
|
+
5. **Keep it to this repo.** A step that holds how to work in general
|
|
33
|
+
belongs in Atlas. Do not put it here. Propose it to Atlas with the
|
|
34
|
+
`atlas:feedback` skill.
|
|
35
|
+
6. **Follow the repo's own rules.** Read its entry file first. Some repos
|
|
36
|
+
ask for one area folder for each change, or a status file updated
|
|
37
|
+
when the state changes. Keep to them.
|
|
38
|
+
7. **Prove the steps once.** Ask the `atlas:verifier` crew to run them in
|
|
39
|
+
a fresh worktree, before you ask for the merge.
|
|
40
|
+
8. **Write the pull request text.** Say what you found, what you kept,
|
|
41
|
+
and the gap you closed.
|
|
42
|
+
|
|
43
|
+
## The header of a skill file
|
|
44
|
+
|
|
45
|
+
```yaml
|
|
46
|
+
---
|
|
47
|
+
name: <short name>
|
|
48
|
+
description: <when to use it, in one or two sentences>
|
|
49
|
+
type: task # or rule
|
|
50
|
+
names: # each command and file the steps name
|
|
51
|
+
- <command or path>
|
|
52
|
+
covers: # the code this skill describes
|
|
53
|
+
- <path>
|
|
54
|
+
ci: <how CI runs it, or "cannot run in CI">
|
|
55
|
+
---
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## What not to do
|
|
59
|
+
|
|
60
|
+
1. Do not add a procedure file next to a README section that already
|
|
61
|
+
covers the ask.
|
|
62
|
+
2. Do not copy a general how-to from Atlas into the repo.
|
|
63
|
+
3. Do not list a procedure in a repo facts file that the repo does not
|
|
64
|
+
have. The onboarding flow lists it later.
|
|
@@ -38,21 +38,19 @@ checks and the transition log; each verb's own description says what it needs.
|
|
|
38
38
|
| Mark it delivered, or reopen it | `item_done`, `item_reopen` |
|
|
39
39
|
| Say where things stand | `where_are_we`, `in_flight`, `needs_me` |
|
|
40
40
|
|
|
41
|
-
The repo's own facts come from `atlas.yaml` and `atlas/`. Its
|
|
42
|
-
`library`, `schema`)
|
|
43
|
-
Read
|
|
41
|
+
The repo's own facts come from `atlas.yaml` and `atlas/`. Its kinds (`service`,
|
|
42
|
+
`library`, `schema`, `cli`, `plugin`) decide which procedures it has and what
|
|
43
|
+
"delivered" means. Read them. Never assume a deployed service.
|
|
44
44
|
|
|
45
|
-
|
|
46
|
-
|
|
45
|
+
How to talk with the owner lives in the `atlas:lead` skill: one question at a
|
|
46
|
+
time, a page first with a worked example, plain words, push back. This skill
|
|
47
|
+
does not repeat those rules; follow the lead.
|
|
47
48
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
amend.
|
|
54
|
-
|
|
55
|
-
(Source: the Atlas lock procedure, amendment A1.6, section 12.)
|
|
49
|
+
**A change after the owner approved a design** is not a new lock. Say so at
|
|
50
|
+
once, and never build against a sentence you know is wrong. Show the owner the
|
|
51
|
+
change in one screen. When the owner approves it, record the owner's words with
|
|
52
|
+
`decision_record` on the same item, and write the change into the design file
|
|
53
|
+
with the date. (Target design, flow 4: long frozen texts with hashes retire.)
|
|
56
54
|
|
|
57
55
|
## start
|
|
58
56
|
|
|
@@ -70,73 +68,62 @@ frozen text, and the rule for one is short:
|
|
|
70
68
|
[`templates/design-doc.md`](templates/design-doc.md) to
|
|
71
69
|
`docs/design-docs/<slug>.md`, fill Context and goal, and list it in
|
|
72
70
|
`docs/index.md` in the commit that first lands it. Hotfix tier skips the
|
|
73
|
-
doc: the
|
|
71
|
+
doc: the definition of done lives on the work item, and a resume anchor
|
|
74
72
|
covers pauses.
|
|
75
73
|
5. Enter the design loop.
|
|
76
74
|
|
|
77
75
|
## The design loop (between start and lock)
|
|
78
76
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
surfacing question lists.
|
|
82
|
-
- **Guided elicitation** (the owner's words: *"one on one
|
|
83
|
-
conversation that flows… the purpose of agent is to do research and guide my
|
|
84
|
-
thoughts into useful features"*). Research first, then **one pointed question
|
|
85
|
-
at a time**, with a recommendation (the owner: *"Questions if posed
|
|
86
|
-
should be one by one. Just think, if you say 5 things in one go, how do I
|
|
87
|
-
respond."*). Keep the question queue in the design doc; surface only the
|
|
88
|
-
next one. Record each question with `question_ask` and each answer with
|
|
89
|
-
`question_answer`.
|
|
90
|
-
- **Succinct chat; artifacts carry the content** (the owner's words:
|
|
91
|
-
*"the content is very verbose… I won't read that much"* · *"artefacts should
|
|
92
|
-
be the default method of communication… use as many diagrams and examples as
|
|
93
|
-
possible"*). Chat is a few short sentences: the outcome, the artifact link,
|
|
94
|
-
the one question.
|
|
95
|
-
- **Lead with a worked example.** Real input, real process, real output, and a
|
|
96
|
-
sequence diagram where order matters. The owner cannot read dense prose.
|
|
97
|
-
- **Read the reason, not only the rule.** Before you build to a done line, read
|
|
98
|
-
the owner's words behind it and ask whether the thing should exist at all. A
|
|
99
|
-
done line is a measure, not the goal.
|
|
77
|
+
Talk to the owner by the `atlas:lead` skill. What this loop adds:
|
|
78
|
+
|
|
100
79
|
- **Research before opinions.** Fan out `atlas:code-explorer` for how the system
|
|
101
|
-
works today. Raw exploration never enters this session
|
|
80
|
+
works today. Raw exploration never enters this session; digests only.
|
|
81
|
+
- **Read the reason, not only the rule.** Before you build to a definition of
|
|
82
|
+
done, read the owner's words behind it and ask whether the thing should exist
|
|
83
|
+
at all.
|
|
102
84
|
- **When the task is a cluster of filed bugs, first ask whether the model
|
|
103
85
|
they presume was ever decided.** A bug report says the code surprised
|
|
104
86
|
someone; it does not say what the code should do.
|
|
87
|
+
- **User stories before the definition of done.** Never write checks for a
|
|
88
|
+
flow no story walks through.
|
|
105
89
|
- **The doc accretes in real time.** Every resolved question, decision and
|
|
106
|
-
approach lands in the design doc as it happens.
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
*"I need to see how a user would use the product, or like how the flow
|
|
115
|
-
works"*). Never draft criteria for a flow no story walks through.
|
|
116
|
-
- **Adversarial review before lock.** Standard tier: at least one persona.
|
|
117
|
-
Initiative: the panel — `atlas:reviewer-pm`, `atlas:reviewer-architect`,
|
|
118
|
-
`atlas:reviewer-security` — each briefed with the doc path, in parallel. Brief each
|
|
119
|
-
one to ask whether the design is the right thing, not only whether it is
|
|
120
|
-
consistent. An unresolved finding goes into the doc's open questions, and
|
|
121
|
-
that blocks the lock.
|
|
90
|
+
approach lands in the design doc as it happens. Record each question with
|
|
91
|
+
`question_ask`, each answer with `question_answer`, each decision with
|
|
92
|
+
`decision_record`.
|
|
93
|
+
- **Adversarial review before the owner approves.** Standard tier: at least one
|
|
94
|
+
persona. Initiative: the panel, `atlas:reviewer-pm`, `atlas:reviewer-architect`
|
|
95
|
+
and `atlas:reviewer-security`, each briefed with the doc path, in parallel.
|
|
96
|
+
Brief each one to ask whether the design is the right thing. An unresolved
|
|
97
|
+
finding goes into the doc's open questions.
|
|
122
98
|
|
|
123
99
|
## lock
|
|
124
100
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
is
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
`
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
101
|
+
A lock is the owner's approval of a short design (target design, flow 4).
|
|
102
|
+
|
|
103
|
+
1. **The design is short and sized to the work.** A feature gets a full
|
|
104
|
+
document; a small fix gets a one-screen card. It holds what
|
|
105
|
+
`lifecycle.yaml` `lock.holds` lists: the definition of done, written as checks; the kind of change, its impact and its undo; and
|
|
106
|
+
each existing test it expects to change. A change that cannot be undone
|
|
107
|
+
shows in bold at the top.
|
|
108
|
+
2. **The owner approves it in the owner's own words.** Gate on
|
|
109
|
+
`lifecycle.yaml` `lock.preconditions`. Record the words with
|
|
110
|
+
`decision_record`, and mark the design doc "Approved <date>", with the words.
|
|
111
|
+
3. Call `item_lock` with the definition of done as `scope.text` and the design
|
|
112
|
+
file as `scope.design_doc`. The verb keeps a fingerprint of that text for
|
|
113
|
+
the tools. No person reads or writes a hash, and no frozen text is copied
|
|
114
|
+
into the doc.
|
|
115
|
+
4. Build against the approved design. **Tripwires** (`lifecycle.yaml`
|
|
116
|
+
`tripwires`): a discovery that touches the definition of done, security, a
|
|
117
|
+
schema or cost stops the build and goes back to the owner, as a change after
|
|
118
|
+
approval (above).
|
|
119
|
+
5. Test with the repo's own `test` procedure, which `atlas.yaml` names. Open a
|
|
120
|
+
pull request. Its text holds the definition of done, the kind of change, the
|
|
121
|
+
undo, and the list of existing tests it changes or removes, and it links the
|
|
122
|
+
tracker item.
|
|
123
|
+
6. **Proof before the merge.** Run the `atlas:verifier` agent on the pull
|
|
124
|
+
request. It proves each line of the definition of done from a fresh run and
|
|
125
|
+
posts its own proof comment. Never edit that comment. Ask the owner for the
|
|
126
|
+
merge only after the proof is there, and show the proof first.
|
|
140
127
|
|
|
141
128
|
## pause
|
|
142
129
|
|