@bongos/core 1.20.42 → 1.20.44
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/.bongos-core.json +99 -74
- package/.claude/skills/backlog-review/SKILL.md +1 -0
- package/.claude/skills/blocker-review/SKILL.md +1 -1
- package/.claude/skills/bug-triage/SKILL.md +1 -0
- package/.claude/skills/builder-backup/SKILL.md +1 -0
- package/.claude/skills/builder-claim/SKILL.md +1 -1
- package/.claude/skills/builder-cost/SKILL.md +1 -0
- package/.claude/skills/builder-exit/SKILL.md +1 -0
- package/.claude/skills/builder-key/SKILL.md +1 -1
- package/.claude/skills/builder-reauth/SKILL.md +1 -1
- package/.claude/skills/builder-redteam/SKILL.md +1 -1
- package/.claude/skills/builder-sequence/SKILL.md +1 -1
- package/.claude/skills/builder-setup/SKILL.md +1 -1
- package/.claude/skills/collab-review/SKILL.md +1 -1
- package/.claude/skills/design/SKILL.md +1 -1
- package/.claude/skills/design-sync/SKILL.md +1 -0
- package/.claude/skills/feedback/SKILL.md +1 -1
- package/.claude/skills/figma-design-sync/SKILL.md +1 -0
- package/.claude/skills/goal-close/SKILL.md +184 -0
- package/.claude/skills/goal-create/SKILL.md +1 -1
- package/.claude/skills/goal-review/SKILL.md +5 -102
- package/.claude/skills/goal-uat/SKILL.md +5 -81
- package/.claude/skills/grade-audit/SKILL.md +6 -85
- package/.claude/skills/grade-recover/SKILL.md +1 -1
- package/.claude/skills/grade-sweep/SKILL.md +174 -0
- package/.claude/skills/grader-health/SKILL.md +5 -72
- package/.claude/skills/idea-triage/SKILL.md +1 -0
- package/.claude/skills/merge-mode/SKILL.md +1 -1
- package/.claude/skills/new-project/SKILL.md +1 -0
- package/.claude/skills/owner-review/SKILL.md +40 -0
- package/.claude/skills/planning-session/SKILL.md +1 -0
- package/.claude/skills/priority-session/SKILL.md +1 -0
- package/.claude/skills/read-session-export/SKILL.md +1 -1
- package/.claude/skills/recall/SKILL.md +1 -1
- package/.claude/skills/scan-before-install/SKILL.md +1 -1
- package/.claude/skills/session-handoff/SKILL.md +1 -1
- package/.claude/skills/worktree-clean/SKILL.md +1 -1
- package/docs/api/openapi.json +1 -1
- package/docs/file-map.md +12 -10
- package/docs/module-api-changelog.md +4 -0
- package/docs/modules-contract.md +3 -0
- package/docs/onboarding/slash-commands.md +17 -11
- package/docs/packs/artist.md +1 -1
- package/docs/packs/engineer.md +4 -5
- package/docs/page-readings.json +21 -21
- package/modules/copy-desk/module.json +1 -1
- package/{.claude → modules/copy-desk}/skills/tweak/SKILL.md +1 -0
- package/modules/hall-ui/public/collab.css +8 -1
- package/modules/hall-ui/public/oversight.css +0 -3
- package/modules/lifecycle/dependency-advisory.js +2 -2
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/release-notes.json +16 -0
- package/scripts/gds/fitness-ratchets.js +2 -0
- package/scripts/gds/module-artifact.js +52 -2
- package/scripts/gds/module.js +57 -4
- package/scripts/gds/skill-lint.js +32 -9
- package/src/bongos/routes/modules.js +5 -4
- package/src/module-api.js +1 -1
- package/src/module-loader/manifest-schema.js +28 -0
- package/tests/hall_lead_row_home.mjs +21 -0
- package/tests/module_manifest.mjs +22 -0
- package/tests/module_store_publish.mjs +88 -4
- package/tests/module_store_publish_route.mjs +20 -1
- package/tests/skill_grade_audit.mjs +34 -17
- package/tests/skill_grader_health.mjs +28 -10
- package/tests/skill_lint.mjs +37 -0
- package/tests/skill_menu_ruling.mjs +99 -0
|
@@ -42,29 +42,31 @@ Every one of these talks to the build system. They're grouped by when you'd reac
|
|
|
42
42
|
| `/builder-setup` | One-time enrolment — signs you in and registers you |
|
|
43
43
|
| `/builder-reauth` | Refresh an expired session |
|
|
44
44
|
| `/builder-key` | Check / set your own API key status |
|
|
45
|
-
| `/builder-cost` | Log
|
|
46
|
-
| `/builder-backup` | Check or trigger a database backup before risky work |
|
|
47
|
-
| `/builder-exit` | Offboard or reactivate a builder *(Archon only)* |
|
|
45
|
+
| `/builder-cost` † | Log or read project spend |
|
|
46
|
+
| `/builder-backup` † | Check or trigger a database backup before risky work |
|
|
47
|
+
| `/builder-exit` † | Offboard or reactivate a builder *(Archon only)* |
|
|
48
48
|
|
|
49
49
|
### Triage and planning *(Metic and above)*
|
|
50
50
|
|
|
51
51
|
| Command | What it does |
|
|
52
52
|
|---|---|
|
|
53
|
-
| `/
|
|
53
|
+
| `/owner-review` | One walk through everything waiting on a decision: backlog → bugs → ideas → priorities. Say *"triage ideas"* or *"review the backlog"* and it opens at that step |
|
|
54
54
|
| `/blocker-review` · `/blocker-solve` | Walk open blockers, or drive one to done |
|
|
55
55
|
| `/goal-create` | Plan and create one goal — scope wall, criteria, seed tasks |
|
|
56
|
-
| `/goal-
|
|
57
|
-
| `/planning-session` | Scope an upcoming version and seed its task list |
|
|
58
|
-
| `/
|
|
56
|
+
| `/goal-close` † | Close a goal's criteria: test them on the live site and sign off, then decide the ones nothing was delivered for |
|
|
57
|
+
| `/planning-session` † | Scope an upcoming version and seed its task list |
|
|
58
|
+
| `/grade-sweep` † | Check the grader is healthy, then audit what shipped past it |
|
|
59
59
|
| `/merge-mode` | Manual fallback when a confirmed task didn't land |
|
|
60
60
|
|
|
61
|
+
The four steps of `/owner-review` still answer to their old names — `/backlog-review`, `/bug-triage`, `/idea-triage`, `/priority-session` — and so do `/goal-uat` · `/goal-review` (now the two parts of `/goal-close`) and `/grader-health` · `/grade-audit` (now the two parts of `/grade-sweep`). All of those are typed-only (†).
|
|
62
|
+
|
|
61
63
|
### Discipline modes — not slash commands any more
|
|
62
64
|
|
|
63
65
|
The three core crafts no longer have a slash command. `/dev`, `/paint` and `/ideate` were **deleted** when the root instructions split into a role-neutral kernel (`CLAUDE.md`) plus one **role pack** per craft: `docs/packs/engineer.md`, `docs/packs/artist.md`, `docs/packs/ideator.md`. A claimed task's discipline routes you to your pack — the Conductor injects its path into your session on the next prompt, and `claim.js` prints a one-line reminder — and you read it. A module-contributed discipline can still ship a skill, which is how `ui` → `/design` below works.
|
|
64
66
|
|
|
65
67
|
### Design and art pipeline
|
|
66
68
|
|
|
67
|
-
`/design` is the ui-discipline playbook (world-first, show-first — shipped by the `ui-design` module, ADR 0197); `/design-sync` and `/figma-design-sync` round-trip the UI design system. The `/otb-*` family — `otb-tile-generate`, `otb-design-review`, `otb-character-review`, `otb-feedback-capture`, `otb-figma-sync` — is the reference instance's pixel-art pipeline; it's only meaningful on an instance that runs that pipeline, so it ships in the `pixel-art` module, which is off unless the project turns it on. The design-style skills (`/impeccable`, `/style`, the taste and look skills) are the same: the `design-styles` module, off unless turned on — `/design` tells you which.
|
|
69
|
+
`/design` is the ui-discipline playbook (world-first, show-first — shipped by the `ui-design` module, ADR 0197); `/design-sync` † and `/figma-design-sync` † round-trip the UI design system. `/tweak` † applies the next page an artist rewrote in the studio; it ships in the `copy-desk` module, where the studio lives. The `/otb-*` family — `otb-tile-generate`, `otb-design-review`, `otb-character-review`, `otb-feedback-capture`, `otb-figma-sync` — is the reference instance's pixel-art pipeline; it's only meaningful on an instance that runs that pipeline, so it ships in the `pixel-art` module, which is off unless the project turns it on. The design-style skills (`/impeccable`, `/style`, the taste and look skills) are the same: the `design-styles` module, off unless turned on — `/design` tells you which.
|
|
68
70
|
|
|
69
71
|
### Session and meta
|
|
70
72
|
|
|
@@ -73,9 +75,13 @@ The three core crafts no longer have a slash command. `/dev`, `/paint` and `/ide
|
|
|
73
75
|
| `/session-handoff` | Emit a paste-ready prompt to start a fresh session with |
|
|
74
76
|
| `/read-session-export` | Read a past session's `/export` zip |
|
|
75
77
|
| `/feedback` | Pull in the latest recorded walkthrough bundle |
|
|
76
|
-
| `/new-project` | Zero-to-live runbook for a brand-new instance |
|
|
78
|
+
| `/new-project` † | Zero-to-live runbook for a brand-new instance |
|
|
77
79
|
| `/builder-redteam` | File a security / vulnerability report |
|
|
78
80
|
|
|
81
|
+
### † Typed-only commands
|
|
82
|
+
|
|
83
|
+
A command marked † is **hidden from Claude's own menu but still works when you type it**. Every listed command's description sits in every session's context whether it is used or not, so the rarely-used admin ones carry `disable-model-invocation: true` in their `SKILL.md`: Claude Code leaves them out of what the model sees, and only a person typing `/name` runs them (task 1004471). The catch: plain English will not reach them, and Claude will not start one on its own — type the slash form.
|
|
84
|
+
|
|
79
85
|
## Claude Code's own commands
|
|
80
86
|
|
|
81
87
|
These work in **any** repository — they have nothing to do with this project. `/help` prints the live, authoritative list for your version; the ones below are simply the ones you'll actually meet.
|
|
@@ -111,11 +117,11 @@ These are the ones that actually cause confusion.
|
|
|
111
117
|
|
|
112
118
|
**`/export` vs `/read-session-export`.** Claude's `/export` *writes* a transcript zip; our `/read-session-export` *reads* one back.
|
|
113
119
|
|
|
114
|
-
**`/review` reviews a GitHub PR.** The project's review commands are `/
|
|
120
|
+
**`/review` reviews a GitHub PR.** The project's review commands are `/owner-review`, `/blocker-review`, and `/goal-close` — different jobs entirely.
|
|
115
121
|
|
|
116
122
|
## Two more things worth knowing
|
|
117
123
|
|
|
118
|
-
**Every command has a plain-English twin.** Each skill lists trigger phrases, so *"what can I work on"* reaches `/builder-start` and *"ship it"* reaches `/builder-ship`. You never have to memorise the slash form.
|
|
124
|
+
**Every listed command has a plain-English twin.** Each skill lists trigger phrases, so *"what can I work on"* reaches `/builder-start` and *"ship it"* reaches `/builder-ship`. You never have to memorise the slash form — except for the typed-only † commands above.
|
|
119
125
|
|
|
120
126
|
**Same commands, outside Claude.** The work-loop commands are also a terminal CLI: `bongos start`, `bongos claim N`, `bongos ship`. Same actions, same API — usable from any terminal, a Chromebook, or CI. Run `bongos help` for the verb list.
|
|
121
127
|
|
package/docs/packs/artist.md
CHANGED
|
@@ -27,7 +27,7 @@ The studio's own words (the greeting and its sub-line) are the studio page itsel
|
|
|
27
27
|
|
|
28
28
|
Only the holder writes. A page someone else holds is read-only and names them. A draft left unsubmitted keeps its words and can be taken up again.
|
|
29
29
|
|
|
30
|
-
**Between submit and approval, a session applies it.** Submitted pages wait for a builder session running `/tweak` ([the skill](
|
|
30
|
+
**Between submit and approval, a session applies it.** Submitted pages wait for a builder session running `/tweak` ([the skill](../../modules/copy-desk/skills/tweak/SKILL.md), Metic+). It transcribes every line, renders the page before and after, and parks it. **It never lands the page.**
|
|
31
31
|
|
|
32
32
|
**The Approval queue.** Pictures of the applied page, desktop or phone, light or dark, flipped **before / after**. Beside them, the changed lines ("was:" / "becomes:"); a line the applier could not apply says why. Then:
|
|
33
33
|
|
package/docs/packs/engineer.md
CHANGED
|
@@ -74,7 +74,7 @@ If this is an autonomous, bypass-permissions, or scheduled run and no one will a
|
|
|
74
74
|
|
|
75
75
|
1. **Resolve your claim** — `/builder-ship` with handoff notes and a value summary, or `/builder-release` on abandonment. Bongos records the session-log row and awards credits.
|
|
76
76
|
2. **Write a session log** as its own file at `docs/session-logs/YYYY-MM-DD-<slug>.md`, using [`docs/handoff-template.md`](../handoff-template.md). Do not hand-edit the kernel's §13 index or `docs/session-log-index.md` — both regenerate from your file at ship. For a single-task session the Bongos `session_logs` row is enough and a separate file isn't needed.
|
|
77
|
-
3. **Review the `idea_inbox`** via `GET /api/bongos/inbox`, or run `/
|
|
77
|
+
3. **Review the `idea_inbox`** via `GET /api/bongos/inbox`, or run `/owner-review ideas`.
|
|
78
78
|
4. **Update the detail files** if anything changed: a new gotcha → a recipe or a captured learning; a new blocker → `POST /api/bongos/blockers`; a decision → a new ADR.
|
|
79
79
|
5. **Update [`docs/architecture.md`](../architecture.md)** if the live system changed, and [`docs/file-map.md`](../file-map.md) if files or folders moved.
|
|
80
80
|
|
|
@@ -82,13 +82,12 @@ If nothing changed in a section, leave it alone — don't churn.
|
|
|
82
82
|
|
|
83
83
|
### Daily cadence (once per day, not per session)
|
|
84
84
|
|
|
85
|
-
|
|
85
|
+
Two manual slash-commands keep the methodology surfaces from accumulating drift. Any session can pick them up; it only matters that they happen.
|
|
86
86
|
|
|
87
|
-
- **`/
|
|
87
|
+
- **`/owner-review`** — one walk through backlog → bugs → ideas → priorities (task 1004471); each step is still typeable alone (`/backlog-review`, `/bug-triage`, `/idea-triage`, `/priority-session`). Ideas: promote, discard, merge, or defer — deferring is fine; the cadence is the discipline. Backlog: rows waiting on a **person** get walked (promote / kill / water); rows waiting on a **trigger** are counted, never walked (a satisfied dep auto-promotes), and rows stranded behind an abandoned dep are surfaced. `/demote` is invalid on a backlog row (409 `cannot_demote` — it requires `ready`).
|
|
88
88
|
- **`/blocker-review`** — walk the open blockers: resolved (which auto-promotes linked tasks via a DB trigger), still blocked with a note, or escalate.
|
|
89
|
-
- **`/backlog-review`** — walk `status='backlog'`, the pre-workable state a human must say go on. Rows waiting on a **person** get walked (promote / kill / water); rows waiting on a **trigger** are counted, never walked (a satisfied dep auto-promotes). It also surfaces rows stranded behind an abandoned dep, which the trigger can never fire for. `/demote` is invalid on a backlog row (409 `cannot_demote` — it requires `ready`).
|
|
90
89
|
|
|
91
|
-
**`/tweak`** (Metic
|
|
90
|
+
**`/tweak`** (Metic+, typed-only, in the `copy-desk` module) works a fourth queue: pages an artist submitted from the studio wait there until a session applies them. It never lands one; the artist approves first (ADR 0341).
|
|
92
91
|
|
|
93
92
|
If a day passes without them, the queues quietly grow. Running them is the structural cure for the markdown-graveyard pattern.
|
|
94
93
|
|
package/docs/page-readings.json
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"surface": "builders",
|
|
13
13
|
"title": "Repo Atlas",
|
|
14
14
|
"states_read": ["map","truth","detail","index","out"],
|
|
15
|
-
"files_hash": "
|
|
15
|
+
"files_hash": "6ad36383395e3de3",
|
|
16
16
|
"reading_hash": "411161b0a6167a1e",
|
|
17
17
|
"counts": {"lines":13,"placed":8,"shared":5,"unplaced":0},
|
|
18
18
|
"omitted": {"data":1},
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"surface": "builders",
|
|
39
39
|
"title": "Blockers",
|
|
40
40
|
"states_read": ["default"],
|
|
41
|
-
"files_hash": "
|
|
41
|
+
"files_hash": "632c93f4db32b846",
|
|
42
42
|
"reading_hash": "c8c742437a2c76c2",
|
|
43
43
|
"counts": {"lines":16,"placed":6,"shared":5,"unplaced":5},
|
|
44
44
|
"omitted": {"data":4},
|
|
@@ -67,7 +67,7 @@
|
|
|
67
67
|
"surface": "builders",
|
|
68
68
|
"title": "Board Room",
|
|
69
69
|
"states_read": ["room","out","sitting-meta","objection-form"],
|
|
70
|
-
"files_hash": "
|
|
70
|
+
"files_hash": "2d1d695b800e13bc",
|
|
71
71
|
"reading_hash": "202a0cbb6bc54aac",
|
|
72
72
|
"counts": {"lines":56,"placed":26,"shared":5,"unplaced":25},
|
|
73
73
|
"omitted": {"data":9},
|
|
@@ -136,7 +136,7 @@
|
|
|
136
136
|
"surface": "builders",
|
|
137
137
|
"title": "Collab",
|
|
138
138
|
"states_read": ["board","out"],
|
|
139
|
-
"files_hash": "
|
|
139
|
+
"files_hash": "2acb05affd061ce7",
|
|
140
140
|
"reading_hash": "cedb8171693a308e",
|
|
141
141
|
"counts": {"lines":68,"placed":23,"shared":4,"unplaced":41},
|
|
142
142
|
"omitted": {"data":12},
|
|
@@ -145,7 +145,7 @@
|
|
|
145
145
|
{"key":"L0001","section":"skip link","text":"Skip to content","placement":"shared","file":"modules/hall-ui/public/shell.js","line":767,"string_id":"87cee78ca134"},
|
|
146
146
|
{"key":"L0002","section":"top bar","text":"Collab","placement":"shared"},
|
|
147
147
|
{"key":"L0003","section":"top bar","text":"Jump to…","placement":"shared","file":"modules/hall-ui/public/shell.js","line":487,"string_id":"eba610d25523"},
|
|
148
|
-
{"key":"L0004","section":"top bar","text":"
|
|
148
|
+
{"key":"L0004","section":"top bar","text":"Ctrl K","placement":"shared"},
|
|
149
149
|
{"key":"L0005","section":"Collab","text":"Collab","placement":"unplaced"},
|
|
150
150
|
{"key":"L0006","section":"Collab","text":"{…} and {…}","placement":"placed","file":"modules/hall-ui/public/profile-nudge.js","line":77,"string_id":"56b00d773232"},
|
|
151
151
|
{"key":"L0007","section":"Collab","text":"Waiting on you","placement":"unplaced"},
|
|
@@ -217,7 +217,7 @@
|
|
|
217
217
|
"surface": "builders",
|
|
218
218
|
"title": "Copy desk",
|
|
219
219
|
"states_read": ["queue","out","search","composer","closer","proposer"],
|
|
220
|
-
"files_hash": "
|
|
220
|
+
"files_hash": "8631e59378897edf",
|
|
221
221
|
"reading_hash": "8d8433d27c7405a0",
|
|
222
222
|
"counts": {"lines":106,"placed":71,"shared":5,"unplaced":30},
|
|
223
223
|
"omitted": {"data":117},
|
|
@@ -260,7 +260,7 @@
|
|
|
260
260
|
{"key":"L0035","section":"Flagged","text":"said, when flagged:","placement":"placed","file":"modules/hall-ui/public/copy-desk.js","line":124,"string_id":"2a42549b34ae"},
|
|
261
261
|
{"key":"L0036","section":"Flagged","text":"{…} of {…}","placement":"placed","file":"modules/hall-ui/public/sky-panel.js","line":120,"string_id":"73c1372b43d9"},
|
|
262
262
|
{"key":"L0037","section":"Flagged","text":"target {…}","placement":"unplaced"},
|
|
263
|
-
{"key":"L0038","section":"Flagged","text":"Restricted.","placement":"placed","file":"modules/hall-ui/public/board-room.js","line":
|
|
263
|
+
{"key":"L0038","section":"Flagged","text":"Restricted.","placement":"placed","file":"modules/hall-ui/public/board-room.js","line":526,"string_id":"0887725744f2"},
|
|
264
264
|
{"key":"L0039","section":"Flagged","text":"off voice","placement":"unplaced"},
|
|
265
265
|
{"key":"L0040","section":"Flagged","text":"moved","placement":"unplaced"},
|
|
266
266
|
{"key":"L0041","section":"Flagged","text":"whole {…}","placement":"unplaced"},
|
|
@@ -278,7 +278,7 @@
|
|
|
278
278
|
{"key":"L0053","section":"Said more than once","text":"Available from the {…} rank up.","placement":"placed","file":"modules/hall-ui/public/gate.js","line":237,"string_id":"1de02052abf2"},
|
|
279
279
|
{"key":"L0054","section":"Said more than once","text":"Could not save. Try again.","placement":"placed","file":"modules/hall-ui/public/settings-interaction.js","line":96,"string_id":"8c234d5c8bd4"},
|
|
280
280
|
{"key":"L0055","section":"Said more than once","text":"already flagged","placement":"unplaced","occurrences":2},
|
|
281
|
-
{"key":"L0056","section":"Said more than once","text":"Restricted.","placement":"placed","file":"modules/hall-ui/public/board-room.js","line":
|
|
281
|
+
{"key":"L0056","section":"Said more than once","text":"Restricted.","placement":"placed","file":"modules/hall-ui/public/board-room.js","line":526,"string_id":"0887725744f2"},
|
|
282
282
|
{"key":"L0057","section":"Said more than once","text":"looked at","placement":"unplaced"},
|
|
283
283
|
{"key":"L0058","section":"Find something to flag","text":"Find something to flag","placement":"placed","file":"modules/hall-ui/public/copy-desk.html","line":64,"string_id":"1def0e7c716e"},
|
|
284
284
|
{"key":"L0059","section":"Find something to flag","text":"Search every string the product shows a person, by what it says or the file it lives in.","placement":"placed","file":"modules/hall-ui/public/copy-desk.html","line":65,"string_id":"46711f7bc3df"},
|
|
@@ -336,7 +336,7 @@
|
|
|
336
336
|
"surface": "builders",
|
|
337
337
|
"title": "Deploy",
|
|
338
338
|
"states_read": ["work","out"],
|
|
339
|
-
"files_hash": "
|
|
339
|
+
"files_hash": "d06badab7642ea93",
|
|
340
340
|
"reading_hash": "eb5acd9bd5fc73e9",
|
|
341
341
|
"counts": {"lines":7,"placed":0,"shared":5,"unplaced":2},
|
|
342
342
|
"omitted": {"data":1},
|
|
@@ -838,7 +838,7 @@
|
|
|
838
838
|
"surface": "builders",
|
|
839
839
|
"title": "Fleet costs",
|
|
840
840
|
"states_read": ["ledger","out"],
|
|
841
|
-
"files_hash": "
|
|
841
|
+
"files_hash": "5056fa71f75d5c6d",
|
|
842
842
|
"reading_hash": "9493385a64bb0e9f",
|
|
843
843
|
"counts": {"lines":22,"placed":6,"shared":5,"unplaced":11},
|
|
844
844
|
"omitted": {"data":11},
|
|
@@ -873,7 +873,7 @@
|
|
|
873
873
|
"surface": "builders",
|
|
874
874
|
"title": "Gate",
|
|
875
875
|
"states_read": ["queue","out","approve"],
|
|
876
|
-
"files_hash": "
|
|
876
|
+
"files_hash": "ec25d2c025db0abd",
|
|
877
877
|
"reading_hash": "08d3e5d3657e5afb",
|
|
878
878
|
"counts": {"lines":41,"placed":17,"shared":5,"unplaced":19},
|
|
879
879
|
"omitted": {"data":34},
|
|
@@ -884,7 +884,7 @@
|
|
|
884
884
|
{"key":"L0003","section":"top bar","text":"Jump to…","placement":"shared","file":"modules/hall-ui/public/shell.js","line":487,"string_id":"eba610d25523"},
|
|
885
885
|
{"key":"L0004","section":"top bar","text":"Ctrl K","placement":"shared"},
|
|
886
886
|
{"key":"L0005","section":"Gate","text":"Gate","placement":"unplaced"},
|
|
887
|
-
{"key":"L0006","section":"Gate","text":"Changes touching protected build surfaces, held for your approval.","placement":"placed","file":"modules/hall-ui/public/gate.js","line":
|
|
887
|
+
{"key":"L0006","section":"Gate","text":"Changes touching protected build surfaces, held for your approval.","placement":"placed","file":"modules/hall-ui/public/gate.js","line":432,"string_id":"4b714191b423"},
|
|
888
888
|
{"key":"L0007","section":"Gate","text":"Awaiting your approval","placement":"unplaced"},
|
|
889
889
|
{"key":"L0008","section":"Gate","text":"held at the gate check","placement":"unplaced"},
|
|
890
890
|
{"key":"L0009","section":"Gate","text":"Hard-floor holds","placement":"unplaced"},
|
|
@@ -997,7 +997,7 @@
|
|
|
997
997
|
"surface": "builders",
|
|
998
998
|
"title": "Goals",
|
|
999
999
|
"states_read": ["list","filters","cards","detail","out"],
|
|
1000
|
-
"files_hash": "
|
|
1000
|
+
"files_hash": "968230876b9152ba",
|
|
1001
1001
|
"reading_hash": "cf7f8688bcae4dd5",
|
|
1002
1002
|
"counts": {"lines":146,"placed":36,"shared":5,"unplaced":105},
|
|
1003
1003
|
"omitted": {"data":250},
|
|
@@ -1008,14 +1008,14 @@
|
|
|
1008
1008
|
{"key":"L0003","section":"top bar","text":"Jump to…","placement":"shared","file":"modules/hall-ui/public/shell.js","line":487,"string_id":"eba610d25523"},
|
|
1009
1009
|
{"key":"L0004","section":"top bar","text":"Ctrl K","placement":"shared"},
|
|
1010
1010
|
{"key":"L0005","section":"Goals","text":"Goals","placement":"unplaced"},
|
|
1011
|
-
{"key":"L0006","section":"Goals","text":"Goal {…}","placement":"placed","file":"modules/hall-ui/public/gate.js","line":
|
|
1011
|
+
{"key":"L0006","section":"Goals","text":"Goal {…}","placement":"placed","file":"modules/hall-ui/public/gate.js","line":288,"string_id":"ec88b946ad16","state":"detail"},
|
|
1012
1012
|
{"key":"L0007","section":"Goals","text":"{…} and {…}","placement":"placed","file":"modules/hall-ui/public/profile-nudge.js","line":77,"string_id":"56b00d773232","occurrences":8},
|
|
1013
1013
|
{"key":"L0008","section":"Goals","text":"See which goals wait on each other →","placement":"placed","file":"modules/hall-ui/public/goals.html","line":47,"string_id":"292761c89fae"},
|
|
1014
1014
|
{"key":"L0009","section":"Goals","text":"← All goals","placement":"placed","file":"modules/hall-ui/public/goals.html","line":83,"string_id":"d4b84b7fbdeb","state":"detail"},
|
|
1015
1015
|
{"key":"L0010","section":"#1000081 {…}","text":"Claude's notes on this goal","placement":"placed","file":"modules/hall-ui/public/goals.html","line":94,"string_id":"5b3b75ee0596","state":"detail"},
|
|
1016
1016
|
{"key":"L0011","section":"Completion3","text":"Completion","placement":"unplaced","state":"detail"},
|
|
1017
1017
|
{"key":"L0012","section":"Completion3","text":"{…} of {…} criteria satisfied","placement":"placed","file":"modules/hall-ui/public/goals-lib.js","line":32,"string_id":"cc5106af4b35","state":"detail"},
|
|
1018
|
-
{"key":"L0013","section":"Completion3","text":"Goal {…}","placement":"placed","file":"modules/hall-ui/public/gate.js","line":
|
|
1018
|
+
{"key":"L0013","section":"Completion3","text":"Goal {…}","placement":"placed","file":"modules/hall-ui/public/gate.js","line":288,"string_id":"ec88b946ad16","state":"detail"},
|
|
1019
1019
|
{"key":"L0014","section":"Completion3","text":"{…} — harness fixture text","placement":"unplaced","state":"detail","occurrences":3},
|
|
1020
1020
|
{"key":"L0015","section":"Members0","text":"Members","placement":"unplaced","state":"detail"},
|
|
1021
1021
|
{"key":"L0016","section":"Members0","text":"No {…} assigned yet — an Archon can appoint one.","placement":"unplaced","state":"detail"},
|
|
@@ -1156,7 +1156,7 @@
|
|
|
1156
1156
|
"surface": "builders",
|
|
1157
1157
|
"title": "Government",
|
|
1158
1158
|
"states_read": ["constitution","out","permissions","board","constitution-tab"],
|
|
1159
|
-
"files_hash": "
|
|
1159
|
+
"files_hash": "c1c4058d40d669d2",
|
|
1160
1160
|
"reading_hash": "f7f7466cabdf5569",
|
|
1161
1161
|
"counts": {"lines":71,"placed":24,"shared":5,"unplaced":42},
|
|
1162
1162
|
"omitted": {"data":10},
|
|
@@ -1185,7 +1185,7 @@
|
|
|
1185
1185
|
{"key":"L0021","section":"Constitution","text":"Every {…} builder at","placement":"unplaced"},
|
|
1186
1186
|
{"key":"L0022","section":"Constitution","text":"or above","placement":"placed","file":"modules/hall-ui/public/government.js","line":564,"string_id":"c38db02adb61"},
|
|
1187
1187
|
{"key":"L0023","section":"Constitution","text":"sits on the board — that is","placement":"unplaced"},
|
|
1188
|
-
{"key":"L0024","section":"Constitution","text":"and","placement":"placed","file":"modules/hall-ui/public/deploy.js","line":
|
|
1188
|
+
{"key":"L0024","section":"Constitution","text":"and","placement":"placed","file":"modules/hall-ui/public/deploy.js","line":541,"string_id":"084748fd85b4"},
|
|
1189
1189
|
{"key":"L0025","section":"Constitution","text":". Membership follows the rank, live.","placement":"unplaced"},
|
|
1190
1190
|
{"key":"L0026","section":"Constitution","text":"What counts as passing","placement":"unplaced"},
|
|
1191
1191
|
{"key":"L0027","section":"Constitution","text":"Items pass by","placement":"unplaced"},
|
|
@@ -1584,7 +1584,7 @@
|
|
|
1584
1584
|
"surface": "builders",
|
|
1585
1585
|
"title": "Modules",
|
|
1586
1586
|
"states_read": ["browse","search-empty","lens","details","out"],
|
|
1587
|
-
"files_hash": "
|
|
1587
|
+
"files_hash": "e02acc87a87fbb67",
|
|
1588
1588
|
"reading_hash": "165201cda2af2264",
|
|
1589
1589
|
"counts": {"lines":42,"placed":14,"shared":5,"unplaced":23},
|
|
1590
1590
|
"omitted": {"data":77},
|
|
@@ -2222,7 +2222,7 @@
|
|
|
2222
2222
|
"surface": "builders",
|
|
2223
2223
|
"title": "Project settings",
|
|
2224
2224
|
"states_read": ["default"],
|
|
2225
|
-
"files_hash": "
|
|
2225
|
+
"files_hash": "01c19996a012a0d3",
|
|
2226
2226
|
"reading_hash": "940a00917a01cd2e",
|
|
2227
2227
|
"counts": {"lines":10,"placed":5,"shared":5,"unplaced":0},
|
|
2228
2228
|
"omitted": {"data":1},
|
|
@@ -2388,7 +2388,7 @@
|
|
|
2388
2388
|
"surface": "builders",
|
|
2389
2389
|
"title": "Sessions",
|
|
2390
2390
|
"states_read": ["ledger","out"],
|
|
2391
|
-
"files_hash": "
|
|
2391
|
+
"files_hash": "ad46927c48018cef",
|
|
2392
2392
|
"reading_hash": "b8315ec3484a1431",
|
|
2393
2393
|
"counts": {"lines":54,"placed":15,"shared":5,"unplaced":34},
|
|
2394
2394
|
"omitted": {"data":16},
|
|
@@ -2980,7 +2980,7 @@
|
|
|
2980
2980
|
"surface": "builders",
|
|
2981
2981
|
"title": "Watch",
|
|
2982
2982
|
"states_read": ["board","out","operations","security"],
|
|
2983
|
-
"files_hash": "
|
|
2983
|
+
"files_hash": "3acbd4398dd35520",
|
|
2984
2984
|
"reading_hash": "de49e347cca76e41",
|
|
2985
2985
|
"counts": {"lines":156,"placed":44,"shared":5,"unplaced":107},
|
|
2986
2986
|
"omitted": {"data":123},
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
"coreVersion": "^1.8.0",
|
|
7
7
|
"default": true,
|
|
8
8
|
"maintenance": { "status": "core-maintained" },
|
|
9
|
-
"contributes": { "routes": ["copy-desk"], "migrations": true },
|
|
9
|
+
"contributes": { "routes": ["copy-desk"], "migrations": true, "skills": ["tweak"] },
|
|
10
10
|
"provides": [],
|
|
11
11
|
"consumes": ["lifecycle"]
|
|
12
12
|
}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
name: tweak
|
|
3
3
|
description: >-
|
|
4
4
|
Apply the next submitted page tweak: claim the round, apply every line, render the page before and after, attach the renders and ship it to wait for the artist. Metic+. Triggers: "/tweak", "apply the next page tweak", "work the tweak queue".
|
|
5
|
+
disable-model-invocation: true
|
|
5
6
|
plain: >-
|
|
6
7
|
Applies the next set of change requests someone made to a page, and shows before and after pictures for the artist to approve.
|
|
7
8
|
reach-for: >-
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
feel collaborative" — asked of you left, your asks right, every open ask
|
|
5
5
|
below, each condensed to the newest three with a show-all). The panel is the
|
|
6
6
|
shell's .scroll, the two-up is the shell's .view-zone--band, the row is
|
|
7
|
-
|
|
7
|
+
the .ov-row--lead below (a face, then the words, then the state), the
|
|
8
8
|
age is a .fact-pill, the context a .fact-chip, the expander the shell's
|
|
9
9
|
.btn-ghost. This sheet holds only what Collab has and no other page does: the
|
|
10
10
|
colour of each age band, the faces, the block head, the lit personal call, and
|
|
@@ -168,6 +168,13 @@
|
|
|
168
168
|
entirely (task 1004041): the age pill says how long in words and carries the
|
|
169
169
|
exact timestamp on its title, so a date beside it was the same fact twice —
|
|
170
170
|
which is what the "All open asks" rows were doing at full width. */
|
|
171
|
+
/* The --lead row: a face, then the words, then the state. Only Collab renders it,
|
|
172
|
+
so the rule lives here (it was in oversight.css, unused by any oversight page). */
|
|
173
|
+
.ov-row--lead { grid-template-columns: auto minmax(0, 1fr) auto; }
|
|
174
|
+
@media (max-width: 640px) {
|
|
175
|
+
.ov-row--lead { grid-template-columns: auto minmax(0, 1fr); }
|
|
176
|
+
.ov-row--lead > .ov-row__right { grid-column: 2; }
|
|
177
|
+
}
|
|
171
178
|
.cb-band .ov-row--lead { grid-template-columns: auto minmax(0, 1fr); row-gap: 8px; }
|
|
172
179
|
.cb-band .ov-row--lead > .ov-row__right {
|
|
173
180
|
grid-column: 2;
|
|
@@ -94,7 +94,6 @@
|
|
|
94
94
|
border-top: var(--line) solid var(--rule-soft);
|
|
95
95
|
}
|
|
96
96
|
.ov-rows > .ov-row:first-child, .ov-group__head + .ov-rows > .ov-row:first-child, .ov-group__head + .ov-row { border-top: 0; }
|
|
97
|
-
.ov-row--lead { grid-template-columns: auto minmax(0, 1fr) auto; }
|
|
98
97
|
/* A dense row: a permission, a voter, a machine principal — sixty of them in
|
|
99
98
|
one panel is the ordinary case, so the air tightens. */
|
|
100
99
|
.ov-row--dense { padding: 10px 0; }
|
|
@@ -131,8 +130,6 @@ a.ov-row__title:hover { color: var(--accent-ink); text-decoration: underline; te
|
|
|
131
130
|
.ov-row__when { font-size: 12.5px; color: var(--ink-faint); font-variant-numeric: tabular-nums; white-space: nowrap; }
|
|
132
131
|
@media (max-width: 640px) {
|
|
133
132
|
.ov-row { grid-template-columns: minmax(0, 1fr); }
|
|
134
|
-
.ov-row--lead { grid-template-columns: auto minmax(0, 1fr); }
|
|
135
|
-
.ov-row--lead > .ov-row__right { grid-column: 2; }
|
|
136
133
|
.ov-row__right { align-items: flex-start; text-align: left; }
|
|
137
134
|
.ov-row__actions { justify-content: flex-start; }
|
|
138
135
|
}
|
|
@@ -17,9 +17,9 @@
|
|
|
17
17
|
// 1. POST /tasks attaches `dependency_advisory` to its 201 body (this
|
|
18
18
|
// file's `buildDependencyAdvisory`), read by the /goal-create skill's
|
|
19
19
|
// "sibling advisory" section (.claude/skills/goal-create/SKILL.md).
|
|
20
|
-
// 2. The periodic sweep: `/goal-
|
|
20
|
+
// 2. The periodic sweep: `/goal-close`'s residue walk (was `/goal-review`) runs
|
|
21
21
|
// `node scripts/gds/audit-deps.js --min high` as one more housekeeping
|
|
22
|
-
// step (idea 1000276's half — see .claude/skills/goal-
|
|
22
|
+
// step (idea 1000276's half — see .claude/skills/goal-close/SKILL.md, Part 2).
|
|
23
23
|
//
|
|
24
24
|
// HARD CONSTRAINT, same as goal-advisory.js: advisory only (a finding addressed
|
|
25
25
|
// to a human never acts by itself — ADR 0158 §2). This
|
package/package-lock.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bongos/core",
|
|
3
|
-
"version": "1.20.
|
|
3
|
+
"version": "1.20.44",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@bongos/core",
|
|
9
|
-
"version": "1.20.
|
|
9
|
+
"version": "1.20.44",
|
|
10
10
|
"license": "AGPL-3.0-or-later",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"express": "^4.21.2",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bongos/core",
|
|
3
|
-
"version": "1.20.
|
|
3
|
+
"version": "1.20.44",
|
|
4
4
|
"description": "Cloud Bongos — the AI-first build platform core (GDS + platform surfaces + module system), installed as a versioned dependency (ADR 0108).",
|
|
5
5
|
"license": "AGPL-3.0-or-later",
|
|
6
6
|
"main": "src/platform-server.js",
|
package/release-notes.json
CHANGED
|
@@ -8361,5 +8361,21 @@
|
|
|
8361
8361
|
"id": "1003792",
|
|
8362
8362
|
"text": "The module store can now run a security check on each module version: it fails a version that ships a secret file, pulls code from outside the official package registry, or depends on a package with a known serious vulnerabili"
|
|
8363
8363
|
}
|
|
8364
|
+
],
|
|
8365
|
+
"1.20.43": [
|
|
8366
|
+
{
|
|
8367
|
+
"id": "1004471",
|
|
8368
|
+
"text": "Claude's list of project commands is now short enough to read in full every session: the rarely used admin commands still work when you type them but no longer take up room, and one new /owner-review walks the backlog, bugs, i"
|
|
8369
|
+
}
|
|
8370
|
+
],
|
|
8371
|
+
"1.20.44": [
|
|
8372
|
+
{
|
|
8373
|
+
"id": "1003637",
|
|
8374
|
+
"text": "The collab page's row layout rule now lives in the collab stylesheet instead of the shared oversight one."
|
|
8375
|
+
},
|
|
8376
|
+
{
|
|
8377
|
+
"id": "1004365",
|
|
8378
|
+
"text": "Every store module now comes with a how-to page, and the store refuses to publish one without it."
|
|
8379
|
+
}
|
|
8364
8380
|
]
|
|
8365
8381
|
}
|
|
@@ -423,6 +423,8 @@ function skillListingMetrics() {
|
|
|
423
423
|
const lint = require('./skill-lint.js');
|
|
424
424
|
// Resident skills only (task 1004470): a skill owned by a module this checkout leaves
|
|
425
425
|
// off (pixel-art, design-styles — both default: false) is in no session's listing here.
|
|
426
|
+
// listingChars also leaves out HIDDEN skills (disable-model-invocation: true, task 1004471):
|
|
427
|
+
// Claude Code keeps their descriptions out of the model's context entirely.
|
|
426
428
|
const files = lint.listSkillFiles();
|
|
427
429
|
return { skill_listing_chars: lint.lintSkills(files, { resident: lint.residentSkillFiles(undefined, { files }) }).listingChars };
|
|
428
430
|
} catch (e) {
|
|
@@ -22,6 +22,13 @@
|
|
|
22
22
|
// secrets), plus credential-named files anywhere in the module (SECRET_FILE_RE). Anything the denylist catches refuses the whole publish rather than being
|
|
23
23
|
// silently dropped: a module that ships without a file it expected is a broken module.
|
|
24
24
|
//
|
|
25
|
+
// THE HOW-TO GATE (ADR 0347 D4, task 1004365). A store version must carry HOWTO.md
|
|
26
|
+
// with the five required sections, each with some text. checkHowto is the ONE checker:
|
|
27
|
+
// `bongos module publish` runs it before uploading and the store's upload route runs
|
|
28
|
+
// it again through verifyModuleArtifact({ requireHowto: true }), so a hand-built upload
|
|
29
|
+
// can't skip it. It is opt-in there because install and update verify with the same
|
|
30
|
+
// function, and a version published before the gate existed must still install.
|
|
31
|
+
//
|
|
25
32
|
// Both halves live here so the CLI (packModule) and the store route
|
|
26
33
|
// (verifyModuleArtifact) cannot disagree about the format. Pure apart from reading the
|
|
27
34
|
// module directory in packModule; never touches the network or the database.
|
|
@@ -47,6 +54,42 @@ const NEVER_PACKED = new Set(['.upstream-signoff.json', INNER_MANIFEST_PATH]);
|
|
|
47
54
|
const MAX_TARBALL_BYTES = 5 * 1024 * 1024;
|
|
48
55
|
const READ_LIMITS = { maxUnpackedBytes: 16 * 1024 * 1024, maxFiles: 2000 };
|
|
49
56
|
|
|
57
|
+
const HOWTO_FILE = 'HOWTO.md';
|
|
58
|
+
// ADR 0347 D2 — level-2 headings, matched case-insensitively, in any order.
|
|
59
|
+
const HOWTO_SECTIONS = ['What it does', 'Install and enable', 'How to use it', 'Configuration', 'Limits and known issues'];
|
|
60
|
+
|
|
61
|
+
// Judge HOWTO.md's text (null = the file is absent). Reads headings only, never the
|
|
62
|
+
// writing: a section counts as filled when it holds any text once HTML comments (the
|
|
63
|
+
// scaffold's prompts) are removed. A heading inside a fenced code block doesn't count.
|
|
64
|
+
// Returns { ok, problems: [a plain sentence naming the file or the section] }.
|
|
65
|
+
function checkHowto(text) {
|
|
66
|
+
if (text == null) return { ok: false, problems: [`${HOWTO_FILE} is missing — every store module ships one (ADR 0347)`] };
|
|
67
|
+
const bodies = new Map();
|
|
68
|
+
let current = null;
|
|
69
|
+
let fence = null;
|
|
70
|
+
for (const line of String(text).replace(/<!--[\s\S]*?-->/g, '').split(/\r?\n/)) {
|
|
71
|
+
const f = line.match(/^\s*(```|~~~)/);
|
|
72
|
+
if (f) fence = fence === f[1] ? null : (fence || f[1]);
|
|
73
|
+
const h = !fence && !f && line.match(/^(#{1,6})\s+(.*?)\s*#*\s*$/);
|
|
74
|
+
if (h) {
|
|
75
|
+
// A level-1/2 heading starts a new section; a deeper one is structure, not text.
|
|
76
|
+
if (h[1].length <= 2) {
|
|
77
|
+
current = h[1].length === 2 ? h[2].toLowerCase() : null;
|
|
78
|
+
if (current !== null && !bodies.has(current)) bodies.set(current, '');
|
|
79
|
+
}
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
if (current !== null) bodies.set(current, bodies.get(current) + line.trim());
|
|
83
|
+
}
|
|
84
|
+
const problems = [];
|
|
85
|
+
for (const name of HOWTO_SECTIONS) {
|
|
86
|
+
const body = bodies.get(name.toLowerCase());
|
|
87
|
+
if (body === undefined) problems.push(`${HOWTO_FILE}: section "${name}" is missing`);
|
|
88
|
+
else if (!body) problems.push(`${HOWTO_FILE}: section "${name}" is empty`);
|
|
89
|
+
}
|
|
90
|
+
return { ok: problems.length === 0, problems };
|
|
91
|
+
}
|
|
92
|
+
|
|
50
93
|
function tarballName(key, version) { return `${ARTIFACT_NAME}-${key}-${version}.tgz`; }
|
|
51
94
|
|
|
52
95
|
// Every file under dir, as module-relative forward-slash paths, sorted. Skips
|
|
@@ -144,7 +187,9 @@ function packModule(key, { modulesDir, now = () => new Date(), modeOf } = {}) {
|
|
|
144
187
|
// `includeFiles: true` (install, task 1003785) also returns `files`: the module's own
|
|
145
188
|
// files — [{ path, mode, buf }], the inner manifest left out — from the SAME parse the
|
|
146
189
|
// hashes were checked against, so a caller that places them never re-reads the bytes.
|
|
147
|
-
|
|
190
|
+
// `requireHowto: true` (the store's upload route, ADR 0347 D4) also refuses a version
|
|
191
|
+
// whose HOWTO.md fails checkHowto.
|
|
192
|
+
async function verifyModuleArtifact(tgz, { key, maxBytes = MAX_TARBALL_BYTES, includeFiles = false, requireHowto = false } = {}) {
|
|
148
193
|
const fail = (code, message) => ({ ok: false, code, message });
|
|
149
194
|
if (!Buffer.isBuffer(tgz) || tgz.length === 0) return fail('empty_artifact', 'the upload is empty');
|
|
150
195
|
if (tgz.length > maxBytes) return fail('artifact_too_large', `the tarball is over ${maxBytes} bytes`);
|
|
@@ -204,6 +249,11 @@ async function verifyModuleArtifact(tgz, { key, maxBytes = MAX_TARBALL_BYTES, in
|
|
|
204
249
|
if (manifest.module_version !== moduleJson.version || manifest.core_version !== moduleJson.coreVersion) {
|
|
205
250
|
return fail('bad_manifest', 'the manifest version does not match module.json');
|
|
206
251
|
}
|
|
252
|
+
if (requireHowto) {
|
|
253
|
+
const howto = byName.get(HOWTO_FILE);
|
|
254
|
+
const h = checkHowto(howto ? howto.buf.toString('utf8') : null);
|
|
255
|
+
if (!h.ok) return fail('howto_incomplete', h.problems.join('; '));
|
|
256
|
+
}
|
|
207
257
|
|
|
208
258
|
const out = {
|
|
209
259
|
ok: true, manifest, moduleJson,
|
|
@@ -216,4 +266,4 @@ async function verifyModuleArtifact(tgz, { key, maxBytes = MAX_TARBALL_BYTES, in
|
|
|
216
266
|
return out;
|
|
217
267
|
}
|
|
218
268
|
|
|
219
|
-
module.exports = { MAX_TARBALL_BYTES, packModule, verifyModuleArtifact, deniedFiles };
|
|
269
|
+
module.exports = { MAX_TARBALL_BYTES, HOWTO_FILE, HOWTO_SECTIONS, packModule, verifyModuleArtifact, deniedFiles, checkHowto };
|