vouchington-tooling 0.39.0 → 0.41.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 +31 -7
- package/dist/cli/usage.d.mts +1 -1
- package/dist/cli/usage.mjs +1 -0
- package/dist/dependency-license-policy/audit-store.d.mts +1 -4
- package/dist/dependency-license-policy/audit-store.mjs +1 -16
- package/dist/dependency-license-policy/collect.d.mts +0 -1
- package/dist/dependency-license-policy/collect.mjs +2 -2
- package/dist/pg-schema-snapshot/generated-arbiter-facts.d.mts +49 -0
- package/dist/pg-schema-snapshot/generated-arbiter-facts.mjs +1 -0
- package/dist/pg-schema-snapshot/generated-arbiter-input.d.mts +21 -0
- package/dist/pg-schema-snapshot/generated-arbiter-input.mjs +73 -0
- package/dist/pg-schema-snapshot/index.d.mts +4 -0
- package/dist/pg-schema-snapshot/index.mjs +2 -0
- package/dist/pg-schema-snapshot/static-string-pairs.d.mts +8 -0
- package/dist/pg-schema-snapshot/static-string-pairs.mjs +26 -0
- package/docs/mcp-server.md +4 -2
- package/package.json +3 -3
- package/skills/blackboard/SKILL.md +28 -14
- package/skills/manifest.json +4 -4
- package/skills/postgres-node-performance-tuning/SKILL.md +2 -0
- package/skills/postgres-node-performance-tuning/references/performance-patterns.md +23 -0
package/README.md
CHANGED
|
@@ -429,18 +429,20 @@ architectures to every `os`, `cpu`, and `libc` selector represented in the lockf
|
|
|
429
429
|
`engines` constraint from the audit copy of the lockfile, and validates the JSON report. Dropping
|
|
430
430
|
`engines` keeps `pnpm fetch` from skipping optional packages that exclude the running Node.js;
|
|
431
431
|
pnpm 12's `fetch` ignores `force`, so their licenses would otherwise report as Unknown.
|
|
432
|
-
Packages are fetched into a
|
|
433
|
-
|
|
434
|
-
|
|
432
|
+
Packages are fetched into a private store inside that temporary workspace. Each audit has its own
|
|
433
|
+
store, and workspace cleanup removes every downloaded package when the audit succeeds or fails,
|
|
434
|
+
without changing the developer's pnpm store. The exported options no longer accept a `storeDir`
|
|
435
|
+
override because caller-owned paths cannot be safely removed; callers that provide a custom
|
|
436
|
+
`prepareWorkspace` own the returned workspace and its nested store lifecycle.
|
|
435
437
|
Pass explicit denied SPDX IDs and prefixes, exact aliases, and justified allowlist scopes to
|
|
436
438
|
`evaluatePnpmLicenseReport`. Unknown, malformed, and custom SPDX references fail closed. Allowlist
|
|
437
439
|
scopes are either intentionally global or an exact package-name set; the library returns structured
|
|
438
440
|
violations and does not format CI-provider diagnostics.
|
|
439
441
|
When present, the repository `.npmrc` is copied into the owner-private temporary workspace so pnpm
|
|
440
|
-
can authenticate to the same registries. The workspace
|
|
441
|
-
process receives SIGINT, SIGTERM, or SIGHUP, and on the next audit if the
|
|
442
|
-
first, including SIGKILL. Each workspace records its owner's PID so a later
|
|
443
|
-
directories whose owner is gone.
|
|
442
|
+
can authenticate to the same registries. The workspace and its package store are removed when the
|
|
443
|
+
audit finishes, when the process receives SIGINT, SIGTERM, or SIGHUP, and on the next audit if the
|
|
444
|
+
previous process died first, including SIGKILL. Each workspace records its owner's PID so a later
|
|
445
|
+
audit can delete directories whose owner is gone.
|
|
444
446
|
|
|
445
447
|
`session-friction` is an opt-in capture and reporting library. Callers supply the session id,
|
|
446
448
|
absolute log directory, host-independent observation, and journal loader; it does not inspect host
|
|
@@ -512,6 +514,18 @@ the dedicated process group to exit after the direct child closes so descendants
|
|
|
512
514
|
`isProcessGroupAlive` and `waitForProcessGroupExit` are also available when callers need the same
|
|
513
515
|
process-group probe and bounded-drain semantics outside a browser session.
|
|
514
516
|
|
|
517
|
+
### Generated arbiter input
|
|
518
|
+
|
|
519
|
+
The `pg-schema-snapshot` export also provides `projectGeneratedArbiterInput(conflict)` for
|
|
520
|
+
`PostgresSqlConflict` facts from `no-mistakes@0.83.0` or newer. It projects normalized key and
|
|
521
|
+
partial-predicate column identities, ordered assignment columns, direct non-EXCLUDED references,
|
|
522
|
+
and assignment indirection. Named constraints and unresolved expression keys have undefined
|
|
523
|
+
`keyColumns`; missing or incomplete expression coverage sets `complete` to false. Callers must
|
|
524
|
+
reject incomplete projections and retain their own snapshot-dependent replay verdict. The adapter
|
|
525
|
+
loads no optional parser peer at runtime and implements no replay-safety policy. Its public
|
|
526
|
+
`GeneratedArbiterConflict` contract is structural, so importing snapshot declarations does not
|
|
527
|
+
require the optional peer either.
|
|
528
|
+
|
|
515
529
|
### Contract schema type queries
|
|
516
530
|
|
|
517
531
|
`getExportedTypeFacts` and `getCallRowTypeFacts` use an existing TypeScript `Program` from the
|
|
@@ -686,6 +700,16 @@ reexports, and literal dynamic/require loads. Missing or incomplete facts for a
|
|
|
686
700
|
throw; external specifiers resolve to `null`. The default file inventory limit is 10,000
|
|
687
701
|
files and can be reduced with `maxFiles`.
|
|
688
702
|
|
|
703
|
+
## Static schema-allowlist pairs
|
|
704
|
+
|
|
705
|
+
`extractStaticStringPairs(source)` from `pg-schema-snapshot` collects the first two string literals
|
|
706
|
+
of every array expression in ESTree field traversal order, including arrays with extra elements.
|
|
707
|
+
Conditional alternatives precede consequents, preserving the existing parser walker. It
|
|
708
|
+
preserves duplicates and decoded string values. It does not evaluate imports, exported constants,
|
|
709
|
+
spreads, or templates, and malformed source throws. Schema-allowlist consumers retain their own
|
|
710
|
+
file selection, key filtering, deduplication, snapshot comparison, and diagnostics. Parsing is
|
|
711
|
+
source-only and does not build a TypeScript compiler program or execute the source.
|
|
712
|
+
|
|
689
713
|
## SQL view declarations
|
|
690
714
|
|
|
691
715
|
`vouchington-tooling/sql-ast` exports `extractViewDeclarations(sql)` and the
|
package/dist/cli/usage.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare const USAGE = "Usage: vouchington <command> [options]\n\nCommands:\n runner-port-policy Print or validate a runner port policy\n with-host-lock Run a command under a host-wide lock\n gha-runtime-audit Audit successful GitHub Actions job runtimes\n require-up-to-date Require HEAD to include a fetched remote branch\n gitleaks-directory-scan Scan a directory with Gitleaks\n ast-grep-examples Run AST-grep rule examples\n ast-grep-pack Print shipped unconditional AST-grep pack paths as JSON\n gha-workspace-policy Check GitHub Actions workspace safety policy\n gha-output Write a collision-safe multiline GITHUB_OUTPUT record\n gha-needs-results Fail if required GitHub Actions job results failed\n download-with-diagnostics Download a URL and report HTTP status on failure\n download-optional-run-artifacts Download optional artifacts from the current run\n host-pressure-diagnostics Print a bounded host memory/OOM/PSI snapshot\n allocate-browser-safe-ports Allocate Fetch-safe localhost ports\n diagnose-port-collision Capture bounded localhost port diagnostics\n prepare-trivy-db Download the Trivy vulnerability database\n gha-artifacts-cleanup Delete classified GitHub Actions artifacts\n http-origin Validate an optional HTTP(S) origin\n vitest-blob-manifest Stamp a vitest-blob-manifest:v1 identity file\n vitest-report-attempt Write or read a Vitest report-attempt marker\n prepare-vitest-reports Validate and select Vitest report JSON files\n pnpm-install Install a pnpm workspace with retry and release-age fail-fast\n check-cache-size Measure a path and decide whether to save a GHA cache\n make-shard-matrix Emit a [1..N] GitHub Actions shard matrix\n load-runner-env Overlay a runner env file onto GITHUB_ENV with injection guards\n clean-workspace Reset a persistent-runner workspace with a fork-PR trust gate\n install-github-release Download a checksum-verified GitHub Release binary\n run-with-timeout Run a command with GNU timeout or a Perl fallback\n lint-links Two-pass lychee: internal links fail, external warn\n materialize-pr-context Dump PR title/body/files/diff/comments and #N crawl\n wait-for-apt-locks Wait until apt/dpkg lock files are free\n install-playwright-chromium-arm64 Install Playwright Chromium from browsers.json\n ghcr-package-retention Delete old GHCR package versions past KEEP_MIN\n harness-admission-lane Compute a GITHUB_RUN_ID admission lane for fleet fan-out\n harness-assert-gates Fail if any named HARNESS_*_ENABLED gate is enabled\n gha-collaborator-trust Classify authors as write-access collaborators or not\n nuget-central-version Validate a Directory.Packages.props PackageVersion delta\n swift-semantic-equal Compare Swift sources ignoring comments and whitespace\n post-review Post one COMMENT review from a staged payload file\n stage-review-payload Validate a review payload file into a staging directory\n retrospective-transcript Format facts from Claude-compatible, Codex, or Grok transcripts\n link-skill Link one packaged skill into an explicit consumer directory\n retrospective-facts Gather immutable facts for a retrospective\n agent-blackboard Probe and journal an Agent Blackboard deployment\n mcp Serve the agent-blackboard journal tools over stdio (MCP)\n\nOptions:\n -h, --help Show this help\n -v, --version Print the package version\n\nrunner-port-policy\n (no args) Print the shipped policy as JSON\n --file <path> Validate and print a policy file\n --reserved <port> Print true if the port is reserved\n\nwith-host-lock\n --name <family>\n [--slots <n>]\n --timeout-seconds <n>\n [--command-timeout-seconds <n>]\n [--failure-diagnostics <absolute-script>]\n [--on-acquire-timeout fail|run-unlocked]\n -- <command> [args...]\n\ngha-runtime-audit\n [--repository owner/name] Default GITHUB_REPOSITORY\n [--branch main]\n [--median-threshold-floor <seconds>] Off unless set. Must be below the ceiling\n [--median-threshold-ceiling <seconds>] Default 360. Flags a five-sample median above this\n --pr-workflow <name|/regex/> Repeatable\n --push-workflow <name|/regex/> Repeatable\n\nrequire-up-to-date --remote <name> --branch <name>\ngitleaks-directory-scan --config <path> [--directory <path>]\nast-grep-examples --rules <directory> --config <path>\nast-grep-pack\ngha-workspace-policy [--root <directory>] [--workflow-directory <directory>] [--action-directory <directory>]\n\ngha-output <name>\ngha-needs-results [label]\ndownload-with-diagnostics <url> <destination> [-- curl-args...]\ndownload-optional-run-artifacts (--name <name>... | --pattern <pattern>) --dir <directory>\nhost-pressure-diagnostics\nallocate-browser-safe-ports <count> [--policy path] [--forbidden-ports path]\ndiagnose-port-collision [--ports \"2200 2216\"] [--output-dir PATH]\nprepare-trivy-db\ngha-artifacts-cleanup run --run-id <id> [--keep-pattern glob] [--delete-pattern glob] [--patterns-file json]\ngha-artifacts-cleanup sweep --older-than-hours <n> [--keep-pattern glob] [--delete-pattern glob] [--patterns-file json]\nhttp-origin [--field NAME] [value]\nvitest-blob-manifest <suite> [reports-directory]\nvitest-report-attempt <write DIRECTORY SUITE|read ROOT>\nprepare-vitest-reports [primary-directory] [fallback-directory] [output-directory]\npnpm-install --runner-lifecycle persistent|ephemeral|ephemeral-full --install-scripts true|false\ncheck-cache-size <path> <max-bytes> <label>\nmake-shard-matrix <total>\nload-runner-env\nclean-workspace\ninstall-github-release --repo owner/name --version X --asset 'name-{platform}.tar.gz' --bin name [--tag-prefix PREFIX] [--expected-sha256 SHA256] [--no-checksum] [--checksums-asset NAME] [--version-flag FLAG] [--bin-dir DIR]\nrun-with-timeout <timeout-seconds> <kill-after-seconds> <command...>\nlint-links [--offline] [--config PATH] [--glob PATTERN] [files...]\nmaterialize-pr-context\nwait-for-apt-locks\ninstall-playwright-chromium-arm64 [name:archive...]\nghcr-package-retention <url-encoded-package>...\nharness-admission-lane <lanes>\nharness-assert-gates <gate>...\ngha-collaborator-trust <owner/repo> [--allow-bot <login>]... < authors.json\nnuget-central-version <trusted-props> <candidate-props> <metadata-json> <output-props>\nswift-semantic-equal <base> <head> <file.swift>\npost-review\nstage-review-payload optional|required <source> <destination>\nretrospective-transcript [--session-id ID] [--jsonl PATH] [--projects-dir PATH] [--codex-sessions-dir PATH] [--grok-sessions-dir PATH]\nlink-skill <name> --source-root <skills-dir> --target-root <consumer-skills-dir> Link a packaged or repository-local skill\nretrospective-facts (--pr NUMBER | --branch NAME | --no-pr) [--repo OWNER/NAME] [--raw]\nagent-blackboard probe\nagent-blackboard journal append --mode interactive|autonomous --source-event-id ID --work-outcome OUTCOME --coverage-status STATUS --session-id UUID --agent NAME --version VERSION --file PATH --repository OWNER/NAME [--repository OWNER/NAME ...] [--parent-session-id UUID] [--timestamp ISO8601] [--coverage-source SOURCE,...] [--dropped-count N] [--outbox-directory PATH]\nagent-blackboard journal entries --session-id UUID\nagent-blackboard journal status --session-id UUID --outbox-directory PATH\nagent-blackboard journal flush --outbox-directory PATH [--session-id UUID]\nInteractive journal append requires --outbox-directory PATH.\nagent-blackboard snapshot partition --snapshot PATH --checksum SHA256 --counts '{\"sessions\":N,\"entries\":N,\"records\":N,\"bytes\":N}'\nagent-blackboard snapshot cleanup [--snapshot PATH] [--partition-directory PATH --receipt JSON]\nmcp\n (no args) Serve journal_append, journal_entries, outbox_status, outbox_flush,\n session_ensure, snapshot_export, and session_archive over stdio.\n Needs the optional @modelcontextprotocol/sdk peer (and zod).\n Launch it from inside the repository's git worktree.\n";
|
|
1
|
+
export declare const USAGE = "Usage: vouchington <command> [options]\n\nCommands:\n runner-port-policy Print or validate a runner port policy\n with-host-lock Run a command under a host-wide lock\n gha-runtime-audit Audit successful GitHub Actions job runtimes\n require-up-to-date Require HEAD to include a fetched remote branch\n gitleaks-directory-scan Scan a directory with Gitleaks\n ast-grep-examples Run AST-grep rule examples\n ast-grep-pack Print shipped unconditional AST-grep pack paths as JSON\n gha-workspace-policy Check GitHub Actions workspace safety policy\n gha-output Write a collision-safe multiline GITHUB_OUTPUT record\n gha-needs-results Fail if required GitHub Actions job results failed\n download-with-diagnostics Download a URL and report HTTP status on failure\n download-optional-run-artifacts Download optional artifacts from the current run\n host-pressure-diagnostics Print a bounded host memory/OOM/PSI snapshot\n allocate-browser-safe-ports Allocate Fetch-safe localhost ports\n diagnose-port-collision Capture bounded localhost port diagnostics\n prepare-trivy-db Download the Trivy vulnerability database\n gha-artifacts-cleanup Delete classified GitHub Actions artifacts\n http-origin Validate an optional HTTP(S) origin\n vitest-blob-manifest Stamp a vitest-blob-manifest:v1 identity file\n vitest-report-attempt Write or read a Vitest report-attempt marker\n prepare-vitest-reports Validate and select Vitest report JSON files\n pnpm-install Install a pnpm workspace with retry and release-age fail-fast\n check-cache-size Measure a path and decide whether to save a GHA cache\n make-shard-matrix Emit a [1..N] GitHub Actions shard matrix\n load-runner-env Overlay a runner env file onto GITHUB_ENV with injection guards\n clean-workspace Reset a persistent-runner workspace with a fork-PR trust gate\n install-github-release Download a checksum-verified GitHub Release binary\n run-with-timeout Run a command with GNU timeout or a Perl fallback\n lint-links Two-pass lychee: internal links fail, external warn\n materialize-pr-context Dump PR title/body/files/diff/comments and #N crawl\n wait-for-apt-locks Wait until apt/dpkg lock files are free\n install-playwright-chromium-arm64 Install Playwright Chromium from browsers.json\n ghcr-package-retention Delete old GHCR package versions past KEEP_MIN\n harness-admission-lane Compute a GITHUB_RUN_ID admission lane for fleet fan-out\n harness-assert-gates Fail if any named HARNESS_*_ENABLED gate is enabled\n gha-collaborator-trust Classify authors as write-access collaborators or not\n nuget-central-version Validate a Directory.Packages.props PackageVersion delta\n swift-semantic-equal Compare Swift sources ignoring comments and whitespace\n post-review Post one COMMENT review from a staged payload file\n stage-review-payload Validate a review payload file into a staging directory\n retrospective-transcript Format facts from Claude-compatible, Codex, or Grok transcripts\n link-skill Link one packaged skill into an explicit consumer directory\n retrospective-facts Gather immutable facts for a retrospective\n agent-blackboard Probe and journal an Agent Blackboard deployment\n mcp Serve the agent-blackboard journal tools over stdio (MCP)\n\nOptions:\n -h, --help Show this help\n -v, --version Print the package version\n\nrunner-port-policy\n (no args) Print the shipped policy as JSON\n --file <path> Validate and print a policy file\n --reserved <port> Print true if the port is reserved\n\nwith-host-lock\n --name <family>\n [--slots <n>]\n --timeout-seconds <n>\n [--command-timeout-seconds <n>]\n [--failure-diagnostics <absolute-script>]\n [--on-acquire-timeout fail|run-unlocked]\n -- <command> [args...]\n\ngha-runtime-audit\n [--repository owner/name] Default GITHUB_REPOSITORY\n [--branch main]\n [--median-threshold-floor <seconds>] Off unless set. Must be below the ceiling\n [--median-threshold-ceiling <seconds>] Default 360. Flags a five-sample median above this\n --pr-workflow <name|/regex/> Repeatable\n --push-workflow <name|/regex/> Repeatable\n\nrequire-up-to-date --remote <name> --branch <name>\ngitleaks-directory-scan --config <path> [--directory <path>]\nast-grep-examples --rules <directory> --config <path>\nast-grep-pack\ngha-workspace-policy [--root <directory>] [--workflow-directory <directory>] [--action-directory <directory>]\n\ngha-output <name>\ngha-needs-results [label]\ndownload-with-diagnostics <url> <destination> [-- curl-args...]\ndownload-optional-run-artifacts (--name <name>... | --pattern <pattern>) --dir <directory>\nhost-pressure-diagnostics\nallocate-browser-safe-ports <count> [--policy path] [--forbidden-ports path]\ndiagnose-port-collision [--ports \"2200 2216\"] [--output-dir PATH]\nprepare-trivy-db\ngha-artifacts-cleanup run --run-id <id> [--keep-pattern glob] [--delete-pattern glob] [--patterns-file json]\ngha-artifacts-cleanup sweep --older-than-hours <n> [--keep-pattern glob] [--delete-pattern glob] [--patterns-file json]\nhttp-origin [--field NAME] [value]\nvitest-blob-manifest <suite> [reports-directory]\nvitest-report-attempt <write DIRECTORY SUITE|read ROOT>\nprepare-vitest-reports [primary-directory] [fallback-directory] [output-directory]\npnpm-install --runner-lifecycle persistent|ephemeral|ephemeral-full --install-scripts true|false\ncheck-cache-size <path> <max-bytes> <label>\nmake-shard-matrix <total>\nload-runner-env\nclean-workspace\ninstall-github-release --repo owner/name --version X --asset 'name-{platform}.tar.gz' --bin name [--tag-prefix PREFIX] [--expected-sha256 SHA256] [--no-checksum] [--checksums-asset NAME] [--version-flag FLAG] [--bin-dir DIR]\nrun-with-timeout <timeout-seconds> <kill-after-seconds> <command...>\nlint-links [--offline] [--config PATH] [--glob PATTERN] [files...]\nmaterialize-pr-context\nwait-for-apt-locks\ninstall-playwright-chromium-arm64 [name:archive...]\nghcr-package-retention <url-encoded-package>...\nharness-admission-lane <lanes>\nharness-assert-gates <gate>...\ngha-collaborator-trust <owner/repo> [--allow-bot <login>]... < authors.json\nnuget-central-version <trusted-props> <candidate-props> <metadata-json> <output-props>\nswift-semantic-equal <base> <head> <file.swift>\npost-review\nstage-review-payload optional|required <source> <destination>\nretrospective-transcript [--session-id ID] [--jsonl PATH] [--projects-dir PATH] [--codex-sessions-dir PATH] [--grok-sessions-dir PATH]\nlink-skill <name> --source-root <skills-dir> --target-root <consumer-skills-dir> Link a packaged or repository-local skill\nretrospective-facts (--pr NUMBER | --branch NAME | --no-pr) [--repo OWNER/NAME] [--raw]\nagent-blackboard probe\nagent-blackboard journal append --mode interactive|autonomous --source-event-id ID --work-outcome OUTCOME --coverage-status STATUS --session-id UUID --agent NAME --version VERSION --file PATH --repository OWNER/NAME [--repository OWNER/NAME ...] [--parent-session-id UUID] [--timestamp ISO8601] [--coverage-source SOURCE,...] [--dropped-count N] [--outbox-directory PATH]\nagent-blackboard journal entries --session-id UUID\nagent-blackboard journal status --session-id UUID --outbox-directory PATH\nagent-blackboard journal flush --outbox-directory PATH [--session-id UUID]\nInteractive journal append requires --outbox-directory PATH.\nagent-blackboard journal is deprecated and being phased out: agents journal through the mcp server.\nagent-blackboard snapshot partition --snapshot PATH --checksum SHA256 --counts '{\"sessions\":N,\"entries\":N,\"records\":N,\"bytes\":N}'\nagent-blackboard snapshot cleanup [--snapshot PATH] [--partition-directory PATH --receipt JSON]\nmcp\n (no args) Serve journal_append, journal_entries, outbox_status, outbox_flush,\n session_ensure, snapshot_export, and session_archive over stdio.\n Needs the optional @modelcontextprotocol/sdk peer (and zod).\n Launch it from inside the repository's git worktree.\n";
|
|
2
2
|
export declare function printUsage(stream?: NodeJS.WritableStream): void;
|
|
3
3
|
export declare function commandNames(usage?: string): string[];
|
|
4
4
|
export declare function commandUsage(command: string, usage?: string): string;
|
package/dist/cli/usage.mjs
CHANGED
|
@@ -121,6 +121,7 @@ agent-blackboard journal entries --session-id UUID
|
|
|
121
121
|
agent-blackboard journal status --session-id UUID --outbox-directory PATH
|
|
122
122
|
agent-blackboard journal flush --outbox-directory PATH [--session-id UUID]
|
|
123
123
|
Interactive journal append requires --outbox-directory PATH.
|
|
124
|
+
agent-blackboard journal is deprecated and being phased out: agents journal through the mcp server.
|
|
124
125
|
agent-blackboard snapshot partition --snapshot PATH --checksum SHA256 --counts '{"sessions":N,"entries":N,"records":N,"bytes":N}'
|
|
125
126
|
agent-blackboard snapshot cleanup [--snapshot PATH] [--partition-directory PATH --receipt JSON]
|
|
126
127
|
mcp
|
|
@@ -4,9 +4,6 @@ export interface DirectoryIdentity {
|
|
|
4
4
|
readonly mode: number;
|
|
5
5
|
readonly uid: number;
|
|
6
6
|
}
|
|
7
|
-
/** pnpm's cache directory. The audit store stays beside it so it is not the developer store. */
|
|
8
|
-
export declare function pnpmCacheDirectory(env?: NodeJS.ProcessEnv, home?: string, hostPlatform?: NodeJS.Platform): string;
|
|
9
|
-
export declare function licenseAuditStoreDirectory(env?: NodeJS.ProcessEnv, home?: string, hostPlatform?: NodeJS.Platform): string;
|
|
10
7
|
export declare function assertOwnedDirectory(stat: DirectoryIdentity, uid: number | undefined, directory: string): void;
|
|
11
|
-
/** Creates the
|
|
8
|
+
/** Creates the private, per-run store beneath the disposable license audit workspace. */
|
|
12
9
|
export declare function ensurePrivateLicenseAuditStore(directory: string): void;
|
|
@@ -1,19 +1,4 @@
|
|
|
1
1
|
import { chmodSync, lstatSync, mkdirSync } from 'node:fs';
|
|
2
|
-
import { homedir } from 'node:os';
|
|
3
|
-
import { join } from 'node:path';
|
|
4
|
-
const STORE_DIRECTORY_NAME = 'dependency-license-audit-store';
|
|
5
|
-
/** pnpm's cache directory. The audit store stays beside it so it is not the developer store. */
|
|
6
|
-
export function pnpmCacheDirectory(env = process.env, home = homedir(), hostPlatform = process.platform) {
|
|
7
|
-
if (hostPlatform === 'darwin')
|
|
8
|
-
return join(home, 'Library', 'Caches', 'pnpm');
|
|
9
|
-
if (hostPlatform === 'win32') {
|
|
10
|
-
return join(env.LOCALAPPDATA ?? join(home, 'AppData', 'Local'), 'pnpm-cache');
|
|
11
|
-
}
|
|
12
|
-
return join(env.XDG_CACHE_HOME ?? join(home, '.cache'), 'pnpm');
|
|
13
|
-
}
|
|
14
|
-
export function licenseAuditStoreDirectory(env = process.env, home = homedir(), hostPlatform = process.platform) {
|
|
15
|
-
return join(pnpmCacheDirectory(env, home, hostPlatform), STORE_DIRECTORY_NAME);
|
|
16
|
-
}
|
|
17
2
|
export function assertOwnedDirectory(stat, uid, directory) {
|
|
18
3
|
if (stat.isSymbolicLink() || !stat.isDirectory()) {
|
|
19
4
|
throw new Error(`dependency license audit store is not a real directory: ${directory}`);
|
|
@@ -22,7 +7,7 @@ export function assertOwnedDirectory(stat, uid, directory) {
|
|
|
22
7
|
throw new Error(`dependency license audit store is not owned by the current user: ${directory}`);
|
|
23
8
|
}
|
|
24
9
|
}
|
|
25
|
-
/** Creates the
|
|
10
|
+
/** Creates the private, per-run store beneath the disposable license audit workspace. */
|
|
26
11
|
export function ensurePrivateLicenseAuditStore(directory) {
|
|
27
12
|
mkdirSync(directory, { recursive: true, mode: 0o700 });
|
|
28
13
|
const stat = lstatSync(directory);
|
|
@@ -5,7 +5,6 @@ export interface CollectPnpmLicenseReportOptions {
|
|
|
5
5
|
readonly execute?: PnpmExecutor;
|
|
6
6
|
readonly prepareWorkspace?: (repoRoot: string, lockfileSource: string, workspaceSource: string) => PnpmLicenseAuditWorkspace;
|
|
7
7
|
readonly readFile?: (path: string, encoding: 'utf8') => string;
|
|
8
|
-
readonly storeDir?: string;
|
|
9
8
|
}
|
|
10
9
|
/** Collects licenses for every platform represented in a pnpm lockfile. */
|
|
11
10
|
export declare function collectPnpmLicenseReport(repoRoot: string, options?: CollectPnpmLicenseReportOptions): Promise<PnpmLicenseReport>;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { readFileSync } from 'node:fs';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
3
|
import { withAuditSignalCleanup } from "./audit-signals.mjs";
|
|
4
|
-
import { ensurePrivateLicenseAuditStore
|
|
4
|
+
import { ensurePrivateLicenseAuditStore } from "./audit-store.mjs";
|
|
5
5
|
import { executePnpm } from "./execute-pnpm.mjs";
|
|
6
6
|
import { parsePnpmLicenseReport } from "./report.mjs";
|
|
7
7
|
import { preparePnpmLicenseAuditWorkspace } from "./workspace.mjs";
|
|
@@ -25,7 +25,7 @@ function assertCommandSucceeded(label, result) {
|
|
|
25
25
|
export async function collectPnpmLicenseReport(repoRoot, options = {}) {
|
|
26
26
|
const { ensureStore, execute, prepareWorkspace, readFile } = { ...DEFAULT_OPTIONS, ...options };
|
|
27
27
|
const auditWorkspace = prepareWorkspace(repoRoot, readFile(join(repoRoot, 'pnpm-lock.yaml'), 'utf8'), readFile(join(repoRoot, 'pnpm-workspace.yaml'), 'utf8'));
|
|
28
|
-
const storeDir =
|
|
28
|
+
const storeDir = join(auditWorkspace.cwd, 'store');
|
|
29
29
|
return withAuditSignalCleanup(auditWorkspace.cleanup, async (signal) => {
|
|
30
30
|
ensureStore(storeDir);
|
|
31
31
|
const storeConfig = `--config.store-dir=${storeDir}`;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/** Minimal structural facts; public declarations do not require the optional SQL parser peer. */
|
|
2
|
+
export type GeneratedArbiterName = {
|
|
3
|
+
parts: readonly {
|
|
4
|
+
identity: string;
|
|
5
|
+
}[];
|
|
6
|
+
};
|
|
7
|
+
type GeneratedArbiterRoot = {
|
|
8
|
+
kind: 'columnReference';
|
|
9
|
+
name: GeneratedArbiterName;
|
|
10
|
+
} | {
|
|
11
|
+
kind: 'parenthesized';
|
|
12
|
+
expression: GeneratedArbiterRoot;
|
|
13
|
+
} | {
|
|
14
|
+
kind: 'functionCall' | 'cast' | 'nullTest' | 'distinctness' | 'parameter' | 'typedLiteral' | 'literal' | 'binary' | 'unary' | 'array' | 'case' | 'subquery' | 'other';
|
|
15
|
+
};
|
|
16
|
+
export type GeneratedArbiterExpression = {
|
|
17
|
+
columns: readonly GeneratedArbiterName[];
|
|
18
|
+
root: GeneratedArbiterRoot;
|
|
19
|
+
childrenComplete?: boolean;
|
|
20
|
+
};
|
|
21
|
+
export type GeneratedArbiterConflict = {
|
|
22
|
+
target: {
|
|
23
|
+
kind: 'columns';
|
|
24
|
+
columns: readonly {
|
|
25
|
+
identity: string;
|
|
26
|
+
}[];
|
|
27
|
+
} | {
|
|
28
|
+
kind: 'expressions';
|
|
29
|
+
expressions: readonly GeneratedArbiterExpression[];
|
|
30
|
+
} | {
|
|
31
|
+
kind: 'constraint' | 'omitted';
|
|
32
|
+
};
|
|
33
|
+
predicate: GeneratedArbiterExpression | null;
|
|
34
|
+
action: {
|
|
35
|
+
kind: 'doNothing';
|
|
36
|
+
} | {
|
|
37
|
+
kind: 'doUpdate';
|
|
38
|
+
assignments: readonly {
|
|
39
|
+
columns: readonly GeneratedArbiterName[];
|
|
40
|
+
expression: GeneratedArbiterExpression;
|
|
41
|
+
complete: boolean;
|
|
42
|
+
target?: {
|
|
43
|
+
subscripts: readonly unknown[];
|
|
44
|
+
indirection?: readonly unknown[];
|
|
45
|
+
};
|
|
46
|
+
}[];
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { GeneratedArbiterConflict } from './generated-arbiter-facts.mts';
|
|
2
|
+
export type GeneratedArbiterAssignmentInput = {
|
|
3
|
+
columns: readonly string[];
|
|
4
|
+
/** A direct column reference, excluding the two-part EXCLUDED namespace. */
|
|
5
|
+
referencedColumn: string | undefined;
|
|
6
|
+
hasIndirection: boolean;
|
|
7
|
+
complete: boolean;
|
|
8
|
+
};
|
|
9
|
+
export type GeneratedArbiterInput = {
|
|
10
|
+
action: 'doNothing' | 'doUpdate';
|
|
11
|
+
/** Undefined for named constraints, omitted keys, or unresolved expression keys. */
|
|
12
|
+
keyColumns: ReadonlySet<string> | undefined;
|
|
13
|
+
predicateColumns: ReadonlySet<string>;
|
|
14
|
+
assignments: readonly GeneratedArbiterAssignmentInput[];
|
|
15
|
+
/** False means callers must reject rather than infer replay safety from partial facts. */
|
|
16
|
+
complete: boolean;
|
|
17
|
+
};
|
|
18
|
+
/** Projects released SQL facts for a snapshot-dependent generated-column replay verdict.
|
|
19
|
+
* This reports syntax and identities only; callers own protection and safety policy.
|
|
20
|
+
*/
|
|
21
|
+
export declare function projectGeneratedArbiterInput(conflict: GeneratedArbiterConflict): GeneratedArbiterInput;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/** Projects released SQL facts for a snapshot-dependent generated-column replay verdict.
|
|
2
|
+
* This reports syntax and identities only; callers own protection and safety policy.
|
|
3
|
+
*/
|
|
4
|
+
export function projectGeneratedArbiterInput(conflict) {
|
|
5
|
+
let complete = true;
|
|
6
|
+
const predicateColumns = new Set();
|
|
7
|
+
if (conflict.predicate) {
|
|
8
|
+
complete = expressionComplete(conflict.predicate);
|
|
9
|
+
collectColumns(conflict.predicate, predicateColumns);
|
|
10
|
+
}
|
|
11
|
+
let keyColumns;
|
|
12
|
+
if (conflict.target.kind === 'columns' && conflict.target.columns.length > 0) {
|
|
13
|
+
keyColumns = new Set(conflict.target.columns.map((column) => column.identity));
|
|
14
|
+
}
|
|
15
|
+
else if (conflict.target.kind === 'expressions') {
|
|
16
|
+
const columns = new Set();
|
|
17
|
+
let resolved = conflict.target.expressions.length > 0;
|
|
18
|
+
for (const expression of conflict.target.expressions) {
|
|
19
|
+
const references = new Set();
|
|
20
|
+
collectColumns(expression, references);
|
|
21
|
+
const represented = expressionComplete(expression);
|
|
22
|
+
complete &&= represented;
|
|
23
|
+
if (!represented || references.size !== 1)
|
|
24
|
+
resolved = false;
|
|
25
|
+
for (const column of references)
|
|
26
|
+
columns.add(column);
|
|
27
|
+
}
|
|
28
|
+
if (resolved)
|
|
29
|
+
keyColumns = columns;
|
|
30
|
+
}
|
|
31
|
+
const assignments = conflict.action.kind === 'doUpdate'
|
|
32
|
+
? conflict.action.assignments.map((assignment) => {
|
|
33
|
+
const columns = assignment.columns.map(lastIdentity);
|
|
34
|
+
const represented = assignment.complete &&
|
|
35
|
+
columns.every((column) => column !== undefined) &&
|
|
36
|
+
expressionComplete(assignment.expression);
|
|
37
|
+
complete &&= represented;
|
|
38
|
+
let root = assignment.expression.root;
|
|
39
|
+
while (root.kind === 'parenthesized')
|
|
40
|
+
root = root.expression;
|
|
41
|
+
return {
|
|
42
|
+
columns: columns.filter((column) => column !== undefined),
|
|
43
|
+
referencedColumn: root.kind === 'columnReference' && !isExcluded(root.name)
|
|
44
|
+
? lastIdentity(root.name)
|
|
45
|
+
: undefined,
|
|
46
|
+
hasIndirection: Boolean(assignment.target &&
|
|
47
|
+
(assignment.target.subscripts.length > 0 ||
|
|
48
|
+
(assignment.target.indirection?.length ?? 0) > 0)),
|
|
49
|
+
complete: represented,
|
|
50
|
+
};
|
|
51
|
+
})
|
|
52
|
+
: [];
|
|
53
|
+
return { action: conflict.action.kind, keyColumns, predicateColumns, assignments, complete };
|
|
54
|
+
}
|
|
55
|
+
function lastIdentity(name) {
|
|
56
|
+
return name.parts.at(-1)?.identity;
|
|
57
|
+
}
|
|
58
|
+
function isExcluded(name) {
|
|
59
|
+
return name.parts.length === 2 && name.parts[0]?.identity === 'excluded';
|
|
60
|
+
}
|
|
61
|
+
function collectColumns(expression, columns) {
|
|
62
|
+
for (const name of expression.columns) {
|
|
63
|
+
const column = lastIdentity(name);
|
|
64
|
+
if (!isExcluded(name) && column !== undefined)
|
|
65
|
+
columns.add(column);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
function expressionComplete(expression) {
|
|
69
|
+
// Older optional peers do not carry completeness; do not silently admit their partial facts.
|
|
70
|
+
return ('childrenComplete' in expression &&
|
|
71
|
+
expression.childrenComplete === true &&
|
|
72
|
+
expression.columns.every((name) => lastIdentity(name) !== undefined));
|
|
73
|
+
}
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
export type { GeneratedArbiterConflict } from './generated-arbiter-facts.mts';
|
|
2
|
+
export { projectGeneratedArbiterInput } from './generated-arbiter-input.mts';
|
|
3
|
+
export type { GeneratedArbiterInput, GeneratedArbiterAssignmentInput, } from './generated-arbiter-input.mts';
|
|
1
4
|
export { buildSchemaSnapshot, buildTableSnapshots } from './build-snapshot.mts';
|
|
2
5
|
export { readColumns, readConstraints, readEnums, readExtensions, readFunctions, readIndexes, readPolicies, readSchemaCatalog, readTables, readTriggers, readViews, } from './catalog-queries.mts';
|
|
3
6
|
export type { CatalogColumnRow, CatalogConstraintRow, CatalogEnumValueRow, CatalogExtensionRow, CatalogFunctionRow, CatalogIndexRow, CatalogPolicyRow, CatalogTableRow, CatalogTriggerRow, CatalogViewRow, SchemaCatalog, } from './catalog-queries.mts';
|
|
@@ -10,3 +13,4 @@ export { renderSchemaMarkdown } from './render-markdown.mts';
|
|
|
10
13
|
export type { SchemaMarkdownFiles } from './render-markdown.mts';
|
|
11
14
|
export { renderTableDocument } from './render-tables.mts';
|
|
12
15
|
export type { CatalogQuery, PartitionPolicy, SchemaColumnSnapshot, SchemaEnumSnapshot, SchemaExtensionSnapshot, SchemaForeignKeySnapshot, SchemaFunctionSnapshot, SchemaGrowthMaps, SchemaIndexKeySnapshot, SchemaIndexSnapshot, SchemaKeyConstraintSnapshot, SchemaPhysicalPartitionSnapshot, SchemaPolicySnapshot, SchemaSnapshot, SchemaTableSnapshot, SchemaViewSnapshot, } from './types.mts';
|
|
16
|
+
export { extractStaticStringPairs } from './static-string-pairs.mts';
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export { projectGeneratedArbiterInput } from "./generated-arbiter-input.mjs";
|
|
1
2
|
export { buildSchemaSnapshot, buildTableSnapshots } from "./build-snapshot.mjs";
|
|
2
3
|
export { readColumns, readConstraints, readEnums, readExtensions, readFunctions, readIndexes, readPolicies, readSchemaCatalog, readTables, readTriggers, readViews, } from "./catalog-queries.mjs";
|
|
3
4
|
export { generateSchemaSnapshot, stableStringify, writeSchemaSnapshot } from "./generate.mjs";
|
|
@@ -5,3 +6,4 @@ export { detectRenamedIndexes, indexShapeKey } from "./index-rename-detect.mjs";
|
|
|
5
6
|
export { createPostgresReplayContext, createPostgresReplayContextFromSchema, } from "./replay-context.mjs";
|
|
6
7
|
export { renderSchemaMarkdown } from "./render-markdown.mjs";
|
|
7
8
|
export { renderTableDocument } from "./render-tables.mjs";
|
|
9
|
+
export { extractStaticStringPairs } from "./static-string-pairs.mjs";
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Collects the first two string literals of every source array in ESTree field traversal order.
|
|
3
|
+
* Order follows the existing parser walker, including conditional alternatives before consequents.
|
|
4
|
+
* Arrays may contain further elements. This does not evaluate constants, imports, or spreads;
|
|
5
|
+
* repeated pairs remain repeated so callers can apply their own selection and deduplication.
|
|
6
|
+
* Invalid source throws through the source-only parser.
|
|
7
|
+
*/
|
|
8
|
+
export declare function extractStaticStringPairs(source: string): readonly (readonly [string, string])[];
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { isNode, parseSource, walk } from "../post-publication-inventory/readers/source-ast.mjs";
|
|
2
|
+
/**
|
|
3
|
+
* Collects the first two string literals of every source array in ESTree field traversal order.
|
|
4
|
+
* Order follows the existing parser walker, including conditional alternatives before consequents.
|
|
5
|
+
* Arrays may contain further elements. This does not evaluate constants, imports, or spreads;
|
|
6
|
+
* repeated pairs remain repeated so callers can apply their own selection and deduplication.
|
|
7
|
+
* Invalid source throws through the source-only parser.
|
|
8
|
+
*/
|
|
9
|
+
export function extractStaticStringPairs(source) {
|
|
10
|
+
const pairs = [];
|
|
11
|
+
const { ast } = parseSource(source);
|
|
12
|
+
walk(ast, (node) => {
|
|
13
|
+
if (node.type !== 'ArrayExpression' || !Array.isArray(node.elements))
|
|
14
|
+
return;
|
|
15
|
+
const [first, second] = node.elements;
|
|
16
|
+
if (isNode(first) &&
|
|
17
|
+
isNode(second) &&
|
|
18
|
+
first.type === 'Literal' &&
|
|
19
|
+
second.type === 'Literal' &&
|
|
20
|
+
typeof first.value === 'string' &&
|
|
21
|
+
typeof second.value === 'string') {
|
|
22
|
+
pairs.push([first.value, second.value]);
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
return pairs;
|
|
26
|
+
}
|
package/docs/mcp-server.md
CHANGED
|
@@ -40,8 +40,10 @@ environment. The server never searches for, prints, or mints them.
|
|
|
40
40
|
|
|
41
41
|
## CLI fallback
|
|
42
42
|
|
|
43
|
-
If
|
|
44
|
-
|
|
43
|
+
MCP is the supported path. If it is unavailable, restore it first as the blackboard skill describes.
|
|
44
|
+
As a last resort, use `vouchington agent-blackboard journal append|entries|flush|status` as described
|
|
45
|
+
there; sandboxed Claude Code and Codex withhold the token, so it can only retain records in the
|
|
46
|
+
outbox the server later flushes. Record the fallback and delivery status in the journal and tell the human. The CLI resolves its
|
|
45
47
|
client from its own installation, so install `agent-blackboard` alongside that trusted CLI.
|
|
46
48
|
Run the script with a verified absolute `node` and a cleared environment (`env -i`), never through
|
|
47
49
|
its `#!/usr/bin/env node` line, which takes `node` from a possibly repository-controlled `PATH`.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vouchington-tooling",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.41.0",
|
|
4
4
|
"description": "Vouchington CLI and extractable tooling libraries.",
|
|
5
5
|
"homepage": "https://github.com/vouchington/vouchington-tooling/tree/main/packages/vouchington-tooling#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -377,11 +377,11 @@
|
|
|
377
377
|
},
|
|
378
378
|
"devDependencies": {
|
|
379
379
|
"@ast-grep/cli": "0.45.3",
|
|
380
|
-
"@modelcontextprotocol/sdk": "1.
|
|
380
|
+
"@modelcontextprotocol/sdk": "1.32.0",
|
|
381
381
|
"@types/picomatch": "^4.0.3",
|
|
382
382
|
"@types/spdx-expression-parse": "4.0.0",
|
|
383
383
|
"agent-blackboard": "^0.6.1",
|
|
384
|
-
"no-mistakes": "0.
|
|
384
|
+
"no-mistakes": "0.83.0",
|
|
385
385
|
"smol-toml": "1.9.0",
|
|
386
386
|
"typescript5": "npm:typescript@5.9.3"
|
|
387
387
|
},
|
|
@@ -38,18 +38,36 @@ Every call may take `worktree`, the absolute path of a worktree of the current r
|
|
|
38
38
|
launch worktree by default). Writing or retrying an entry needs no provider skill, temporary file,
|
|
39
39
|
`--file` flag, or replay command.
|
|
40
40
|
Search for `journal_append` (by bare name, so every prefix matches) before concluding the server is
|
|
41
|
-
unavailable; a deferred harness lists the tool only on request.
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
41
|
+
unavailable; a deferred harness lists the tool only on request. A tool error is not
|
|
42
|
+
unavailability: act on its message and retry through MCP.
|
|
43
|
+
|
|
44
|
+
## When the server is unavailable
|
|
45
|
+
|
|
46
|
+
MCP is the supported journaling path. If the search finds no such tool, stop journaling and tell the
|
|
47
|
+
human which case applies before continuing:
|
|
48
|
+
|
|
49
|
+
- Not registered: the machine's agent configuration must register it; follow the consumer's
|
|
50
|
+
registration and diagnosis steps.
|
|
51
|
+
- Registered but disconnected: reconnect it through the harness's MCP controls, or restart the
|
|
52
|
+
harness.
|
|
53
|
+
- Automated runs with no human to ask: report "journaling unavailable" in the final report.
|
|
54
|
+
|
|
55
|
+
Prefer restoring MCP over the CLI fallback below, and use the fallback only when the human asks or
|
|
56
|
+
MCP cannot be restored for this session. Harness sandboxes commonly withhold
|
|
57
|
+
`AGENT_BLACKBOARD_TOKEN` from shell commands, so the fallback usually cannot deliver there. Never
|
|
58
|
+
request an unsandboxed run only to obtain the token. When the fallback is used, record its reason,
|
|
59
|
+
entrypoint, affected operations, and observed delivery status in the caller's journal. Do not treat
|
|
60
|
+
a permission denial as tool unavailability or bypass a host approval requirement through the CLI.
|
|
61
|
+
If neither path persists the note, stop and report the blocker.
|
|
47
62
|
|
|
48
63
|
## CLI fallback
|
|
49
64
|
|
|
65
|
+
Deprecated and being phased out: the MCP tools replace it, and retrospective and PR writers are
|
|
66
|
+
moving to MCP tools as well.
|
|
67
|
+
|
|
50
68
|
Use a trusted machine-installed `vouchington` executable at a verified absolute path outside the
|
|
51
69
|
consumer worktree. Resolve its symlinks and verify the installation's source and version before
|
|
52
|
-
using credentials
|
|
70
|
+
using credentials; its runtime dependencies must also belong to
|
|
53
71
|
that trusted installation. The CLI resolves its client relative to its own installation; installing
|
|
54
72
|
`agent-blackboard` only in the consumer worktree is insufficient for CLI fallback. Do not resolve the executable through the consumer's `node_modules/.bin`,
|
|
55
73
|
`pnpm exec`, or repository-controlled `PATH`. Set `BLACKBOARD_CLI` below to that verified absolute
|
|
@@ -93,13 +111,9 @@ explicit coverage sources when assessed. Omit `--timestamp` so the writer owns t
|
|
|
93
111
|
mode omits `--outbox-directory` and still requires fresh online admission plus readback.
|
|
94
112
|
For session-only or snapshot operations not exposed by this CLI, use the upstream
|
|
95
113
|
`agent-blackboard` CLI under its skill's operation contract; preserve exact identities and tags.
|
|
96
|
-
A sandboxed fallback may only write the outbox:
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
normal approval path for running one command outside the sandbox, with each such run approved
|
|
100
|
-
individually. Never read, print, copy, or export the token
|
|
101
|
-
to work around the sandbox. If approval is denied, leave the record pending in the outbox, report
|
|
102
|
-
`pendingCount`, and tell the human.
|
|
114
|
+
A sandboxed fallback may only write the outbox: without `AGENT_BLACKBOARD_TOKEN` it cannot deliver
|
|
115
|
+
or read back. Leave the record pending, report `pendingCount`, and deliver it with `outbox_flush`
|
|
116
|
+
once MCP is restored. Never read, print, copy, or export the token to work around the sandbox.
|
|
103
117
|
Return to MCP when available and journal recovery. Never silently downgrade envelope validation,
|
|
104
118
|
retention, or delivery checks because the transport changed.
|
|
105
119
|
|
package/skills/manifest.json
CHANGED
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
{
|
|
25
25
|
"name": "bounded-iteration",
|
|
26
26
|
"plugin": "vouchington-database",
|
|
27
|
-
"pluginVersion": "0.
|
|
27
|
+
"pluginVersion": "0.6.0",
|
|
28
28
|
"path": "bounded-iteration/SKILL.md"
|
|
29
29
|
},
|
|
30
30
|
{
|
|
@@ -109,19 +109,19 @@
|
|
|
109
109
|
{
|
|
110
110
|
"name": "postgres-node-performance-tuning",
|
|
111
111
|
"plugin": "vouchington-database",
|
|
112
|
-
"pluginVersion": "0.
|
|
112
|
+
"pluginVersion": "0.6.0",
|
|
113
113
|
"path": "postgres-node-performance-tuning/SKILL.md"
|
|
114
114
|
},
|
|
115
115
|
{
|
|
116
116
|
"name": "postgres-partitioning-uuid-v7",
|
|
117
117
|
"plugin": "vouchington-database",
|
|
118
|
-
"pluginVersion": "0.
|
|
118
|
+
"pluginVersion": "0.6.0",
|
|
119
119
|
"path": "postgres-partitioning-uuid-v7/SKILL.md"
|
|
120
120
|
},
|
|
121
121
|
{
|
|
122
122
|
"name": "postgres-schema-design",
|
|
123
123
|
"plugin": "vouchington-database",
|
|
124
|
-
"pluginVersion": "0.
|
|
124
|
+
"pluginVersion": "0.6.0",
|
|
125
125
|
"path": "postgres-schema-design/SKILL.md"
|
|
126
126
|
},
|
|
127
127
|
{
|
|
@@ -18,6 +18,8 @@ Measure the query plan and the workload shape before changing code.
|
|
|
18
18
|
- Keep connection-pool usage bounded.
|
|
19
19
|
- Validate a query change at representative cardinality. Watch latency, memory, lock time, and
|
|
20
20
|
connection pressure together.
|
|
21
|
+
- Cut round trips: fold dependent reads, batch per-item lookups, and overlap independent reads; see
|
|
22
|
+
[round trips](references/performance-patterns.md#round-trips).
|
|
21
23
|
- Read [performance patterns](references/performance-patterns.md) before changing a high-volume
|
|
22
24
|
path.
|
|
23
25
|
|
|
@@ -37,3 +37,26 @@ recipient-keyed fan-out rows. Verify actual pruning with EXPLAIN.
|
|
|
37
37
|
|
|
38
38
|
Generic `jonathanong/no-mistakes` checks include `postgres-no-offset`; inspect available rules
|
|
39
39
|
and configure reviewed cross-partition exceptions rather than treating a rule as plan evidence.
|
|
40
|
+
|
|
41
|
+
## Round trips
|
|
42
|
+
|
|
43
|
+
Sequential queries can add network round trips when the client waits between statements, and planning
|
|
44
|
+
can add latency when PostgreSQL does not reuse a prepared plan; count round trips per request before
|
|
45
|
+
tuning individual statements.
|
|
46
|
+
|
|
47
|
+
Load a parent and the viewer's relation to it in one query: join the membership row, or use a
|
|
48
|
+
lateral subquery, rather than reading the parent and then the relation.
|
|
49
|
+
|
|
50
|
+
`Promise.all` over statements on one transaction client is still serial, because one connection
|
|
51
|
+
runs one statement at a time. Merge them instead: CTEs, `UNNEST`, or one multi-row statement.
|
|
52
|
+
|
|
53
|
+
Give every per-item lookup helper a batch twin that takes an array of keys and returns a keyed
|
|
54
|
+
map, and call the twin from loops, `.map` callbacks, and `Promise.all` fan-outs. `no-await-in-loop`
|
|
55
|
+
misses a helper that queries internally and `Promise.all(items.map(helper))`; review those call
|
|
56
|
+
sites by hand.
|
|
57
|
+
|
|
58
|
+
Overlap independent cache and PostgreSQL reads with `Promise.all`, such as a rate-limiter check
|
|
59
|
+
alongside the user fetch. Serialize only true dependencies, where one result feeds the next call.
|
|
60
|
+
|
|
61
|
+
Run a symmetric check, such as "is either party blocking the other", as one query with an `OR`
|
|
62
|
+
or both-direction predicate, not twice with the arguments swapped.
|