@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/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 ratchet's check-file case does not fire on every release.
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 = 2;
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 ratchet's base tree. The check scores the base
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 ratchet
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 ratchet's own two inputs, from slice L2 stage two.
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 ratchet never runs at all. That is the same class of hole
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 ratchet never runs and a pull request can take a part away with the job still green`);
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 ratchet has no tree to compare against`);
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 ratchet needs a red job
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 ratchet can score a base tree that
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 ratchet's one lever. It replaces the kind and the spec this
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 ratchet. Milestone M2, slice L2 stage two.
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 ratchet and not a level. Turning `fail-on` up to `required` goes red on
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 ratchet asks it not to go backwards.
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 ratchet reports and does not gate. Each is named in
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 RATCHET_CASES = Object.freeze(['check-file', 'workflow', 'kind', 'spec', 'base-tree']);
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 ratchet({ headRoot, baseRoot, baseSha = null, repoId = null, secretPatterns: patterns = secretPatterns() }) {
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.ratchet) lines.push('', ...ratchetLines(report.ratchet));
1642
+ if (report.noLoss) lines.push('', ...noLossLines(report.noLoss));
1643
1643
  return `${lines.join('\n')}\n`;
1644
1644
  }
1645
1645
 
1646
- // The ratchet, in the CI log. It says which tree it compared against, what it
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 ratchetLines(state) {
1650
- const out = ['Ratchet: instruction-class parts, base to head.'];
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 ratchet reports and does not gate on this pull request');
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.ratchet) {
1700
- out.push('### Ratchet', '');
1701
- for (const line of ratchetLines(report.ratchet).slice(1)) out.push(`- ${line.trim()}`);
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 ratchet answers "did this pull request take something away?" It is 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.ratchet;
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 ratchetWhy = state ? (state.gates ? '; no instruction-class part went backwards' : `; the ratchet 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}"${ratchetWhy}` };
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 ratchet's two inputs. `--base` is the directory the workflow checked
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 ratchet then does not run at all, and the report says nothing
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.ratchet = options.base
1769
- ? ratchet({ headRoot: options.root, baseRoot: options.base, baseSha: options.baseSha, repoId, secretPatterns: patterns })
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);
@@ -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 `kind` (`service`,
42
- `library`, `schema`) decides which procedures it has and what "delivered" means.
43
- Read it. Never assume a deployed service.
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
- A change to the process itself is not a task. It is an amendment to the
46
- frozen text, and the rule for one is short:
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
- 1. Say so at once. Never build against a sentence you know is wrong.
49
- 2. Write the amendment as its own dated file: what changes, why, the new
50
- frozen text in full, one new hash over the whole frozen section, and the old
51
- hash named as retired.
52
- 3. Never edit frozen text in place. A reviewer's finding is a normal reason to
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 acceptance criteria live on the work item, and a resume anchor
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
- - **One voice.** The owner talks to one colleague. Crews run behind the
80
- curtain as subagents and come back as digests — never as a committee
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 — digests only.
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. The doc is the pause and
107
- resume state. Record each decision with `decision_record`.
108
- - **HTML is the owner's reading surface.** Any design, review or status the
109
- owner reads is a styled artifact, rendered by the `atlas:artifact-renderer`
110
- crew. Its treatment contract lives in that crew; do not restate it.
111
- - **No bare acronyms in front of the owner.** Spell a thing out on first
112
- mention. Ids are for the machine; names are for the human.
113
- - **User stories before acceptance criteria** (the owner's words:
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
- Gate on `lifecycle.yaml` `lock.preconditions`, all four: the open questions
126
- are empty, the owner ratified the criteria, the approach is chosen, the tier
127
- is confirmed. Then:
128
-
129
- 1. Stamp the design doc's lock block: date, ratifier, tier, the sha256 of the
130
- acceptance criteria text, frozen interfaces, the work list. Commit.
131
- 2. Call `item_lock` with the frozen scope and its hash.
132
- 3. Build against the frozen text. **Tripwires** (`lifecycle.yaml`
133
- `tripwires`): a discovery after lock that touches the criteria, security,
134
- a schema or cost stops the build and goes back to the owner. If the frozen
135
- text is wrong, say so at once and write an amendment. Never build against a
136
- sentence you know is wrong.
137
- 4. Test with the repo's own `test` procedure, which `atlas.yaml` names. Open a
138
- pull request. Keep a separate acceptance reviewer, and close its findings
139
- before acceptance.
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