vouchington-tooling 0.26.0 → 0.28.0
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 +5 -1
- package/dist/agent-blackboard/feedback-canonical.d.mts +7 -0
- package/dist/agent-blackboard/feedback-canonical.mjs +8 -0
- package/dist/agent-blackboard/feedback-delivery.mjs +8 -6
- package/dist/agent-blackboard/feedback-online.mjs +11 -4
- package/dist/agent-blackboard/feedback-outbox.d.mts +8 -1
- package/dist/agent-blackboard/feedback-outbox.mjs +17 -4
- package/dist/agent-blackboard/feedback-types.d.mts +4 -0
- package/dist/agent-blackboard/index.d.mts +1 -1
- package/dist/agent-blackboard/index.mjs +1 -1
- package/dist/cli/index.mjs +4 -0
- package/dist/cli/parse.d.mts +1 -1
- package/dist/cli/parse.mjs +1 -0
- package/dist/cli/usage.d.mts +1 -1
- package/dist/cli/usage.mjs +2 -0
- package/dist/mcp-server/dispatch.mjs +5 -4
- package/dist/mcp-server/fake-blackboard.test-helpers.d.mts +3 -0
- package/dist/mcp-server/fake-blackboard.test-helpers.mjs +7 -1
- package/dist/mcp-server/handlers-journal.d.mts +0 -2
- package/dist/mcp-server/handlers-journal.mjs +22 -30
- package/dist/mcp-server/handlers-outbox.d.mts +11 -0
- package/dist/mcp-server/handlers-outbox.mjs +45 -0
- package/dist/mcp-server/harness.test-helpers.d.mts +6 -1
- package/dist/mcp-server/harness.test-helpers.mjs +14 -2
- package/dist/mcp-server/server.mjs +5 -1
- package/dist/mcp-server/tools.mjs +12 -10
- package/dist/pnpm-install/pnpm-install-fake-pnpm.test-helpers.mjs +2 -2
- package/docs/mcp-server.md +58 -14
- package/package.json +3 -3
- package/scripts/gha/gha-collaborator-trust.sh +75 -0
- package/skills/blackboard/SKILL.md +27 -17
- package/skills/manifest.json +27 -21
- package/skills/postgres-node-performance-tuning/references/performance-patterns.md +22 -0
- package/skills/postgres-partitioning-uuid-v7/SKILL.md +3 -0
- package/skills/postgres-schema-design/SKILL.md +21 -0
- package/skills/postgres-schema-design/references/naming.md +34 -0
- package/skills/postgres-schema-design/references/relations.md +46 -0
- package/skills/postgres-schema-design/references/table-shapes.md +56 -0
- package/skills/retrospective-distill/SKILL.md +13 -8
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Relations
|
|
2
|
+
|
|
3
|
+
An identity that readers join is an FK column or an FK child row. JSON holds structured,
|
|
4
|
+
schemaless data and history snapshots, including identities recorded as they were at the time.
|
|
5
|
+
Do not use UUID arrays, JSON ids, or type/id pairs for live relations. A column never names a
|
|
6
|
+
table: use one table per target and generate any per-relation progress enum from the same metadata.
|
|
7
|
+
Cursor positions and random fencing tokens are intentionally not live entity references; record
|
|
8
|
+
their reviewed exception instead of inventing a foreign key.
|
|
9
|
+
|
|
10
|
+
Split tables when their columns or FK targets differ; share a table when only a value differs.
|
|
11
|
+
Identical lookup values share a row without a source discriminator. Put subtype-only columns in
|
|
12
|
+
a subtype table whose primary key also references the base row (`business_accounts.account_id`
|
|
13
|
+
references `accounts.id`). A 1:N child remains an ordinary child table.
|
|
14
|
+
|
|
15
|
+
For one of several sources, use an exclusive arc:
|
|
16
|
+
|
|
17
|
+
```sql
|
|
18
|
+
CHECK (num_nonnulls(order_id, invoice_id) = 1)
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Both source columns have their own FK. If a reference must belong to the same account, enforce
|
|
22
|
+
`FOREIGN KEY (account_id, invoice_id) REFERENCES invoices (account_id, id)` with a corresponding
|
|
23
|
+
unique key on the target. A validation trigger is unnecessary. With nullable `invoice_id`,
|
|
24
|
+
default `MATCH SIMPLE` skips that composite check when the reference is absent.
|
|
25
|
+
|
|
26
|
+
A ledger that survives deletion references a retained identity row with explicit deletion
|
|
27
|
+
behavior. Retained identities preserve history; they do not authorize operations on a deleted
|
|
28
|
+
account, order, or invoice. Index FK columns with a leading key usable by referential checks.
|
|
29
|
+
|
|
30
|
+
Finite code-defined values use enums. Use a lookup table when values carry attributes or arrive
|
|
31
|
+
at runtime. Authenticated vendor-defined values are inserted into a shared lookup on first sight,
|
|
32
|
+
with validation and concurrent insertion handled explicitly. Do not let untrusted strangers
|
|
33
|
+
create unbounded permanent lookup rows; reviewed raw text can be appropriate for their input.
|
|
34
|
+
Free text and a lookup's own natural key are not finite sets.
|
|
35
|
+
|
|
36
|
+
Arrays are for enums or outside-defined lists; live identity collections use FK child rows,
|
|
37
|
+
never `uuid[]`. User-submitted URLs go through one registry with centralized normalization and
|
|
38
|
+
validation, then use URL FKs. Keep exact external protocol identifiers, capability URLs, and
|
|
39
|
+
evidence snapshots unchanged when their contract requires it; document the exception.
|
|
40
|
+
Do not duplicate a child collection into a parent column unless a trigger maintains the projection.
|
|
41
|
+
|
|
42
|
+
Generic enforcement in `jonathanong/no-mistakes`: `postgres-column-naming`,
|
|
43
|
+
`postgres-array-columns`, `postgres-table-shape`, `postgres-fk-index`, and
|
|
44
|
+
`postgres-require-fk-on-delete`. These cover naming, configured shapes, and FK mechanics;
|
|
45
|
+
inspect the installed rule versions and options rather than assuming complete semantic coverage.
|
|
46
|
+
Comments and reviewed exceptions remain necessary.
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Table shapes
|
|
2
|
+
|
|
3
|
+
Choose a shape by lifecycle and meaning. Do not store hand-synchronized status beside lifecycle
|
|
4
|
+
timestamps. A final lifecycle derives enum status with an immutable generated expression over
|
|
5
|
+
timestamps such as `claimed_at`, `completed_at`, and `failed_at`. A time-based expiry needs an
|
|
6
|
+
explicit sweeper-written timestamp; `now()` cannot appear in an immutable generated expression.
|
|
7
|
+
When state keeps returning to earlier states, record append-only attempts or changes and derive
|
|
8
|
+
current state from the latest row rather than erasing the previous lifecycle.
|
|
9
|
+
|
|
10
|
+
| Concept | Shape |
|
|
11
|
+
| -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
12
|
+
| Field-diff history | `<entity>_revisions`: UUIDv7 `id`, entity FK, nullable revision actor FK with `ON DELETE SET NULL`, revision-type enum, `changes jsonb`. |
|
|
13
|
+
| Typed lifecycle ledger | `<entity>_changes`: UUIDv7 `id`, entity FK, change-type enum, retained actor identity FK with `ON DELETE RESTRICT`, typed joined payload and JSON for unjoined data. Time comes from `id`. |
|
|
14
|
+
| Current state from a log | Latest change by `id DESC`, projected through a shared trigger or read through a view. |
|
|
15
|
+
| Per-entity work | `<entity>_<job>_work_items`: entity FK, lease and final-outcome columns, claim index, retention. |
|
|
16
|
+
| Job progress | `<job>_cursors`: finite enum key or checked singleton, keyset positions without FKs, optional sweep upper bound. |
|
|
17
|
+
| Inbound or protocol events | Append-only `<source>_events` with `occurred_at` recording the event's business time. |
|
|
18
|
+
|
|
19
|
+
Revisions and changes are append-only through a generic `fn_reject_mutation`, parameterized by
|
|
20
|
+
actor columns that may be erased to NULL. Permit only those erasures; parent-cascade deletion
|
|
21
|
+
may be permitted by policy. A trigger-depth test alone cannot prove a delete came from a parent
|
|
22
|
+
cascade, because another trigger also increases depth. Do not copy the parent into each ledger
|
|
23
|
+
row. Keep historical before/after snapshots as JSON rather than joined history child tables.
|
|
24
|
+
A system change has a NULL actor. Retained actors remain historical identities, without authority.
|
|
25
|
+
|
|
26
|
+
## Work leases
|
|
27
|
+
|
|
28
|
+
The lease lives on a row that exists only for the work. If an invoice outlives a delivery job,
|
|
29
|
+
use `invoice_delivery_work_items`, with an invoice FK and `ON DELETE CASCADE`, rather than putting
|
|
30
|
+
the lease on the invoice. Do not create a shared polymorphic lease table.
|
|
31
|
+
|
|
32
|
+
Use `lease_token uuid`, `leased_at`, `lease_expires_at`, `attempt_count`, `available_at`, and
|
|
33
|
+
`completed_at` plus timestamps for final outcomes. Add `generation` only when re-enqueue can race
|
|
34
|
+
a running worker. Each claim or reclaim gets a fresh opaque token. Every renewal, completion,
|
|
35
|
+
and failure must include `WHERE lease_token = $mine`; zero affected rows means ownership was lost.
|
|
36
|
+
Keep retries in an optional `_attempts` ledger with `attempt_number` when their lifecycle must
|
|
37
|
+
survive. One-shot compare-and-set claims and human assignments need their own shapes.
|
|
38
|
+
|
|
39
|
+
## Cursors and shared functions
|
|
40
|
+
|
|
41
|
+
A cursor key names the finite thing being swept. A singleton uses
|
|
42
|
+
`is_singleton boolean PRIMARY KEY DEFAULT true CHECK (is_singleton)`; the job seeds its own row
|
|
43
|
+
with `ON CONFLICT DO NOTHING`. `cursor_<thing>_id` and optional `sweep_upper_bound_<thing>_id` are
|
|
44
|
+
FK-free UUIDv7 positions; NULL means the start. Per-unit work progress belongs in work items.
|
|
45
|
+
A UUIDv7 is assigned at insert, not commit: jobs that must see every committed row re-scan an
|
|
46
|
+
overlap rather than assuming an id high-water mark proves commit order.
|
|
47
|
+
|
|
48
|
+
Use `updated_at` only for mutable rows, always maintained by its trigger; application code never
|
|
49
|
+
writes it. Comment every table, column, and view, including generated objects. Self-explanatory
|
|
50
|
+
columns may have explicit reviewed local exceptions; view comments describe their reader boundary.
|
|
51
|
+
Reuse generic trigger functions with `TG_ARGV` and `TG_TABLE_NAME`; quote dynamic identifiers
|
|
52
|
+
with `format('%I', ...)`. A trigger function and a SQL-callable helper are separate functions.
|
|
53
|
+
|
|
54
|
+
Generic enforcement in `jonathanong/no-mistakes`: `postgres-table-shape` and
|
|
55
|
+
`postgres-duplicate-function-body`. Configure canonical shapes explicitly and verify which
|
|
56
|
+
rules the installed release supports; lifecycle and authority decisions still need review.
|
|
@@ -17,11 +17,15 @@ Use when completed retrospectives or journals should become durable follow-up wo
|
|
|
17
17
|
`data` fields, `dataArrayContains`, and `inactiveForHours`. It exports non-archived sessions to a
|
|
18
18
|
private local file and returns the path, counts, checksum, and manifest, never the records.
|
|
19
19
|
Before exporting, call `outbox_flush` and then `outbox_status` for every worktree that
|
|
20
|
-
`git worktree list` reports, passing each path as `worktree`, and stop if any
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
20
|
+
`git worktree list` reports, passing each path as `worktree`, and stop if any reports a
|
|
21
|
+
`worktreePendingCount` above 0. Use the worktree count, never `pendingCount` or `status`, which
|
|
22
|
+
cover only the caller's own session: the sessions to distill belong to other agents, and an
|
|
23
|
+
archived session refuses later delivery, so a retained record would never be distilled. Outboxes
|
|
24
|
+
in removed worktrees or on other machines cannot be drained this way, so select with
|
|
25
|
+
`inactiveForHours` to give them time to deliver. Leave in-progress sessions intact. If a search
|
|
26
|
+
for `snapshot_export` (the tool names carry a harness prefix, see the
|
|
27
|
+
[blackboard skill](../blackboard/SKILL.md)) finds no server, stop and report it; do not fall back
|
|
28
|
+
to a CLI command.
|
|
25
29
|
2. Before using any record, verify the file against the returned checksum, counts, and terminal
|
|
26
30
|
manifest with the consumer's approved snapshot reader, and stop on a mismatch rather than
|
|
27
31
|
treating missing records as absent. Read full records, with their storage type, repository
|
|
@@ -34,7 +38,8 @@ Use when completed retrospectives or journals should become durable follow-up wo
|
|
|
34
38
|
3. Validate storage type and the shared envelope independently of optional category. Never repair
|
|
35
39
|
unknown legacy types or repository provenance by inference. Quarantine malformed sessions with
|
|
36
40
|
an explicit reason while processing valid unrelated sessions. Deduplicate at-least-once records
|
|
37
|
-
by exact session/source identity and reject conflicting duplicate content.
|
|
41
|
+
by exact session/source identity and reject conflicting duplicate content. Records that differ
|
|
42
|
+
only in their server-assigned `timestamp` are one event. Retain coverage,
|
|
38
43
|
dropped counts, requested versus observed outcomes, and useful resolved findings.
|
|
39
44
|
4. Cluster findings by root cause. Prefer a few broad actionable themes over many narrow issues.
|
|
40
45
|
Treat a finding already linked to an open tracker as context, not a duplicate.
|
|
@@ -47,8 +52,8 @@ Use when completed retrospectives or journals should become durable follow-up wo
|
|
|
47
52
|
[github-issue](../github-issue/SKILL.md), including its repository gate, label approval, and
|
|
48
53
|
denied-external tracking behavior.
|
|
49
54
|
7. Archive only verified records fully processed across every represented repository, and never
|
|
50
|
-
while any worktree's `outbox_status` reports
|
|
51
|
-
rules. Make one `session_archive` call per session, whose `sessionId` is the archived session,
|
|
55
|
+
while any worktree's `outbox_status` reports a `worktreePendingCount` above 0, under the
|
|
56
|
+
repository's retention rules. Make one `session_archive` call per session, whose `sessionId` is the archived session,
|
|
52
57
|
not the caller. Immediately before each call, read that session with `journal_entries` and
|
|
53
58
|
archive only if its entries match the verified snapshot's by source identity; otherwise leave it
|
|
54
59
|
for the next pass, because an entry added after the export would never be distilled.
|