@etiquekit/etq 1.0.13 → 1.0.14
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
CHANGED
|
@@ -1,78 +1,80 @@
|
|
|
1
1
|
# Etiquette
|
|
2
2
|
|
|
3
|
-
Etiquette is a
|
|
3
|
+
Etiquette is a local-first workflow and evidence CLI for teams that use coding
|
|
4
|
+
agents. Each task gets a named seat, bounded write scope, validation contract,
|
|
5
|
+
and receipt. Agents execute and report evidence; your human or Git gate still
|
|
6
|
+
decides what becomes canonical.
|
|
4
7
|
|
|
5
|
-
|
|
6
|
-
under which seat, inside what scope, with what evidence, and who accepted the
|
|
7
|
-
result.
|
|
8
|
+
## Install
|
|
8
9
|
|
|
9
|
-
|
|
10
|
+
Prerequisites: Git `>=2.40` and Bun `>=1.3`.
|
|
10
11
|
|
|
11
|
-
|
|
12
|
+
```sh
|
|
13
|
+
npm install --global @etiquekit/etq
|
|
14
|
+
etq --version
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
`etq` and `etiquette` are aliases for the same CLI.
|
|
12
18
|
|
|
13
|
-
## Start
|
|
19
|
+
## Start A Governed Task
|
|
14
20
|
|
|
15
|
-
|
|
16
|
-
For a clean repo or a new seat, read [QuickStart.md](QuickStart.md). For private team rollout, use [docs/TEAM_HANDOFF.md](docs/TEAM_HANDOFF.md), then:
|
|
21
|
+
Run inside a Git repository:
|
|
17
22
|
|
|
18
23
|
```sh
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
./bin/etiquette status --project /tmp/etiquette-start
|
|
25
|
-
./bin/etiquette join --project /tmp/etiquette-start --seat impl-seat
|
|
26
|
-
./bin/etiquette pickup --project /tmp/etiquette-start --seat impl-seat --task APP-001 --allow-current-project --text
|
|
27
|
-
./bin/etiquette console board --project /tmp/etiquette-start --text
|
|
24
|
+
etq bootstrap local --project . --task-prefix APP --ask
|
|
25
|
+
etq doctor --project .
|
|
26
|
+
etq whereami --project . --seat impl-seat --task APP-001
|
|
27
|
+
etq join --project . --seat impl-seat
|
|
28
|
+
etq pickup --project . --seat impl-seat --task APP-001 --allow-current-project --text
|
|
28
29
|
```
|
|
29
30
|
|
|
30
|
-
|
|
31
|
+
The default is one implementation seat and one bounded task. Etiquette asks
|
|
32
|
+
before adding review seats and remains non-interactive in CI. A seat is a
|
|
33
|
+
durable role; Claude Code, Codex, Gemini, or another runtime is its temporary
|
|
34
|
+
occupant.
|
|
31
35
|
|
|
32
|
-
|
|
33
|
-
local packet events, and pickup docs without global bus writes or authority.
|
|
34
|
-
`whereami` is the context readback: runner resume restores conversation
|
|
35
|
-
history; `whereami` tells the seat which project, worktree, task, and runbook it
|
|
36
|
-
is actually operating in.
|
|
36
|
+
## Daily Loop
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
```text
|
|
39
|
+
orient -> pick up bounded work -> implement -> validate -> return a receipt -> promote through the existing gate
|
|
40
|
+
```
|
|
39
41
|
|
|
40
|
-
|
|
42
|
+
Use `whereami`, `status`, `console board`, and `return check` to inspect work.
|
|
43
|
+
Read commands do not initialize directories or rewrite event streams. Explicit
|
|
44
|
+
setup, bootstrap, post, and lifecycle commands own their writes.
|
|
41
45
|
|
|
42
|
-
|
|
43
|
-
- Task envelope: scope, allowed writes, validation, and stop conditions.
|
|
44
|
-
- Receipt: evidence of what happened; it proves but does not authorize.
|
|
45
|
-
- Promotion gate: the human/Git gate where candidate work becomes truth.
|
|
46
|
-
- Ledger: durable local record of sessions, receipts, and decisions.
|
|
46
|
+
## Core Records
|
|
47
47
|
|
|
48
|
-
|
|
48
|
+
- **Seat:** durable work identity, independent of model or vendor.
|
|
49
|
+
- **Task envelope:** allowed writes, required validation, and stop conditions.
|
|
50
|
+
- **Receipt:** evidence of what ran and changed; evidence is not authority.
|
|
51
|
+
- **Local ledger:** Git-readable events and packet references.
|
|
52
|
+
- **Promotion gate:** the existing decision that accepts candidate work.
|
|
49
53
|
|
|
50
|
-
|
|
54
|
+
Etiquette is not a hosted executor, transport service, portal, or replacement
|
|
55
|
+
for source-control permissions. Consumers may bind packet profiles and their
|
|
56
|
+
own transport; the package does not silently write a global ledger.
|
|
51
57
|
|
|
52
|
-
|
|
53
|
-
sh templates/seat-packs-v0/bin/provision-seat codex /tmp/dev-codex-seat
|
|
54
|
-
sh templates/seat-packs-v0/bin/provision-seat claude-code /tmp/dev-claude-code-seat
|
|
55
|
-
sh templates/seat-packs-v0/bin/provision-seat gemini /tmp/dev-gemini-seat
|
|
56
|
-
sh templates/seat-packs-v0/bin/provision-seat ollama /tmp/dev-ollama-seat
|
|
57
|
-
sh templates/seat-packs-v0/bin/provision-seat openrouter /tmp/dev-openrouter-seat
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
## Validate
|
|
58
|
+
## Author A Draft Without Project State
|
|
61
59
|
|
|
62
60
|
```sh
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
61
|
+
etq post --profile ./packet-profile.yaml --draft \
|
|
62
|
+
--out /tmp/review-return.md --kind review-return --work-id APP-001 \
|
|
63
|
+
--author impl-seat --recipient review-seat \
|
|
64
|
+
--summary "Implementation complete." --evidence "Checks passed." \
|
|
65
|
+
--next-step "Review the candidate."
|
|
66
66
|
```
|
|
67
67
|
|
|
68
|
-
|
|
68
|
+
Draft mode writes only the requested output. It does not create `.etiquette`,
|
|
69
|
+
emit an event, grant authority, merge, close, or publish.
|
|
69
70
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
71
|
+
Optional runtime packs: `provision-seat claude-code`, `provision-seat codex`, `provision-seat gemini`, `provision-seat ollama`, `provision-seat openrouter`.
|
|
72
|
+
## Documentation
|
|
73
|
+
|
|
74
|
+
[Quick start](QuickStart.md) | [Concepts](docs/CONCEPTS.md) |
|
|
75
|
+
[Core profile](docs/CORE_PROFILE.md) | [Seats](docs/SEAT_PROVISIONING.md) |
|
|
76
|
+
[Worktrees](docs/WORKTREE_QOL.md)
|
|
75
77
|
|
|
76
78
|
## License
|
|
77
79
|
|
|
78
|
-
Apache-2.0
|
|
80
|
+
Apache-2.0. See [LICENSE](LICENSE) and [NOTICE](NOTICE).
|
|
@@ -94,7 +94,7 @@ package_surface:
|
|
|
94
94
|
npm_pack_entries: 183
|
|
95
95
|
max_budget: 190
|
|
96
96
|
posture: local devkit package plus signed user-local installer
|
|
97
|
-
distribution_origin: https://
|
|
97
|
+
distribution_origin: https://etiquekit.com
|
|
98
98
|
excludes: workspace package metadata, workspace fixtures, internal, conformance, apps, site, dist, hosted parity docs, portal docs, root kernel manuals
|
|
99
99
|
```
|
|
100
100
|
|
|
@@ -142,7 +142,7 @@ npm run release:scan
|
|
|
142
142
|
|
|
143
143
|
## Package Readiness Check
|
|
144
144
|
|
|
145
|
-
Use `etiquette release readiness --json` before changing distribution settings. It also binds the canonical package identity, version floor, source-shipping mode, required bins, source ancestry, and candidate verifier to `release/lineage.v0.json`; `release:candidate` preserves the exact verified tarball and checksum under ignored `dist/` for later signing without rebuilding.
|
|
145
|
+
Use `etiquette release readiness --json` before changing distribution settings. It also binds the canonical package identity, version floor, source-shipping mode, required bins, source ancestry, public distribution repository, and candidate verifier to `release/lineage.v0.json`; the source-of-record and public package home remain separate, explicit lineage fields. `release:candidate` preserves the exact verified tarball and checksum under ignored `dist/` for later signing without rebuilding.
|
|
146
146
|
Codex-backed remote-runtime, plugin-MCP, and hook/action-auth canaries require CLI `0.141.0`+ (`docs/CODEX_CLIENT_COMPATIBILITY.md`). GA additionally runs `etiquette release ga-readiness --channel shell-installer,npm --tag-free-confirmed --json`; it requires a non-prerelease version, final tarball checksums, trusted RSA signature, private-compatible channels, and explicit remote-tag uniqueness confirmation, while still unable to publish, sign, tag, or create a channel. Git source archives must exclude maintainer-only `internal/`, `conformance/`, `site/`, `fixtures/`, `apps/`, local state, and `dist/`.
|
|
147
147
|
|
|
148
148
|
## Local-Thin Purge (v0.2.1)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@etiquekit/etq",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.14",
|
|
4
4
|
"description": "Governance and evidence CLI for AI-assisted engineering seats.",
|
|
5
5
|
"private": false,
|
|
6
6
|
"type": "module",
|
|
@@ -51,9 +51,9 @@
|
|
|
51
51
|
"homepage": "https://etiquekit.com",
|
|
52
52
|
"repository": {
|
|
53
53
|
"type": "git",
|
|
54
|
-
"url": "git+https://github.com/leepickdev/etq
|
|
54
|
+
"url": "git+https://github.com/leepickdev/etq.git"
|
|
55
55
|
},
|
|
56
56
|
"bugs": {
|
|
57
|
-
"url": "https://github.com/leepickdev/etq
|
|
57
|
+
"url": "https://github.com/leepickdev/etq/issues"
|
|
58
58
|
}
|
|
59
59
|
}
|
|
@@ -550,6 +550,14 @@ function isInitializedLocalProject(root: string): boolean {
|
|
|
550
550
|
return existsSync(projectBindingPath(root)) && existsSync(eventPath(root));
|
|
551
551
|
}
|
|
552
552
|
|
|
553
|
+
async function requireInitializedProjectBinding(root: string, command: string): Promise<NonNullable<Awaited<ReturnType<typeof readProjectBinding>>>> {
|
|
554
|
+
const project = await readProjectBinding(root);
|
|
555
|
+
if (!project || !isInitializedLocalProject(root)) {
|
|
556
|
+
throw new Error(`${command} requires an initialized local Etiquette project; run etiquette init --project <path> first`);
|
|
557
|
+
}
|
|
558
|
+
return project;
|
|
559
|
+
}
|
|
560
|
+
|
|
553
561
|
function relativeRef(root: string, path: string): string {
|
|
554
562
|
const rel = relative(root, resolve(path));
|
|
555
563
|
if (rel.length === 0 || rel.startsWith('..') || rel.includes('\\')) {
|
|
@@ -1368,8 +1376,8 @@ async function ensureLocalProject(root: string): Promise<void> {
|
|
|
1368
1376
|
}
|
|
1369
1377
|
|
|
1370
1378
|
async function readEvents(root: string): Promise<LocalEvent[]> {
|
|
1371
|
-
await
|
|
1372
|
-
|
|
1379
|
+
const raw = await readTextIfExists(eventPath(root));
|
|
1380
|
+
if (!raw) return [];
|
|
1373
1381
|
return raw
|
|
1374
1382
|
.split('\n')
|
|
1375
1383
|
.map((line) => line.trim())
|
|
@@ -1844,17 +1852,14 @@ async function validateSeatCard(path: string): Promise<string> {
|
|
|
1844
1852
|
}
|
|
1845
1853
|
|
|
1846
1854
|
async function enrollmentPath(root: string, seat: string): Promise<string> {
|
|
1847
|
-
await ensureLocalProject(root);
|
|
1848
1855
|
return join(root, '.etiquette', 'roster', 'enrollments', `${safeName(seat)}.json`);
|
|
1849
1856
|
}
|
|
1850
1857
|
|
|
1851
1858
|
async function subscriptionPath(root: string, seat: string): Promise<string> {
|
|
1852
|
-
await ensureLocalProject(root);
|
|
1853
1859
|
return join(root, '.etiquette', 'notify', 'subscriptions', `${safeName(seat)}.json`);
|
|
1854
1860
|
}
|
|
1855
1861
|
|
|
1856
1862
|
async function wakeQueuePath(root: string, seat: string): Promise<string> {
|
|
1857
|
-
await ensureLocalProject(root);
|
|
1858
1863
|
return join(root, '.etiquette', 'notify', 'queues', `${safeName(seat)}.json`);
|
|
1859
1864
|
}
|
|
1860
1865
|
|
|
@@ -2492,7 +2497,6 @@ async function retirePath(
|
|
|
2492
2497
|
async function dispatchTrash(positionals: string[], flags: Record<string, string | boolean>): Promise<void> {
|
|
2493
2498
|
const verb = positionals[1];
|
|
2494
2499
|
const root = projectRoot(flags);
|
|
2495
|
-
await ensureLocalProject(root);
|
|
2496
2500
|
|
|
2497
2501
|
if (verb === 'retire') {
|
|
2498
2502
|
await retirePath(requirePositional(positionals, 2, 'path'), flags);
|
|
@@ -2521,6 +2525,7 @@ async function dispatchTrash(positionals: string[], flags: Record<string, string
|
|
|
2521
2525
|
}
|
|
2522
2526
|
|
|
2523
2527
|
if (verb === 'restore') {
|
|
2528
|
+
await ensureLocalProject(root);
|
|
2524
2529
|
const trashId = requirePositional(positionals, 2, 'trash-id');
|
|
2525
2530
|
const entries = await readTrashEntries(root);
|
|
2526
2531
|
const entry = entries.find((candidate) => candidate.trash_id === trashId);
|
|
@@ -2550,6 +2555,7 @@ async function dispatchTrash(positionals: string[], flags: Record<string, string
|
|
|
2550
2555
|
}
|
|
2551
2556
|
|
|
2552
2557
|
if (verb === 'rebuild') {
|
|
2558
|
+
await ensureLocalProject(root);
|
|
2553
2559
|
const events = await readEvents(root);
|
|
2554
2560
|
const entries = events
|
|
2555
2561
|
.map((event) => asRecord(event, 'local event').trash_entry)
|
|
@@ -3041,8 +3047,7 @@ async function dispatchHandoff(flags: Record<string, string | boolean>): Promise
|
|
|
3041
3047
|
|
|
3042
3048
|
async function dispatchJoin(flags: Record<string, string | boolean>): Promise<void> {
|
|
3043
3049
|
const root = projectRoot(flags);
|
|
3044
|
-
await
|
|
3045
|
-
const project = await ensureProjectBinding(root, optionalString(flags, 'at'));
|
|
3050
|
+
const project = await requireInitializedProjectBinding(root, 'join');
|
|
3046
3051
|
assertEngagementProject(project.project_id, optionalString(flags, 'expect-project-id'), 'current project');
|
|
3047
3052
|
const seatInput = requireString(flags, 'seat');
|
|
3048
3053
|
const resolvedSeat = resolveSeatFromEnrollments(await listEnrollments(root), seatInput);
|
|
@@ -3519,8 +3524,7 @@ async function dispatchWhereami(flags: Record<string, string | boolean>): Promis
|
|
|
3519
3524
|
|
|
3520
3525
|
async function dispatchPickup(flags: Record<string, string | boolean>): Promise<void> {
|
|
3521
3526
|
const root = projectRoot(flags);
|
|
3522
|
-
await
|
|
3523
|
-
const project = await ensureProjectBinding(root, optionalString(flags, 'at'));
|
|
3527
|
+
const project = await requireInitializedProjectBinding(root, 'pickup');
|
|
3524
3528
|
assertPickupProjectExpectation(project.project_id, flags);
|
|
3525
3529
|
const seatInput = requireString(flags, 'seat');
|
|
3526
3530
|
const task = requireString(flags, 'task');
|
|
@@ -3624,7 +3628,6 @@ async function dispatchAudit(positionals: string[], flags: Record<string, string
|
|
|
3624
3628
|
async function dispatchRoster(positionals: string[], flags: Record<string, string | boolean>): Promise<void> {
|
|
3625
3629
|
const verb = positionals[1];
|
|
3626
3630
|
const root = projectRoot(flags);
|
|
3627
|
-
await ensureLocalProject(root);
|
|
3628
3631
|
|
|
3629
3632
|
if (verb === 'card') {
|
|
3630
3633
|
const cardVerb = positionals[2];
|
|
@@ -3636,6 +3639,7 @@ async function dispatchRoster(positionals: string[], flags: Record<string, strin
|
|
|
3636
3639
|
}
|
|
3637
3640
|
|
|
3638
3641
|
if (verb === 'enroll') {
|
|
3642
|
+
await ensureLocalProject(root);
|
|
3639
3643
|
const seat = requirePositional(positionals, 2, 'seat');
|
|
3640
3644
|
const project = await ensureProjectBinding(root, optionalString(flags, 'at'));
|
|
3641
3645
|
const card = requireString(flags, 'card');
|
|
@@ -3687,6 +3691,7 @@ async function dispatchRoster(positionals: string[], flags: Record<string, strin
|
|
|
3687
3691
|
}
|
|
3688
3692
|
|
|
3689
3693
|
if (verb === 'ready') {
|
|
3694
|
+
await ensureLocalProject(root);
|
|
3690
3695
|
const seat = requirePositional(positionals, 2, 'seat');
|
|
3691
3696
|
const project = await ensureProjectBinding(root, optionalString(flags, 'at'));
|
|
3692
3697
|
const path = await enrollmentPath(root, seat);
|
|
@@ -3732,6 +3737,7 @@ async function dispatchRoster(positionals: string[], flags: Record<string, strin
|
|
|
3732
3737
|
}
|
|
3733
3738
|
|
|
3734
3739
|
if (verb === 'lifecycle') {
|
|
3740
|
+
await ensureLocalProject(root);
|
|
3735
3741
|
const seat = requirePositional(positionals, 2, 'seat');
|
|
3736
3742
|
const rawState = requireString(flags, 'state');
|
|
3737
3743
|
assertLifecycleState(rawState, '--state');
|
|
@@ -3963,9 +3969,8 @@ async function dispatchNotify(positionals: string[], flags: Record<string, strin
|
|
|
3963
3969
|
return;
|
|
3964
3970
|
}
|
|
3965
3971
|
|
|
3966
|
-
await ensureLocalProject(root);
|
|
3967
|
-
|
|
3968
3972
|
if (verb === 'subscribe') {
|
|
3973
|
+
await ensureLocalProject(root);
|
|
3969
3974
|
const seatInput = requireString(flags, 'seat');
|
|
3970
3975
|
const resolvedSeat = resolveSeatFromEnrollments(await listEnrollments(root), seatInput);
|
|
3971
3976
|
const seat = resolvedSeat.seat;
|
|
@@ -4004,6 +4009,7 @@ async function dispatchNotify(positionals: string[], flags: Record<string, strin
|
|
|
4004
4009
|
}
|
|
4005
4010
|
|
|
4006
4011
|
if (verb === 'poll') {
|
|
4012
|
+
await ensureLocalProject(root);
|
|
4007
4013
|
const seatInput = requireString(flags, 'seat');
|
|
4008
4014
|
const resolvedSeat = resolveSeatFromEnrollments(await listEnrollments(root), seatInput);
|
|
4009
4015
|
const seat = resolvedSeat.seat;
|
|
@@ -4121,7 +4127,6 @@ async function dispatchRig(positionals: string[], flags: Record<string, string |
|
|
|
4121
4127
|
const verb = positionals[1];
|
|
4122
4128
|
if (verb !== 'doctor') throw new Error('rig verb must be: doctor');
|
|
4123
4129
|
const root = projectRoot(flags);
|
|
4124
|
-
await ensureLocalProject(root);
|
|
4125
4130
|
const required = [
|
|
4126
4131
|
projectBindingPath(root),
|
|
4127
4132
|
eventPath(root),
|
|
@@ -4130,7 +4135,8 @@ async function dispatchRig(positionals: string[], flags: Record<string, string |
|
|
|
4130
4135
|
];
|
|
4131
4136
|
const missing = required.filter((path) => !existsSync(path));
|
|
4132
4137
|
if (missing.length > 0) throw new Error(`rig doctor failed; missing: ${missing.map((path) => relativeRef(root, path)).join(', ')}`);
|
|
4133
|
-
const project = await
|
|
4138
|
+
const project = await readProjectBinding(root);
|
|
4139
|
+
if (!project) throw new Error('rig doctor failed; project binding is missing');
|
|
4134
4140
|
const sessions = await listSessions(root);
|
|
4135
4141
|
const mismatched = sessions.filter((session) => session.project_id !== project.project_id);
|
|
4136
4142
|
if (mismatched.length > 0) {
|
|
@@ -4236,7 +4242,6 @@ async function dispatchBus(positionals: string[], flags: Record<string, string |
|
|
|
4236
4242
|
console.log(format === 'markdown' ? renderLocalLedgerViewMarkdown(view) : renderLocalLedgerViewText(view));
|
|
4237
4243
|
return;
|
|
4238
4244
|
}
|
|
4239
|
-
await ensureLocalProject(root);
|
|
4240
4245
|
const events = await readEvents(root);
|
|
4241
4246
|
|
|
4242
4247
|
if (verb === 'status') {
|
|
@@ -4263,14 +4268,14 @@ async function dispatchBus(positionals: string[], flags: Record<string, string |
|
|
|
4263
4268
|
|
|
4264
4269
|
async function dispatchStatus(flags: Record<string, string | boolean>): Promise<void> {
|
|
4265
4270
|
const root = projectRoot(flags);
|
|
4266
|
-
await
|
|
4267
|
-
const project = await ensureProjectBinding(root, optionalString(flags, 'at'));
|
|
4271
|
+
const project = await readProjectBinding(root);
|
|
4268
4272
|
const events = await readEvents(root);
|
|
4269
4273
|
const enrollments = await listJsonFiles(join(root, '.etiquette', 'roster', 'enrollments'));
|
|
4270
4274
|
console.log([
|
|
4271
4275
|
'workspace_status:',
|
|
4272
4276
|
` project: ${root}`,
|
|
4273
|
-
` project_id: ${project
|
|
4277
|
+
` project_id: ${project?.project_id ?? 'none'}`,
|
|
4278
|
+
` initialized: ${String(isInitializedLocalProject(root))}`,
|
|
4274
4279
|
` events: ${events.length}`,
|
|
4275
4280
|
` enrolled_seats: ${enrollments.length}`,
|
|
4276
4281
|
' authority_boundary: read_only_without_grant',
|
|
@@ -4666,7 +4671,6 @@ export async function dispatchLocalWorkflow(
|
|
|
4666
4671
|
|
|
4667
4672
|
export async function renderLocalBoard(projectRoot: string, seat?: string): Promise<string> {
|
|
4668
4673
|
const root = resolve(projectRoot);
|
|
4669
|
-
await ensureLocalProject(root);
|
|
4670
4674
|
const resolvedSeat = seat ? resolveSeatFromEnrollments(await listEnrollments(root), seat) : null;
|
|
4671
4675
|
const boardSeat = resolvedSeat?.seat ?? null;
|
|
4672
4676
|
const board = await readTextIfExists(join(root, 'docs', 'work', 'BOARD.md'));
|
|
@@ -452,6 +452,7 @@ async function appendReleaseLineageChecks(
|
|
|
452
452
|
const registryFloor = asString(lineage.registry_floor);
|
|
453
453
|
const distributionMode = asString(lineage.distribution_mode);
|
|
454
454
|
const sourceRepository = asString(lineage.source_repository);
|
|
455
|
+
const distributionRepository = asString(lineage.distribution_repository);
|
|
455
456
|
const sourceBaseCommit = asString(lineage.source_base_commit);
|
|
456
457
|
const requiredBins = asStringArray(lineage.required_bins);
|
|
457
458
|
const packageRepository = repositoryUrl(packageJson.repository);
|
|
@@ -491,14 +492,24 @@ async function appendReleaseLineageChecks(
|
|
|
491
492
|
'restore all reviewed CLI aliases before building the candidate',
|
|
492
493
|
));
|
|
493
494
|
|
|
494
|
-
checks.push(sourceRepository
|
|
495
|
-
? check('pass', 'release_source_repository', `
|
|
495
|
+
checks.push(sourceRepository
|
|
496
|
+
? check('pass', 'release_source_repository', `source repository is declared: ${sourceRepository}`, RELEASE_LINEAGE_REF)
|
|
496
497
|
: check(
|
|
497
498
|
'block',
|
|
498
499
|
'release_source_repository',
|
|
499
|
-
|
|
500
|
+
'source repository is missing from release lineage',
|
|
500
501
|
RELEASE_LINEAGE_REF,
|
|
501
|
-
'
|
|
502
|
+
'declare the reviewed source-of-record repository',
|
|
503
|
+
));
|
|
504
|
+
|
|
505
|
+
checks.push(distributionRepository && packageRepository === distributionRepository
|
|
506
|
+
? check('pass', 'release_distribution_repository', `package repository matches public distribution home: ${distributionRepository}`, RELEASE_LINEAGE_REF)
|
|
507
|
+
: check(
|
|
508
|
+
'block',
|
|
509
|
+
'release_distribution_repository',
|
|
510
|
+
`package repository does not match public distribution home: package=${packageRepository ?? 'unknown'} lineage=${distributionRepository ?? 'unknown'}`,
|
|
511
|
+
RELEASE_LINEAGE_REF,
|
|
512
|
+
'point package metadata at the reviewed public distribution repository',
|
|
502
513
|
));
|
|
503
514
|
|
|
504
515
|
const shipsSource = packageInfo.files.includes('packages/control/src/')
|
package/release/lineage.v0.json
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schema": "etq-release-lineage.v0",
|
|
3
3
|
"package_name": "@etiquekit/etq",
|
|
4
|
-
"candidate_version": "1.0.
|
|
4
|
+
"candidate_version": "1.0.14",
|
|
5
5
|
"distribution_mode": "bun-typescript-source",
|
|
6
6
|
"source_repository": "git+https://github.com/leepickdev/etq-devkit.git",
|
|
7
|
-
"
|
|
8
|
-
"
|
|
7
|
+
"distribution_repository": "git+https://github.com/leepickdev/etq.git",
|
|
8
|
+
"source_base_commit": "b2384dc782548ce0d712da3bd33e108d977adb44",
|
|
9
|
+
"registry_floor": "1.0.13",
|
|
9
10
|
"required_bins": [
|
|
10
11
|
"etq",
|
|
11
12
|
"etiquette",
|