@arjunkhera/atlas 0.4.44 → 0.4.46
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/door/cli.mjs +9 -41
- package/door/lib/owner-only.mjs +1 -1
- package/door/lib/tooling.mjs +32 -1
- package/door/lib/upkeep.mjs +14 -82
- package/owner-only.yaml +17 -9
- package/package.json +1 -1
- package/shape/check.mjs +436 -485
- package/shape/releases.json +10 -0
- package/skills/lead/SKILL.md +7 -5
- package/door/lib/kind-drift.mjs +0 -86
package/shape/releases.json
CHANGED
|
@@ -47,6 +47,16 @@
|
|
|
47
47
|
"check_version": 8,
|
|
48
48
|
"sha256": "8cf521f6e8f89ae65a257c521c583281e0c3c27ef968b4bd96eb336a8d095795",
|
|
49
49
|
"workflow_sha256": "fcddebef030e6564f97e1a5fb81c8ad1b3084ebef9622167c6565698312dcdd7"
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
"check_version": 9,
|
|
53
|
+
"sha256": "87896abfc09afd22724cfa645bbb5ef029d83887caf70f38b88d00b21cddef02",
|
|
54
|
+
"workflow_sha256": "fcddebef030e6564f97e1a5fb81c8ad1b3084ebef9622167c6565698312dcdd7"
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
"check_version": 10,
|
|
58
|
+
"sha256": "8943d8ea9f1af9a16c677942053b6ec7f9f767080d52f626d0960d7f36499732",
|
|
59
|
+
"workflow_sha256": "fcddebef030e6564f97e1a5fb81c8ad1b3084ebef9622167c6565698312dcdd7"
|
|
50
60
|
}
|
|
51
61
|
]
|
|
52
62
|
}
|
package/skills/lead/SKILL.md
CHANGED
|
@@ -83,9 +83,12 @@ the turn ends. Do not wait for a second miss.
|
|
|
83
83
|
|
|
84
84
|
## 5. The area rule
|
|
85
85
|
|
|
86
|
-
1. A repo
|
|
87
|
-
|
|
88
|
-
|
|
86
|
+
1. A repo lists its areas in `atlas.yaml`, under `areas:`. Its entry
|
|
87
|
+
file can list them too. Then run Atlas flows only in a listed area.
|
|
88
|
+
Outside them, say that the area is not listed, and stop. A repo with
|
|
89
|
+
no `areas:` is one area.
|
|
90
|
+
2. Some areas hold outside text, such as email. In `atlas.yaml` such an
|
|
91
|
+
area says `outside_text: true`. A session must hold no
|
|
89
92
|
tool that reads that outside text until Atlas has its outside-text
|
|
90
93
|
reader. If the session holds such a tool, stop and say so.
|
|
91
94
|
3. Until then, work in such an area uses made-up test data only.
|
|
@@ -100,10 +103,9 @@ set. A test keeps the two lists equal.
|
|
|
100
103
|
| `atlas install` | Once on a new Mac, when the owner asks for Atlas there |
|
|
101
104
|
| `atlas upgrade` | When the owner asks to upgrade Atlas. Call the `atlas_upgrade` tool instead: the Bash sandbox blocks this command. Run the command by hand only where that tool is missing. In a cloud session, call the tool with `check: true` at the first reply, as section 7 says |
|
|
102
105
|
| `atlas doctor` | When Atlas seems missing or broken in a session |
|
|
103
|
-
| `atlas check` | Before you ask for a merge in a repo that has the shape check |
|
|
106
|
+
| `atlas check` | Before you ask for a merge in a repo that has the shape check. `--json` prints the counts of listed parts, procedures and jobs |
|
|
104
107
|
| `atlas status` | To learn whether a repo's check is current or behind. `atlas status --all --json <repo>` lists each Atlas copy in a repo, with have, want and state |
|
|
105
108
|
| `atlas tooling` | When `atlas status` says behind; `pr` opens the pull request |
|
|
106
|
-
| `atlas kind-drift` | When the repo record and `atlas.yaml` may disagree on the kind; this command retires in stage 2, the onboarding stage |
|
|
107
109
|
| `atlas code-read` | To resolve the citations of a code digest |
|
|
108
110
|
| `atlas ste` | Before each publish; `--share` before a page goes to anyone else |
|
|
109
111
|
| `atlas tests` | `write` puts the test kit in an area. `check` runs before a merge. `kept` runs the kept tests of a path 1 area and writes their evidence. `proof`, `verdict`, `named`, `covers` and `rerun` read the results of a run. `changed`, `before` and `after` run the test checks of the gate: changed tests, new cases fail on old code, old cases pass on new code. `sweep` and `issues` run the daily sweep |
|
package/door/lib/kind-drift.mjs
DELETED
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
// The facts helper's kind drift report.
|
|
2
|
-
//
|
|
3
|
-
// Milestone M2, slice L2 stage one: "The facts helper compares the `kind` in
|
|
4
|
-
// `atlas.yaml` with the `kind` on the repo record and reports drift."
|
|
5
|
-
//
|
|
6
|
-
// The kind decides which of the six files a repository needs, so the two
|
|
7
|
-
// copies disagreeing is not a detail. A repo record that says `service` while
|
|
8
|
-
// atlas.yaml says `library` means four required parts read "not applicable" in
|
|
9
|
-
// CI and "required" everywhere else.
|
|
10
|
-
//
|
|
11
|
-
// Which of the two is the source is open question O-9, and the owner settles it
|
|
12
|
-
// before slice L2 ends. This report is neutral on that: it names both values
|
|
13
|
-
// and says they differ. It never picks a winner, and it never writes.
|
|
14
|
-
//
|
|
15
|
-
// Where the record comes from. Reading it live needs the Atlas work verbs and
|
|
16
|
-
// an Engram owner token, which CI does not have and this module does not hold.
|
|
17
|
-
// So the record's kind is an input. Pass one repo's kind, or the JSON the
|
|
18
|
-
// `registry_list` verb returns.
|
|
19
|
-
import { readFileSync, existsSync } from 'node:fs';
|
|
20
|
-
import { join } from 'node:path';
|
|
21
|
-
import { parseYaml, SPECS } from '../../shape/check.mjs';
|
|
22
|
-
import { REPO_KINDS, repoKinds } from '../../work/lib/verb-fields.mjs';
|
|
23
|
-
|
|
24
|
-
// Stage 1: the repo record holds a list of kinds, and atlas.yaml one kind.
|
|
25
|
-
// They agree when the list holds the file's kind. This report retires in
|
|
26
|
-
// stage 2, with the fixed kind tables.
|
|
27
|
-
export const KINDS = REPO_KINDS;
|
|
28
|
-
const asList = (value) => (value === null || value === undefined ? null : (Array.isArray(value) ? value : String(value).split(',').map((one) => one.trim()).filter(Boolean)));
|
|
29
|
-
|
|
30
|
-
// The kind a repository's own file declares, with the repo id beside it.
|
|
31
|
-
export function fileKind(root) {
|
|
32
|
-
const path = join(root, 'atlas.yaml');
|
|
33
|
-
if (!existsSync(path)) return { kind: null, repo: null, error: 'atlas.yaml does not exist' };
|
|
34
|
-
try {
|
|
35
|
-
const facts = parseYaml(readFileSync(path, 'utf8'));
|
|
36
|
-
return { kind: facts?.kind ?? null, repo: facts?.repo ?? null, spec: facts?.spec ?? null, error: null };
|
|
37
|
-
} catch (error) {
|
|
38
|
-
// The parse error names a line and a column and never the content. That is
|
|
39
|
-
// the rule the whole check follows (amendment A1.6, section 4.9).
|
|
40
|
-
return { kind: null, repo: null, error: `atlas.yaml cannot be read: ${error.message}` };
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
// One repository, one verdict.
|
|
45
|
-
export function driftOne({ root, recordKind = null, recordRepo = null }) {
|
|
46
|
-
const file = fileKind(root);
|
|
47
|
-
const known = (kind) => kind === null || KINDS.includes(kind);
|
|
48
|
-
const recordKinds = asList(recordKind);
|
|
49
|
-
recordKind = recordKinds && recordKinds.length ? recordKinds.join(', ') : null;
|
|
50
|
-
const row = {
|
|
51
|
-
root,
|
|
52
|
-
repo: file.repo ?? recordRepo ?? null,
|
|
53
|
-
file_kind: file.kind,
|
|
54
|
-
record_kind: recordKind,
|
|
55
|
-
spec: file.spec ?? null,
|
|
56
|
-
state: 'unknown',
|
|
57
|
-
why: '',
|
|
58
|
-
};
|
|
59
|
-
if (file.error) { row.state = 'unreadable'; row.why = file.error; return row; }
|
|
60
|
-
if (!known(file.kind)) { row.state = 'unreadable'; row.why = `atlas.yaml names kind "${file.kind}"; a kind is one of ${KINDS.join(', ')}`; return row; }
|
|
61
|
-
if (recordKind === null) { row.state = 'unknown'; row.why = 'no repo record kind was given, so there is nothing to compare with. Read it with the registry_list verb and pass it in.'; return row; }
|
|
62
|
-
const strange = recordKinds.find((kind) => !known(kind));
|
|
63
|
-
if (strange) { row.state = 'unreadable'; row.why = `the repo record names kind "${strange}"; a kind is one of ${KINDS.join(', ')}`; return row; }
|
|
64
|
-
if (file.kind === null) { row.state = 'drift'; row.why = `the repo record says "${recordKind}" and atlas.yaml names no kind at all, so CI cannot tell which files this repo needs`; return row; }
|
|
65
|
-
if (recordKinds.includes(file.kind)) { row.state = 'agree'; row.why = recordKinds.length === 1 ? `both say "${file.kind}"` : `the repo record's kinds (${recordKind}) hold "${file.kind}"`; return row; }
|
|
66
|
-
row.state = 'drift';
|
|
67
|
-
row.why = `atlas.yaml says "${file.kind}" and the repo record says "${recordKind}". The kind decides which parts are required, so the check in CI and the work verbs are scoring two different repos. Open question O-9 says which one is the source.`;
|
|
68
|
-
return row;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
// The registry the `registry_list` verb returns, as { repoId: kinds }. A
|
|
72
|
-
// row from before stage 1 has only kind, and reads as a list of one.
|
|
73
|
-
export function kindsFromRegistry(registry) {
|
|
74
|
-
const out = {};
|
|
75
|
-
const kindsOf = (repo) => { const list = repoKinds(repo); return list.length ? list : null; };
|
|
76
|
-
for (const product of registry?.products ?? []) {
|
|
77
|
-
for (const repo of product?.repos ?? []) if (repo?.registry_id) out[repo.registry_id] = kindsOf(repo);
|
|
78
|
-
}
|
|
79
|
-
for (const repo of registry?.repos ?? []) if (repo?.registry_id) out[repo.registry_id] = kindsOf(repo);
|
|
80
|
-
return out;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
export function drift(rows) {
|
|
84
|
-
const out = rows.map(driftOne);
|
|
85
|
-
return { rows: out, drifting: out.filter((row) => row.state === 'drift').length, specs_read: Object.keys(SPECS).map(Number) };
|
|
86
|
-
}
|