@arjunkhera/atlas 0.4.45 → 0.4.47
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/approve.mjs +193 -35
- package/door/lib/owner-only.mjs +1 -1
- package/door/lib/signed-act.mjs +39 -0
- 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 +402 -487
- package/shape/releases.json +5 -0
- package/skills/lead/SKILL.md +8 -6
- package/work/lib/delivery.mjs +22 -6
- package/door/lib/kind-drift.mjs +0 -86
package/door/lib/upkeep.mjs
CHANGED
|
@@ -7,7 +7,8 @@
|
|
|
7
7
|
//
|
|
8
8
|
// 1. Docs index. docs/index.md lists each .md file under docs/. A file in a
|
|
9
9
|
// design folder (a folder that holds design.yaml) counts as listed when the
|
|
10
|
-
// index lists that folder's design.yaml. Each listed path exists.
|
|
10
|
+
// index lists that folder's design.yaml. Each listed path exists. The rule
|
|
11
|
+
// is the shape check's own, docsIndexRule (roadmap R62 line 5).
|
|
11
12
|
// 2. Dead links. Each relative link in a tracked .md file names a file or a
|
|
12
13
|
// folder that exists. archive/ is frozen, and test fixtures are planted on
|
|
13
14
|
// purpose, so both are skipped; so is text inside code.
|
|
@@ -24,8 +25,9 @@
|
|
|
24
25
|
// and a stale page is listed.
|
|
25
26
|
//
|
|
26
27
|
// It reads the tree and the event file, and writes nothing.
|
|
27
|
-
import { readFileSync, existsSync
|
|
28
|
-
import { join, dirname,
|
|
28
|
+
import { readFileSync, existsSync } from 'node:fs';
|
|
29
|
+
import { join, dirname, resolve } from 'node:path';
|
|
30
|
+
import { DOCS_INDEX_PATH, docsIndexRule, markdownFiles, proseOf, linkTargets } from '../../shape/check.mjs';
|
|
29
31
|
import { listChanged } from './changed-tests.mjs';
|
|
30
32
|
import { docSourceFindings, replay } from './doc-sources.mjs';
|
|
31
33
|
import { proceduresCommand } from './procedure-steps.mjs';
|
|
@@ -37,62 +39,13 @@ import { changedDocFindings } from './changed-docs.mjs';
|
|
|
37
39
|
// touched doc with no update and no mark a note, not a finding.
|
|
38
40
|
export const TOUCHED_DOCS_GATE = true;
|
|
39
41
|
|
|
40
|
-
const INDEX =
|
|
41
|
-
const SKIP_DIRS = new Set(['node_modules', 'archive', 'fixtures']);
|
|
42
|
+
const INDEX = DOCS_INDEX_PATH;
|
|
42
43
|
const MAX_LISTED = 20;
|
|
43
44
|
|
|
44
|
-
//
|
|
45
|
-
//
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
const walk = (rel) => {
|
|
49
|
-
let entries;
|
|
50
|
-
try { entries = readdirSync(join(root, rel), { withFileTypes: true }); } catch { return; }
|
|
51
|
-
for (const entry of entries) {
|
|
52
|
-
if (entry.name.startsWith('.')) continue;
|
|
53
|
-
const path = rel ? `${rel}/${entry.name}` : entry.name;
|
|
54
|
-
if (entry.isDirectory()) { if (!SKIP_DIRS.has(entry.name)) walk(path); }
|
|
55
|
-
else if (entry.isFile() && entry.name.endsWith('.md')) out.push(path);
|
|
56
|
-
}
|
|
57
|
-
};
|
|
58
|
-
walk(under);
|
|
59
|
-
return out.sort();
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
// Text outside code: fenced blocks of three or more marks, and inline code.
|
|
63
|
-
export function proseOf(text) {
|
|
64
|
-
const lines = String(text ?? '').split('\n');
|
|
65
|
-
const kept = [];
|
|
66
|
-
let fence = null;
|
|
67
|
-
for (const one of lines) {
|
|
68
|
-
const open = one.match(/^\s*(`{3,}|~{3,})/);
|
|
69
|
-
if (fence) {
|
|
70
|
-
if (open && open[1][0] === fence[0] && open[1].length >= fence.length && !one.trim().slice(open[1].length).trim()) fence = null;
|
|
71
|
-
kept.push('');
|
|
72
|
-
continue;
|
|
73
|
-
}
|
|
74
|
-
if (open) { fence = open[1]; kept.push(''); continue; }
|
|
75
|
-
kept.push(one.replace(/`+[^`\n]*`+/g, ''));
|
|
76
|
-
}
|
|
77
|
-
return kept.join('\n');
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// The relative link targets in one markdown text, with their line numbers.
|
|
81
|
-
export function linkTargets(text) {
|
|
82
|
-
const out = [];
|
|
83
|
-
proseOf(text).split('\n').forEach((one, index) => {
|
|
84
|
-
for (const [, angled, bare] of one.matchAll(/\]\(\s*(?:<([^>\n]+)>|([^)\s]+))(?:\s+"[^"]*")?\s*\)/g)) {
|
|
85
|
-
const raw = angled ?? bare;
|
|
86
|
-
const target = raw.split('#')[0].split('?')[0];
|
|
87
|
-
if (!target || /^[a-z][a-z0-9+.-]*:/i.test(raw) || raw.startsWith('#')) continue;
|
|
88
|
-
if (/[{}$*\\]/.test(target)) continue;
|
|
89
|
-
let decoded = target;
|
|
90
|
-
try { decoded = decodeURIComponent(target); } catch { /* keep it as written */ }
|
|
91
|
-
out.push({ target: decoded, line: index + 1 });
|
|
92
|
-
}
|
|
93
|
-
});
|
|
94
|
-
return out;
|
|
95
|
-
}
|
|
45
|
+
// markdownFiles, proseOf and linkTargets live in the shape check, beside the
|
|
46
|
+
// one docs index rule (roadmap R62 line 5). They stay exported here, so their
|
|
47
|
+
// readers keep one door.
|
|
48
|
+
export { markdownFiles, proseOf, linkTargets };
|
|
96
49
|
|
|
97
50
|
export function deadLinks(root) {
|
|
98
51
|
const dead = [];
|
|
@@ -106,32 +59,11 @@ export function deadLinks(root) {
|
|
|
106
59
|
return dead;
|
|
107
60
|
}
|
|
108
61
|
|
|
109
|
-
// The
|
|
110
|
-
|
|
111
|
-
let dir = posix.dirname(file);
|
|
112
|
-
while (dir && dir !== '.' && dir !== 'docs') {
|
|
113
|
-
if (existsSync(join(root, dir, 'design.yaml'))) return dir;
|
|
114
|
-
dir = posix.dirname(dir);
|
|
115
|
-
}
|
|
116
|
-
return null;
|
|
117
|
-
}
|
|
118
|
-
|
|
62
|
+
// The docs index rule is the shape check's, so the check and this command
|
|
63
|
+
// give one count on one tree (roadmap R62 line 5).
|
|
119
64
|
export function docsIndex(root) {
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
const listed = new Set();
|
|
123
|
-
for (const { target } of linkTargets(readFileSync(join(root, INDEX), 'utf8'))) {
|
|
124
|
-
if (target.startsWith('/')) continue;
|
|
125
|
-
const path = posix.normalize(posix.join('docs', target)).replace(/\/$/, '');
|
|
126
|
-
if (path.startsWith('docs/')) listed.add(path);
|
|
127
|
-
}
|
|
128
|
-
const unlisted = markdownFiles(root, 'docs').filter((path) => {
|
|
129
|
-
if (path === INDEX || listed.has(path)) return false;
|
|
130
|
-
const folder = designFolderOf(root, path);
|
|
131
|
-
return !(folder && listed.has(`${folder}/design.yaml`));
|
|
132
|
-
});
|
|
133
|
-
const gone = [...listed].filter((path) => !existsSync(join(root, path))).sort();
|
|
134
|
-
return { checked: true, unlisted, gone };
|
|
65
|
+
const { checked, missing, unlisted, gone } = docsIndexRule(root);
|
|
66
|
+
return missing ? { checked, missing, unlisted, gone } : { checked, unlisted, gone };
|
|
135
67
|
}
|
|
136
68
|
|
|
137
69
|
const UUID = /\b[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\b/i;
|
package/owner-only.yaml
CHANGED
|
@@ -218,22 +218,30 @@ floor:
|
|
|
218
218
|
# does not follow names out of it (shape/check.mjs, the exemption).
|
|
219
219
|
entry_map: docs/index.md
|
|
220
220
|
|
|
221
|
-
# The
|
|
222
|
-
#
|
|
223
|
-
#
|
|
221
|
+
# The key rule for atlas.yaml (roadmap R2 line 11, R62 line 3). Each key of
|
|
222
|
+
# atlas.yaml is on one of the two lists. A pull request may add entries under
|
|
223
|
+
# an add_only key and merge on green; any other change to it, and any change
|
|
224
|
+
# to a fixed key, comes to the owner. A key on neither list comes to the owner
|
|
225
|
+
# too, until a pull request puts it on one.
|
|
224
226
|
atlas_yaml:
|
|
225
227
|
add_only:
|
|
226
228
|
- parts
|
|
229
|
+
- procedures
|
|
230
|
+
- files
|
|
231
|
+
- kinds_of_change
|
|
227
232
|
fixed:
|
|
228
|
-
-
|
|
233
|
+
- spec
|
|
234
|
+
- product
|
|
235
|
+
- repo
|
|
229
236
|
- areas
|
|
237
|
+
- owner_only
|
|
230
238
|
- required_checks
|
|
231
|
-
- product
|
|
232
239
|
- product_paths
|
|
233
|
-
- repo
|
|
234
|
-
- kind
|
|
235
|
-
- kinds
|
|
236
240
|
- up_to_date
|
|
237
241
|
- brake
|
|
242
|
+
- live
|
|
243
|
+
- jobs
|
|
244
|
+
- design
|
|
238
245
|
- generated
|
|
239
|
-
-
|
|
246
|
+
- verbatim
|
|
247
|
+
- private_terms
|
package/package.json
CHANGED