@assuredloop/cli 0.1.0 → 0.2.1
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/README.md +263 -211
- package/bin/al.js +82 -64
- package/package.json +12 -1
- package/skills/assuredloop/SKILL.md +203 -44
- package/src/v4/base.js +80 -0
- package/src/v4/check.js +81 -0
- package/src/v4/checks.js +383 -0
- package/src/v4/commands.js +168 -0
- package/src/v4/conclude.js +119 -0
- package/src/v4/config.js +75 -0
- package/src/v4/dispositions.js +191 -0
- package/src/v4/export.js +469 -0
- package/src/v4/git.js +153 -0
- package/src/v4/ids.js +87 -0
- package/src/v4/indexer.js +361 -0
- package/src/v4/level2.js +154 -0
- package/src/v4/markers.js +290 -0
- package/src/v4/records.js +66 -0
- package/src/v4/repos.js +329 -0
- package/src/v4/request-md.js +108 -0
- package/src/v4/results.js +42 -0
- package/src/v4/scope.js +167 -0
- package/src/v4/search.js +431 -0
- package/src/v4/snapshot.js +20 -0
- package/src/v4/spec.js +148 -0
- package/src/v4/state.js +208 -0
- package/src/v4/views.js +480 -0
- package/src/v4/words.js +98 -0
- package/src/adrs.js +0 -110
- package/src/audit.js +0 -176
- package/src/check.js +0 -127
- package/src/commands.js +0 -456
- package/src/conclude.js +0 -293
- package/src/consolidate.js +0 -279
- package/src/git.js +0 -155
- package/src/hints.js +0 -433
- package/src/links.js +0 -181
- package/src/record-section.js +0 -126
- package/src/sections.js +0 -125
- package/src/signoff.js +0 -166
- package/src/snapshot.js +0 -63
- package/src/spec.js +0 -228
- package/src/states.js +0 -227
- package/src/tests.js +0 -267
- package/src/tree.js +0 -113
- package/src/views.js +0 -390
package/README.md
CHANGED
|
@@ -1,243 +1,293 @@
|
|
|
1
1
|
# AssuredLoop
|
|
2
2
|
|
|
3
3
|
AssuredLoop keeps an AI focused on one change. It holds together:
|
|
4
|
-
- the owner's words;
|
|
5
|
-
- the organized requirement the owner signs
|
|
6
|
-
- the
|
|
7
|
-
|
|
8
|
-
-
|
|
9
|
-
- the
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
`
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
4
|
+
- the owner's words, as snapshots;
|
|
5
|
+
- the organized requirement that the owner signs;
|
|
6
|
+
- the consolidated spec in `specs/`: the system now, the promises and the
|
|
7
|
+
lasting design, each paragraph with a hidden ID;
|
|
8
|
+
- each change's own design, its change spec, beside its request;
|
|
9
|
+
- the decisions and the ADRs;
|
|
10
|
+
- the code, the tests and the documents that came with the change.
|
|
11
|
+
|
|
12
|
+
Its command, `al`, keeps these records, checks them, and says what to do
|
|
13
|
+
next. It refuses only in its own `al conclude`. Every other check is a hint;
|
|
14
|
+
a project that wants blocks turns on `al check --strict` in its CI.
|
|
15
|
+
|
|
16
|
+
AssuredLoop is not a lifecycle tool. It has no phases, no roles, no task
|
|
17
|
+
states and no approvals beyond the owner's sign-off. How and when you design,
|
|
18
|
+
test and review is your project's way of working.
|
|
16
19
|
|
|
17
20
|
## Install
|
|
18
21
|
|
|
19
|
-
|
|
20
|
-
|
|
22
|
+
Version 0.2.0 is v4. It is a breaking release: it does not read the records
|
|
23
|
+
of 0.1.0. To move a project from 0.1.0, see "From 0.1.0" in "Adopting
|
|
24
|
+
AssuredLoop".
|
|
25
|
+
|
|
26
|
+
It needs Node 24 or newer and git 2.31 or newer. Install the npm package
|
|
27
|
+
`@assuredloop/cli`, which puts `al` on your PATH:
|
|
21
28
|
|
|
22
29
|
npm install --global @assuredloop/cli
|
|
23
30
|
|
|
24
|
-
|
|
25
|
-
|
|
31
|
+
The recommended install adds the embedding model's library beside it, for
|
|
32
|
+
search at level 2 (see "Search"). `al` names the library as an optional
|
|
33
|
+
dependency, so npm installs it only when you ask:
|
|
34
|
+
|
|
35
|
+
npm install --global @assuredloop/cli @huggingface/transformers@4.3.1
|
|
36
|
+
|
|
37
|
+
To pin a version, name it: `npm install --global @assuredloop/cli@<version>`.
|
|
26
38
|
|
|
27
|
-
The package carries the skill
|
|
28
|
-
`$(npm root -g)/@assuredloop/cli
|
|
29
|
-
|
|
30
|
-
line to the project's AGENTS.md:
|
|
39
|
+
The package carries the skill, at
|
|
40
|
+
`$(npm root -g)/@assuredloop/cli/skills/assuredloop/SKILL.md`. Add one line to
|
|
41
|
+
the project's AGENTS.md:
|
|
31
42
|
|
|
32
43
|
```
|
|
33
|
-
AssuredLoop keeps this project's requests and spec: before work that changes
|
|
44
|
+
AssuredLoop keeps this project's requests and spec: before work that changes the spec, read <dir>/skills/assuredloop/SKILL.md and run `al context`.
|
|
34
45
|
```
|
|
35
46
|
|
|
36
47
|
In a shared repo whose contributors install `al` in different places, copy
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
48
|
+
the skill at the pinned version into the project, for example as
|
|
49
|
+
`.claude/skills/assuredloop/SKILL.md`. Name that path in the AGENTS.md line,
|
|
50
|
+
and say in the commit which version it came from.
|
|
51
|
+
|
|
52
|
+
Search at level 2 needs the library `@huggingface/transformers` 4.3.1 (see
|
|
53
|
+
"Search"). Install it in the project, or beside `al`.
|
|
54
|
+
|
|
55
|
+
## The model in one page
|
|
56
|
+
|
|
57
|
+
- **Paragraphs and markers.** Every paragraph of a spec doc has an ID in a
|
|
58
|
+
hidden HTML comment on its own line before it, with a blank line before and
|
|
59
|
+
after it. The marker holds the ID, the kind and the links:
|
|
60
|
+
|
|
61
|
+
```markdown
|
|
62
|
+
<!-- INV-41 rule serves:invoice-exports/R2 builds-on:INV-12 -->
|
|
63
|
+
|
|
64
|
+
The export link MUST expire 30 minutes after the email is sent.
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
GitHub does not show the marker. The ID is one flat number per file, and
|
|
68
|
+
it is never used again. `al` computes a display number, for example
|
|
69
|
+
`INV-41 (2.3:4, in Export links)`, which can change when text moves.
|
|
70
|
+
- **Kinds.** Promise kinds (purpose, scope, rule, limit, definition): a
|
|
71
|
+
change needs a signed requirement that covers it. Design kinds (component,
|
|
72
|
+
interface, data, flow, choice) and `approach` (how one change is built):
|
|
73
|
+
a change needs review. Informative kinds (rationale, example, open), `note`
|
|
74
|
+
(headings and connecting text), and the change-only kinds (plan, step,
|
|
75
|
+
migration).
|
|
76
|
+
- **A request** is the folder `requests/<name>/`: `origin/` (the owner's words
|
|
77
|
+
and the sign-offs, as snapshots with SHA-256), `request.md` (the dialog, the
|
|
78
|
+
organized requirement R1…, the decisions D1…) and, from path 2, `spec.md`,
|
|
79
|
+
the change spec, with IDs SP-1, SP-2…
|
|
80
|
+
- **Records** in `.assuredloop/records/`, committed to git: one per request
|
|
81
|
+
(its sources, requirement versions, sign-offs, decisions, tasks, the
|
|
82
|
+
bindings of its links and the dispositions of its paragraphs) and one per
|
|
83
|
+
doc (fields that `al index` can always rebuild). `al` writes every hash and
|
|
84
|
+
every derived field.
|
|
85
|
+
- **Bindings.** When a link is first indexed, `al index` records the hash of
|
|
86
|
+
both ends. Ordinary indexing never moves a binding. When the target
|
|
87
|
+
changes, the source gets a hint until someone checks it and runs
|
|
88
|
+
`al index --align <ID>`.
|
|
89
|
+
- **Consolidation is by hand.** A PR copies a change paragraph into `specs/`
|
|
90
|
+
word for word, and records its disposition: `incorporated`, `removed`,
|
|
91
|
+
`superseded` or `abandoned`. No command writes the spec.
|
|
92
|
+
|
|
93
|
+
## Paths
|
|
94
|
+
|
|
95
|
+
The user picks the path. The skill has the steps of each path.
|
|
96
|
+
|
|
97
|
+
| Path | When | Records | Sign-off | Closes when |
|
|
98
|
+
|---|---|---|---|---|
|
|
99
|
+
| 0. Fix | no promise changes: it restores what the spec says, or claims a typo in any paragraph | none | no | the PR merges |
|
|
100
|
+
| 1. Small promise amend | one or a few promise paragraphs change | a short request; the PR edits `specs/` directly | yes | the PR merges |
|
|
101
|
+
| 1d. Small design correction | names or wording of design paragraphs only | a short request with a one-line source note; the PR edits `specs/` directly | no | the PR merges |
|
|
102
|
+
| 2. Big change | a real design, one or a few PRs | a request and a change spec | if a promise kind changes | the close rule holds |
|
|
103
|
+
| 3. Epic | big, in parts over time | as 2, with optional task references | as 2 | the close rule holds |
|
|
104
|
+
| S. Spike | not yet clear what to build | a request with an organized question; the findings open with the answer | yes, on the question | the answer names the question version |
|
|
105
|
+
|
|
106
|
+
Every PR states its path and its claim in a commit message, for example
|
|
107
|
+
`Tier: 0 — typo in INV-3` or `Tier: 2 — invoice-payments, part 1`. `al check`
|
|
108
|
+
reads the newest `Tier:` line in the branch's commits, and checks the claim
|
|
109
|
+
against the kinds and the changed paragraphs: "path 0, but a rule paragraph
|
|
110
|
+
is changed with no typo claim" is `not ok`. It checks the labels, not their
|
|
111
|
+
meaning.
|
|
112
|
+
|
|
113
|
+
**The close rule.** `al conclude <name>` refuses while a promise change has
|
|
114
|
+
no sign-off, a spike's current question is not signed, or a change paragraph
|
|
115
|
+
with a baseline effect has no valid disposition for its current version.
|
|
62
116
|
|
|
63
117
|
## The commands
|
|
64
118
|
|
|
65
|
-
- `al new <name> --from <file|-> [--tier <1|2|3|S>] [--title <text>]`:
|
|
66
|
-
a request from the owner's words (`-` reads standard input)
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
- `al
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
- `al
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
- `al
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
119
|
+
- `al new <name> --from <file|-> [--tier <1|1d|2|3|S>] [--title <text>]`:
|
|
120
|
+
start a request from the owner's words (`-` reads standard input).
|
|
121
|
+
- `al record <name> origin --url <source> --from <file|->`: a snapshot of
|
|
122
|
+
later words of the owner, or of a source you rely on.
|
|
123
|
+
- `al record <name> signoff --source <where> --words <their words>`: show what
|
|
124
|
+
the owner signs; with `--yes`, record the sign-off on the owner's own yes.
|
|
125
|
+
- `al record <name> decision --source <who> --text <decision>
|
|
126
|
+
[--clarifies R<n>]`: add D1, D2…
|
|
127
|
+
- `al spec`: every doc's IDs, display numbers and kinds.
|
|
128
|
+
`al spec --add-ids <file> [--prefix <P>]`: give each unmarked paragraph the
|
|
129
|
+
next free ID.
|
|
130
|
+
- `al index`: write the derived facts and the new bindings, and list the AI
|
|
131
|
+
hints to refresh. `al index --align <ID>` moves the bindings of one
|
|
132
|
+
paragraph to its targets' current text, on purpose.
|
|
133
|
+
- `al check [--strict]`: the checks of this branch against its base.
|
|
134
|
+
- `al context [<name> | <ID>]`: where the project, a request or a paragraph
|
|
135
|
+
stands. `--diff <range> --for review` is the review view. `--audit` gives a
|
|
136
|
+
request's whole trace; `--at <commit>` any v4 state.
|
|
137
|
+
- `al conclude <name>`: the close rule; with `--yes` it writes the Outcome
|
|
138
|
+
and moves the request to `requests/archive/<name>/`.
|
|
139
|
+
- `al export [--at <commit>] [--out <file>]`: one JSONL row per paragraph
|
|
140
|
+
version, with its role, version, commit and links. It is not committed.
|
|
141
|
+
- `al search <words>`: see "Search".
|
|
142
|
+
|
|
143
|
+
Every command that changes files, except `new` and `index`, shows what it
|
|
144
|
+
would write, and writes only with `--yes`. Each output ends with three lines:
|
|
145
|
+
`Read` (what it read), `Next` (what to do next) and `Not known` (what the
|
|
146
|
+
tool cannot know).
|
|
90
147
|
|
|
91
148
|
## Settings
|
|
92
149
|
|
|
93
|
-
|
|
94
|
-
each path inside the repo:
|
|
95
|
-
- `root: <folder>`: the baseline's folder, `specs` when there is no such line;
|
|
96
|
-
- `tests: <path>`: a test file or folder beyond the usual names;
|
|
97
|
-
- `results: <path>`: a test result file or folder for `al check` to read;
|
|
98
|
-
- `adrs: <folder>`: a folder of decision records; `docs/adr` is always read too.
|
|
99
|
-
|
|
100
|
-
`tests:`, `results:` and `adrs:` may each be given on several lines.
|
|
101
|
-
|
|
102
|
-
## Common situations
|
|
103
|
-
|
|
104
|
-
Each example gives the steps, and what `al check` says on the PR. The `Tier:`
|
|
105
|
-
line goes in a commit message and in the PR.
|
|
106
|
-
|
|
107
|
-
### Adopting when the spec lives elsewhere
|
|
108
|
-
|
|
109
|
-
Say the design is `docs/prd.md`, and the root is to be `docs/prd/`. Use two
|
|
110
|
-
PRs.
|
|
111
|
-
|
|
112
|
-
PR 1 moves the file, fixes each relative link the move breaks (`(adr/)`
|
|
113
|
-
becomes `(../adr/)`), and sets the root. It comes before the project adopts
|
|
114
|
-
AssuredLoop, so it carries no Tier line:
|
|
115
|
-
|
|
116
|
-
mkdir docs/prd && git mv docs/prd.md docs/prd/prd.md
|
|
117
|
-
printf 'root: docs/prd\n' > .assuredloop
|
|
118
|
-
|
|
119
|
-
This is the step before the baseline exists. `al check`, if run on it, exits 0
|
|
120
|
-
(`--strict` too) with two notes:
|
|
121
|
-
|
|
122
|
-
note: <sha> changes docs/prd/prd.md with no request linked (fine for tier 0; say why); git show <sha>
|
|
123
|
-
note: no Tier line in origin/main..HEAD; add "Tier: <n> — <claim>" to a commit message, e.g. with git commit --amend
|
|
124
|
-
|
|
125
|
-
A tier-0 claim here would get
|
|
126
|
-
`not ok: the claim is tier 0, but origin/main..HEAD edits the baseline`: the
|
|
127
|
-
fork had no baseline, so the whole file reads as new.
|
|
128
|
-
|
|
129
|
-
PR 2, after PR 1 merges, adopts: the AGENTS.md line from Install, and IDs. It
|
|
130
|
-
claims `Tier: 0 — adds section IDs; no promise changes`:
|
|
131
|
-
|
|
132
|
-
al spec --add-ids docs/prd/prd.md --prefix PRD --yes
|
|
133
|
-
|
|
134
|
-
`al check --strict` passes, with one note: the commit changes
|
|
135
|
-
`docs/prd/prd.md` with no request linked (fine for tier 0; say why). In one PR,
|
|
136
|
-
the IDs read as edits too: `edits the baseline: [PRD-1], [PRD-2], [PRD-3]`.
|
|
137
|
-
|
|
138
|
-
### Adding IDs to a spec file in the root
|
|
150
|
+
`.assuredloop/config.yaml`, at the repo's root. Every key is optional.
|
|
139
151
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
`moves [R-3] specs/rules.md → specs/dates.md, text unchanged`. A new file holds
|
|
150
|
-
only the moved sections: a title or an intro line in it is new text, and gets
|
|
151
|
-
a `not ok`.
|
|
152
|
-
|
|
153
|
-
### A move that forces a text change
|
|
154
|
-
|
|
155
|
-
Moving `[R-2]` from `specs/` into `specs/files/` breaks its link
|
|
156
|
-
`(limits.md)`. The fix, `(../limits.md)`, changes the section's text. So does a
|
|
157
|
-
heading reworded on the way. `al` follows neither. Claimed as tier 0:
|
|
158
|
-
|
|
159
|
-
not ok: the claim is tier 0, but origin/main..HEAD edits the baseline: [R-2]; al context --diff origin/main..HEAD
|
|
160
|
-
|
|
161
|
-
Either keep the change out of the move: move the section where its text still
|
|
162
|
-
works (a file in the same folder keeps its links), and reword in a tier-1 PR of
|
|
163
|
-
its own. Or claim tier 1 for the whole PR, as in the skill's quick path, with
|
|
164
|
-
`Amends: [R-2]` and the owner's sign-off. `al check --strict` then passes.
|
|
165
|
-
|
|
166
|
-
### Renaming a section's ID
|
|
167
|
-
|
|
168
|
-
Code, tests and requests cite a section by its ID. Rename `[R-2]` to
|
|
169
|
-
`[SIZE-1]`, claim tier 0, and `al check` says
|
|
170
|
-
`not ok: the claim is tier 0, but origin/main..HEAD edits the baseline: [R-2], [SIZE-1]`.
|
|
171
|
-
`al context R-2` then says `[R-2] not in the baseline`, and still lists the
|
|
172
|
-
code and tests that name it.
|
|
173
|
-
|
|
174
|
-
Keep the ID: it names the promise, not the file it sits in. If it must change,
|
|
175
|
-
claim tier 1, with the owner's sign-off and `Amends: [R-2], [SIZE-1]` (name
|
|
176
|
-
both, or a note says the new one is not named). In the same PR, change the
|
|
177
|
-
citations in code and tests; `al context R-2` lists them. `[R-2]` is never used
|
|
178
|
-
again.
|
|
179
|
-
|
|
180
|
-
Do not replace `[R-2]` across the whole repo:
|
|
181
|
-
- Archived requests and the other append-only records ([REC-12]) stay as they
|
|
182
|
-
are, and keep `[R-2]` as history. Editing one gives
|
|
183
|
-
`not ok: <sha> requests/archive/<name>/request.md: changes a request archived on main ([REC-12])`.
|
|
184
|
-
- An open request that holds `[R-2]` then reads it as
|
|
185
|
-
`not found; candidates SIZE-1`, shown as that request's own information. It
|
|
186
|
-
is re-aligned in that request's own work. A replace there edits its signed
|
|
187
|
-
`origin/` snapshot, which gives a `not ok`.
|
|
188
|
-
|
|
189
|
-
### Starting a new repo from an already-agreed spec
|
|
190
|
-
|
|
191
|
-
Adopt the agreed text as it is, with no request: the owner signs a request's
|
|
192
|
-
organized requirement, never the spec text ([REC-5]). Say in the commit
|
|
193
|
-
message where and when the owner agreed it. Use two steps, as in the first
|
|
194
|
-
example.
|
|
152
|
+
```yaml
|
|
153
|
+
root: specs # the spec folder; every *.md in it except adr/ is a spec doc
|
|
154
|
+
docs: # each file and its ID prefix; other files may be listed too
|
|
155
|
+
- {file: specs/invoices.md, prefix: INV}
|
|
156
|
+
results: .assuredloop/results # where result files are
|
|
157
|
+
outputs: # in the central repo: its output repos
|
|
158
|
+
- {name: invoicer-web, path: ../invoicer-web, commit: <sha>}
|
|
159
|
+
central: {path: ../invoicer} # in an output repo: the central repo
|
|
160
|
+
```
|
|
195
161
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
line: AssuredLoop is not adopted yet, and its rules start at adoption.
|
|
199
|
-
`al check`, if run on it, exits 0 with the two notes PR 1 above gets. In an
|
|
200
|
-
empty repo, PR 1 can instead be the first commit, straight to main.
|
|
162
|
+
`.assuredloop/schema.yaml` holds the kinds and the link words, with a version.
|
|
163
|
+
`al spec --add-ids` writes both files when they are absent.
|
|
201
164
|
|
|
202
|
-
|
|
203
|
-
`
|
|
165
|
+
ADRs are `specs/adr/NNNN-<slug>.md`, with `Status: proposed`, `accepted` or
|
|
166
|
+
`superseded` on the first line. The heading's marker holds `ADR-<n>` and its
|
|
167
|
+
`decides:`, `source:` and `supersedes:` links. The text of an accepted ADR
|
|
168
|
+
does not change; a new ADR supersedes it.
|
|
204
169
|
|
|
205
|
-
|
|
170
|
+
## Search
|
|
206
171
|
|
|
207
|
-
`al
|
|
208
|
-
|
|
209
|
-
with the owner's sign-off, start at the first promise change after that.
|
|
172
|
+
`al search` answers at the strongest level that is installed, falls back by
|
|
173
|
+
itself (2, then 1, then 0), and says which level answered and why.
|
|
210
174
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
175
|
+
| Level | What it is | Needs |
|
|
176
|
+
|---|---|---|
|
|
177
|
+
| 0 | a scan of the export | nothing |
|
|
178
|
+
| 1 | a local full-text index (SQLite FTS5, BM25), with the ID in its own exact column | Node 24 or newer (`node:sqlite`) |
|
|
179
|
+
| 2 | level 1, plus a small local embedding model; word and vector results are fused | the library `@huggingface/transformers` 4.3.1, in the project or beside `al` |
|
|
180
|
+
|
|
181
|
+
- The default query is the current system: the spec text at the selected
|
|
182
|
+
commit. `--change <name>` adds that request's open change spec, its
|
|
183
|
+
sources and its evidence. `--history` adds removed, abandoned and replaced
|
|
184
|
+
text, marked as history.
|
|
185
|
+
- `--id <ID>` finds one paragraph by its exact ID, never through search.
|
|
186
|
+
`--level <0|1|2>` asks for a lower level; `--at <commit>` another commit.
|
|
187
|
+
- Each hit shows its role (`baseline`, `proposal`, `spike`, `source`,
|
|
188
|
+
`evidence` or `history`), its version and its commit.
|
|
189
|
+
- In the central repo, search covers the output repos that its committed
|
|
190
|
+
config lists, each at its resolved commit. The `Repos` line names each repo
|
|
191
|
+
and its commit, for example
|
|
192
|
+
`Repos invoicer@a6ac3a7785dd invoicer-web@5aa04042117b`. An output repo
|
|
193
|
+
gives `evidence` rows: its result files, and the files that cite a central
|
|
194
|
+
ID or that a record declares. Such a hit shows `<repo>:<path>`, and each
|
|
195
|
+
line that names a central ID, with its line number. A repo that is absent,
|
|
196
|
+
or a commit that cannot be found, gives no rows and a `Not known` line with
|
|
197
|
+
the reason.
|
|
198
|
+
- The index is one SQLite file inside `.git`, never committed. `al search`
|
|
199
|
+
brings it up to date before it answers; `--rebuild` builds it again.
|
|
200
|
+
- Level 2 runs a small local model (bge-small-en-v1.5, pinned by its
|
|
201
|
+
revision). The model download is the only data that leaves the machine.
|
|
202
|
+
`al` itself makes no network call. Without the library, `al search`
|
|
203
|
+
answers at level 1, and a `Not known` line says how to add level 2. Only
|
|
204
|
+
`al search` loads the library.
|
|
205
|
+
|
|
206
|
+
## One central repo, and output repos
|
|
207
|
+
|
|
208
|
+
The central repo holds `specs/`, the ADRs, the requests and the records. Its
|
|
209
|
+
config lists the output repos. An output repo holds code, tests and user
|
|
210
|
+
documents only; its config names the central repo.
|
|
211
|
+
|
|
212
|
+
- Code and tests in an output repo cite central IDs with a qualifier:
|
|
213
|
+
`central:INV-41`, `central:invoice-exports/R3`. A fix there says
|
|
214
|
+
`Tier: 0 — restores central:INV-41`.
|
|
215
|
+
- `al` reads another repo only through git, at the commit that config pins
|
|
216
|
+
or at the clone's HEAD, and never fetches. A repo or a commit that is not
|
|
217
|
+
there is "unknown", never a guess.
|
|
218
|
+
- In an output repo, `al check` looks up the central IDs that the branch's
|
|
219
|
+
changed files cite.
|
|
220
|
+
|
|
221
|
+
## Adopting AssuredLoop
|
|
222
|
+
|
|
223
|
+
1. Put the spec under the root (`specs/` by default), or set `root:`.
|
|
224
|
+
2. Mark every paragraph: `al spec --add-ids specs/<file>.md --prefix <P> --yes`
|
|
225
|
+
for each spec file. Headings get the kind `note`. Write the kind of each
|
|
226
|
+
other paragraph into its marker. An adopted paragraph needs no link.
|
|
227
|
+
3. Add the AGENTS.md line from "Install". Claim
|
|
228
|
+
`Tier: 0 — adds paragraph IDs; no promise changes`.
|
|
229
|
+
4. `al spec --add-ids --yes` also records where the adopted text came from.
|
|
230
|
+
For each paragraph it marks whose text is a block of the file at HEAD, in
|
|
231
|
+
the same place, it writes an entry with HEAD's commit and the text's hash
|
|
232
|
+
to `.assuredloop/records/requests/adoption.yaml`. It writes
|
|
233
|
+
`requests/archive/adoption/request.md` when that file is absent. So commit
|
|
234
|
+
the spec unmarked before you mark it. A paragraph whose text is not at
|
|
235
|
+
HEAD is not adopted: the command names it, and it follows its path as a
|
|
236
|
+
change. `source: adoption` says where the text came from. It is not an
|
|
237
|
+
owner approval, and it does not excuse a later change.
|
|
238
|
+
5. Run `al index`, and commit the markers and the records together. On that
|
|
239
|
+
branch, `al check --strict` reads the adopted paragraphs as unchanged, so
|
|
240
|
+
they need no sign-off and no path claim.
|
|
241
|
+
|
|
242
|
+
**A sign-off bound to the whole text.** Markers change a file's bytes. If a
|
|
243
|
+
signed requirement, or any other record, binds the whole text of a spec file
|
|
244
|
+
by its SHA-256, that hash no longer matches after the markers are added. Ask
|
|
245
|
+
the owner for a new approval after the conversion. The paragraph text itself
|
|
246
|
+
does not change; `al` hashes each paragraph without its marker.
|
|
247
|
+
|
|
248
|
+
**From 0.1.0.** v4 (0.2.0) does not read 0.1.0 records. Keep 0.1.0 pinned
|
|
249
|
+
until you move. Older records stay readable as files; run the pinned 0.1.0 at
|
|
250
|
+
those commits. To move:
|
|
251
|
+
|
|
252
|
+
1. Finish each open 0.1.0 request on its pinned copy, or start it again
|
|
253
|
+
under v4.
|
|
254
|
+
2. Install 0.2.0 (see "Install").
|
|
255
|
+
3. Run `al spec --add-ids`, as in steps 1-5 above. It marks every paragraph
|
|
256
|
+
and writes the adoption record.
|
|
214
257
|
|
|
215
258
|
## What is enforced, and by whom
|
|
216
259
|
|
|
217
|
-
The way of working (tests first, review, the PR flow) belongs to the bots that
|
|
218
|
-
use AssuredLoop, and is not in this table.
|
|
219
|
-
|
|
220
260
|
| The tool checks | The skill asks | The owner decides |
|
|
221
261
|
|---|---|---|
|
|
222
|
-
| `
|
|
223
|
-
|
|
|
224
|
-
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
262
|
+
| `al conclude` refuses on its three conditions (see "The close rule") | write the owner's words and the organized requirement, and ask for the sign-off | what is wanted, by signing the organized requirement |
|
|
263
|
+
| IDs: missing, used twice, lost, used again; kinds and links; links that do not resolve; sign-off coverage of promise changes; path and typo claims; dispositions and exact equality; stale bindings; overlapping changes; ADR text changes; result applicability, as hints | choose the path, and state it in a commit message and the PR | whether a changed requirement is signed again |
|
|
264
|
+
| `check --strict` exits 1 on a `not ok`, when a project opts in | record each later decision, with its source | decisions whose source is the owner, such as dropping or keeping work |
|
|
265
|
+
|
|
266
|
+
`al` checks that declarations are well formed and that references resolve.
|
|
267
|
+
It does not check that a kind is right, that a requirement is fully
|
|
268
|
+
covered, that a test checks the rule it names, or that a change is
|
|
269
|
+
authorized in substance; its views say "not checked" for these. Nothing is
|
|
270
|
+
installed in git hooks.
|
|
271
|
+
|
|
272
|
+
## Beyond code: results
|
|
273
|
+
|
|
274
|
+
A result file in `.assuredloop/results/` (or the `results:` folder) records a
|
|
275
|
+
check, a test run or a review:
|
|
276
|
+
|
|
277
|
+
```yaml
|
|
278
|
+
check: test/export-link.test.js
|
|
279
|
+
outcome: pass # pass, fail or not run
|
|
280
|
+
commit: <sha> # or unknown
|
|
281
|
+
inputs:
|
|
282
|
+
- {file: src/export-link.js, sha256: <sha256 of its bytes>}
|
|
283
|
+
by: ci # optional, with source and note
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
`al` shows "declared inputs unchanged since <commit>" when the inputs still
|
|
287
|
+
have those hashes, "does not apply to the current text" when one changed,
|
|
288
|
+
and "applicability unknown" when it cannot tell. That the declared inputs
|
|
289
|
+
are complete is a claim. The same works for a repo of documents: the report
|
|
290
|
+
is the deliverable, and a review result names it as its input.
|
|
241
291
|
|
|
242
292
|
## This repository
|
|
243
293
|
|
|
@@ -256,6 +306,8 @@ in this repository.
|
|
|
256
306
|
pre-release to publish under npm's `next` tag.
|
|
257
307
|
|
|
258
308
|
`.github/workflows/publish.yml` does the rest: it runs the tests and
|
|
259
|
-
`al check --strict`, checks that the tag matches `package.json`, and
|
|
260
|
-
@assuredloop/cli to npm. It
|
|
261
|
-
|
|
309
|
+
`al check --strict`, checks that the tag matches `package.json`, and
|
|
310
|
+
publishes @assuredloop/cli to npm. It skips a version that is already on npm,
|
|
311
|
+
so a failed run can run again. It stores no npm token: npm trusts the
|
|
312
|
+
workflow by name, and adds a provenance statement saying which commit built
|
|
313
|
+
the package.
|