mirror of
https://github.com/garrytan/gstack.git
synced 2026-09-21 20:30:47 +02:00
feat(gstack2): consolidated runtime — execution-result contract, profiles, capability readiness, hardening (#10)
feat(gstack2): consolidated runtime — execution-result contract, profiles, capability readiness, hardening
This commit is contained in:
+1
-1
@@ -49,5 +49,5 @@ bin/* text eol=lf
|
|||||||
# The committed diagram-render bundle is hash-pinned (BUILD_INFO sha256);
|
# The committed diagram-render bundle is hash-pinned (BUILD_INFO sha256);
|
||||||
# a CRLF rewrite on Windows checkout would break the drift test and change
|
# a CRLF rewrite on Windows checkout would break the drift test and change
|
||||||
# the content-addressed staged filename.
|
# the content-addressed staged filename.
|
||||||
lib/diagram-render/dist/*.html text eol=lf
|
lib/diagram-render/dist/*.html text eol=lf whitespace=-trailing-space
|
||||||
lib/diagram-render/dist/*.json text eol=lf
|
lib/diagram-render/dist/*.json text eol=lf
|
||||||
|
|||||||
@@ -4,6 +4,10 @@ on: [push, pull_request]
|
|||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: actionlint-${{ github.workflow }}-${{ github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
actionlint:
|
actionlint:
|
||||||
runs-on: ubicloud-standard-8
|
runs-on: ubicloud-standard-8
|
||||||
|
|||||||
@@ -16,6 +16,10 @@ on:
|
|||||||
# Manual trigger
|
# Manual trigger
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: ci-image
|
||||||
|
cancel-in-progress: false
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: ubicloud-standard-8
|
runs-on: ubicloud-standard-8
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
name: Dependency Review
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
branches: [main]
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: dependency-review-${{ github.event.pull_request.number }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
dependency-review:
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
steps:
|
||||||
|
- name: Review dependency changes
|
||||||
|
uses: actions/dependency-review-action@2031cfc080254a8a887f58cffee85186f0e49e48 # v4.9.0
|
||||||
|
with:
|
||||||
|
fail-on-severity: high
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
name: OSV Scanner
|
||||||
|
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: '23 7 * * 1'
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: osv-scanner
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
scan:
|
||||||
|
permissions:
|
||||||
|
actions: read
|
||||||
|
contents: read
|
||||||
|
security-events: write
|
||||||
|
uses: google/osv-scanner-action/.github/workflows/osv-scanner-reusable.yml@3adb4b14a2b0623876d18d863a498b785fb3752d # v2.3.8
|
||||||
|
with:
|
||||||
|
scan-args: |-
|
||||||
|
--include-git-root
|
||||||
|
--recursive
|
||||||
|
./
|
||||||
@@ -10,6 +10,10 @@ on:
|
|||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: quality-gate-${{ github.workflow }}-${{ github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
quality:
|
quality:
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
name: OpenSSF Scorecard
|
||||||
|
|
||||||
|
on:
|
||||||
|
branch_protection_rule:
|
||||||
|
schedule:
|
||||||
|
- cron: '41 7 * * 1'
|
||||||
|
push:
|
||||||
|
branches: [main]
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: scorecard-${{ github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
analysis:
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
security-events: write
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
|
||||||
|
with:
|
||||||
|
persist-credentials: false
|
||||||
|
|
||||||
|
- name: Run Scorecard analysis
|
||||||
|
uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a # v2.4.3
|
||||||
|
with:
|
||||||
|
results_file: results.sarif
|
||||||
|
results_format: sarif
|
||||||
|
publish_results: false
|
||||||
|
|
||||||
|
- name: Upload Scorecard results to code scanning
|
||||||
|
uses: github/codeql-action/upload-sarif@85b88275909735f5bc23196090e03d2eb148b3de # v3.32.4
|
||||||
|
with:
|
||||||
|
sarif_file: results.sarif
|
||||||
|
|
||||||
|
- name: Upload Scorecard results artifact
|
||||||
|
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
|
||||||
|
with:
|
||||||
|
name: scorecard-results
|
||||||
|
path: results.sarif
|
||||||
|
retention-days: 5
|
||||||
@@ -4,6 +4,10 @@ on: [push, pull_request]
|
|||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: skill-docs-${{ github.workflow }}-${{ github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
check-freshness:
|
check-freshness:
|
||||||
runs-on: ubicloud-standard-8
|
runs-on: ubicloud-standard-8
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
# OSV-Scanner configuration.
|
||||||
|
# Direct/transitive dependency versions are pinned to their fixed releases via
|
||||||
|
# the `overrides` block in package.json; this file only records advisories we
|
||||||
|
# have assessed as not-reachable or not-fixable without disproportionate risk.
|
||||||
|
|
||||||
|
[[IgnoredVulns]]
|
||||||
|
id = "GHSA-frvp-7c67-39w9"
|
||||||
|
# @hono/node-server 1.19.x. Reachable only through @modelcontextprotocol/sdk,
|
||||||
|
# which is an unused transitive dependency (no source file imports it) and never
|
||||||
|
# starts a Hono HTTP server, so the advisory's request path is not exercised.
|
||||||
|
# The only fix is @hono/node-server 2.0.5, a major bump the MCP SDK pins against
|
||||||
|
# (^1.19.9); forcing it via override risks breaking the SDK at runtime for a
|
||||||
|
# vulnerability we do not expose. Re-evaluate if the MCP SDK becomes a direct,
|
||||||
|
# server-hosting dependency.
|
||||||
|
reason = "Unreachable transitive (unused @modelcontextprotocol/sdk); fix requires a risky major override on a pinned peer dep."
|
||||||
@@ -611,8 +611,12 @@ Data is stored in [Supabase](https://supabase.com) (open source Firebase alterna
|
|||||||
|
|
||||||
## Troubleshooting
|
## Troubleshooting
|
||||||
|
|
||||||
For GStack 2, first run `gstack doctor` (or `gstack doctor --json`) when the
|
For GStack 2, run `gstack doctor --capability browser|design|diagram|pdf|ios`
|
||||||
optional runtime is installed. For skill discovery problems, use the standard
|
(optionally `--json`) for a focused, non-mutating readiness result. It reports
|
||||||
|
pure-judgment availability, platform support, preview consent, install consent,
|
||||||
|
and runtime readiness separately; see
|
||||||
|
[`docs/gstack-2/CAPABILITY-READINESS.md`](docs/gstack-2/CAPABILITY-READINESS.md).
|
||||||
|
For skill discovery problems, use the standard
|
||||||
installer's list and reinstall commands; do not manually copy host paths. The
|
installer's list and reinstall commands; do not manually copy host paths. The
|
||||||
entries below apply to legacy 1.x installations.
|
entries below apply to legacy 1.x installations.
|
||||||
|
|
||||||
|
|||||||
@@ -118,10 +118,14 @@ describe('validateTempPath', () => {
|
|||||||
expect(() => validateTempPath('/tmp/nonexistent-file-12345.jpg')).toThrow(/not found/i);
|
expect(() => validateTempPath('/tmp/nonexistent-file-12345.jpg')).toThrow(/not found/i);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('rejects paths in cwd', () => {
|
it('rejects a temp-directory symlink that resolves outside temp', () => {
|
||||||
// Create a real file in cwd to test the path check (not the existence check)
|
const link = path.join(TEMP_DIR, `test-temp-link-${Date.now()}`);
|
||||||
const cwdFile = path.join(process.cwd(), 'package.json');
|
fs.symlinkSync('/etc/passwd', link);
|
||||||
expect(() => validateTempPath(cwdFile)).toThrow(/temp directory/i);
|
try {
|
||||||
|
expect(() => validateTempPath(link)).toThrow(/temp directory/i);
|
||||||
|
} finally {
|
||||||
|
fs.unlinkSync(link);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
it('rejects absolute paths outside safe dirs', () => {
|
it('rejects absolute paths outside safe dirs', () => {
|
||||||
|
|||||||
@@ -1,25 +1,29 @@
|
|||||||
/**
|
/** Tests for the retired passive updater and its explicit compatibility check. */
|
||||||
* Tests for bin/gstack-update-check bash script.
|
|
||||||
*
|
|
||||||
* Uses Bun.spawnSync to invoke the script with temp dirs and
|
|
||||||
* GSTACK_DIR / GSTACK_STATE_DIR / GSTACK_REMOTE_URL env overrides
|
|
||||||
* for full isolation.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { describe, test, expect, beforeEach, afterEach } from 'bun:test';
|
import { afterEach, beforeEach, describe, expect, test } from 'bun:test';
|
||||||
import { mkdtempSync, writeFileSync, rmSync, existsSync, readFileSync, mkdirSync, symlinkSync, utimesSync } from 'fs';
|
import {
|
||||||
import { join } from 'path';
|
existsSync,
|
||||||
import { tmpdir } from 'os';
|
mkdirSync,
|
||||||
|
mkdtempSync,
|
||||||
|
readFileSync,
|
||||||
|
rmSync,
|
||||||
|
symlinkSync,
|
||||||
|
writeFileSync,
|
||||||
|
} from 'node:fs';
|
||||||
|
import { tmpdir } from 'node:os';
|
||||||
|
import { join } from 'node:path';
|
||||||
|
|
||||||
const SCRIPT = join(import.meta.dir, '..', '..', 'bin', 'gstack-update-check');
|
const ROOT = join(import.meta.dir, '..', '..');
|
||||||
|
const SCRIPT = join(ROOT, 'bin', 'gstack-update-check');
|
||||||
|
|
||||||
let gstackDir: string;
|
let gstackDir: string;
|
||||||
let stateDir: string;
|
let stateDir: string;
|
||||||
|
|
||||||
function run(extraEnv: Record<string, string> = {}, args: string[] = []) {
|
function run(args: string[] = [], extraEnv: Record<string, string> = {}) {
|
||||||
const result = Bun.spawnSync(['bash', SCRIPT, ...args], {
|
const result = Bun.spawnSync(['bash', SCRIPT, ...args], {
|
||||||
env: {
|
env: {
|
||||||
...process.env,
|
...process.env,
|
||||||
|
GSTACK_HOME: '',
|
||||||
GSTACK_DIR: gstackDir,
|
GSTACK_DIR: gstackDir,
|
||||||
GSTACK_STATE_DIR: stateDir,
|
GSTACK_STATE_DIR: stateDir,
|
||||||
GSTACK_REMOTE_URL: `file://${join(gstackDir, 'REMOTE_VERSION')}`,
|
GSTACK_REMOTE_URL: `file://${join(gstackDir, 'REMOTE_VERSION')}`,
|
||||||
@@ -38,10 +42,9 @@ function run(extraEnv: Record<string, string> = {}, args: string[] = []) {
|
|||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
gstackDir = mkdtempSync(join(tmpdir(), 'gstack-upd-test-'));
|
gstackDir = mkdtempSync(join(tmpdir(), 'gstack-upd-test-'));
|
||||||
stateDir = mkdtempSync(join(tmpdir(), 'gstack-state-test-'));
|
stateDir = mkdtempSync(join(tmpdir(), 'gstack-state-test-'));
|
||||||
// Link real gstack-config so update_check config check works
|
|
||||||
const binDir = join(gstackDir, 'bin');
|
const binDir = join(gstackDir, 'bin');
|
||||||
mkdirSync(binDir);
|
mkdirSync(binDir);
|
||||||
symlinkSync(join(import.meta.dir, '..', '..', 'bin', 'gstack-config'), join(binDir, 'gstack-config'));
|
symlinkSync(join(ROOT, 'bin', 'gstack-config'), join(binDir, 'gstack-config'));
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
@@ -49,500 +52,69 @@ afterEach(() => {
|
|||||||
rmSync(stateDir, { recursive: true, force: true });
|
rmSync(stateDir, { recursive: true, force: true });
|
||||||
});
|
});
|
||||||
|
|
||||||
function writeSnooze(version: string, level: number, epochSeconds: number) {
|
describe('gstack-update-check compatibility boundary', () => {
|
||||||
writeFileSync(join(stateDir, 'update-snoozed'), `${version} ${level} ${epochSeconds}`);
|
test('passive invocation is a no-op even when an update and legacy state exist', () => {
|
||||||
}
|
writeFileSync(join(gstackDir, 'VERSION'), '1.0.0\n');
|
||||||
|
writeFileSync(join(gstackDir, 'REMOTE_VERSION'), '2.0.0\n');
|
||||||
|
writeFileSync(join(stateDir, 'last-update-check'), 'UPGRADE_AVAILABLE 1.0.0 2.0.0');
|
||||||
|
writeFileSync(join(stateDir, 'update-snoozed'), '2.0.0 3 1');
|
||||||
|
|
||||||
function writeConfig(content: string) {
|
expect(run()).toEqual({ exitCode: 0, stdout: '', stderr: '' });
|
||||||
writeFileSync(join(stateDir, 'config.yaml'), content);
|
expect(readFileSync(join(stateDir, 'last-update-check'), 'utf8')).toContain('UPGRADE_AVAILABLE');
|
||||||
}
|
expect(existsSync(join(stateDir, 'update-snoozed'))).toBe(true);
|
||||||
|
|
||||||
function nowEpoch(): number {
|
|
||||||
return Math.floor(Date.now() / 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
describe('gstack-update-check', () => {
|
|
||||||
// ─── Path A: No VERSION file ────────────────────────────────
|
|
||||||
test('exits 0 with no output when VERSION file is missing', () => {
|
|
||||||
const { exitCode, stdout } = run();
|
|
||||||
expect(exitCode).toBe(0);
|
|
||||||
expect(stdout).toBe('');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// ─── Path B: Empty VERSION file ─────────────────────────────
|
test('passive invocation performs no network or state setup', () => {
|
||||||
test('exits 0 with no output when VERSION file is empty', () => {
|
writeFileSync(join(gstackDir, 'VERSION'), '1.0.0\n');
|
||||||
writeFileSync(join(gstackDir, 'VERSION'), '');
|
const missingStateDir = join(stateDir, 'not-created');
|
||||||
const { exitCode, stdout } = run();
|
const result = run([], {
|
||||||
expect(exitCode).toBe(0);
|
GSTACK_STATE_DIR: missingStateDir,
|
||||||
expect(stdout).toBe('');
|
GSTACK_REMOTE_URL: 'https://127.0.0.1:1/must-not-be-requested',
|
||||||
});
|
|
||||||
|
|
||||||
// ─── Path C: Just-upgraded marker ───────────────────────────
|
|
||||||
test('outputs JUST_UPGRADED and deletes marker', () => {
|
|
||||||
writeFileSync(join(gstackDir, 'VERSION'), '0.4.0\n');
|
|
||||||
writeFileSync(join(stateDir, 'just-upgraded-from'), '0.3.3\n');
|
|
||||||
|
|
||||||
const { exitCode, stdout } = run();
|
|
||||||
expect(exitCode).toBe(0);
|
|
||||||
expect(stdout).toBe('JUST_UPGRADED 0.3.3 0.4.0');
|
|
||||||
// Marker should be deleted
|
|
||||||
expect(existsSync(join(stateDir, 'just-upgraded-from'))).toBe(false);
|
|
||||||
// Cache should be written
|
|
||||||
const cache = readFileSync(join(stateDir, 'last-update-check'), 'utf-8');
|
|
||||||
expect(cache).toContain('UP_TO_DATE');
|
|
||||||
});
|
|
||||||
|
|
||||||
// ─── Path C2: Just-upgraded marker + newer remote ──────────
|
|
||||||
test('just-upgraded marker does not mask newer remote version', () => {
|
|
||||||
writeFileSync(join(gstackDir, 'VERSION'), '0.4.0\n');
|
|
||||||
writeFileSync(join(stateDir, 'just-upgraded-from'), '0.3.3\n');
|
|
||||||
writeFileSync(join(gstackDir, 'REMOTE_VERSION'), '0.5.0\n');
|
|
||||||
|
|
||||||
const { exitCode, stdout } = run();
|
|
||||||
expect(exitCode).toBe(0);
|
|
||||||
// Should output both the just-upgraded notice AND the new upgrade
|
|
||||||
expect(stdout).toContain('JUST_UPGRADED 0.3.3 0.4.0');
|
|
||||||
expect(stdout).toContain('UPGRADE_AVAILABLE 0.4.0 0.5.0');
|
|
||||||
// Cache should reflect the upgrade available, not UP_TO_DATE
|
|
||||||
const cache = readFileSync(join(stateDir, 'last-update-check'), 'utf-8');
|
|
||||||
expect(cache).toContain('UPGRADE_AVAILABLE 0.4.0 0.5.0');
|
|
||||||
});
|
|
||||||
|
|
||||||
// ─── Path C3: Just-upgraded marker + remote matches local ──
|
|
||||||
test('just-upgraded with no further updates writes UP_TO_DATE cache', () => {
|
|
||||||
writeFileSync(join(gstackDir, 'VERSION'), '0.4.0\n');
|
|
||||||
writeFileSync(join(stateDir, 'just-upgraded-from'), '0.3.3\n');
|
|
||||||
writeFileSync(join(gstackDir, 'REMOTE_VERSION'), '0.4.0\n');
|
|
||||||
|
|
||||||
const { exitCode, stdout } = run();
|
|
||||||
expect(exitCode).toBe(0);
|
|
||||||
expect(stdout).toBe('JUST_UPGRADED 0.3.3 0.4.0');
|
|
||||||
const cache = readFileSync(join(stateDir, 'last-update-check'), 'utf-8');
|
|
||||||
expect(cache).toContain('UP_TO_DATE');
|
|
||||||
});
|
|
||||||
|
|
||||||
// ─── Path D1: Fresh cache, UP_TO_DATE ───────────────────────
|
|
||||||
test('exits silently when cache says UP_TO_DATE and is fresh', () => {
|
|
||||||
writeFileSync(join(gstackDir, 'VERSION'), '0.3.3\n');
|
|
||||||
writeFileSync(join(stateDir, 'last-update-check'), 'UP_TO_DATE 0.3.3');
|
|
||||||
|
|
||||||
const { exitCode, stdout } = run();
|
|
||||||
expect(exitCode).toBe(0);
|
|
||||||
expect(stdout).toBe('');
|
|
||||||
});
|
|
||||||
|
|
||||||
// ─── Path D1b: Fresh UP_TO_DATE cache, but local version changed ──
|
|
||||||
test('re-checks when UP_TO_DATE cache version does not match local', () => {
|
|
||||||
writeFileSync(join(gstackDir, 'VERSION'), '0.4.0\n');
|
|
||||||
// Cache says UP_TO_DATE for 0.3.3, but local is now 0.4.0
|
|
||||||
writeFileSync(join(stateDir, 'last-update-check'), 'UP_TO_DATE 0.3.3');
|
|
||||||
// Remote says 0.5.0 — should detect upgrade
|
|
||||||
writeFileSync(join(gstackDir, 'REMOTE_VERSION'), '0.5.0\n');
|
|
||||||
|
|
||||||
const { exitCode, stdout } = run();
|
|
||||||
expect(exitCode).toBe(0);
|
|
||||||
expect(stdout).toBe('UPGRADE_AVAILABLE 0.4.0 0.5.0');
|
|
||||||
});
|
|
||||||
|
|
||||||
// ─── Path D2: Fresh cache, UPGRADE_AVAILABLE ────────────────
|
|
||||||
test('echoes cached UPGRADE_AVAILABLE when cache is fresh', () => {
|
|
||||||
writeFileSync(join(gstackDir, 'VERSION'), '0.3.3\n');
|
|
||||||
writeFileSync(join(stateDir, 'last-update-check'), 'UPGRADE_AVAILABLE 0.3.3 0.4.0');
|
|
||||||
|
|
||||||
const { exitCode, stdout } = run();
|
|
||||||
expect(exitCode).toBe(0);
|
|
||||||
expect(stdout).toBe('UPGRADE_AVAILABLE 0.3.3 0.4.0');
|
|
||||||
});
|
|
||||||
|
|
||||||
// ─── Path D3: Fresh cache, but local version changed ────────
|
|
||||||
test('re-checks when local version does not match cached old version', () => {
|
|
||||||
writeFileSync(join(gstackDir, 'VERSION'), '0.4.0\n');
|
|
||||||
// Cache says 0.3.3 → 0.4.0 but we're already on 0.4.0
|
|
||||||
writeFileSync(join(stateDir, 'last-update-check'), 'UPGRADE_AVAILABLE 0.3.3 0.4.0');
|
|
||||||
// Remote also says 0.4.0 — should be up to date
|
|
||||||
writeFileSync(join(gstackDir, 'REMOTE_VERSION'), '0.4.0\n');
|
|
||||||
|
|
||||||
const { exitCode, stdout } = run();
|
|
||||||
expect(exitCode).toBe(0);
|
|
||||||
expect(stdout).toBe(''); // Up to date after re-check
|
|
||||||
const cache = readFileSync(join(stateDir, 'last-update-check'), 'utf-8');
|
|
||||||
expect(cache).toContain('UP_TO_DATE');
|
|
||||||
});
|
|
||||||
|
|
||||||
// ─── Path E: Versions match (remote fetch) ─────────────────
|
|
||||||
test('writes UP_TO_DATE cache when versions match', () => {
|
|
||||||
writeFileSync(join(gstackDir, 'VERSION'), '0.3.3\n');
|
|
||||||
writeFileSync(join(gstackDir, 'REMOTE_VERSION'), '0.3.3\n');
|
|
||||||
|
|
||||||
const { exitCode, stdout } = run();
|
|
||||||
expect(exitCode).toBe(0);
|
|
||||||
expect(stdout).toBe('');
|
|
||||||
const cache = readFileSync(join(stateDir, 'last-update-check'), 'utf-8');
|
|
||||||
expect(cache).toContain('UP_TO_DATE');
|
|
||||||
});
|
|
||||||
|
|
||||||
// ─── Path F: Versions differ (remote fetch) ─────────────────
|
|
||||||
test('outputs UPGRADE_AVAILABLE when versions differ', () => {
|
|
||||||
writeFileSync(join(gstackDir, 'VERSION'), '0.3.3\n');
|
|
||||||
writeFileSync(join(gstackDir, 'REMOTE_VERSION'), '0.4.0\n');
|
|
||||||
|
|
||||||
const { exitCode, stdout } = run();
|
|
||||||
expect(exitCode).toBe(0);
|
|
||||||
expect(stdout).toBe('UPGRADE_AVAILABLE 0.3.3 0.4.0');
|
|
||||||
const cache = readFileSync(join(stateDir, 'last-update-check'), 'utf-8');
|
|
||||||
expect(cache).toContain('UPGRADE_AVAILABLE 0.3.3 0.4.0');
|
|
||||||
});
|
|
||||||
|
|
||||||
// ─── Path G: Invalid remote response ────────────────────────
|
|
||||||
test('treats invalid remote response as up to date', () => {
|
|
||||||
writeFileSync(join(gstackDir, 'VERSION'), '0.3.3\n');
|
|
||||||
writeFileSync(join(gstackDir, 'REMOTE_VERSION'), '<html>404 Not Found</html>\n');
|
|
||||||
|
|
||||||
const { exitCode, stdout } = run();
|
|
||||||
expect(exitCode).toBe(0);
|
|
||||||
expect(stdout).toBe('');
|
|
||||||
const cache = readFileSync(join(stateDir, 'last-update-check'), 'utf-8');
|
|
||||||
expect(cache).toContain('UP_TO_DATE');
|
|
||||||
});
|
|
||||||
|
|
||||||
// ─── Path H: Curl fails (bad URL) ──────────────────────────
|
|
||||||
test('exits silently when remote URL is unreachable', () => {
|
|
||||||
writeFileSync(join(gstackDir, 'VERSION'), '0.3.3\n');
|
|
||||||
|
|
||||||
const { exitCode, stdout } = run({
|
|
||||||
GSTACK_REMOTE_URL: 'file:///nonexistent/path/VERSION',
|
|
||||||
});
|
});
|
||||||
expect(exitCode).toBe(0);
|
expect(result).toEqual({ exitCode: 0, stdout: '', stderr: '' });
|
||||||
expect(stdout).toBe('');
|
expect(existsSync(missingStateDir)).toBe(false);
|
||||||
const cache = readFileSync(join(stateDir, 'last-update-check'), 'utf-8');
|
|
||||||
expect(cache).toContain('UP_TO_DATE');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// ─── Path I: Corrupt cache file ─────────────────────────────
|
test('--force reports and caches a newer valid version', () => {
|
||||||
test('falls through to remote fetch when cache is corrupt', () => {
|
|
||||||
writeFileSync(join(gstackDir, 'VERSION'), '0.3.3\n');
|
|
||||||
writeFileSync(join(stateDir, 'last-update-check'), 'garbage data here');
|
|
||||||
// Remote says same version — should end up UP_TO_DATE
|
|
||||||
writeFileSync(join(gstackDir, 'REMOTE_VERSION'), '0.3.3\n');
|
|
||||||
|
|
||||||
const { exitCode, stdout } = run();
|
|
||||||
expect(exitCode).toBe(0);
|
|
||||||
expect(stdout).toBe('');
|
|
||||||
// Cache should be overwritten with valid content
|
|
||||||
const cache = readFileSync(join(stateDir, 'last-update-check'), 'utf-8');
|
|
||||||
expect(cache).toContain('UP_TO_DATE');
|
|
||||||
});
|
|
||||||
|
|
||||||
// ─── State dir creation ─────────────────────────────────────
|
|
||||||
test('creates state dir if it does not exist', () => {
|
|
||||||
const newStateDir = join(stateDir, 'nested', 'dir');
|
|
||||||
writeFileSync(join(gstackDir, 'VERSION'), '0.3.3\n');
|
|
||||||
writeFileSync(join(gstackDir, 'REMOTE_VERSION'), '0.3.3\n');
|
|
||||||
|
|
||||||
const { exitCode } = run({ GSTACK_STATE_DIR: newStateDir });
|
|
||||||
expect(exitCode).toBe(0);
|
|
||||||
expect(existsSync(join(newStateDir, 'last-update-check'))).toBe(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
// ─── E2E regression: always exit 0 ───────────────────────────
|
|
||||||
// Agents call this on every skill invocation. Exit code 1 breaks
|
|
||||||
// the preamble and confuses the agent. This test guards against
|
|
||||||
// regressions like the "exits 1 when up to date" bug.
|
|
||||||
test('exits 0 with real project VERSION and unreachable remote', () => {
|
|
||||||
// Simulate agent context: real VERSION file, network unavailable
|
|
||||||
const projectRoot = join(import.meta.dir, '..', '..');
|
|
||||||
const versionFile = join(projectRoot, 'VERSION');
|
|
||||||
if (!existsSync(versionFile)) return; // skip if no VERSION
|
|
||||||
const version = readFileSync(versionFile, 'utf-8').trim();
|
|
||||||
|
|
||||||
// Copy VERSION into test dir
|
|
||||||
writeFileSync(join(gstackDir, 'VERSION'), version + '\n');
|
|
||||||
|
|
||||||
// Remote is unreachable (simulates offline / CI / sandboxed agent)
|
|
||||||
const { exitCode, stdout } = run({
|
|
||||||
GSTACK_REMOTE_URL: 'file:///nonexistent/path/VERSION',
|
|
||||||
});
|
|
||||||
expect(exitCode).toBe(0);
|
|
||||||
// Should write UP_TO_DATE cache (not crash)
|
|
||||||
const cache = readFileSync(join(stateDir, 'last-update-check'), 'utf-8');
|
|
||||||
expect(cache).toContain('UP_TO_DATE');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('exits 0 when up to date (not exit 1)', () => {
|
|
||||||
// Regression test: script previously exited 1 when versions matched.
|
|
||||||
// This broke every skill preamble that called it without || true.
|
|
||||||
writeFileSync(join(gstackDir, 'VERSION'), '0.3.3\n');
|
|
||||||
writeFileSync(join(gstackDir, 'REMOTE_VERSION'), '0.3.3\n');
|
|
||||||
|
|
||||||
// First call: fetches remote, writes cache
|
|
||||||
const first = run();
|
|
||||||
expect(first.exitCode).toBe(0);
|
|
||||||
expect(first.stdout).toBe('');
|
|
||||||
|
|
||||||
// Second call: reads fresh cache
|
|
||||||
const second = run();
|
|
||||||
expect(second.exitCode).toBe(0);
|
|
||||||
expect(second.stdout).toBe('');
|
|
||||||
|
|
||||||
// Third call with upgrade available: still exit 0
|
|
||||||
writeFileSync(join(gstackDir, 'REMOTE_VERSION'), '0.4.0\n');
|
|
||||||
rmSync(join(stateDir, 'last-update-check')); // force re-fetch
|
|
||||||
const third = run();
|
|
||||||
expect(third.exitCode).toBe(0);
|
|
||||||
expect(third.stdout).toBe('UPGRADE_AVAILABLE 0.3.3 0.4.0');
|
|
||||||
});
|
|
||||||
|
|
||||||
// ─── Snooze tests ───────────────────────────────────────────
|
|
||||||
test('snoozed level 1 within 24h → silent (cached path)', () => {
|
|
||||||
writeFileSync(join(gstackDir, 'VERSION'), '0.3.3\n');
|
|
||||||
writeFileSync(join(stateDir, 'last-update-check'), 'UPGRADE_AVAILABLE 0.3.3 0.4.0');
|
|
||||||
writeSnooze('0.4.0', 1, nowEpoch() - 3600); // 1h ago (within 24h)
|
|
||||||
|
|
||||||
const { exitCode, stdout } = run();
|
|
||||||
expect(exitCode).toBe(0);
|
|
||||||
expect(stdout).toBe('');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('snoozed level 1 expired (25h ago) → outputs UPGRADE_AVAILABLE', () => {
|
|
||||||
writeFileSync(join(gstackDir, 'VERSION'), '0.3.3\n');
|
|
||||||
writeFileSync(join(stateDir, 'last-update-check'), 'UPGRADE_AVAILABLE 0.3.3 0.4.0');
|
|
||||||
writeSnooze('0.4.0', 1, nowEpoch() - 90000); // 25h ago
|
|
||||||
|
|
||||||
const { exitCode, stdout } = run();
|
|
||||||
expect(exitCode).toBe(0);
|
|
||||||
expect(stdout).toBe('UPGRADE_AVAILABLE 0.3.3 0.4.0');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('snoozed level 2 within 48h → silent', () => {
|
|
||||||
writeFileSync(join(gstackDir, 'VERSION'), '0.3.3\n');
|
|
||||||
writeFileSync(join(stateDir, 'last-update-check'), 'UPGRADE_AVAILABLE 0.3.3 0.4.0');
|
|
||||||
writeSnooze('0.4.0', 2, nowEpoch() - 86400); // 24h ago (within 48h)
|
|
||||||
|
|
||||||
const { exitCode, stdout } = run();
|
|
||||||
expect(exitCode).toBe(0);
|
|
||||||
expect(stdout).toBe('');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('snoozed level 2 expired (49h ago) → outputs', () => {
|
|
||||||
writeFileSync(join(gstackDir, 'VERSION'), '0.3.3\n');
|
|
||||||
writeFileSync(join(stateDir, 'last-update-check'), 'UPGRADE_AVAILABLE 0.3.3 0.4.0');
|
|
||||||
writeSnooze('0.4.0', 2, nowEpoch() - 176400); // 49h ago
|
|
||||||
|
|
||||||
const { exitCode, stdout } = run();
|
|
||||||
expect(exitCode).toBe(0);
|
|
||||||
expect(stdout).toBe('UPGRADE_AVAILABLE 0.3.3 0.4.0');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('snoozed level 3 within 7d → silent', () => {
|
|
||||||
writeFileSync(join(gstackDir, 'VERSION'), '0.3.3\n');
|
|
||||||
writeFileSync(join(stateDir, 'last-update-check'), 'UPGRADE_AVAILABLE 0.3.3 0.4.0');
|
|
||||||
writeSnooze('0.4.0', 3, nowEpoch() - 518400); // 6d ago (within 7d)
|
|
||||||
|
|
||||||
const { exitCode, stdout } = run();
|
|
||||||
expect(exitCode).toBe(0);
|
|
||||||
expect(stdout).toBe('');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('snoozed level 3 expired (8d ago) → outputs', () => {
|
|
||||||
writeFileSync(join(gstackDir, 'VERSION'), '0.3.3\n');
|
|
||||||
writeFileSync(join(stateDir, 'last-update-check'), 'UPGRADE_AVAILABLE 0.3.3 0.4.0');
|
|
||||||
writeSnooze('0.4.0', 3, nowEpoch() - 691200); // 8d ago
|
|
||||||
|
|
||||||
const { exitCode, stdout } = run();
|
|
||||||
expect(exitCode).toBe(0);
|
|
||||||
expect(stdout).toBe('UPGRADE_AVAILABLE 0.3.3 0.4.0');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('snooze ignored when version differs (new version resets snooze)', () => {
|
|
||||||
writeFileSync(join(gstackDir, 'VERSION'), '0.3.3\n');
|
|
||||||
writeFileSync(join(stateDir, 'last-update-check'), 'UPGRADE_AVAILABLE 0.3.3 0.5.0');
|
|
||||||
// Snoozed for 0.4.0, but remote is now 0.5.0
|
|
||||||
writeSnooze('0.4.0', 3, nowEpoch() - 60); // very recent
|
|
||||||
|
|
||||||
const { exitCode, stdout } = run();
|
|
||||||
expect(exitCode).toBe(0);
|
|
||||||
expect(stdout).toBe('UPGRADE_AVAILABLE 0.3.3 0.5.0');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('corrupt snooze file → outputs normally', () => {
|
|
||||||
writeFileSync(join(gstackDir, 'VERSION'), '0.3.3\n');
|
|
||||||
writeFileSync(join(stateDir, 'last-update-check'), 'UPGRADE_AVAILABLE 0.3.3 0.4.0');
|
|
||||||
writeFileSync(join(stateDir, 'update-snoozed'), 'garbage');
|
|
||||||
|
|
||||||
const { exitCode, stdout } = run();
|
|
||||||
expect(exitCode).toBe(0);
|
|
||||||
expect(stdout).toBe('UPGRADE_AVAILABLE 0.3.3 0.4.0');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('non-numeric epoch in snooze file → outputs', () => {
|
|
||||||
writeFileSync(join(gstackDir, 'VERSION'), '0.3.3\n');
|
|
||||||
writeFileSync(join(stateDir, 'last-update-check'), 'UPGRADE_AVAILABLE 0.3.3 0.4.0');
|
|
||||||
writeFileSync(join(stateDir, 'update-snoozed'), '0.4.0 1 abc');
|
|
||||||
|
|
||||||
const { exitCode, stdout } = run();
|
|
||||||
expect(exitCode).toBe(0);
|
|
||||||
expect(stdout).toBe('UPGRADE_AVAILABLE 0.3.3 0.4.0');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('non-numeric level in snooze file → outputs', () => {
|
|
||||||
writeFileSync(join(gstackDir, 'VERSION'), '0.3.3\n');
|
|
||||||
writeFileSync(join(stateDir, 'last-update-check'), 'UPGRADE_AVAILABLE 0.3.3 0.4.0');
|
|
||||||
writeFileSync(join(stateDir, 'update-snoozed'), `0.4.0 abc ${nowEpoch()}`);
|
|
||||||
|
|
||||||
const { exitCode, stdout } = run();
|
|
||||||
expect(exitCode).toBe(0);
|
|
||||||
expect(stdout).toBe('UPGRADE_AVAILABLE 0.3.3 0.4.0');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('snooze respected on remote fetch path (no cache)', () => {
|
|
||||||
writeFileSync(join(gstackDir, 'VERSION'), '0.3.3\n');
|
|
||||||
writeFileSync(join(gstackDir, 'REMOTE_VERSION'), '0.4.0\n');
|
|
||||||
// No cache file — goes to remote fetch path
|
|
||||||
writeSnooze('0.4.0', 1, nowEpoch() - 3600); // 1h ago
|
|
||||||
|
|
||||||
const { exitCode, stdout } = run();
|
|
||||||
expect(exitCode).toBe(0);
|
|
||||||
expect(stdout).toBe('');
|
|
||||||
// Cache should still be written
|
|
||||||
const cache = readFileSync(join(stateDir, 'last-update-check'), 'utf-8');
|
|
||||||
expect(cache).toContain('UPGRADE_AVAILABLE 0.3.3 0.4.0');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('just-upgraded clears snooze file', () => {
|
|
||||||
writeFileSync(join(gstackDir, 'VERSION'), '0.4.0\n');
|
|
||||||
writeFileSync(join(stateDir, 'just-upgraded-from'), '0.3.3\n');
|
|
||||||
writeSnooze('0.4.0', 2, nowEpoch() - 3600);
|
|
||||||
|
|
||||||
const { exitCode, stdout } = run();
|
|
||||||
expect(exitCode).toBe(0);
|
|
||||||
expect(stdout).toBe('JUST_UPGRADED 0.3.3 0.4.0');
|
|
||||||
expect(existsSync(join(stateDir, 'update-snoozed'))).toBe(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
// ─── Config tests ──────────────────────────────────────────
|
|
||||||
test('update_check: false disables all checks', () => {
|
|
||||||
writeFileSync(join(gstackDir, 'VERSION'), '0.3.3\n');
|
|
||||||
writeFileSync(join(gstackDir, 'REMOTE_VERSION'), '0.4.0\n');
|
|
||||||
writeConfig('update_check: false\n');
|
|
||||||
|
|
||||||
const { exitCode, stdout } = run();
|
|
||||||
expect(exitCode).toBe(0);
|
|
||||||
expect(stdout).toBe('');
|
|
||||||
// No cache should be written
|
|
||||||
expect(existsSync(join(stateDir, 'last-update-check'))).toBe(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('missing config.yaml does not crash', () => {
|
|
||||||
writeFileSync(join(gstackDir, 'VERSION'), '0.3.3\n');
|
|
||||||
writeFileSync(join(gstackDir, 'REMOTE_VERSION'), '0.4.0\n');
|
|
||||||
// No config file — should behave normally
|
|
||||||
|
|
||||||
const { exitCode, stdout } = run();
|
|
||||||
expect(exitCode).toBe(0);
|
|
||||||
expect(stdout).toBe('UPGRADE_AVAILABLE 0.3.3 0.4.0');
|
|
||||||
});
|
|
||||||
|
|
||||||
// ─── --force flag tests ──────────────────────────────────────
|
|
||||||
|
|
||||||
test('--force busts fresh UP_TO_DATE cache', () => {
|
|
||||||
writeFileSync(join(gstackDir, 'VERSION'), '0.3.3\n');
|
|
||||||
writeFileSync(join(gstackDir, 'REMOTE_VERSION'), '0.4.0\n');
|
|
||||||
writeFileSync(join(stateDir, 'last-update-check'), 'UP_TO_DATE 0.3.3');
|
|
||||||
|
|
||||||
// Without --force: cache hit, silent
|
|
||||||
const cached = run();
|
|
||||||
expect(cached.stdout).toBe('');
|
|
||||||
|
|
||||||
// With --force: cache busted, re-fetches, finds upgrade
|
|
||||||
const forced = run({}, ['--force']);
|
|
||||||
expect(forced.exitCode).toBe(0);
|
|
||||||
expect(forced.stdout).toBe('UPGRADE_AVAILABLE 0.3.3 0.4.0');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('--force busts fresh UPGRADE_AVAILABLE cache', () => {
|
|
||||||
writeFileSync(join(gstackDir, 'VERSION'), '0.3.3\n');
|
|
||||||
writeFileSync(join(gstackDir, 'REMOTE_VERSION'), '0.3.3\n');
|
|
||||||
writeFileSync(join(stateDir, 'last-update-check'), 'UPGRADE_AVAILABLE 0.3.3 0.4.0');
|
|
||||||
|
|
||||||
// Without --force: cache hit, outputs stale upgrade
|
|
||||||
const cached = run();
|
|
||||||
expect(cached.stdout).toBe('UPGRADE_AVAILABLE 0.3.3 0.4.0');
|
|
||||||
|
|
||||||
// With --force: cache busted, re-fetches, now up to date
|
|
||||||
const forced = run({}, ['--force']);
|
|
||||||
expect(forced.exitCode).toBe(0);
|
|
||||||
expect(forced.stdout).toBe('');
|
|
||||||
const cache = readFileSync(join(stateDir, 'last-update-check'), 'utf-8');
|
|
||||||
expect(cache).toContain('UP_TO_DATE');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('--force clears snooze so user can upgrade after snoozing', () => {
|
|
||||||
writeFileSync(join(gstackDir, 'VERSION'), '0.3.3\n');
|
|
||||||
writeFileSync(join(gstackDir, 'REMOTE_VERSION'), '0.4.0\n');
|
|
||||||
writeSnooze('0.4.0', 1, nowEpoch() - 60); // snoozed 1 min ago (within 24h)
|
|
||||||
|
|
||||||
// Without --force: snoozed, silent
|
|
||||||
const snoozed = run();
|
|
||||||
expect(snoozed.exitCode).toBe(0);
|
|
||||||
expect(snoozed.stdout).toBe('');
|
|
||||||
|
|
||||||
// With --force: snooze cleared, outputs upgrade
|
|
||||||
const forced = run({}, ['--force']);
|
|
||||||
expect(forced.exitCode).toBe(0);
|
|
||||||
expect(forced.stdout).toBe('UPGRADE_AVAILABLE 0.3.3 0.4.0');
|
|
||||||
// Snooze file should be deleted
|
|
||||||
expect(existsSync(join(stateDir, 'update-snoozed'))).toBe(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
// ─── Split TTL tests ─────────────────────────────────────────
|
|
||||||
|
|
||||||
// ─── Semver-order guard ─────────────────────────────────────
|
|
||||||
// When the upstream raw CDN serves a stale (older) VERSION right after a
|
|
||||||
// release, the script previously emitted a backwards UPGRADE_AVAILABLE
|
|
||||||
// line. The guard treats REMOTE < LOCAL as up-to-date.
|
|
||||||
|
|
||||||
test('remote older than local (stale CDN) → silent, cache UP_TO_DATE', () => {
|
|
||||||
writeFileSync(join(gstackDir, 'VERSION'), '1.34.0.0\n');
|
|
||||||
writeFileSync(join(gstackDir, 'REMOTE_VERSION'), '1.33.2.0\n');
|
|
||||||
|
|
||||||
const { exitCode, stdout } = run();
|
|
||||||
expect(exitCode).toBe(0);
|
|
||||||
expect(stdout).toBe('');
|
|
||||||
const cache = readFileSync(join(stateDir, 'last-update-check'), 'utf-8');
|
|
||||||
expect(cache).toContain('UP_TO_DATE 1.34.0.0');
|
|
||||||
});
|
|
||||||
|
|
||||||
test('multi-segment sort: 1.9.0.0 < 1.10.0.0', () => {
|
|
||||||
writeFileSync(join(gstackDir, 'VERSION'), '1.9.0.0\n');
|
writeFileSync(join(gstackDir, 'VERSION'), '1.9.0.0\n');
|
||||||
writeFileSync(join(gstackDir, 'REMOTE_VERSION'), '1.10.0.0\n');
|
writeFileSync(join(gstackDir, 'REMOTE_VERSION'), '1.10.0.0\n');
|
||||||
|
|
||||||
const { stdout } = run();
|
expect(run(['--force']).stdout).toBe('UPGRADE_AVAILABLE 1.9.0.0 1.10.0.0');
|
||||||
expect(stdout).toBe('UPGRADE_AVAILABLE 1.9.0.0 1.10.0.0');
|
expect(readFileSync(join(stateDir, 'last-update-check'), 'utf8').trim())
|
||||||
|
.toBe('UPGRADE_AVAILABLE 1.9.0.0 1.10.0.0');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('multi-segment reverse sort: 1.10.0.0 > 1.9.0.0 → no rewind', () => {
|
test('--force never offers a downgrade', () => {
|
||||||
writeFileSync(join(gstackDir, 'VERSION'), '1.10.0.0\n');
|
writeFileSync(join(gstackDir, 'VERSION'), '1.10.0.0\n');
|
||||||
writeFileSync(join(gstackDir, 'REMOTE_VERSION'), '1.9.0.0\n');
|
writeFileSync(join(gstackDir, 'REMOTE_VERSION'), '1.9.0.0\n');
|
||||||
|
|
||||||
const { stdout } = run();
|
expect(run(['--force']).stdout).toBe('');
|
||||||
expect(stdout).toBe('');
|
expect(readFileSync(join(stateDir, 'last-update-check'), 'utf8').trim())
|
||||||
const cache = readFileSync(join(stateDir, 'last-update-check'), 'utf-8');
|
.toBe('UP_TO_DATE 1.10.0.0');
|
||||||
expect(cache).toContain('UP_TO_DATE 1.10.0.0');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('UP_TO_DATE cache expires after 60 min (not 720)', () => {
|
test('--force treats malformed or unavailable responses as non-updates', () => {
|
||||||
writeFileSync(join(gstackDir, 'VERSION'), '0.3.3\n');
|
writeFileSync(join(gstackDir, 'VERSION'), '1.0.0\n');
|
||||||
writeFileSync(join(gstackDir, 'REMOTE_VERSION'), '0.4.0\n');
|
writeFileSync(join(gstackDir, 'REMOTE_VERSION'), '<html>not a version</html>\n');
|
||||||
writeFileSync(join(stateDir, 'last-update-check'), 'UP_TO_DATE 0.3.3');
|
|
||||||
|
|
||||||
// Set cache mtime to 90 minutes ago (past 60-min TTL)
|
expect(run(['--force']).stdout).toBe('');
|
||||||
const ninetyMinAgo = new Date(Date.now() - 90 * 60 * 1000);
|
expect(readFileSync(join(stateDir, 'last-update-check'), 'utf8').trim())
|
||||||
const cachePath = join(stateDir, 'last-update-check');
|
.toBe('UP_TO_DATE 1.0.0');
|
||||||
utimesSync(cachePath, ninetyMinAgo, ninetyMinAgo);
|
});
|
||||||
|
|
||||||
// Cache should be stale at 60-min TTL, re-fetches and finds upgrade
|
test('--force clears obsolete snooze state and consumes the upgrade marker', () => {
|
||||||
const { exitCode, stdout } = run();
|
writeFileSync(join(gstackDir, 'VERSION'), '1.0.0\n');
|
||||||
expect(exitCode).toBe(0);
|
writeFileSync(join(gstackDir, 'REMOTE_VERSION'), '1.0.0\n');
|
||||||
expect(stdout).toBe('UPGRADE_AVAILABLE 0.3.3 0.4.0');
|
writeFileSync(join(stateDir, 'just-upgraded-from'), '0.9.0\n');
|
||||||
|
writeFileSync(join(stateDir, 'update-snoozed'), '1.0.0 3 9999999999');
|
||||||
|
|
||||||
|
expect(run(['--force']).stdout).toBe('JUST_UPGRADED 0.9.0 1.0.0');
|
||||||
|
expect(existsSync(join(stateDir, 'just-upgraded-from'))).toBe(false);
|
||||||
|
expect(existsSync(join(stateDir, 'update-snoozed'))).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('--force with no local version exits cleanly without creating a cache', () => {
|
||||||
|
expect(run(['--force'])).toEqual({ exitCode: 0, stdout: '', stderr: '' });
|
||||||
|
expect(existsSync(join(stateDir, 'last-update-check'))).toBe(false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { validateReadPath, SENSITIVE_COOKIE_NAME, SENSITIVE_COOKIE_VALUE } from
|
|||||||
import { BLOCKED_METADATA_HOSTS } from '../src/url-validation';
|
import { BLOCKED_METADATA_HOSTS } from '../src/url-validation';
|
||||||
import { readFileSync, symlinkSync, unlinkSync, writeFileSync, realpathSync } from 'fs';
|
import { readFileSync, symlinkSync, unlinkSync, writeFileSync, realpathSync } from 'fs';
|
||||||
import { tmpdir } from 'os';
|
import { tmpdir } from 'os';
|
||||||
import { join } from 'path';
|
import { join, relative } from 'path';
|
||||||
|
|
||||||
describe('validateOutputPath', () => {
|
describe('validateOutputPath', () => {
|
||||||
it('allows paths within /tmp', () => {
|
it('allows paths within /tmp', () => {
|
||||||
@@ -82,7 +82,8 @@ describe('validateReadPath', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('blocks nested path traversal', () => {
|
it('blocks nested path traversal', () => {
|
||||||
expect(() => validateReadPath('src/../../etc/passwd')).toThrow(/Path must be within/);
|
const escapeToEtc = relative(process.cwd(), '/etc/passwd');
|
||||||
|
expect(() => validateReadPath(`src/../${escapeToEtc}`)).toThrow(/Path must be within/);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('blocks symlink inside safe dir pointing outside', () => {
|
it('blocks symlink inside safe dir pointing outside', () => {
|
||||||
|
|||||||
@@ -5,55 +5,64 @@
|
|||||||
"": {
|
"": {
|
||||||
"name": "gstack",
|
"name": "gstack",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@anthropic-ai/sdk": "^0.78.0",
|
"@anthropic-ai/sdk": "^0.112.4",
|
||||||
"@ngrok/ngrok": "^1.7.0",
|
"@ngrok/ngrok": "^1.7.0",
|
||||||
"diff": "^9.0.0",
|
"diff": "^9.0.0",
|
||||||
"html-to-docx": "1.8.0",
|
"html-to-docx": "1.8.0",
|
||||||
"marked": "^18.0.2",
|
"marked": "^18.0.6",
|
||||||
"playwright": "npm:playwright-core@^1.58.2",
|
"playwright": "npm:playwright-core@^1.58.2",
|
||||||
"sharp": "^0.34.5",
|
"sharp": "^0.34.5",
|
||||||
"socks": "^2.8.8",
|
"socks": "^2.8.9",
|
||||||
"xterm": "5",
|
"xterm": "5",
|
||||||
"xterm-addon-fit": "^0.8.0",
|
"xterm-addon-fit": "^0.8.0",
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@anthropic-ai/claude-agent-sdk": "0.2.117",
|
"@anthropic-ai/claude-agent-sdk": "0.3.216",
|
||||||
"@huggingface/transformers": "^4.1.0",
|
"@huggingface/transformers": "4.2.0",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
"overrides": {
|
||||||
|
"@protobufjs/utf8": "1.1.1",
|
||||||
|
"adm-zip": "0.6.0",
|
||||||
|
"fast-uri": "3.1.3",
|
||||||
|
"hono": "4.12.27",
|
||||||
|
"ip-address": "10.2.0",
|
||||||
|
"protobufjs": "7.6.5",
|
||||||
|
"qs": "6.15.2",
|
||||||
|
},
|
||||||
"packages": {
|
"packages": {
|
||||||
"@anthropic-ai/claude-agent-sdk": ["@anthropic-ai/claude-agent-sdk@0.2.117", "", { "dependencies": { "@anthropic-ai/sdk": "^0.81.0", "@modelcontextprotocol/sdk": "^1.29.0" }, "optionalDependencies": { "@anthropic-ai/claude-agent-sdk-darwin-arm64": "0.2.117", "@anthropic-ai/claude-agent-sdk-darwin-x64": "0.2.117", "@anthropic-ai/claude-agent-sdk-linux-arm64": "0.2.117", "@anthropic-ai/claude-agent-sdk-linux-arm64-musl": "0.2.117", "@anthropic-ai/claude-agent-sdk-linux-x64": "0.2.117", "@anthropic-ai/claude-agent-sdk-linux-x64-musl": "0.2.117", "@anthropic-ai/claude-agent-sdk-win32-arm64": "0.2.117", "@anthropic-ai/claude-agent-sdk-win32-x64": "0.2.117" }, "peerDependencies": { "zod": "^4.0.0" } }, "sha512-pVBss1Vu0w87nKCBhWtjMggSgCh6GVUtdRmuE58ZvXv0E2q0JcnUCQHehmn92BAW0+VCwPY8q/k7uKWkgwz/gA=="],
|
"@anthropic-ai/claude-agent-sdk": ["@anthropic-ai/claude-agent-sdk@0.3.216", "", { "optionalDependencies": { "@anthropic-ai/claude-agent-sdk-darwin-arm64": "0.3.216", "@anthropic-ai/claude-agent-sdk-darwin-x64": "0.3.216", "@anthropic-ai/claude-agent-sdk-linux-arm64": "0.3.216", "@anthropic-ai/claude-agent-sdk-linux-arm64-musl": "0.3.216", "@anthropic-ai/claude-agent-sdk-linux-x64": "0.3.216", "@anthropic-ai/claude-agent-sdk-linux-x64-musl": "0.3.216", "@anthropic-ai/claude-agent-sdk-win32-arm64": "0.3.216", "@anthropic-ai/claude-agent-sdk-win32-x64": "0.3.216" }, "peerDependencies": { "@anthropic-ai/sdk": ">=0.93.0", "@modelcontextprotocol/sdk": "^1.29.0", "zod": "^4.0.0" } }, "sha512-Fl/d9yGW7Pm0aGwUNkJMvruOVobleYcoprGJqufdP4J9W2XL/2xKXqanY8KqUdfySRMI2N46rY4/lryq5SfgFg=="],
|
||||||
|
|
||||||
"@anthropic-ai/claude-agent-sdk-darwin-arm64": ["@anthropic-ai/claude-agent-sdk-darwin-arm64@0.2.117", "", { "os": "darwin", "cpu": "arm64" }, "sha512-ZeC/Lz8XMKQ5w+GmjTziPR8bSSarBtNCJMkMAYRT9ekNmyXSWXEwGLENe5TDDmtpzNNzAB1mQNuIYoqTsqgV3w=="],
|
"@anthropic-ai/claude-agent-sdk-darwin-arm64": ["@anthropic-ai/claude-agent-sdk-darwin-arm64@0.3.216", "", { "os": "darwin", "cpu": "arm64" }, "sha512-TWtTUabXj+AMOBMknSe3EVQb/7qucw5pHYi0HWoKoixQt1JE6J/CiLDBIY69OD3eQn9k1XG6LaurT239kFxLUw=="],
|
||||||
|
|
||||||
"@anthropic-ai/claude-agent-sdk-darwin-x64": ["@anthropic-ai/claude-agent-sdk-darwin-x64@0.2.117", "", { "os": "darwin", "cpu": "x64" }, "sha512-DKyggGzzpDcr9S435xlpbpwkEYKZNbePSekug75tJclK8l4ddD9+M9BFgMiSUq9F1Zt53kUaRDihDu/cBKvkdQ=="],
|
"@anthropic-ai/claude-agent-sdk-darwin-x64": ["@anthropic-ai/claude-agent-sdk-darwin-x64@0.3.216", "", { "os": "darwin", "cpu": "x64" }, "sha512-tULuvqhJUwGTj71Uln4uPumm0la4EO1XydFbISTbdc1BsuvGx3FOtFcVs0Qg3dhNBFAoU/iYVTO/B1rImeJZig=="],
|
||||||
|
|
||||||
"@anthropic-ai/claude-agent-sdk-linux-arm64": ["@anthropic-ai/claude-agent-sdk-linux-arm64@0.2.117", "", { "os": "linux", "cpu": "arm64" }, "sha512-jyHmyZQavpPOe3zxBRX3KbdOAJ8JwZ8m/wMr5bhHhhcstugm/vJx6IIs7D44VvFjk+8sqdvR2ZrliL8PUcJL0g=="],
|
"@anthropic-ai/claude-agent-sdk-linux-arm64": ["@anthropic-ai/claude-agent-sdk-linux-arm64@0.3.216", "", { "os": "linux", "cpu": "arm64" }, "sha512-kX6x0otwOuA1zIeEiuAKQqOk2TUAOkDUzm4MmLoQHOM2xWvr/pc+xY4DZxaX4ef9dUFQuHA4r5Vtbk7tPTL7Bw=="],
|
||||||
|
|
||||||
"@anthropic-ai/claude-agent-sdk-linux-arm64-musl": ["@anthropic-ai/claude-agent-sdk-linux-arm64-musl@0.2.117", "", { "os": "linux", "cpu": "arm64" }, "sha512-bJU5gEOmM4VCOn4h8vipOKgdhPATePQ23mMpvyVqtVyipWppHfOUfVkqXb+SrF/hfkNSMYxDuoKxbJ+MmKtGjg=="],
|
"@anthropic-ai/claude-agent-sdk-linux-arm64-musl": ["@anthropic-ai/claude-agent-sdk-linux-arm64-musl@0.3.216", "", { "os": "linux", "cpu": "arm64" }, "sha512-sisWj2nhQolKu6aGWnu+I7d8EU6/m5J3G6bGfR7YvZ1wkQTQZAX3aOq6DVLIfCaZSH22wtqyuXhE/gn5eU1syw=="],
|
||||||
|
|
||||||
"@anthropic-ai/claude-agent-sdk-linux-x64": ["@anthropic-ai/claude-agent-sdk-linux-x64@0.2.117", "", { "os": "linux", "cpu": "x64" }, "sha512-Zb5PXKrDNbQ1dyNYwxZMNL+F2Dhgjh9f9B21wZUJqkhJL69hRJwJyxO42HiNmB2zGCaTxQTyjPhLdB/eQJo74Q=="],
|
"@anthropic-ai/claude-agent-sdk-linux-x64": ["@anthropic-ai/claude-agent-sdk-linux-x64@0.3.216", "", { "os": "linux", "cpu": "x64" }, "sha512-WbJTLQafcYw9wl+gh/YpepdbWsOoJS7JZQA0obpzBBWzpx9PqPbjUDXDfCDrtzDI2fmr3Nz0//vC12bvlMZd8g=="],
|
||||||
|
|
||||||
"@anthropic-ai/claude-agent-sdk-linux-x64-musl": ["@anthropic-ai/claude-agent-sdk-linux-x64-musl@0.2.117", "", { "os": "linux", "cpu": "x64" }, "sha512-LIkKTAYZGugEVssAuWCPqlDWSqhVZAveNPNsfKLbuG1naIMCR04fUqil6i3d3mAAfk7FaS5D4IdHp45psi+GDw=="],
|
"@anthropic-ai/claude-agent-sdk-linux-x64-musl": ["@anthropic-ai/claude-agent-sdk-linux-x64-musl@0.3.216", "", { "os": "linux", "cpu": "x64" }, "sha512-3Ts2Ab6oEGG2r+epmWc6lOR1ahECjvH4y+lPb32qLKMdYxT2PU6TAc4Z/USLLuqDpgw3nSb8xuiYEH77rv88fw=="],
|
||||||
|
|
||||||
"@anthropic-ai/claude-agent-sdk-win32-arm64": ["@anthropic-ai/claude-agent-sdk-win32-arm64@0.2.117", "", { "os": "win32", "cpu": "arm64" }, "sha512-uetggH3B83PiH0a9D/5MVXB5Hqnlr2DVajehwAP2x0Mt4DBd632ICnHpu6pnSP+vVkWgq3FgQlkHe91RfP+peA=="],
|
"@anthropic-ai/claude-agent-sdk-win32-arm64": ["@anthropic-ai/claude-agent-sdk-win32-arm64@0.3.216", "", { "os": "win32", "cpu": "arm64" }, "sha512-xGB8rKatsXl9enqmPXixYNvdjGh1AL2jFmMRC9lR9M1prf2FGl7dkpdHz8YyItKAciRwpPIfts/9dSGhxlgT3A=="],
|
||||||
|
|
||||||
"@anthropic-ai/claude-agent-sdk-win32-x64": ["@anthropic-ai/claude-agent-sdk-win32-x64@0.2.117", "", { "os": "win32", "cpu": "x64" }, "sha512-TT4KngAokDTJSvQ2mrAP6ZRkXj50OLj7Tb1zZA4CnkmrrEidgs4KrMx7er1ZwoivngIvCekV9+TbtC9giknr5w=="],
|
"@anthropic-ai/claude-agent-sdk-win32-x64": ["@anthropic-ai/claude-agent-sdk-win32-x64@0.3.216", "", { "os": "win32", "cpu": "x64" }, "sha512-cGbBgoKNzB6wRL6bMOwM2iJEG/wx0B6FCblmKF+ZAYKcj5oNi3jM6oQsnPJbKfrzVKrip3YEpXxopQ9O30LrSg=="],
|
||||||
|
|
||||||
"@anthropic-ai/sdk": ["@anthropic-ai/sdk@0.78.0", "", { "dependencies": { "json-schema-to-ts": "^3.1.1" }, "peerDependencies": { "zod": "^3.25.0 || ^4.0.0" }, "optionalPeers": ["zod"], "bin": { "anthropic-ai-sdk": "bin/cli" } }, "sha512-PzQhR715td/m1UaaN5hHXjYB8Gl2lF9UVhrrGrZeysiF6Rb74Wc9GCB8hzLdzmQtBd1qe89F9OptgB9Za1Ib5w=="],
|
"@anthropic-ai/sdk": ["@anthropic-ai/sdk@0.112.4", "", { "dependencies": { "json-schema-to-ts": "^3.1.1", "standardwebhooks": "^1.0.0" }, "peerDependencies": { "zod": "^3.25.0 || ^4.0.0" }, "optionalPeers": ["zod"], "bin": { "anthropic-ai-sdk": "bin/cli" } }, "sha512-7eXJJnrmBI5GMC6drrCiSkycVsT7crRZX3qv5HusLSm+qiILjmtqP7gf+UiT7ASu/7Gdj+Zfl4f2haV8wATKUg=="],
|
||||||
|
|
||||||
"@babel/runtime": ["@babel/runtime@7.29.2", "", {}, "sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g=="],
|
"@babel/runtime": ["@babel/runtime@7.29.7", "", {}, "sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw=="],
|
||||||
|
|
||||||
"@emnapi/runtime": ["@emnapi/runtime@1.10.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA=="],
|
"@emnapi/runtime": ["@emnapi/runtime@1.11.2", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-kyOl3X0DuTiT1h2ft8r2fYO8JYtU9a9Xis/zBSiGArNaagCOWx90N1k2wxp18czFDH+OgcWGb5ZP/XMt3dcyPA=="],
|
||||||
|
|
||||||
"@hono/node-server": ["@hono/node-server@1.19.14", "", { "peerDependencies": { "hono": "^4" } }, "sha512-GwtvgtXxnWsucXvbQXkRgqksiH2Qed37H9xHZocE5sA3N8O8O8/8FA3uclQXxXVzc9XBZuEOMK7+r02FmSpHtw=="],
|
"@hono/node-server": ["@hono/node-server@1.19.14", "", { "peerDependencies": { "hono": "^4" } }, "sha512-GwtvgtXxnWsucXvbQXkRgqksiH2Qed37H9xHZocE5sA3N8O8O8/8FA3uclQXxXVzc9XBZuEOMK7+r02FmSpHtw=="],
|
||||||
|
|
||||||
"@huggingface/jinja": ["@huggingface/jinja@0.5.7", "", {}, "sha512-OosMEbF/R6zkKNNzqhI7kvKYCpo1F0UeIv46/h4D4UjVEKKd6k3TiV8sgu6fkreX4lbBiRI+lZG8UnXnqVQmEQ=="],
|
"@huggingface/jinja": ["@huggingface/jinja@0.5.9", "", {}, "sha512-uWTG+l3VJRsl7EXxYizuL3P+cCPoc3cRqbWWRcQN0FhejRfbdq0RNhCmbY/YDtnTcz9icdLYuLDjsnz4d8JMuw=="],
|
||||||
|
|
||||||
"@huggingface/tokenizers": ["@huggingface/tokenizers@0.1.3", "", {}, "sha512-8rF/RRT10u+kn7YuUbUg0OF30K8rjTc78aHpxT+qJ1uWSqxT1MHi8+9ltwYfkFYJzT/oS+qw3JVfHtNMGAdqyA=="],
|
"@huggingface/tokenizers": ["@huggingface/tokenizers@0.1.3", "", {}, "sha512-8rF/RRT10u+kn7YuUbUg0OF30K8rjTc78aHpxT+qJ1uWSqxT1MHi8+9ltwYfkFYJzT/oS+qw3JVfHtNMGAdqyA=="],
|
||||||
|
|
||||||
"@huggingface/transformers": ["@huggingface/transformers@4.1.0", "", { "dependencies": { "@huggingface/jinja": "^0.5.6", "@huggingface/tokenizers": "^0.1.3", "onnxruntime-node": "1.24.3", "onnxruntime-web": "1.26.0-dev.20260410-5e55544225", "sharp": "^0.34.5" } }, "sha512-WiMf9eyvF6V2pj4gs12A7GQV3svyFIBtB/W+Hn5lT5E5DyqWUno1ZrWoAfJv69X1RNv/0GoOo6DFmL6NOYd+rg=="],
|
"@huggingface/transformers": ["@huggingface/transformers@4.2.0", "", { "dependencies": { "@huggingface/jinja": "^0.5.6", "@huggingface/tokenizers": "^0.1.3", "onnxruntime-node": "1.24.3", "onnxruntime-web": "1.26.0-dev.20260416-b7804b056c", "sharp": "^0.34.5" } }, "sha512-8BRCoBMH0XsWaEIamuR0LrJGAfftgHAfb2Vrffy0VKlSAE/MnUJ5/h/zTfEP3fDIft+nk7TqB8xXEyABGitBjQ=="],
|
||||||
|
|
||||||
"@img/colour": ["@img/colour@1.1.0", "", {}, "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ=="],
|
"@img/colour": ["@img/colour@1.1.0", "", {}, "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ=="],
|
||||||
|
|
||||||
@@ -147,33 +156,33 @@
|
|||||||
|
|
||||||
"@protobufjs/base64": ["@protobufjs/base64@1.1.2", "", {}, "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg=="],
|
"@protobufjs/base64": ["@protobufjs/base64@1.1.2", "", {}, "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg=="],
|
||||||
|
|
||||||
"@protobufjs/codegen": ["@protobufjs/codegen@2.0.4", "", {}, "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg=="],
|
"@protobufjs/codegen": ["@protobufjs/codegen@2.0.5", "", {}, "sha512-zgXFLzW3Ap33e6d0Wlj4MGIm6Ce8O89n/apUaGNB/jx+hw+ruWEp7EwGUshdLKVRCxZW12fp9r40E1mQrf/34g=="],
|
||||||
|
|
||||||
"@protobufjs/eventemitter": ["@protobufjs/eventemitter@1.1.0", "", {}, "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q=="],
|
"@protobufjs/eventemitter": ["@protobufjs/eventemitter@1.1.1", "", {}, "sha512-vW1GmwMZNnL+gMRaovlh9yZX74kc+TTU3FObkkurpMaRtBfLP3ldjS9KQWlwZgraRE0+dheEEoAxdzcJQ8eXZg=="],
|
||||||
|
|
||||||
"@protobufjs/fetch": ["@protobufjs/fetch@1.1.0", "", { "dependencies": { "@protobufjs/aspromise": "^1.1.1", "@protobufjs/inquire": "^1.1.0" } }, "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ=="],
|
"@protobufjs/fetch": ["@protobufjs/fetch@1.1.1", "", { "dependencies": { "@protobufjs/aspromise": "^1.1.1" } }, "sha512-GpptLrs57adMSuHi3VNj0mAF8dwh36LMaYF6XyJ6JMWlVsc+t42tm1HSEDmOs3A8fC9yyeisgLhsTVQokOZ0zw=="],
|
||||||
|
|
||||||
"@protobufjs/float": ["@protobufjs/float@1.0.2", "", {}, "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ=="],
|
"@protobufjs/float": ["@protobufjs/float@1.0.2", "", {}, "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ=="],
|
||||||
|
|
||||||
"@protobufjs/inquire": ["@protobufjs/inquire@1.1.0", "", {}, "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q=="],
|
|
||||||
|
|
||||||
"@protobufjs/path": ["@protobufjs/path@1.1.2", "", {}, "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA=="],
|
"@protobufjs/path": ["@protobufjs/path@1.1.2", "", {}, "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA=="],
|
||||||
|
|
||||||
"@protobufjs/pool": ["@protobufjs/pool@1.1.0", "", {}, "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw=="],
|
"@protobufjs/pool": ["@protobufjs/pool@1.1.0", "", {}, "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw=="],
|
||||||
|
|
||||||
"@protobufjs/utf8": ["@protobufjs/utf8@1.1.0", "", {}, "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw=="],
|
"@protobufjs/utf8": ["@protobufjs/utf8@1.1.1", "", {}, "sha512-oOAWABowe8EAbMyWKM0tYDKi8Yaox52D+HWZhAIJqQXbqe0xI/GV7FhLWqlEKreMkfDjshR5FKgi3mnle0h6Eg=="],
|
||||||
|
|
||||||
"@types/node": ["@types/node@25.5.0", "", { "dependencies": { "undici-types": "~7.18.0" } }, "sha512-jp2P3tQMSxWugkCUKLRPVUpGaL5MVFwF8RDuSRztfwgN1wmqJeMSbKlnEtQqU8UrhTmzEmZdu2I6v2dpp7XIxw=="],
|
"@stablelib/base64": ["@stablelib/base64@1.0.1", "", {}, "sha512-1bnPQqSxSuc3Ii6MhBysoWCg58j97aUjuCSZrGSmDxNqtytIi0k8utUenAwTZN4V5mXXYGsVUI9zeBqy+jBOSQ=="],
|
||||||
|
|
||||||
|
"@types/node": ["@types/node@26.1.1", "", { "dependencies": { "undici-types": "~8.3.0" } }, "sha512-nxAkRSVkN1Y0JC1W8ky/fTfkGsMmcrRsbx+3XoZE+rMOX71kLYTV7fLXpqud1GpbpP5TuffXFqfX7fH2GgZREw=="],
|
||||||
|
|
||||||
"accepts": ["accepts@2.0.0", "", { "dependencies": { "mime-types": "^3.0.0", "negotiator": "^1.0.0" } }, "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng=="],
|
"accepts": ["accepts@2.0.0", "", { "dependencies": { "mime-types": "^3.0.0", "negotiator": "^1.0.0" } }, "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng=="],
|
||||||
|
|
||||||
"adm-zip": ["adm-zip@0.5.17", "", {}, "sha512-+Ut8d9LLqwEvHHJl1+PIHqoyDxFgVN847JTVM3Izi3xHDWPE4UtzzXysMZQs64DMcrJfBeS/uoEP4AD3HQHnQQ=="],
|
"adm-zip": ["adm-zip@0.6.0", "", {}, "sha512-XleryMhbuksdKtofnWZ9Sk+4CUTbms4Mb/EU32SZwToAyZ5RgVos/ki8n+yr0LWHOGKuakbXTuuYNHLQjhddgg=="],
|
||||||
|
|
||||||
"ajv": ["ajv@8.18.0", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A=="],
|
"ajv": ["ajv@8.20.0", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA=="],
|
||||||
|
|
||||||
"ajv-formats": ["ajv-formats@3.0.1", "", { "dependencies": { "ajv": "^8.0.0" } }, "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ=="],
|
"ajv-formats": ["ajv-formats@3.0.1", "", { "dependencies": { "ajv": "^8.0.0" } }, "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ=="],
|
||||||
|
|
||||||
"body-parser": ["body-parser@2.2.2", "", { "dependencies": { "bytes": "^3.1.2", "content-type": "^1.0.5", "debug": "^4.4.3", "http-errors": "^2.0.0", "iconv-lite": "^0.7.0", "on-finished": "^2.4.1", "qs": "^6.14.1", "raw-body": "^3.0.1", "type-is": "^2.0.1" } }, "sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA=="],
|
"body-parser": ["body-parser@2.3.0", "", { "dependencies": { "bytes": "^3.1.2", "content-type": "^2.0.0", "debug": "^4.4.3", "http-errors": "^2.0.1", "iconv-lite": "^0.7.2", "on-finished": "^2.4.1", "qs": "^6.15.2", "raw-body": "^3.0.2", "type-is": "^2.1.0" } }, "sha512-2cGmJupaNgg+QUwVLAucDuWuoMZ6EX9iHDRswZ5lsNYEmwPaRknMPCLZz07yTzVq/83p4o/wzbDZbBrTvGGTIw=="],
|
||||||
|
|
||||||
"boolean": ["boolean@3.2.0", "", {}, "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw=="],
|
"boolean": ["boolean@3.2.0", "", {}, "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw=="],
|
||||||
|
|
||||||
@@ -203,7 +212,7 @@
|
|||||||
|
|
||||||
"cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="],
|
"cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="],
|
||||||
|
|
||||||
"debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
|
"debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" }, "peerDependencies": { "supports-color": "*" }, "optionalPeers": ["supports-color"] }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
|
||||||
|
|
||||||
"define-data-property": ["define-data-property@1.1.4", "", { "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", "gopd": "^1.0.1" } }, "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A=="],
|
"define-data-property": ["define-data-property@1.1.4", "", { "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", "gopd": "^1.0.1" } }, "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A=="],
|
||||||
|
|
||||||
@@ -243,7 +252,7 @@
|
|||||||
|
|
||||||
"es-errors": ["es-errors@1.3.0", "", {}, "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="],
|
"es-errors": ["es-errors@1.3.0", "", {}, "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="],
|
||||||
|
|
||||||
"es-object-atoms": ["es-object-atoms@1.1.1", "", { "dependencies": { "es-errors": "^1.3.0" } }, "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA=="],
|
"es-object-atoms": ["es-object-atoms@1.1.2", "", { "dependencies": { "es-errors": "^1.3.0" } }, "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw=="],
|
||||||
|
|
||||||
"es6-error": ["es6-error@4.1.1", "", {}, "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg=="],
|
"es6-error": ["es6-error@4.1.1", "", {}, "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg=="],
|
||||||
|
|
||||||
@@ -257,15 +266,17 @@
|
|||||||
|
|
||||||
"eventsource": ["eventsource@3.0.7", "", { "dependencies": { "eventsource-parser": "^3.0.1" } }, "sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA=="],
|
"eventsource": ["eventsource@3.0.7", "", { "dependencies": { "eventsource-parser": "^3.0.1" } }, "sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA=="],
|
||||||
|
|
||||||
"eventsource-parser": ["eventsource-parser@3.0.8", "", {}, "sha512-70QWGkr4snxr0OXLRWsFLeRBIRPuQOvt4s8QYjmUlmlkyTZkRqS7EDVRZtzU3TiyDbXSzaOeF0XUKy8PchzukQ=="],
|
"eventsource-parser": ["eventsource-parser@3.1.0", "", {}, "sha512-kJezFj9YFAMLeORyi7aCLxLbD5/qWMQnoMVlVPyHIll7lgRJCc3JVln9Vgl9nwQi0YkMnhdGTMNn7CkRRAptMg=="],
|
||||||
|
|
||||||
"express": ["express@5.2.1", "", { "dependencies": { "accepts": "^2.0.0", "body-parser": "^2.2.1", "content-disposition": "^1.0.0", "content-type": "^1.0.5", "cookie": "^0.7.1", "cookie-signature": "^1.2.1", "debug": "^4.4.0", "depd": "^2.0.0", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "etag": "^1.8.1", "finalhandler": "^2.1.0", "fresh": "^2.0.0", "http-errors": "^2.0.0", "merge-descriptors": "^2.0.0", "mime-types": "^3.0.0", "on-finished": "^2.4.1", "once": "^1.4.0", "parseurl": "^1.3.3", "proxy-addr": "^2.0.7", "qs": "^6.14.0", "range-parser": "^1.2.1", "router": "^2.2.0", "send": "^1.1.0", "serve-static": "^2.2.0", "statuses": "^2.0.1", "type-is": "^2.0.1", "vary": "^1.1.2" } }, "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw=="],
|
"express": ["express@5.2.1", "", { "dependencies": { "accepts": "^2.0.0", "body-parser": "^2.2.1", "content-disposition": "^1.0.0", "content-type": "^1.0.5", "cookie": "^0.7.1", "cookie-signature": "^1.2.1", "debug": "^4.4.0", "depd": "^2.0.0", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "etag": "^1.8.1", "finalhandler": "^2.1.0", "fresh": "^2.0.0", "http-errors": "^2.0.0", "merge-descriptors": "^2.0.0", "mime-types": "^3.0.0", "on-finished": "^2.4.1", "once": "^1.4.0", "parseurl": "^1.3.3", "proxy-addr": "^2.0.7", "qs": "^6.14.0", "range-parser": "^1.2.1", "router": "^2.2.0", "send": "^1.1.0", "serve-static": "^2.2.0", "statuses": "^2.0.1", "type-is": "^2.0.1", "vary": "^1.1.2" } }, "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw=="],
|
||||||
|
|
||||||
"express-rate-limit": ["express-rate-limit@8.3.2", "", { "dependencies": { "ip-address": "10.1.0" }, "peerDependencies": { "express": ">= 4.11" } }, "sha512-77VmFeJkO0/rvimEDuUC5H30oqUC4EyOhyGccfqoLebB0oiEYfM7nwPrsDsBL1gsTpwfzX8SFy2MT3TDyRq+bg=="],
|
"express-rate-limit": ["express-rate-limit@8.6.0", "", { "dependencies": { "debug": "^4.4.3", "ip-address": "^10.2.0" }, "peerDependencies": { "express": ">= 4.11" } }, "sha512-XKJXDsASUOo0LLtFwW5hCcQGH0N4WQc/Rn8/Pvoia+TJFOkkFPvrtW9lZOeeNcxQJspvOIERMwiRLsVFlhHEkA=="],
|
||||||
|
|
||||||
"fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="],
|
"fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="],
|
||||||
|
|
||||||
"fast-uri": ["fast-uri@3.1.0", "", {}, "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA=="],
|
"fast-sha256": ["fast-sha256@1.3.0", "", {}, "sha512-n11RGP/lrWEFI/bWdygLxhI+pVeo1ZYIVwvvPkW7azl/rOy+F3HYRZ2K5zeE9mmkhQppyv9sQFx0JM9UabnpPQ=="],
|
||||||
|
|
||||||
|
"fast-uri": ["fast-uri@3.1.3", "", {}, "sha512-i70LwGWUduXqzicKXWshooq+sWL1K3WUU5rKZNG/0i3a1OSoX3HqhH5WbWwTmqWfor4urUakGPiRQcleRZTwOg=="],
|
||||||
|
|
||||||
"finalhandler": ["finalhandler@2.1.1", "", { "dependencies": { "debug": "^4.4.0", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "on-finished": "^2.4.1", "parseurl": "^1.3.3", "statuses": "^2.0.1" } }, "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA=="],
|
"finalhandler": ["finalhandler@2.1.1", "", { "dependencies": { "debug": "^4.4.0", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "on-finished": "^2.4.1", "parseurl": "^1.3.3", "statuses": "^2.0.1" } }, "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA=="],
|
||||||
|
|
||||||
@@ -297,9 +308,9 @@
|
|||||||
|
|
||||||
"has-tostringtag": ["has-tostringtag@1.0.2", "", { "dependencies": { "has-symbols": "^1.0.3" } }, "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw=="],
|
"has-tostringtag": ["has-tostringtag@1.0.2", "", { "dependencies": { "has-symbols": "^1.0.3" } }, "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw=="],
|
||||||
|
|
||||||
"hasown": ["hasown@2.0.3", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg=="],
|
"hasown": ["hasown@2.0.4", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A=="],
|
||||||
|
|
||||||
"hono": ["hono@4.12.14", "", {}, "sha512-am5zfg3yu6sqn5yjKBNqhnTX7Cv+m00ox+7jbaKkrLMRJ4rAdldd1xPd/JzbBWspqaQv6RSTrgFN95EsfhC+7w=="],
|
"hono": ["hono@4.12.27", "", {}, "sha512-1yrb/+w6HWQJrUCLkJ2IF5jNIPvvFkblV5RNOYl6bV+OA6p9GLcMpHFFGTosSvHvcAUibuUukRqhlYI4z32C7Q=="],
|
||||||
|
|
||||||
"html-entities": ["html-entities@2.6.0", "", {}, "sha512-kig+rMn/QOVRvr7c86gQ8lWXq+Hkv6CbAH1hLu+RG338StTpE8Z0b44SDVaqVu7HGKf27frdmUYEs9hTUX/cLQ=="],
|
"html-entities": ["html-entities@2.6.0", "", {}, "sha512-kig+rMn/QOVRvr7c86gQ8lWXq+Hkv6CbAH1hLu+RG338StTpE8Z0b44SDVaqVu7HGKf27frdmUYEs9hTUX/cLQ=="],
|
||||||
|
|
||||||
@@ -311,7 +322,7 @@
|
|||||||
|
|
||||||
"http-errors": ["http-errors@2.0.1", "", { "dependencies": { "depd": "~2.0.0", "inherits": "~2.0.4", "setprototypeof": "~1.2.0", "statuses": "~2.0.2", "toidentifier": "~1.0.1" } }, "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ=="],
|
"http-errors": ["http-errors@2.0.1", "", { "dependencies": { "depd": "~2.0.0", "inherits": "~2.0.4", "setprototypeof": "~1.2.0", "statuses": "~2.0.2", "toidentifier": "~1.0.1" } }, "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ=="],
|
||||||
|
|
||||||
"iconv-lite": ["iconv-lite@0.7.2", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw=="],
|
"iconv-lite": ["iconv-lite@0.7.3", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-IKXpvIzjnC9XTAUbVBcMfGS0EPaIXtW6v+zr+RRp+hqULEpo0owZax6wyRwPOJbWbzjYspQwusTsfVr0ifh4uQ=="],
|
||||||
|
|
||||||
"image-size": ["image-size@1.2.1", "", { "dependencies": { "queue": "6.0.2" }, "bin": { "image-size": "bin/image-size.js" } }, "sha512-rH+46sQJ2dlwfjfhCyNx5thzrv+dtmBIhPHk0zgRUukHzZ/kRueTJXoYYsclBaKcSMBWuGbOFXtioLpzTb5euw=="],
|
"image-size": ["image-size@1.2.1", "", { "dependencies": { "queue": "6.0.2" }, "bin": { "image-size": "bin/image-size.js" } }, "sha512-rH+46sQJ2dlwfjfhCyNx5thzrv+dtmBIhPHk0zgRUukHzZ/kRueTJXoYYsclBaKcSMBWuGbOFXtioLpzTb5euw=="],
|
||||||
|
|
||||||
@@ -337,7 +348,7 @@
|
|||||||
|
|
||||||
"isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="],
|
"isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="],
|
||||||
|
|
||||||
"jose": ["jose@6.2.2", "", {}, "sha512-d7kPDd34KO/YnzaDOlikGpOurfF0ByC2sEV4cANCtdqLlTfBlw2p14O/5d/zv40gJPbIQxfES3nSx1/oYNyuZQ=="],
|
"jose": ["jose@6.2.3", "", {}, "sha512-YYVDInQKFJfR/xa3ojUTl8c2KoTwiL1R5Wg9YCydwH0x0B9grbzlg5HC7mMjCtUJjbQ/YnGEZIhI5tCgfTb4Hw=="],
|
||||||
|
|
||||||
"json-schema-to-ts": ["json-schema-to-ts@3.1.1", "", { "dependencies": { "@babel/runtime": "^7.18.3", "ts-algebra": "^2.0.0" } }, "sha512-+DWg8jCJG2TEnpy7kOm/7/AxaYoaRbjVB4LFZLySZlWn8exGs3A4OLJR966cVvU26N7X9TWxl+Jsw7dzAqKT6g=="],
|
"json-schema-to-ts": ["json-schema-to-ts@3.1.1", "", { "dependencies": { "@babel/runtime": "^7.18.3", "ts-algebra": "^2.0.0" } }, "sha512-+DWg8jCJG2TEnpy7kOm/7/AxaYoaRbjVB4LFZLySZlWn8exGs3A4OLJR966cVvU26N7X9TWxl+Jsw7dzAqKT6g=="],
|
||||||
|
|
||||||
@@ -355,7 +366,7 @@
|
|||||||
|
|
||||||
"long": ["long@5.3.2", "", {}, "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA=="],
|
"long": ["long@5.3.2", "", {}, "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA=="],
|
||||||
|
|
||||||
"marked": ["marked@18.0.2", "", { "bin": { "marked": "bin/marked.js" } }, "sha512-NsmlUYBS/Zg57rgDWMYdnre6OTj4e+qq/JS2ot3KrYLSoHLw+sDu0Nm1ZGpRgYAq6c+b1ekaY5NzVchMCQnzcg=="],
|
"marked": ["marked@18.0.7", "", { "bin": { "marked": "bin/marked.js" } }, "sha512-iDVQ5ldaiKXn6b2JroX5kgRfmwgqolW7NpaEzTl1k/2Zh1njIEN9yniyLV/mOvWwtsE8OGgkjsCYvijuPk1dtA=="],
|
||||||
|
|
||||||
"matcher": ["matcher@3.0.0", "", { "dependencies": { "escape-string-regexp": "^4.0.0" } }, "sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng=="],
|
"matcher": ["matcher@3.0.0", "", { "dependencies": { "escape-string-regexp": "^4.0.0" } }, "sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng=="],
|
||||||
|
|
||||||
@@ -373,7 +384,7 @@
|
|||||||
|
|
||||||
"ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
|
"ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
|
||||||
|
|
||||||
"nanoid": ["nanoid@3.3.12", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ=="],
|
"nanoid": ["nanoid@3.3.16", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-bzlKTyNJ7+LdGIIwy8ijFpIqEQIvafahV7eYykJ8Cvh42EdJeODoJ6gUJXpQJvej1BddH8OqTXZNE/KfbWAu8Q=="],
|
||||||
|
|
||||||
"negotiator": ["negotiator@1.0.0", "", {}, "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg=="],
|
"negotiator": ["negotiator@1.0.0", "", {}, "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg=="],
|
||||||
|
|
||||||
@@ -395,7 +406,7 @@
|
|||||||
|
|
||||||
"onnxruntime-node": ["onnxruntime-node@1.24.3", "", { "dependencies": { "adm-zip": "^0.5.16", "global-agent": "^3.0.0", "onnxruntime-common": "1.24.3" }, "os": [ "linux", "win32", "darwin", ] }, "sha512-JH7+czbc8ALA819vlTgcV+Q214/+VjGeBHDjX81+ZCD0PCVCIFGFNtT0V4sXG/1JXypKPgScQcB3ij/hk3YnTg=="],
|
"onnxruntime-node": ["onnxruntime-node@1.24.3", "", { "dependencies": { "adm-zip": "^0.5.16", "global-agent": "^3.0.0", "onnxruntime-common": "1.24.3" }, "os": [ "linux", "win32", "darwin", ] }, "sha512-JH7+czbc8ALA819vlTgcV+Q214/+VjGeBHDjX81+ZCD0PCVCIFGFNtT0V4sXG/1JXypKPgScQcB3ij/hk3YnTg=="],
|
||||||
|
|
||||||
"onnxruntime-web": ["onnxruntime-web@1.26.0-dev.20260410-5e55544225", "", { "dependencies": { "flatbuffers": "^25.1.24", "guid-typescript": "^1.0.9", "long": "^5.2.3", "onnxruntime-common": "1.24.0-dev.20251116-b39e144322", "platform": "^1.3.6", "protobufjs": "^7.2.4" } }, "sha512-hHd9n8DzIfGSAjM4Dvslesc8i6h9HEEcl8qt7X3LfhUxMgls6FBJ32j2xrDtJjKJFEehFeJmyB/pvad1I8KS8w=="],
|
"onnxruntime-web": ["onnxruntime-web@1.26.0-dev.20260416-b7804b056c", "", { "dependencies": { "flatbuffers": "^25.1.24", "guid-typescript": "^1.0.9", "long": "^5.2.3", "onnxruntime-common": "1.24.0-dev.20251116-b39e144322", "platform": "^1.3.6", "protobufjs": "^7.2.4" } }, "sha512-MD6Ss4GSpQBo6zqoJzyT9LRbKYs7x/JVN23FT24EcEvlqF4VuzPOeH6X38orZPKHQDbprn7K+SBpu0/mj2CQiw=="],
|
||||||
|
|
||||||
"pako": ["pako@1.0.11", "", {}, "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw=="],
|
"pako": ["pako@1.0.11", "", {}, "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw=="],
|
||||||
|
|
||||||
@@ -409,23 +420,23 @@
|
|||||||
|
|
||||||
"platform": ["platform@1.3.6", "", {}, "sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg=="],
|
"platform": ["platform@1.3.6", "", {}, "sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg=="],
|
||||||
|
|
||||||
"playwright": ["playwright-core@1.58.2", "", { "bin": { "playwright-core": "cli.js" } }, "sha512-yZkEtftgwS8CsfYo7nm0KE8jsvm6i/PTgVtB8DL726wNf6H2IMsDuxCpJj59KDaxCtSnrWan2AeDqM7JBaultg=="],
|
"playwright": ["playwright-core@1.61.1", "", { "bin": { "playwright-core": "cli.js" } }, "sha512-h7Qlt6m4REp25qvIdvbDtVmD4LqVXfpRxhORv9L0jzETM05p4fuPJ3dKyuSXQxDSbXnmS79HAgi9589lGSpLkg=="],
|
||||||
|
|
||||||
"process": ["process@0.11.10", "", {}, "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A=="],
|
"process": ["process@0.11.10", "", {}, "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A=="],
|
||||||
|
|
||||||
"process-nextick-args": ["process-nextick-args@2.0.1", "", {}, "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="],
|
"process-nextick-args": ["process-nextick-args@2.0.1", "", {}, "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="],
|
||||||
|
|
||||||
"protobufjs": ["protobufjs@7.5.5", "", { "dependencies": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", "@protobufjs/codegen": "^2.0.4", "@protobufjs/eventemitter": "^1.1.0", "@protobufjs/fetch": "^1.1.0", "@protobufjs/float": "^1.0.2", "@protobufjs/inquire": "^1.1.0", "@protobufjs/path": "^1.1.2", "@protobufjs/pool": "^1.1.0", "@protobufjs/utf8": "^1.1.0", "@types/node": ">=13.7.0", "long": "^5.0.0" } }, "sha512-3wY1AxV+VBNW8Yypfd1yQY9pXnqTAN+KwQxL8iYm3/BjKYMNg4i0owhEe26PWDOMaIrzeeF98Lqd5NGz4omiIg=="],
|
"protobufjs": ["protobufjs@7.6.5", "", { "dependencies": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", "@protobufjs/codegen": "^2.0.5", "@protobufjs/eventemitter": "^1.1.1", "@protobufjs/fetch": "^1.1.1", "@protobufjs/float": "^1.0.2", "@protobufjs/path": "^1.1.2", "@protobufjs/pool": "^1.1.0", "@protobufjs/utf8": "^1.1.1", "@types/node": ">=13.7.0", "long": "^5.3.2" } }, "sha512-/FPD0nUc9jH6rfFjji9IBqOz4pcSE3CsT1m7Ep6Mdb0LxSUMj8hgl6GomOvZzpNpAqqGaXA0P3VSrZLFzIhQrw=="],
|
||||||
|
|
||||||
"proxy-addr": ["proxy-addr@2.0.7", "", { "dependencies": { "forwarded": "0.2.0", "ipaddr.js": "1.9.1" } }, "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg=="],
|
"proxy-addr": ["proxy-addr@2.0.7", "", { "dependencies": { "forwarded": "0.2.0", "ipaddr.js": "1.9.1" } }, "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg=="],
|
||||||
|
|
||||||
"punycode": ["punycode@1.4.1", "", {}, "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ=="],
|
"punycode": ["punycode@1.4.1", "", {}, "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ=="],
|
||||||
|
|
||||||
"qs": ["qs@6.15.1", "", { "dependencies": { "side-channel": "^1.1.0" } }, "sha512-6YHEFRL9mfgcAvql/XhwTvf5jKcOiiupt2FiJxHkiX1z4j7WL8J/jRHYLluORvc1XxB5rV20KoeK00gVJamspg=="],
|
"qs": ["qs@6.15.2", "", { "dependencies": { "side-channel": "^1.1.0" } }, "sha512-Rzq0KEyX/w/tEybncDgdkZrJgVUsUMk3xjh3t5bv3S1HTAtg+uOYt72+ZfwiQwKdysThkTBdL/rTi6HDmX9Ddw=="],
|
||||||
|
|
||||||
"queue": ["queue@6.0.2", "", { "dependencies": { "inherits": "~2.0.3" } }, "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA=="],
|
"queue": ["queue@6.0.2", "", { "dependencies": { "inherits": "~2.0.3" } }, "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA=="],
|
||||||
|
|
||||||
"range-parser": ["range-parser@1.2.1", "", {}, "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="],
|
"range-parser": ["range-parser@1.3.0", "", {}, "sha512-hek2mFQpPuI4E1BBKrSto+BU3e3x4xuarsbiwr3+lf7p44juvFMV0XFWQAP3xUyqXA4RrXLIoaSUGbSt056ZMw=="],
|
||||||
|
|
||||||
"raw-body": ["raw-body@3.0.2", "", { "dependencies": { "bytes": "~3.1.2", "http-errors": "~2.0.1", "iconv-lite": "~0.7.0", "unpipe": "~1.0.0" } }, "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA=="],
|
"raw-body": ["raw-body@3.0.2", "", { "dependencies": { "bytes": "~3.1.2", "http-errors": "~2.0.1", "iconv-lite": "~0.7.0", "unpipe": "~1.0.0" } }, "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA=="],
|
||||||
|
|
||||||
@@ -443,7 +454,7 @@
|
|||||||
|
|
||||||
"safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="],
|
"safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="],
|
||||||
|
|
||||||
"semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="],
|
"semver": ["semver@7.8.5", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA=="],
|
||||||
|
|
||||||
"semver-compare": ["semver-compare@1.0.0", "", {}, "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow=="],
|
"semver-compare": ["semver-compare@1.0.0", "", {}, "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow=="],
|
||||||
|
|
||||||
@@ -463,7 +474,7 @@
|
|||||||
|
|
||||||
"shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="],
|
"shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="],
|
||||||
|
|
||||||
"side-channel": ["side-channel@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3", "side-channel-list": "^1.0.0", "side-channel-map": "^1.0.1", "side-channel-weakmap": "^1.0.2" } }, "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw=="],
|
"side-channel": ["side-channel@1.1.1", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.4", "side-channel-list": "^1.0.1", "side-channel-map": "^1.0.1", "side-channel-weakmap": "^1.0.2" } }, "sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ=="],
|
||||||
|
|
||||||
"side-channel-list": ["side-channel-list@1.0.1", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.4" } }, "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w=="],
|
"side-channel-list": ["side-channel-list@1.0.1", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.4" } }, "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w=="],
|
||||||
|
|
||||||
@@ -473,10 +484,12 @@
|
|||||||
|
|
||||||
"smart-buffer": ["smart-buffer@4.2.0", "", {}, "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg=="],
|
"smart-buffer": ["smart-buffer@4.2.0", "", {}, "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg=="],
|
||||||
|
|
||||||
"socks": ["socks@2.8.8", "", { "dependencies": { "ip-address": "^10.1.1", "smart-buffer": "^4.2.0" } }, "sha512-NlGELfPrgX2f1TAAcz0WawlLn+0r3FyhhCRpFFK2CemXenPYvzMWWZINv3eDNo9ucdwme7oCHRY0Jnbs4aIkog=="],
|
"socks": ["socks@2.8.9", "", { "dependencies": { "ip-address": "^10.1.1", "smart-buffer": "^4.2.0" } }, "sha512-LJhUYUvItdQ0LkJTmPeaEObWXAqFyfmP85x0tch/ez9cahmhlBBLbIqDFnvBnUJGagb0JbIQrkBs1wJ+yRYpEw=="],
|
||||||
|
|
||||||
"sprintf-js": ["sprintf-js@1.1.3", "", {}, "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA=="],
|
"sprintf-js": ["sprintf-js@1.1.3", "", {}, "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA=="],
|
||||||
|
|
||||||
|
"standardwebhooks": ["standardwebhooks@1.0.0", "", { "dependencies": { "@stablelib/base64": "^1.0.0", "fast-sha256": "^1.3.0" } }, "sha512-BbHGOQK9olHPMvQNHWul6MYlrRTAOKn03rOe4A8O3CLWhNf4YHBqq2HJKKC+sfqpxiBY52pNeesD6jIiLDz8jg=="],
|
||||||
|
|
||||||
"statuses": ["statuses@2.0.2", "", {}, "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw=="],
|
"statuses": ["statuses@2.0.2", "", {}, "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw=="],
|
||||||
|
|
||||||
"string-template": ["string-template@0.2.1", "", {}, "sha512-Yptehjogou2xm4UJbxJ4CxgZx12HBfeystp0y3x7s4Dj32ltVVG1Gg8YhKjHZkHicuKpZX/ffilA8505VbUbpw=="],
|
"string-template": ["string-template@0.2.1", "", {}, "sha512-Yptehjogou2xm4UJbxJ4CxgZx12HBfeystp0y3x7s4Dj32ltVVG1Gg8YhKjHZkHicuKpZX/ffilA8505VbUbpw=="],
|
||||||
@@ -493,9 +506,9 @@
|
|||||||
|
|
||||||
"type-fest": ["type-fest@0.13.1", "", {}, "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg=="],
|
"type-fest": ["type-fest@0.13.1", "", {}, "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg=="],
|
||||||
|
|
||||||
"type-is": ["type-is@2.0.1", "", { "dependencies": { "content-type": "^1.0.5", "media-typer": "^1.1.0", "mime-types": "^3.0.0" } }, "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw=="],
|
"type-is": ["type-is@2.1.0", "", { "dependencies": { "content-type": "^2.0.0", "media-typer": "^1.1.0", "mime-types": "^3.0.0" } }, "sha512-faYHw0anBbc/kWF3zFTEnxSFOAGUX9GFbOBthvDdLsIlEoWOFOtS0zgCiQYwIskL9iGXZL3kAXD8OoZ4GmMATA=="],
|
||||||
|
|
||||||
"undici-types": ["undici-types@7.18.2", "", {}, "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w=="],
|
"undici-types": ["undici-types@8.3.0", "", {}, "sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ=="],
|
||||||
|
|
||||||
"unpipe": ["unpipe@1.0.0", "", {}, "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ=="],
|
"unpipe": ["unpipe@1.0.0", "", {}, "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ=="],
|
||||||
|
|
||||||
@@ -525,12 +538,10 @@
|
|||||||
|
|
||||||
"xterm-addon-fit": ["xterm-addon-fit@0.8.0", "", { "peerDependencies": { "xterm": "^5.0.0" } }, "sha512-yj3Np7XlvxxhYF/EJ7p3KHaMt6OdwQ+HDu573Vx1lRXsVxOcnVJs51RgjZOouIZOczTsskaS+CpXspK81/DLqw=="],
|
"xterm-addon-fit": ["xterm-addon-fit@0.8.0", "", { "peerDependencies": { "xterm": "^5.0.0" } }, "sha512-yj3Np7XlvxxhYF/EJ7p3KHaMt6OdwQ+HDu573Vx1lRXsVxOcnVJs51RgjZOouIZOczTsskaS+CpXspK81/DLqw=="],
|
||||||
|
|
||||||
"zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="],
|
"zod": ["zod@4.4.3", "", {}, "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ=="],
|
||||||
|
|
||||||
"zod-to-json-schema": ["zod-to-json-schema@3.25.2", "", { "peerDependencies": { "zod": "^3.25.28 || ^4" } }, "sha512-O/PgfnpT1xKSDeQYSCfRI5Gy3hPf91mKVDuYLUHZJMiDFptvP41MSnWofm8dnCm0256ZNfZIM7DSzuSMAFnjHA=="],
|
"zod-to-json-schema": ["zod-to-json-schema@3.25.2", "", { "peerDependencies": { "zod": "^3.25.28 || ^4" } }, "sha512-O/PgfnpT1xKSDeQYSCfRI5Gy3hPf91mKVDuYLUHZJMiDFptvP41MSnWofm8dnCm0256ZNfZIM7DSzuSMAFnjHA=="],
|
||||||
|
|
||||||
"@anthropic-ai/claude-agent-sdk/@anthropic-ai/sdk": ["@anthropic-ai/sdk@0.81.0", "", { "dependencies": { "json-schema-to-ts": "^3.1.1" }, "peerDependencies": { "zod": "^3.25.0 || ^4.0.0" }, "optionalPeers": ["zod"], "bin": { "anthropic-ai-sdk": "bin/cli" } }, "sha512-D4K5PvEV6wPiRtVlVsJHIUhHAmOZ6IT/I9rKlTf84gR7GyyAurPJK7z9BOf/AZqC5d1DhYQGJNKRmV+q8dGhgw=="],
|
|
||||||
|
|
||||||
"@oozcitak/infra/@oozcitak/util": ["@oozcitak/util@8.0.0", "", {}, "sha512-+9Hq6yuoq/3TRV/n/xcpydGBq2qN2/DEDMqNTG7rm95K6ZE2/YY/sPyx62+1n8QsE9O26e5M1URlXsk+AnN9Jw=="],
|
"@oozcitak/infra/@oozcitak/util": ["@oozcitak/util@8.0.0", "", {}, "sha512-+9Hq6yuoq/3TRV/n/xcpydGBq2qN2/DEDMqNTG7rm95K6ZE2/YY/sPyx62+1n8QsE9O26e5M1URlXsk+AnN9Jw=="],
|
||||||
|
|
||||||
"@oozcitak/url/@oozcitak/infra": ["@oozcitak/infra@1.0.3", "", { "dependencies": { "@oozcitak/util": "1.0.1" } }, "sha512-9O2wxXGnRzy76O1XUxESxDGsXT5kzETJPvYbreO4mv6bqe1+YSuux2cZTagjJ/T4UfEwFJz5ixanOqB0QgYAag=="],
|
"@oozcitak/url/@oozcitak/infra": ["@oozcitak/infra@1.0.3", "", { "dependencies": { "@oozcitak/util": "1.0.1" } }, "sha512-9O2wxXGnRzy76O1XUxESxDGsXT5kzETJPvYbreO4mv6bqe1+YSuux2cZTagjJ/T4UfEwFJz5ixanOqB0QgYAag=="],
|
||||||
@@ -539,20 +550,22 @@
|
|||||||
|
|
||||||
"accepts/mime-types": ["mime-types@3.0.2", "", { "dependencies": { "mime-db": "^1.54.0" } }, "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A=="],
|
"accepts/mime-types": ["mime-types@3.0.2", "", { "dependencies": { "mime-db": "^1.54.0" } }, "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A=="],
|
||||||
|
|
||||||
|
"body-parser/content-type": ["content-type@2.0.0", "", {}, "sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ=="],
|
||||||
|
|
||||||
"dom-serializer/domelementtype": ["domelementtype@2.3.0", "", {}, "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw=="],
|
"dom-serializer/domelementtype": ["domelementtype@2.3.0", "", {}, "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw=="],
|
||||||
|
|
||||||
"dom-serializer/entities": ["entities@2.2.0", "", {}, "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A=="],
|
"dom-serializer/entities": ["entities@2.2.0", "", {}, "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A=="],
|
||||||
|
|
||||||
"express/mime-types": ["mime-types@3.0.2", "", { "dependencies": { "mime-db": "^1.54.0" } }, "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A=="],
|
"express/mime-types": ["mime-types@3.0.2", "", { "dependencies": { "mime-db": "^1.54.0" } }, "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A=="],
|
||||||
|
|
||||||
"express-rate-limit/ip-address": ["ip-address@10.1.0", "", {}, "sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q=="],
|
|
||||||
|
|
||||||
"htmlparser2/readable-stream": ["readable-stream@3.6.2", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA=="],
|
"htmlparser2/readable-stream": ["readable-stream@3.6.2", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA=="],
|
||||||
|
|
||||||
"onnxruntime-web/onnxruntime-common": ["onnxruntime-common@1.24.0-dev.20251116-b39e144322", "", {}, "sha512-BOoomdHYmNRL5r4iQ4bMvsl2t0/hzVQ3OM3PHD0gxeXu1PmggqBv3puZicEUVOA3AtHHYmqZtjMj9FOfGrATTw=="],
|
"onnxruntime-web/onnxruntime-common": ["onnxruntime-common@1.24.0-dev.20251116-b39e144322", "", {}, "sha512-BOoomdHYmNRL5r4iQ4bMvsl2t0/hzVQ3OM3PHD0gxeXu1PmggqBv3puZicEUVOA3AtHHYmqZtjMj9FOfGrATTw=="],
|
||||||
|
|
||||||
"send/mime-types": ["mime-types@3.0.2", "", { "dependencies": { "mime-db": "^1.54.0" } }, "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A=="],
|
"send/mime-types": ["mime-types@3.0.2", "", { "dependencies": { "mime-db": "^1.54.0" } }, "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A=="],
|
||||||
|
|
||||||
|
"type-is/content-type": ["content-type@2.0.0", "", {}, "sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ=="],
|
||||||
|
|
||||||
"type-is/mime-types": ["mime-types@3.0.2", "", { "dependencies": { "mime-db": "^1.54.0" } }, "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A=="],
|
"type-is/mime-types": ["mime-types@3.0.2", "", { "dependencies": { "mime-db": "^1.54.0" } }, "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A=="],
|
||||||
|
|
||||||
"xmlbuilder2/@oozcitak/dom": ["@oozcitak/dom@1.15.5", "", { "dependencies": { "@oozcitak/infra": "1.0.5", "@oozcitak/url": "1.0.0", "@oozcitak/util": "8.0.0" } }, "sha512-L6v3Mwb0TaYBYgeYlIeBaHnc+2ZEaDSbFiRm5KmqZQSoBlbPlf+l6aIH/sD5GUf2MYwULw00LT7+dOnEuAEC0A=="],
|
"xmlbuilder2/@oozcitak/dom": ["@oozcitak/dom@1.15.5", "", { "dependencies": { "@oozcitak/infra": "1.0.5", "@oozcitak/url": "1.0.0", "@oozcitak/util": "8.0.0" } }, "sha512-L6v3Mwb0TaYBYgeYlIeBaHnc+2ZEaDSbFiRm5KmqZQSoBlbPlf+l6aIH/sD5GUf2MYwULw00LT7+dOnEuAEC0A=="],
|
||||||
|
|||||||
@@ -0,0 +1,75 @@
|
|||||||
|
# Capability readiness
|
||||||
|
|
||||||
|
GStack's six public skills provide pure judgment without the optional runtime.
|
||||||
|
When a workflow needs executable evidence, inspect one of the five user-facing
|
||||||
|
capabilities without changing the machine:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
gstack doctor --capability browser
|
||||||
|
gstack doctor --capability design --json
|
||||||
|
gstack doctor --capability diagram
|
||||||
|
gstack doctor --capability pdf
|
||||||
|
gstack doctor --capability ios
|
||||||
|
```
|
||||||
|
|
||||||
|
The focused result deliberately keeps five questions separate:
|
||||||
|
|
||||||
|
| Axis | Meaning |
|
||||||
|
|---|---|
|
||||||
|
| `judgment` | `available` even when no optional runtime exists. |
|
||||||
|
| `platform` | `supported` or `unsupported`; physical iOS is macOS-only. |
|
||||||
|
| `consent.preview` | Whether consent is required before an uncached public signed-manifest metadata request. Doctor never makes that request or grants consent. |
|
||||||
|
| `consent.install` | Separate consent required only after the complete preview. Doctor never installs or records consent. |
|
||||||
|
| `readiness` | Whether the selected local runtime capability is usable now. |
|
||||||
|
|
||||||
|
Readiness has exactly five states:
|
||||||
|
|
||||||
|
- `ready`: capability and managed-runtime checks passed.
|
||||||
|
- `degraded`: the capability passed, but the managed runtime reported a warning
|
||||||
|
such as recovery from an interrupted upgrade.
|
||||||
|
- `unavailable`: the capability is not selected, no runtime is active, or runtime
|
||||||
|
inspection could not establish availability.
|
||||||
|
- `unsupported`: the platform cannot provide the capability with GStack's
|
||||||
|
existing architecture.
|
||||||
|
- `failed`: an installed/selected capability failed its readiness evidence.
|
||||||
|
|
||||||
|
The JSON form follows the runtime's result convention: `ok` is true only for
|
||||||
|
`ready` and `degraded`; a non-ready focused doctor exits 1. Usage errors still
|
||||||
|
exit 2 through the standard CLI error envelope.
|
||||||
|
|
||||||
|
## Consent and setup flow
|
||||||
|
|
||||||
|
```text
|
||||||
|
pure judgment (always available)
|
||||||
|
|
|
||||||
|
v
|
||||||
|
capability doctor (local, non-mutating)
|
||||||
|
|
|
||||||
|
+-- ready/degraded --> capability-dependent work
|
||||||
|
|
|
||||||
|
+-- unsupported ----> judgment-only work or supported platform
|
||||||
|
|
|
||||||
|
+-- unavailable/failed
|
||||||
|
|
|
||||||
|
v
|
||||||
|
ask for preview consent
|
||||||
|
|
|
||||||
|
v
|
||||||
|
packaged bootstrap preview (no install)
|
||||||
|
|
|
||||||
|
v
|
||||||
|
ask for install consent
|
||||||
|
|
|
||||||
|
v
|
||||||
|
packaged bootstrap install
|
||||||
|
|
|
||||||
|
v
|
||||||
|
capability doctor again
|
||||||
|
```
|
||||||
|
|
||||||
|
Preview consent is not install consent. Deferring either does not block pure
|
||||||
|
judgment. Follow the packaged bootstrap contract for exact dependency closure,
|
||||||
|
compressed bytes, signature checks, and atomic installation. Do not run setup
|
||||||
|
from a standards-installed skill directory, add a browser provider, replace the
|
||||||
|
local Chromium/Playwright backend, or replace the physical-iOS
|
||||||
|
DebugBridge/CoreDevice harness.
|
||||||
@@ -43,7 +43,7 @@
|
|||||||
"prompt_sha256": "a0fcff9cad68f9305da861fa5a58990e1ef51d9d84298fe2df7ba8a2f56b1dba",
|
"prompt_sha256": "a0fcff9cad68f9305da861fa5a58990e1ef51d9d84298fe2df7ba8a2f56b1dba",
|
||||||
"semantic_attempt_sha256": "7724c3d954f421753c597364c383bd76bc01ba9803f99fb14488287bb925aeb6"
|
"semantic_attempt_sha256": "7724c3d954f421753c597364c383bd76bc01ba9803f99fb14488287bb925aeb6"
|
||||||
},
|
},
|
||||||
"policy_sha256": "951fd945e7ecb438bcedadccd563df430652d35f4cff1d513dfdcf16ee77d02d",
|
"policy_sha256": "c7df25a16073d69da15243f258a2ef72a69c03ee3114eac2c19cf1c7e126532b",
|
||||||
"policy_present": true,
|
"policy_present": true,
|
||||||
"prompt_is_not_authority_input": true,
|
"prompt_is_not_authority_input": true,
|
||||||
"verdict": "PASS"
|
"verdict": "PASS"
|
||||||
@@ -88,7 +88,7 @@
|
|||||||
"prompt_sha256": "04d82a21358f188cb823dcceeecaebea0b4ed8b9c1f8d00220ef3b499c48b1c8",
|
"prompt_sha256": "04d82a21358f188cb823dcceeecaebea0b4ed8b9c1f8d00220ef3b499c48b1c8",
|
||||||
"semantic_attempt_sha256": "9639406995955284517acb30f56b37dedc42a6c08142163dfa8fe0295105cbbf"
|
"semantic_attempt_sha256": "9639406995955284517acb30f56b37dedc42a6c08142163dfa8fe0295105cbbf"
|
||||||
},
|
},
|
||||||
"policy_sha256": "e5fc3019062512de84ade87c8c45b34c8f46b95a65ef84a49fd25bbdee63e41e",
|
"policy_sha256": "8dd78f6f8e01eb9cf1fe0f3f43d7fcd072a4f3f2f0dc14d9f1b5d3ff1250b972",
|
||||||
"policy_present": true,
|
"policy_present": true,
|
||||||
"prompt_is_not_authority_input": true,
|
"prompt_is_not_authority_input": true,
|
||||||
"verdict": "PASS"
|
"verdict": "PASS"
|
||||||
@@ -138,7 +138,7 @@
|
|||||||
"prompt_sha256": "8ad639f708a2ccd5c7c438b1dedf6afacdfa4eac3883a7a046ea23f29314e1c4",
|
"prompt_sha256": "8ad639f708a2ccd5c7c438b1dedf6afacdfa4eac3883a7a046ea23f29314e1c4",
|
||||||
"semantic_attempt_sha256": "4c450039e4c622fbeaa34b7f7dfc810d3b7369aaf7e5f4d240cd6cc18a31331a"
|
"semantic_attempt_sha256": "4c450039e4c622fbeaa34b7f7dfc810d3b7369aaf7e5f4d240cd6cc18a31331a"
|
||||||
},
|
},
|
||||||
"policy_sha256": "78df79ecb49744ff13f044b8f5a486705ef43172c4dc19d7dbc616d84f4d578c",
|
"policy_sha256": "7c7ccb7ff64ea6c73b668848ae5a663606798abc345d7e5c6bb0880732bb29c3",
|
||||||
"policy_present": true,
|
"policy_present": true,
|
||||||
"prompt_is_not_authority_input": true,
|
"prompt_is_not_authority_input": true,
|
||||||
"verdict": "PASS"
|
"verdict": "PASS"
|
||||||
@@ -188,7 +188,7 @@
|
|||||||
"prompt_sha256": "d2aa9aee06a116bf04cb62772e8abdf8dbd606811b6d38565389c88e86c79ede",
|
"prompt_sha256": "d2aa9aee06a116bf04cb62772e8abdf8dbd606811b6d38565389c88e86c79ede",
|
||||||
"semantic_attempt_sha256": "64885a66bdc6688b880cbb9a59babf314834c068eb040657501bf287bfcb0d2b"
|
"semantic_attempt_sha256": "64885a66bdc6688b880cbb9a59babf314834c068eb040657501bf287bfcb0d2b"
|
||||||
},
|
},
|
||||||
"policy_sha256": "951fd945e7ecb438bcedadccd563df430652d35f4cff1d513dfdcf16ee77d02d",
|
"policy_sha256": "c7df25a16073d69da15243f258a2ef72a69c03ee3114eac2c19cf1c7e126532b",
|
||||||
"policy_present": true,
|
"policy_present": true,
|
||||||
"prompt_is_not_authority_input": true,
|
"prompt_is_not_authority_input": true,
|
||||||
"verdict": "PASS"
|
"verdict": "PASS"
|
||||||
@@ -232,7 +232,7 @@
|
|||||||
"prompt_sha256": "377e3a2dfc7b04272f857d27e77c9aa3c9f36c3feb63c03e5aee3ecd3dea8e2a",
|
"prompt_sha256": "377e3a2dfc7b04272f857d27e77c9aa3c9f36c3feb63c03e5aee3ecd3dea8e2a",
|
||||||
"semantic_attempt_sha256": "a49b1528091886749278dc22e7da4556c090800989b2bca9c0e1c09dd880fed7"
|
"semantic_attempt_sha256": "a49b1528091886749278dc22e7da4556c090800989b2bca9c0e1c09dd880fed7"
|
||||||
},
|
},
|
||||||
"policy_sha256": "7a8cb7346851f9d948139dbf33cb8c6dd5eb8b2cc7de94e30a53824a94f027a6",
|
"policy_sha256": "7969ac784f398b09cec2ad44f623de95f1e326721043272b12aaec1c622e840c",
|
||||||
"policy_present": true,
|
"policy_present": true,
|
||||||
"prompt_is_not_authority_input": true,
|
"prompt_is_not_authority_input": true,
|
||||||
"verdict": "PASS"
|
"verdict": "PASS"
|
||||||
@@ -279,7 +279,7 @@
|
|||||||
"prompt_sha256": "a01bb977de84e53d8ce3dfa427bcc93d73c6e449cd4e9c1ff63b436fd41fb0d1",
|
"prompt_sha256": "a01bb977de84e53d8ce3dfa427bcc93d73c6e449cd4e9c1ff63b436fd41fb0d1",
|
||||||
"semantic_attempt_sha256": "ce5c64c62c3ff9b60949f34717dffbc908f62ce30f8a4a48ec182eba4363a206"
|
"semantic_attempt_sha256": "ce5c64c62c3ff9b60949f34717dffbc908f62ce30f8a4a48ec182eba4363a206"
|
||||||
},
|
},
|
||||||
"policy_sha256": "a65efa55d992f63d0bdb356e1e8c4900b966364af1e22f0b6412e20e7ef30a58",
|
"policy_sha256": "4134088a9b22fd7d3d2d6492c812ecbc55650df25ab1101189dd24721fe1763d",
|
||||||
"policy_present": true,
|
"policy_present": true,
|
||||||
"prompt_is_not_authority_input": true,
|
"prompt_is_not_authority_input": true,
|
||||||
"verdict": "PASS"
|
"verdict": "PASS"
|
||||||
@@ -330,7 +330,7 @@
|
|||||||
"prompt_sha256": "95e97e26268ad7e509527e0f54c943ed6c4105d919f250648a2ad59ce77cbdb9",
|
"prompt_sha256": "95e97e26268ad7e509527e0f54c943ed6c4105d919f250648a2ad59ce77cbdb9",
|
||||||
"semantic_attempt_sha256": "dacd11a78e32aeb6c0065496bedd4a9770f7bbac1036e003d3768fac41eb84f0"
|
"semantic_attempt_sha256": "dacd11a78e32aeb6c0065496bedd4a9770f7bbac1036e003d3768fac41eb84f0"
|
||||||
},
|
},
|
||||||
"policy_sha256": "951fd945e7ecb438bcedadccd563df430652d35f4cff1d513dfdcf16ee77d02d",
|
"policy_sha256": "c7df25a16073d69da15243f258a2ef72a69c03ee3114eac2c19cf1c7e126532b",
|
||||||
"policy_present": true,
|
"policy_present": true,
|
||||||
"prompt_is_not_authority_input": true,
|
"prompt_is_not_authority_input": true,
|
||||||
"verdict": "PASS"
|
"verdict": "PASS"
|
||||||
@@ -381,7 +381,7 @@
|
|||||||
"prompt_sha256": "bdd7e8adfa7c15cf8531f84c3adaaacc725075f1a78f7487225300750547b82d",
|
"prompt_sha256": "bdd7e8adfa7c15cf8531f84c3adaaacc725075f1a78f7487225300750547b82d",
|
||||||
"semantic_attempt_sha256": "32c11b63412c5d873ff29dcc87c45bef1b50daa218a5c6c1075864aa24d7c3b6"
|
"semantic_attempt_sha256": "32c11b63412c5d873ff29dcc87c45bef1b50daa218a5c6c1075864aa24d7c3b6"
|
||||||
},
|
},
|
||||||
"policy_sha256": "951fd945e7ecb438bcedadccd563df430652d35f4cff1d513dfdcf16ee77d02d",
|
"policy_sha256": "c7df25a16073d69da15243f258a2ef72a69c03ee3114eac2c19cf1c7e126532b",
|
||||||
"policy_present": true,
|
"policy_present": true,
|
||||||
"prompt_is_not_authority_input": true,
|
"prompt_is_not_authority_input": true,
|
||||||
"verdict": "PASS"
|
"verdict": "PASS"
|
||||||
@@ -426,7 +426,7 @@
|
|||||||
"prompt_sha256": "51b7d53bc342e8632e34ae31a167cbde568ab5ee2a6dd2ccc980583a30604164",
|
"prompt_sha256": "51b7d53bc342e8632e34ae31a167cbde568ab5ee2a6dd2ccc980583a30604164",
|
||||||
"semantic_attempt_sha256": "06f77b27c9bd360562655b23ca00a0dd021bdb14ebaaf3d836845e4e0cb43d68"
|
"semantic_attempt_sha256": "06f77b27c9bd360562655b23ca00a0dd021bdb14ebaaf3d836845e4e0cb43d68"
|
||||||
},
|
},
|
||||||
"policy_sha256": "65f28f454b67d4904c1857a2a6cfcff387c0aa6e4ae58aec490bc95289dce59f",
|
"policy_sha256": "43d5cbbf88ed4f9afa3e7af214b4aa8c3a764a7006d76a864344df05d1f76392",
|
||||||
"policy_present": true,
|
"policy_present": true,
|
||||||
"prompt_is_not_authority_input": true,
|
"prompt_is_not_authority_input": true,
|
||||||
"verdict": "PASS"
|
"verdict": "PASS"
|
||||||
|
|||||||
+22
-103
@@ -5,14 +5,19 @@
|
|||||||
"": {
|
"": {
|
||||||
"name": "@gstack/diagram-render",
|
"name": "@gstack/diagram-render",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@excalidraw/excalidraw": "0.18.0",
|
"@excalidraw/excalidraw": "0.18.1",
|
||||||
"@excalidraw/mermaid-to-excalidraw": "1.1.2",
|
"@excalidraw/mermaid-to-excalidraw": "2.2.2",
|
||||||
"mermaid": "11.12.2",
|
"mermaid": "11.16.0",
|
||||||
"react": "18.3.1",
|
"react": "18.3.1",
|
||||||
"react-dom": "18.3.1",
|
"react-dom": "18.3.1",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
"overrides": {
|
||||||
|
"dompurify": "3.4.11",
|
||||||
|
"lodash-es": "4.18.1",
|
||||||
|
"nanoid": "5.0.9",
|
||||||
|
},
|
||||||
"packages": {
|
"packages": {
|
||||||
"@antfu/install-pkg": ["@antfu/install-pkg@1.1.0", "", { "dependencies": { "package-manager-detector": "^1.3.0", "tinyexec": "^1.0.1" } }, "sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ=="],
|
"@antfu/install-pkg": ["@antfu/install-pkg@1.1.0", "", { "dependencies": { "package-manager-detector": "^1.3.0", "tinyexec": "^1.0.1" } }, "sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ=="],
|
||||||
|
|
||||||
@@ -26,17 +31,17 @@
|
|||||||
|
|
||||||
"@chevrotain/regexp-to-ast": ["@chevrotain/regexp-to-ast@11.0.3", "", {}, "sha512-1fMHaBZxLFvWI067AVbGJav1eRY7N8DDvYCTwGBiE/ytKBgP8azTdgyrKyWZ9Mfh09eHWb5PgTSO8wi7U824RA=="],
|
"@chevrotain/regexp-to-ast": ["@chevrotain/regexp-to-ast@11.0.3", "", {}, "sha512-1fMHaBZxLFvWI067AVbGJav1eRY7N8DDvYCTwGBiE/ytKBgP8azTdgyrKyWZ9Mfh09eHWb5PgTSO8wi7U824RA=="],
|
||||||
|
|
||||||
"@chevrotain/types": ["@chevrotain/types@11.0.3", "", {}, "sha512-gsiM3G8b58kZC2HaWR50gu6Y1440cHiJ+i3JUvcp/35JchYejb2+5MVeJK0iKThYpAa/P2PYFV4hoi44HD+aHQ=="],
|
"@chevrotain/types": ["@chevrotain/types@11.1.2", "", {}, "sha512-U+HFai5+zmJCkK86QsaJtoITlboZHBqrVketcO2ROv865xfCMSFpELQoz1GkX5GzME8pTa+3kbKrZHQtI0gdbw=="],
|
||||||
|
|
||||||
"@chevrotain/utils": ["@chevrotain/utils@11.0.3", "", {}, "sha512-YslZMgtJUyuMbZ+aKvfF3x1f5liK4mWNxghFRv7jqRR9C3R3fAOGTTKvxXDa2Y1s9zSbcpuO0cAxDYsc9SrXoQ=="],
|
"@chevrotain/utils": ["@chevrotain/utils@11.0.3", "", {}, "sha512-YslZMgtJUyuMbZ+aKvfF3x1f5liK4mWNxghFRv7jqRR9C3R3fAOGTTKvxXDa2Y1s9zSbcpuO0cAxDYsc9SrXoQ=="],
|
||||||
|
|
||||||
"@excalidraw/excalidraw": ["@excalidraw/excalidraw@0.18.0", "", { "dependencies": { "@braintree/sanitize-url": "6.0.2", "@excalidraw/laser-pointer": "1.3.1", "@excalidraw/mermaid-to-excalidraw": "1.1.2", "@excalidraw/random-username": "1.1.0", "@radix-ui/react-popover": "1.1.6", "@radix-ui/react-tabs": "1.0.2", "browser-fs-access": "0.29.1", "canvas-roundrect-polyfill": "0.0.1", "clsx": "1.1.1", "cross-env": "7.0.3", "es6-promise-pool": "2.5.0", "fractional-indexing": "3.2.0", "fuzzy": "0.1.3", "image-blob-reduce": "3.0.1", "jotai": "2.11.0", "jotai-scope": "0.7.2", "lodash.debounce": "4.0.8", "lodash.throttle": "4.1.1", "nanoid": "3.3.3", "open-color": "1.9.1", "pako": "2.0.3", "perfect-freehand": "1.2.0", "pica": "7.1.1", "png-chunk-text": "1.0.0", "png-chunks-encode": "1.0.0", "png-chunks-extract": "1.0.0", "points-on-curve": "1.0.1", "pwacompat": "2.0.17", "roughjs": "4.6.4", "sass": "1.51.0", "tunnel-rat": "0.1.2" }, "peerDependencies": { "react": "^17.0.2 || ^18.2.0 || ^19.0.0", "react-dom": "^17.0.2 || ^18.2.0 || ^19.0.0" } }, "sha512-QkIiS+5qdy8lmDWTKsuy0sK/fen/LRDtbhm2lc2xcFcqhv2/zdg95bYnl+wnwwXGHo7kEmP65BSiMHE7PJ3Zpw=="],
|
"@excalidraw/excalidraw": ["@excalidraw/excalidraw@0.18.1", "", { "dependencies": { "@braintree/sanitize-url": "6.0.2", "@excalidraw/laser-pointer": "1.3.1", "@excalidraw/mermaid-to-excalidraw": "2.2.2", "@excalidraw/random-username": "1.1.0", "@radix-ui/react-popover": "1.1.6", "@radix-ui/react-tabs": "1.0.2", "browser-fs-access": "0.29.1", "canvas-roundrect-polyfill": "0.0.1", "clsx": "1.1.1", "cross-env": "7.0.3", "es6-promise-pool": "2.5.0", "fractional-indexing": "3.2.0", "fuzzy": "0.1.3", "image-blob-reduce": "3.0.1", "jotai": "2.11.0", "jotai-scope": "0.7.2", "lodash.debounce": "4.0.8", "lodash.throttle": "4.1.1", "nanoid": "3.3.3", "open-color": "1.9.1", "pako": "2.0.3", "perfect-freehand": "1.2.0", "pica": "7.1.1", "png-chunk-text": "1.0.0", "png-chunks-encode": "1.0.0", "png-chunks-extract": "1.0.0", "points-on-curve": "1.0.1", "pwacompat": "2.0.17", "roughjs": "4.6.4", "sass": "1.51.0", "tunnel-rat": "0.1.2" }, "peerDependencies": { "react": "^17.0.2 || ^18.2.0 || ^19.0.0", "react-dom": "^17.0.2 || ^18.2.0 || ^19.0.0" } }, "sha512-6i5Gt7IDTOH//qa0Z315Ly5iVRhjWpu2whrlQFqkuwrkKUWgRsMk0P5qdE7bpyDpai7jeLeWYkyj1eVAfni1lw=="],
|
||||||
|
|
||||||
"@excalidraw/laser-pointer": ["@excalidraw/laser-pointer@1.3.1", "", {}, "sha512-psA1z1N2qeAfsORdXc9JmD2y4CmDwmuMRxnNdJHZexIcPwaNEyIpNcelw+QkL9rz9tosaN9krXuKaRqYpRAR6g=="],
|
"@excalidraw/laser-pointer": ["@excalidraw/laser-pointer@1.3.1", "", {}, "sha512-psA1z1N2qeAfsORdXc9JmD2y4CmDwmuMRxnNdJHZexIcPwaNEyIpNcelw+QkL9rz9tosaN9krXuKaRqYpRAR6g=="],
|
||||||
|
|
||||||
"@excalidraw/markdown-to-text": ["@excalidraw/markdown-to-text@0.1.2", "", {}, "sha512-1nDXBNAojfi3oSFwJswKREkFm5wrSjqay81QlyRv2pkITG/XYB5v+oChENVBQLcxQwX4IUATWvXM5BcaNhPiIg=="],
|
"@excalidraw/markdown-to-text": ["@excalidraw/markdown-to-text@0.1.2", "", {}, "sha512-1nDXBNAojfi3oSFwJswKREkFm5wrSjqay81QlyRv2pkITG/XYB5v+oChENVBQLcxQwX4IUATWvXM5BcaNhPiIg=="],
|
||||||
|
|
||||||
"@excalidraw/mermaid-to-excalidraw": ["@excalidraw/mermaid-to-excalidraw@1.1.2", "", { "dependencies": { "@excalidraw/markdown-to-text": "0.1.2", "mermaid": "10.9.3", "nanoid": "4.0.2" } }, "sha512-hAFv/TTIsOdoy0dL5v+oBd297SQ+Z88gZ5u99fCIFuEMHfQuPgLhU/ztKhFSTs7fISwVo6fizny/5oQRR3d4tQ=="],
|
"@excalidraw/mermaid-to-excalidraw": ["@excalidraw/mermaid-to-excalidraw@2.2.2", "", { "dependencies": { "@excalidraw/markdown-to-text": "0.1.2", "@mermaid-js/parser": "^0.6.3", "mermaid": "^11.12.1", "nanoid": "4.0.2" } }, "sha512-5VKQq5CdRocC82vOIUpQ5ufJOVV9FpBTdHGA+ULqazeIVV+cr299877omQCibsdS3Bpitz2fsnTwnIXEmLVDSg=="],
|
||||||
|
|
||||||
"@excalidraw/random-username": ["@excalidraw/random-username@1.1.0", "", {}, "sha512-nULYsQxkWHnbmHvcs+efMkJ4/9TtvNyFeLyHdeGxW0zHs6P+jYVqcRff9A6Vq9w9JXeDRnRh2VKvTtS19GW2qA=="],
|
"@excalidraw/random-username": ["@excalidraw/random-username@1.1.0", "", {}, "sha512-nULYsQxkWHnbmHvcs+efMkJ4/9TtvNyFeLyHdeGxW0zHs6P+jYVqcRff9A6Vq9w9JXeDRnRh2VKvTtS19GW2qA=="],
|
||||||
|
|
||||||
@@ -166,17 +171,11 @@
|
|||||||
|
|
||||||
"@types/d3-zoom": ["@types/d3-zoom@3.0.8", "", { "dependencies": { "@types/d3-interpolate": "*", "@types/d3-selection": "*" } }, "sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw=="],
|
"@types/d3-zoom": ["@types/d3-zoom@3.0.8", "", { "dependencies": { "@types/d3-interpolate": "*", "@types/d3-selection": "*" } }, "sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw=="],
|
||||||
|
|
||||||
"@types/debug": ["@types/debug@4.1.13", "", { "dependencies": { "@types/ms": "*" } }, "sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw=="],
|
|
||||||
|
|
||||||
"@types/geojson": ["@types/geojson@7946.0.16", "", {}, "sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg=="],
|
"@types/geojson": ["@types/geojson@7946.0.16", "", {}, "sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg=="],
|
||||||
|
|
||||||
"@types/mdast": ["@types/mdast@3.0.15", "", { "dependencies": { "@types/unist": "^2" } }, "sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ=="],
|
|
||||||
|
|
||||||
"@types/ms": ["@types/ms@2.1.0", "", {}, "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA=="],
|
|
||||||
|
|
||||||
"@types/trusted-types": ["@types/trusted-types@2.0.7", "", {}, "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw=="],
|
"@types/trusted-types": ["@types/trusted-types@2.0.7", "", {}, "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw=="],
|
||||||
|
|
||||||
"@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="],
|
"@upsetjs/venn.js": ["@upsetjs/venn.js@2.0.0", "", { "optionalDependencies": { "d3-selection": "^3.0.0", "d3-transition": "^3.0.1" } }, "sha512-WbBhLrooyePuQ1VZxrJjtLvTc4NVfpOyKx0sKqioq9bX1C1m7Jgykkn8gLrtwumBioXIqam8DLxp88Adbue6Hw=="],
|
||||||
|
|
||||||
"anymatch": ["anymatch@3.1.3", "", { "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" } }, "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw=="],
|
"anymatch": ["anymatch@3.1.3", "", { "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" } }, "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw=="],
|
||||||
|
|
||||||
@@ -190,8 +189,6 @@
|
|||||||
|
|
||||||
"canvas-roundrect-polyfill": ["canvas-roundrect-polyfill@0.0.1", "", {}, "sha512-yWq+R3U3jE+coOeEb3a3GgE2j/0MMiDKM/QpLb6h9ihf5fGY9UXtvK9o4vNqjWXoZz7/3EaSVU3IX53TvFFUOw=="],
|
"canvas-roundrect-polyfill": ["canvas-roundrect-polyfill@0.0.1", "", {}, "sha512-yWq+R3U3jE+coOeEb3a3GgE2j/0MMiDKM/QpLb6h9ihf5fGY9UXtvK9o4vNqjWXoZz7/3EaSVU3IX53TvFFUOw=="],
|
||||||
|
|
||||||
"character-entities": ["character-entities@2.0.2", "", {}, "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ=="],
|
|
||||||
|
|
||||||
"chevrotain": ["chevrotain@11.0.3", "", { "dependencies": { "@chevrotain/cst-dts-gen": "11.0.3", "@chevrotain/gast": "11.0.3", "@chevrotain/regexp-to-ast": "11.0.3", "@chevrotain/types": "11.0.3", "@chevrotain/utils": "11.0.3", "lodash-es": "4.17.21" } }, "sha512-ci2iJH6LeIkvP9eJW6gpueU8cnZhv85ELY8w8WiFtNjMHA5ad6pQLaJo9mEly/9qUyCpvqX8/POVUTf18/HFdw=="],
|
"chevrotain": ["chevrotain@11.0.3", "", { "dependencies": { "@chevrotain/cst-dts-gen": "11.0.3", "@chevrotain/gast": "11.0.3", "@chevrotain/regexp-to-ast": "11.0.3", "@chevrotain/types": "11.0.3", "@chevrotain/utils": "11.0.3", "lodash-es": "4.17.21" } }, "sha512-ci2iJH6LeIkvP9eJW6gpueU8cnZhv85ELY8w8WiFtNjMHA5ad6pQLaJo9mEly/9qUyCpvqX8/POVUTf18/HFdw=="],
|
||||||
|
|
||||||
"chevrotain-allstar": ["chevrotain-allstar@0.3.1", "", { "dependencies": { "lodash-es": "^4.17.21" }, "peerDependencies": { "chevrotain": "^11.0.0" } }, "sha512-b7g+y9A0v4mxCW1qUhf3BSVPg+/NvGErk/dOkrDaHA0nQIQGAtrOjlX//9OQtRlSCy+x9rfB5N8yC71lH1nvMw=="],
|
"chevrotain-allstar": ["chevrotain-allstar@0.3.1", "", { "dependencies": { "lodash-es": "^4.17.21" }, "peerDependencies": { "chevrotain": "^11.0.0" } }, "sha512-b7g+y9A0v4mxCW1qUhf3BSVPg+/NvGErk/dOkrDaHA0nQIQGAtrOjlX//9OQtRlSCy+x9rfB5N8yC71lH1nvMw=="],
|
||||||
@@ -280,25 +277,17 @@
|
|||||||
|
|
||||||
"d3-zoom": ["d3-zoom@3.0.0", "", { "dependencies": { "d3-dispatch": "1 - 3", "d3-drag": "2 - 3", "d3-interpolate": "1 - 3", "d3-selection": "2 - 3", "d3-transition": "2 - 3" } }, "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw=="],
|
"d3-zoom": ["d3-zoom@3.0.0", "", { "dependencies": { "d3-dispatch": "1 - 3", "d3-drag": "2 - 3", "d3-interpolate": "1 - 3", "d3-selection": "2 - 3", "d3-transition": "2 - 3" } }, "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw=="],
|
||||||
|
|
||||||
"dagre-d3-es": ["dagre-d3-es@7.0.13", "", { "dependencies": { "d3": "^7.9.0", "lodash-es": "^4.17.21" } }, "sha512-efEhnxpSuwpYOKRm/L5KbqoZmNNukHa/Flty4Wp62JRvgH2ojwVgPgdYyr4twpieZnyRDdIH7PY2mopX26+j2Q=="],
|
"dagre-d3-es": ["dagre-d3-es@7.0.14", "", { "dependencies": { "d3": "^7.9.0", "lodash-es": "^4.17.21" } }, "sha512-P4rFMVq9ESWqmOgK+dlXvOtLwYg0i7u0HBGJER0LZDJT2VHIPAMZ/riPxqJceWMStH5+E61QxFra9kIS3AqdMg=="],
|
||||||
|
|
||||||
"dayjs": ["dayjs@1.11.21", "", {}, "sha512-98IT+HOahAisibz/yjKbzuOBwYcjJ7BCLPzARyHiyEBmRz4fatF+KPJszEHXsGYjUG234aH/cOjW1wwTbKUZlA=="],
|
"dayjs": ["dayjs@1.11.21", "", {}, "sha512-98IT+HOahAisibz/yjKbzuOBwYcjJ7BCLPzARyHiyEBmRz4fatF+KPJszEHXsGYjUG234aH/cOjW1wwTbKUZlA=="],
|
||||||
|
|
||||||
"debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
|
|
||||||
|
|
||||||
"decode-named-character-reference": ["decode-named-character-reference@1.3.0", "", { "dependencies": { "character-entities": "^2.0.0" } }, "sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q=="],
|
|
||||||
|
|
||||||
"delaunator": ["delaunator@5.1.0", "", { "dependencies": { "robust-predicates": "^3.0.2" } }, "sha512-AGrQ4QSgssa1NGmWmLPqN5NY2KajF5MqxetNEO+o0n3ZwZZeTmt7bBnvzHWrmkZFxGgr4HdyFgelzgi06otLuQ=="],
|
"delaunator": ["delaunator@5.1.0", "", { "dependencies": { "robust-predicates": "^3.0.2" } }, "sha512-AGrQ4QSgssa1NGmWmLPqN5NY2KajF5MqxetNEO+o0n3ZwZZeTmt7bBnvzHWrmkZFxGgr4HdyFgelzgi06otLuQ=="],
|
||||||
|
|
||||||
"dequal": ["dequal@2.0.3", "", {}, "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA=="],
|
|
||||||
|
|
||||||
"detect-node-es": ["detect-node-es@1.1.0", "", {}, "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ=="],
|
"detect-node-es": ["detect-node-es@1.1.0", "", {}, "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ=="],
|
||||||
|
|
||||||
"diff": ["diff@5.2.2", "", {}, "sha512-vtcDfH3TOjP8UekytvnHH1o1P4FcUdt4eQ1Y+Abap1tk/OB2MWQvcwS2ClCd1zuIhc3JKOx6p3kod8Vfys3E+A=="],
|
"dompurify": ["dompurify@3.4.11", "", { "optionalDependencies": { "@types/trusted-types": "^2.0.7" } }, "sha512-zhlUV12GsaRzMsf9q5M254YhA4+VuF0fG+QFqu6aYpoGlKtz+w8//jBcGVYBgQkR5GHjUomejY84AV+/uPbWdw=="],
|
||||||
|
|
||||||
"dompurify": ["dompurify@3.4.9", "", { "optionalDependencies": { "@types/trusted-types": "^2.0.7" } }, "sha512-4dPSRMRDqHvs0V4YDFCsaIZo4if5u0xM+llyxiM2fwuZFdKArUBAF3VtI2+n8NKg9P870WMdYk0UhqQNoWXbfQ=="],
|
"es-toolkit": ["es-toolkit@1.49.0", "", {}, "sha512-G5iZ6Pc/FNRY/soKZHC+TxGDD83rHUDXxzaWhGCX44vAv/tMs56WMusnm/KMNK+luUPsgA9U28cGr4RDlSzL2g=="],
|
||||||
|
|
||||||
"elkjs": ["elkjs@0.9.3", "", {}, "sha512-f/ZeWvW/BCXbhGEf1Ujp29EASo/lk1FDnETgNKwJrsVvGZhUWCZyg3xLJjAsxfOmt8KjswHmI5EwCQcPMpOYhQ=="],
|
|
||||||
|
|
||||||
"es6-promise-pool": ["es6-promise-pool@2.5.0", "", {}, "sha512-VHErXfzR/6r/+yyzPKeBvO0lgjfC5cbDCQWjWwMZWSb6YU39TGIl51OUmCfWCq4ylMdJSB8zkz2vIuIeIxXApA=="],
|
"es6-promise-pool": ["es6-promise-pool@2.5.0", "", {}, "sha512-VHErXfzR/6r/+yyzPKeBvO0lgjfC5cbDCQWjWwMZWSb6YU39TGIl51OUmCfWCq4ylMdJSB8zkz2vIuIeIxXApA=="],
|
||||||
|
|
||||||
@@ -350,8 +339,6 @@
|
|||||||
|
|
||||||
"khroma": ["khroma@2.1.0", "", {}, "sha512-Ls993zuzfayK269Svk9hzpeGUKob/sIgZzyHYdjQoAdQetRKpOLj+k/QQQ/6Qi0Yz65mlROrfd+Ev+1+7dz9Kw=="],
|
"khroma": ["khroma@2.1.0", "", {}, "sha512-Ls993zuzfayK269Svk9hzpeGUKob/sIgZzyHYdjQoAdQetRKpOLj+k/QQQ/6Qi0Yz65mlROrfd+Ev+1+7dz9Kw=="],
|
||||||
|
|
||||||
"kleur": ["kleur@4.1.5", "", {}, "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ=="],
|
|
||||||
|
|
||||||
"langium": ["langium@3.3.1", "", { "dependencies": { "chevrotain": "~11.0.3", "chevrotain-allstar": "~0.3.0", "vscode-languageserver": "~9.0.1", "vscode-languageserver-textdocument": "~1.0.11", "vscode-uri": "~3.0.8" } }, "sha512-QJv/h939gDpvT+9SiLVlY7tZC3xB2qK57v0J04Sh9wpMb6MP1q8gB21L3WIo8T5P1MSMg3Ep14L7KkDCFG3y4w=="],
|
"langium": ["langium@3.3.1", "", { "dependencies": { "chevrotain": "~11.0.3", "chevrotain-allstar": "~0.3.0", "vscode-languageserver": "~9.0.1", "vscode-languageserver-textdocument": "~1.0.11", "vscode-uri": "~3.0.8" } }, "sha512-QJv/h939gDpvT+9SiLVlY7tZC3xB2qK57v0J04Sh9wpMb6MP1q8gB21L3WIo8T5P1MSMg3Ep14L7KkDCFG3y4w=="],
|
||||||
|
|
||||||
"layout-base": ["layout-base@1.0.2", "", {}, "sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg=="],
|
"layout-base": ["layout-base@1.0.2", "", {}, "sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg=="],
|
||||||
@@ -366,63 +353,11 @@
|
|||||||
|
|
||||||
"marked": ["marked@16.4.2", "", { "bin": { "marked": "bin/marked.js" } }, "sha512-TI3V8YYWvkVf3KJe1dRkpnjs68JUPyEa5vjKrp1XEEJUAOaQc+Qj+L1qWbPd0SJuAdQkFU0h73sXXqwDYxsiDA=="],
|
"marked": ["marked@16.4.2", "", { "bin": { "marked": "bin/marked.js" } }, "sha512-TI3V8YYWvkVf3KJe1dRkpnjs68JUPyEa5vjKrp1XEEJUAOaQc+Qj+L1qWbPd0SJuAdQkFU0h73sXXqwDYxsiDA=="],
|
||||||
|
|
||||||
"mdast-util-from-markdown": ["mdast-util-from-markdown@1.3.1", "", { "dependencies": { "@types/mdast": "^3.0.0", "@types/unist": "^2.0.0", "decode-named-character-reference": "^1.0.0", "mdast-util-to-string": "^3.1.0", "micromark": "^3.0.0", "micromark-util-decode-numeric-character-reference": "^1.0.0", "micromark-util-decode-string": "^1.0.0", "micromark-util-normalize-identifier": "^1.0.0", "micromark-util-symbol": "^1.0.0", "micromark-util-types": "^1.0.0", "unist-util-stringify-position": "^3.0.0", "uvu": "^0.5.0" } }, "sha512-4xTO/M8c82qBcnQc1tgpNtubGUW/Y1tBQ1B0i5CtSoelOLKFYlElIr3bvgREYYO5iRqbMY1YuqZng0GVOI8Qww=="],
|
"mermaid": ["mermaid@11.16.0", "", { "dependencies": { "@braintree/sanitize-url": "^7.1.2", "@iconify/utils": "^3.0.2", "@mermaid-js/parser": "^1.2.0", "@types/d3": "^7.4.3", "@upsetjs/venn.js": "^2.0.0", "cytoscape": "^3.33.3", "cytoscape-cose-bilkent": "^4.1.0", "cytoscape-fcose": "^2.2.0", "d3": "^7.9.0", "d3-sankey": "^0.12.3", "dagre-d3-es": "7.0.14", "dayjs": "^1.11.20", "dompurify": "^3.3.3", "es-toolkit": "^1.45.1", "katex": "^0.16.45", "khroma": "^2.1.0", "marked": "^16.3.0", "roughjs": "^4.6.6", "stylis": "^4.3.6", "ts-dedent": "^2.2.0", "uuid": "^11.1.0 || ^12 || ^13 || ^14.0.0" } }, "sha512-Zvm3kbstgdpvIJPPItlL7fppIZ3kibvc1oZIGxdvk9t6UFz6flv+Jw7FtRGKwfcI8OckmH04LqG6LlS6X4B1pA=="],
|
||||||
|
|
||||||
"mdast-util-to-string": ["mdast-util-to-string@3.2.0", "", { "dependencies": { "@types/mdast": "^3.0.0" } }, "sha512-V4Zn/ncyN1QNSqSBxTrMOLpjr+IKdHl2v3KVLoWmDPscP4r9GcCi71gjgvUV1SFSKh92AjAG4peFuBl2/YgCJg=="],
|
|
||||||
|
|
||||||
"mermaid": ["mermaid@11.12.2", "", { "dependencies": { "@braintree/sanitize-url": "^7.1.1", "@iconify/utils": "^3.0.1", "@mermaid-js/parser": "^0.6.3", "@types/d3": "^7.4.3", "cytoscape": "^3.29.3", "cytoscape-cose-bilkent": "^4.1.0", "cytoscape-fcose": "^2.2.0", "d3": "^7.9.0", "d3-sankey": "^0.12.3", "dagre-d3-es": "7.0.13", "dayjs": "^1.11.18", "dompurify": "^3.2.5", "katex": "^0.16.22", "khroma": "^2.1.0", "lodash-es": "^4.17.21", "marked": "^16.2.1", "roughjs": "^4.6.6", "stylis": "^4.3.6", "ts-dedent": "^2.2.0", "uuid": "^11.1.0" } }, "sha512-n34QPDPEKmaeCG4WDMGy0OT6PSyxKCfy2pJgShP+Qow2KLrvWjclwbc3yXfSIf4BanqWEhQEpngWwNp/XhZt6w=="],
|
|
||||||
|
|
||||||
"micromark": ["micromark@3.2.0", "", { "dependencies": { "@types/debug": "^4.0.0", "debug": "^4.0.0", "decode-named-character-reference": "^1.0.0", "micromark-core-commonmark": "^1.0.1", "micromark-factory-space": "^1.0.0", "micromark-util-character": "^1.0.0", "micromark-util-chunked": "^1.0.0", "micromark-util-combine-extensions": "^1.0.0", "micromark-util-decode-numeric-character-reference": "^1.0.0", "micromark-util-encode": "^1.0.0", "micromark-util-normalize-identifier": "^1.0.0", "micromark-util-resolve-all": "^1.0.0", "micromark-util-sanitize-uri": "^1.0.0", "micromark-util-subtokenize": "^1.0.0", "micromark-util-symbol": "^1.0.0", "micromark-util-types": "^1.0.1", "uvu": "^0.5.0" } }, "sha512-uD66tJj54JLYq0De10AhWycZWGQNUvDI55xPgk2sQM5kn1JYlhbCMTtEeT27+vAhW2FBQxLlOmS3pmA7/2z4aA=="],
|
|
||||||
|
|
||||||
"micromark-core-commonmark": ["micromark-core-commonmark@1.1.0", "", { "dependencies": { "decode-named-character-reference": "^1.0.0", "micromark-factory-destination": "^1.0.0", "micromark-factory-label": "^1.0.0", "micromark-factory-space": "^1.0.0", "micromark-factory-title": "^1.0.0", "micromark-factory-whitespace": "^1.0.0", "micromark-util-character": "^1.0.0", "micromark-util-chunked": "^1.0.0", "micromark-util-classify-character": "^1.0.0", "micromark-util-html-tag-name": "^1.0.0", "micromark-util-normalize-identifier": "^1.0.0", "micromark-util-resolve-all": "^1.0.0", "micromark-util-subtokenize": "^1.0.0", "micromark-util-symbol": "^1.0.0", "micromark-util-types": "^1.0.1", "uvu": "^0.5.0" } }, "sha512-BgHO1aRbolh2hcrzL2d1La37V0Aoz73ymF8rAcKnohLy93titmv62E0gP8Hrx9PKcKrqCZ1BbLGbP3bEhoXYlw=="],
|
|
||||||
|
|
||||||
"micromark-factory-destination": ["micromark-factory-destination@1.1.0", "", { "dependencies": { "micromark-util-character": "^1.0.0", "micromark-util-symbol": "^1.0.0", "micromark-util-types": "^1.0.0" } }, "sha512-XaNDROBgx9SgSChd69pjiGKbV+nfHGDPVYFs5dOoDd7ZnMAE+Cuu91BCpsY8RT2NP9vo/B8pds2VQNCLiu0zhg=="],
|
|
||||||
|
|
||||||
"micromark-factory-label": ["micromark-factory-label@1.1.0", "", { "dependencies": { "micromark-util-character": "^1.0.0", "micromark-util-symbol": "^1.0.0", "micromark-util-types": "^1.0.0", "uvu": "^0.5.0" } }, "sha512-OLtyez4vZo/1NjxGhcpDSbHQ+m0IIGnT8BoPamh+7jVlzLJBH98zzuCoUeMxvM6WsNeh8wx8cKvqLiPHEACn0w=="],
|
|
||||||
|
|
||||||
"micromark-factory-space": ["micromark-factory-space@1.1.0", "", { "dependencies": { "micromark-util-character": "^1.0.0", "micromark-util-types": "^1.0.0" } }, "sha512-cRzEj7c0OL4Mw2v6nwzttyOZe8XY/Z8G0rzmWQZTBi/jjwyw/U4uqKtUORXQrR5bAZZnbTI/feRV/R7hc4jQYQ=="],
|
|
||||||
|
|
||||||
"micromark-factory-title": ["micromark-factory-title@1.1.0", "", { "dependencies": { "micromark-factory-space": "^1.0.0", "micromark-util-character": "^1.0.0", "micromark-util-symbol": "^1.0.0", "micromark-util-types": "^1.0.0" } }, "sha512-J7n9R3vMmgjDOCY8NPw55jiyaQnH5kBdV2/UXCtZIpnHH3P6nHUKaH7XXEYuWwx/xUJcawa8plLBEjMPU24HzQ=="],
|
|
||||||
|
|
||||||
"micromark-factory-whitespace": ["micromark-factory-whitespace@1.1.0", "", { "dependencies": { "micromark-factory-space": "^1.0.0", "micromark-util-character": "^1.0.0", "micromark-util-symbol": "^1.0.0", "micromark-util-types": "^1.0.0" } }, "sha512-v2WlmiymVSp5oMg+1Q0N1Lxmt6pMhIHD457whWM7/GUlEks1hI9xj5w3zbc4uuMKXGisksZk8DzP2UyGbGqNsQ=="],
|
|
||||||
|
|
||||||
"micromark-util-character": ["micromark-util-character@1.2.0", "", { "dependencies": { "micromark-util-symbol": "^1.0.0", "micromark-util-types": "^1.0.0" } }, "sha512-lXraTwcX3yH/vMDaFWCQJP1uIszLVebzUa3ZHdrgxr7KEU/9mL4mVgCpGbyhvNLNlauROiNUq7WN5u7ndbY6xg=="],
|
|
||||||
|
|
||||||
"micromark-util-chunked": ["micromark-util-chunked@1.1.0", "", { "dependencies": { "micromark-util-symbol": "^1.0.0" } }, "sha512-Ye01HXpkZPNcV6FiyoW2fGZDUw4Yc7vT0E9Sad83+bEDiCJ1uXu0S3mr8WLpsz3HaG3x2q0HM6CTuPdcZcluFQ=="],
|
|
||||||
|
|
||||||
"micromark-util-classify-character": ["micromark-util-classify-character@1.1.0", "", { "dependencies": { "micromark-util-character": "^1.0.0", "micromark-util-symbol": "^1.0.0", "micromark-util-types": "^1.0.0" } }, "sha512-SL0wLxtKSnklKSUplok1WQFoGhUdWYKggKUiqhX+Swala+BtptGCu5iPRc+xvzJ4PXE/hwM3FNXsfEVgoZsWbw=="],
|
|
||||||
|
|
||||||
"micromark-util-combine-extensions": ["micromark-util-combine-extensions@1.1.0", "", { "dependencies": { "micromark-util-chunked": "^1.0.0", "micromark-util-types": "^1.0.0" } }, "sha512-Q20sp4mfNf9yEqDL50WwuWZHUrCO4fEyeDCnMGmG5Pr0Cz15Uo7KBs6jq+dq0EgX4DPwwrh9m0X+zPV1ypFvUA=="],
|
|
||||||
|
|
||||||
"micromark-util-decode-numeric-character-reference": ["micromark-util-decode-numeric-character-reference@1.1.0", "", { "dependencies": { "micromark-util-symbol": "^1.0.0" } }, "sha512-m9V0ExGv0jB1OT21mrWcuf4QhP46pH1KkfWy9ZEezqHKAxkj4mPCy3nIH1rkbdMlChLHX531eOrymlwyZIf2iw=="],
|
|
||||||
|
|
||||||
"micromark-util-decode-string": ["micromark-util-decode-string@1.1.0", "", { "dependencies": { "decode-named-character-reference": "^1.0.0", "micromark-util-character": "^1.0.0", "micromark-util-decode-numeric-character-reference": "^1.0.0", "micromark-util-symbol": "^1.0.0" } }, "sha512-YphLGCK8gM1tG1bd54azwyrQRjCFcmgj2S2GoJDNnh4vYtnL38JS8M4gpxzOPNyHdNEpheyWXCTnnTDY3N+NVQ=="],
|
|
||||||
|
|
||||||
"micromark-util-encode": ["micromark-util-encode@1.1.0", "", {}, "sha512-EuEzTWSTAj9PA5GOAs992GzNh2dGQO52UvAbtSOMvXTxv3Criqb6IOzJUBCmEqrrXSblJIJBbFFv6zPxpreiJw=="],
|
|
||||||
|
|
||||||
"micromark-util-html-tag-name": ["micromark-util-html-tag-name@1.2.0", "", {}, "sha512-VTQzcuQgFUD7yYztuQFKXT49KghjtETQ+Wv/zUjGSGBioZnkA4P1XXZPT1FHeJA6RwRXSF47yvJ1tsJdoxwO+Q=="],
|
|
||||||
|
|
||||||
"micromark-util-normalize-identifier": ["micromark-util-normalize-identifier@1.1.0", "", { "dependencies": { "micromark-util-symbol": "^1.0.0" } }, "sha512-N+w5vhqrBihhjdpM8+5Xsxy71QWqGn7HYNUvch71iV2PM7+E3uWGox1Qp90loa1ephtCxG2ftRV/Conitc6P2Q=="],
|
|
||||||
|
|
||||||
"micromark-util-resolve-all": ["micromark-util-resolve-all@1.1.0", "", { "dependencies": { "micromark-util-types": "^1.0.0" } }, "sha512-b/G6BTMSg+bX+xVCshPTPyAu2tmA0E4X98NSR7eIbeC6ycCqCeE7wjfDIgzEbkzdEVJXRtOG4FbEm/uGbCRouA=="],
|
|
||||||
|
|
||||||
"micromark-util-sanitize-uri": ["micromark-util-sanitize-uri@1.2.0", "", { "dependencies": { "micromark-util-character": "^1.0.0", "micromark-util-encode": "^1.0.0", "micromark-util-symbol": "^1.0.0" } }, "sha512-QO4GXv0XZfWey4pYFndLUKEAktKkG5kZTdUNaTAkzbuJxn2tNBOr+QtxR2XpWaMhbImT2dPzyLrPXLlPhph34A=="],
|
|
||||||
|
|
||||||
"micromark-util-subtokenize": ["micromark-util-subtokenize@1.1.0", "", { "dependencies": { "micromark-util-chunked": "^1.0.0", "micromark-util-symbol": "^1.0.0", "micromark-util-types": "^1.0.0", "uvu": "^0.5.0" } }, "sha512-kUQHyzRoxvZO2PuLzMt2P/dwVsTiivCK8icYTeR+3WgbuPqfHgPPy7nFKbeqRivBvn/3N3GBiNC+JRTMSxEC7A=="],
|
|
||||||
|
|
||||||
"micromark-util-symbol": ["micromark-util-symbol@1.1.0", "", {}, "sha512-uEjpEYY6KMs1g7QfJ2eX1SQEV+ZT4rUD3UcF6l57acZvLNK7PBZL+ty82Z1qhK1/yXIY4bdx04FKMgR0g4IAag=="],
|
|
||||||
|
|
||||||
"micromark-util-types": ["micromark-util-types@1.1.0", "", {}, "sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg=="],
|
|
||||||
|
|
||||||
"mri": ["mri@1.2.0", "", {}, "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA=="],
|
|
||||||
|
|
||||||
"ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
|
|
||||||
|
|
||||||
"multimath": ["multimath@2.0.0", "", { "dependencies": { "glur": "^1.1.2", "object-assign": "^4.1.1" } }, "sha512-toRx66cAMJ+Ccz7pMIg38xSIrtnbozk0dchXezwQDMgQmbGpfxjtv68H+L00iFL8hxDaVjrmwAFSb3I6bg8Q2g=="],
|
"multimath": ["multimath@2.0.0", "", { "dependencies": { "glur": "^1.1.2", "object-assign": "^4.1.1" } }, "sha512-toRx66cAMJ+Ccz7pMIg38xSIrtnbozk0dchXezwQDMgQmbGpfxjtv68H+L00iFL8hxDaVjrmwAFSb3I6bg8Q2g=="],
|
||||||
|
|
||||||
"nanoid": ["nanoid@3.3.3", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w=="],
|
"nanoid": ["nanoid@5.0.9", "", { "bin": { "nanoid": "bin/nanoid.js" } }, "sha512-Aooyr6MXU6HpvvWXKoVoXwKMs/KyVakWwg7xQfv5/S/RIgJMy0Ifa45H9qqYy7pTCszrHzP21Uk4PZq2HpEM8Q=="],
|
||||||
|
|
||||||
"non-layered-tidy-tree-layout": ["non-layered-tidy-tree-layout@2.0.2", "", {}, "sha512-gkXMxRzUH+PB0ax9dUN0yYF0S25BqeAYqhgMaLUFmpXLEk7Fcu8f4emJuOAY0V8kjDICxROIKsTAKsV/v355xw=="],
|
|
||||||
|
|
||||||
"normalize-path": ["normalize-path@3.0.0", "", {}, "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="],
|
"normalize-path": ["normalize-path@3.0.0", "", {}, "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="],
|
||||||
|
|
||||||
@@ -474,8 +409,6 @@
|
|||||||
|
|
||||||
"rw": ["rw@1.3.3", "", {}, "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ=="],
|
"rw": ["rw@1.3.3", "", {}, "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ=="],
|
||||||
|
|
||||||
"sade": ["sade@1.8.1", "", { "dependencies": { "mri": "^1.1.0" } }, "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A=="],
|
|
||||||
|
|
||||||
"safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="],
|
"safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="],
|
||||||
|
|
||||||
"sass": ["sass@1.51.0", "", { "dependencies": { "chokidar": ">=3.0.0 <4.0.0", "immutable": "^4.0.0", "source-map-js": ">=0.6.2 <2.0.0" }, "bin": { "sass": "sass.js" } }, "sha512-haGdpTgywJTvHC2b91GSq+clTKGbtkkZmVAb82jZQN/wTy6qs8DdFm2lhEQbEwrY0QDRgSQ3xDurqM977C3noA=="],
|
"sass": ["sass@1.51.0", "", { "dependencies": { "chokidar": ">=3.0.0 <4.0.0", "immutable": "^4.0.0", "source-map-js": ">=0.6.2 <2.0.0" }, "bin": { "sass": "sass.js" } }, "sha512-haGdpTgywJTvHC2b91GSq+clTKGbtkkZmVAb82jZQN/wTy6qs8DdFm2lhEQbEwrY0QDRgSQ3xDurqM977C3noA=="],
|
||||||
@@ -502,8 +435,6 @@
|
|||||||
|
|
||||||
"tunnel-rat": ["tunnel-rat@0.1.2", "", { "dependencies": { "zustand": "^4.3.2" } }, "sha512-lR5VHmkPhzdhrM092lI2nACsLO4QubF0/yoOhzX7c+wIpbN1GjHNzCc91QlpxBi+cnx8vVJ+Ur6vL5cEoQPFpQ=="],
|
"tunnel-rat": ["tunnel-rat@0.1.2", "", { "dependencies": { "zustand": "^4.3.2" } }, "sha512-lR5VHmkPhzdhrM092lI2nACsLO4QubF0/yoOhzX7c+wIpbN1GjHNzCc91QlpxBi+cnx8vVJ+Ur6vL5cEoQPFpQ=="],
|
||||||
|
|
||||||
"unist-util-stringify-position": ["unist-util-stringify-position@3.0.3", "", { "dependencies": { "@types/unist": "^2.0.0" } }, "sha512-k5GzIBZ/QatR8N5X2y+drfpWG8IDBzdnVj6OInRNWm1oXrzydiaAT2OQiA8DPRRZyAKb9b6I2a6PxYklZD0gKg=="],
|
|
||||||
|
|
||||||
"use-callback-ref": ["use-callback-ref@1.3.3", "", { "dependencies": { "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg=="],
|
"use-callback-ref": ["use-callback-ref@1.3.3", "", { "dependencies": { "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg=="],
|
||||||
|
|
||||||
"use-sidecar": ["use-sidecar@1.1.3", "", { "dependencies": { "detect-node-es": "^1.1.0", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ=="],
|
"use-sidecar": ["use-sidecar@1.1.3", "", { "dependencies": { "detect-node-es": "^1.1.0", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ=="],
|
||||||
@@ -512,8 +443,6 @@
|
|||||||
|
|
||||||
"uuid": ["uuid@11.1.1", "", { "bin": { "uuid": "dist/esm/bin/uuid" } }, "sha512-vIYxrBCC/N/K+Js3qSN88go7kIfNPssr/hHCesKCQNAjmgvYS2oqr69kIufEG+O4+PfezOH4EbIeHCfFov8ZgQ=="],
|
"uuid": ["uuid@11.1.1", "", { "bin": { "uuid": "dist/esm/bin/uuid" } }, "sha512-vIYxrBCC/N/K+Js3qSN88go7kIfNPssr/hHCesKCQNAjmgvYS2oqr69kIufEG+O4+PfezOH4EbIeHCfFov8ZgQ=="],
|
||||||
|
|
||||||
"uvu": ["uvu@0.5.6", "", { "dependencies": { "dequal": "^2.0.0", "diff": "^5.0.0", "kleur": "^4.0.3", "sade": "^1.7.3" }, "bin": { "uvu": "bin.js" } }, "sha512-+g8ENReyr8YsOc6fv/NVJs2vFdHBnBNdfE49rshrTzDWOlUx4Gq7KOS2GD8eqhy2j+Ejq29+SbKH8yjkAqXqoA=="],
|
|
||||||
|
|
||||||
"vscode-jsonrpc": ["vscode-jsonrpc@8.2.0", "", {}, "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA=="],
|
"vscode-jsonrpc": ["vscode-jsonrpc@8.2.0", "", {}, "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA=="],
|
||||||
|
|
||||||
"vscode-languageserver": ["vscode-languageserver@9.0.1", "", { "dependencies": { "vscode-languageserver-protocol": "3.17.5" }, "bin": { "installServerIntoExtension": "bin/installServerIntoExtension" } }, "sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g=="],
|
"vscode-languageserver": ["vscode-languageserver@9.0.1", "", { "dependencies": { "vscode-languageserver-protocol": "3.17.5" }, "bin": { "installServerIntoExtension": "bin/installServerIntoExtension" } }, "sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g=="],
|
||||||
@@ -526,21 +455,15 @@
|
|||||||
|
|
||||||
"vscode-uri": ["vscode-uri@3.0.8", "", {}, "sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw=="],
|
"vscode-uri": ["vscode-uri@3.0.8", "", {}, "sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw=="],
|
||||||
|
|
||||||
"web-worker": ["web-worker@1.5.0", "", {}, "sha512-RiMReJrTAiA+mBjGONMnjVDP2u3p9R1vkcGz6gDIrOMT3oGuYwX2WRMYI9ipkphSuE5XKEhydbhNEJh4NY9mlw=="],
|
|
||||||
|
|
||||||
"webworkify": ["webworkify@1.5.0", "", {}, "sha512-AMcUeyXAhbACL8S2hqqdqOLqvJ8ylmIbNwUIqQujRSouf4+eUFaXbG6F1Rbu+srlJMmxQWsiU7mOJi0nMBfM1g=="],
|
"webworkify": ["webworkify@1.5.0", "", {}, "sha512-AMcUeyXAhbACL8S2hqqdqOLqvJ8ylmIbNwUIqQujRSouf4+eUFaXbG6F1Rbu+srlJMmxQWsiU7mOJi0nMBfM1g=="],
|
||||||
|
|
||||||
"which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="],
|
"which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="],
|
||||||
|
|
||||||
"zustand": ["zustand@4.5.7", "", { "dependencies": { "use-sync-external-store": "^1.2.2" }, "peerDependencies": { "@types/react": ">=16.8", "immer": ">=9.0.6", "react": ">=16.8" }, "optionalPeers": ["@types/react", "immer", "react"] }, "sha512-CHOUy7mu3lbD6o6LJLfllpjkzhHXSBlX8B9+qPddUsIfeF5S/UZ5q0kmCsnRqT1UHFQZchNFDDzMbQsuesHWlw=="],
|
"zustand": ["zustand@4.5.7", "", { "dependencies": { "use-sync-external-store": "^1.2.2" }, "peerDependencies": { "@types/react": ">=16.8", "immer": ">=9.0.6", "react": ">=16.8" }, "optionalPeers": ["@types/react", "immer", "react"] }, "sha512-CHOUy7mu3lbD6o6LJLfllpjkzhHXSBlX8B9+qPddUsIfeF5S/UZ5q0kmCsnRqT1UHFQZchNFDDzMbQsuesHWlw=="],
|
||||||
|
|
||||||
"@chevrotain/cst-dts-gen/lodash-es": ["lodash-es@4.17.21", "", {}, "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="],
|
"@chevrotain/cst-dts-gen/@chevrotain/types": ["@chevrotain/types@11.0.3", "", {}, "sha512-gsiM3G8b58kZC2HaWR50gu6Y1440cHiJ+i3JUvcp/35JchYejb2+5MVeJK0iKThYpAa/P2PYFV4hoi44HD+aHQ=="],
|
||||||
|
|
||||||
"@chevrotain/gast/lodash-es": ["lodash-es@4.17.21", "", {}, "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="],
|
"@chevrotain/gast/@chevrotain/types": ["@chevrotain/types@11.0.3", "", {}, "sha512-gsiM3G8b58kZC2HaWR50gu6Y1440cHiJ+i3JUvcp/35JchYejb2+5MVeJK0iKThYpAa/P2PYFV4hoi44HD+aHQ=="],
|
||||||
|
|
||||||
"@excalidraw/mermaid-to-excalidraw/mermaid": ["mermaid@10.9.3", "", { "dependencies": { "@braintree/sanitize-url": "^6.0.1", "@types/d3-scale": "^4.0.3", "@types/d3-scale-chromatic": "^3.0.0", "cytoscape": "^3.28.1", "cytoscape-cose-bilkent": "^4.1.0", "d3": "^7.4.0", "d3-sankey": "^0.12.3", "dagre-d3-es": "7.0.10", "dayjs": "^1.11.7", "dompurify": "^3.0.5 <3.1.7", "elkjs": "^0.9.0", "katex": "^0.16.9", "khroma": "^2.0.0", "lodash-es": "^4.17.21", "mdast-util-from-markdown": "^1.3.0", "non-layered-tidy-tree-layout": "^2.0.2", "stylis": "^4.1.3", "ts-dedent": "^2.2.0", "uuid": "^9.0.0", "web-worker": "^1.2.0" } }, "sha512-V80X1isSEvAewIL3xhmz/rVmc27CVljcsbWxkxlWJWY/1kQa4XOABqpDl2qQLGKzpKm6WbTfUEKImBlUfFYArw=="],
|
|
||||||
|
|
||||||
"@excalidraw/mermaid-to-excalidraw/nanoid": ["nanoid@4.0.2", "", { "bin": { "nanoid": "bin/nanoid.js" } }, "sha512-7ZtY5KTCNheRGfEFxnedV5zFiORN1+Y1N6zvPTnHQd8ENUvfaDBeuJDZb2bN/oXwXxu3qkTXDzy57W5vAmDTBw=="],
|
|
||||||
|
|
||||||
"@radix-ui/react-collection/@radix-ui/react-compose-refs": ["@radix-ui/react-compose-refs@1.0.0", "", { "dependencies": { "@babel/runtime": "^7.13.10" }, "peerDependencies": { "react": "^16.8 || ^17.0 || ^18.0" } }, "sha512-0KaSv6sx787/hK3eF53iOkiSLwAGlFMx5lotrqD2pTjB18KbybKoEIgkNZTKC60YECDQTKGTRcDBILwZVqVKvA=="],
|
"@radix-ui/react-collection/@radix-ui/react-compose-refs": ["@radix-ui/react-compose-refs@1.0.0", "", { "dependencies": { "@babel/runtime": "^7.13.10" }, "peerDependencies": { "react": "^16.8 || ^17.0 || ^18.0" } }, "sha512-0KaSv6sx787/hK3eF53iOkiSLwAGlFMx5lotrqD2pTjB18KbybKoEIgkNZTKC60YECDQTKGTRcDBILwZVqVKvA=="],
|
||||||
|
|
||||||
@@ -576,7 +499,7 @@
|
|||||||
|
|
||||||
"@radix-ui/react-tabs/@radix-ui/react-use-controllable-state": ["@radix-ui/react-use-controllable-state@1.0.0", "", { "dependencies": { "@babel/runtime": "^7.13.10", "@radix-ui/react-use-callback-ref": "1.0.0" }, "peerDependencies": { "react": "^16.8 || ^17.0 || ^18.0" } }, "sha512-FohDoZvk3mEXh9AWAVyRTYR4Sq7/gavuofglmiXB2g1aKyboUD4YtgWxKj8O5n+Uak52gXQ4wKz5IFST4vtJHg=="],
|
"@radix-ui/react-tabs/@radix-ui/react-use-controllable-state": ["@radix-ui/react-use-controllable-state@1.0.0", "", { "dependencies": { "@babel/runtime": "^7.13.10", "@radix-ui/react-use-callback-ref": "1.0.0" }, "peerDependencies": { "react": "^16.8 || ^17.0 || ^18.0" } }, "sha512-FohDoZvk3mEXh9AWAVyRTYR4Sq7/gavuofglmiXB2g1aKyboUD4YtgWxKj8O5n+Uak52gXQ4wKz5IFST4vtJHg=="],
|
||||||
|
|
||||||
"chevrotain/lodash-es": ["lodash-es@4.17.21", "", {}, "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="],
|
"chevrotain/@chevrotain/types": ["@chevrotain/types@11.0.3", "", {}, "sha512-gsiM3G8b58kZC2HaWR50gu6Y1440cHiJ+i3JUvcp/35JchYejb2+5MVeJK0iKThYpAa/P2PYFV4hoi44HD+aHQ=="],
|
||||||
|
|
||||||
"cytoscape-fcose/cose-base": ["cose-base@2.2.0", "", { "dependencies": { "layout-base": "^2.0.0" } }, "sha512-AzlgcsCbUMymkADOJtQm3wO9S3ltPfYOFD5033keQn9NJzIbtnZj+UdBJe7DYml/8TdbtHJW3j58SOnKhWY/5g=="],
|
"cytoscape-fcose/cose-base": ["cose-base@2.2.0", "", { "dependencies": { "layout-base": "^2.0.0" } }, "sha512-AzlgcsCbUMymkADOJtQm3wO9S3ltPfYOFD5033keQn9NJzIbtnZj+UdBJe7DYml/8TdbtHJW3j58SOnKhWY/5g=="],
|
||||||
|
|
||||||
@@ -588,18 +511,14 @@
|
|||||||
|
|
||||||
"mermaid/@braintree/sanitize-url": ["@braintree/sanitize-url@7.1.2", "", {}, "sha512-jigsZK+sMF/cuiB7sERuo9V7N9jx+dhmHHnQyDSVdpZwVutaBu7WvNYqMDLSgFgfB30n452TP3vjDAvFC973mA=="],
|
"mermaid/@braintree/sanitize-url": ["@braintree/sanitize-url@7.1.2", "", {}, "sha512-jigsZK+sMF/cuiB7sERuo9V7N9jx+dhmHHnQyDSVdpZwVutaBu7WvNYqMDLSgFgfB30n452TP3vjDAvFC973mA=="],
|
||||||
|
|
||||||
|
"mermaid/@mermaid-js/parser": ["@mermaid-js/parser@1.2.0", "", { "dependencies": { "@chevrotain/types": "~11.1.2" } }, "sha512-oYPyv8A4As1yH5Bx+04iQEQxXuIQDe0GKCNSRgao6z8AM9jixXIfP0vsppRLvGf+nKIOb9/LdpWA4YuJiVvESA=="],
|
||||||
|
|
||||||
"mermaid/roughjs": ["roughjs@4.6.6", "", { "dependencies": { "hachure-fill": "^0.5.2", "path-data-parser": "^0.1.0", "points-on-curve": "^0.2.0", "points-on-path": "^0.2.1" } }, "sha512-ZUz/69+SYpFN/g/lUlo2FXcIjRkSu3nDarreVdGGndHEBJ6cXPdKguS8JGxwj5HA5xIbVKSmLgr5b3AWxtRfvQ=="],
|
"mermaid/roughjs": ["roughjs@4.6.6", "", { "dependencies": { "hachure-fill": "^0.5.2", "path-data-parser": "^0.1.0", "points-on-curve": "^0.2.0", "points-on-path": "^0.2.1" } }, "sha512-ZUz/69+SYpFN/g/lUlo2FXcIjRkSu3nDarreVdGGndHEBJ6cXPdKguS8JGxwj5HA5xIbVKSmLgr5b3AWxtRfvQ=="],
|
||||||
|
|
||||||
"points-on-path/points-on-curve": ["points-on-curve@0.2.0", "", {}, "sha512-0mYKnYYe9ZcqMCWhUjItv/oHjvgEsfKvnUTg8sAtnHr3GVy7rGkXCb6d5cSyqrWqL4k81b9CPg3urd+T7aop3A=="],
|
"points-on-path/points-on-curve": ["points-on-curve@0.2.0", "", {}, "sha512-0mYKnYYe9ZcqMCWhUjItv/oHjvgEsfKvnUTg8sAtnHr3GVy7rGkXCb6d5cSyqrWqL4k81b9CPg3urd+T7aop3A=="],
|
||||||
|
|
||||||
"roughjs/points-on-curve": ["points-on-curve@0.2.0", "", {}, "sha512-0mYKnYYe9ZcqMCWhUjItv/oHjvgEsfKvnUTg8sAtnHr3GVy7rGkXCb6d5cSyqrWqL4k81b9CPg3urd+T7aop3A=="],
|
"roughjs/points-on-curve": ["points-on-curve@0.2.0", "", {}, "sha512-0mYKnYYe9ZcqMCWhUjItv/oHjvgEsfKvnUTg8sAtnHr3GVy7rGkXCb6d5cSyqrWqL4k81b9CPg3urd+T7aop3A=="],
|
||||||
|
|
||||||
"@excalidraw/mermaid-to-excalidraw/mermaid/dagre-d3-es": ["dagre-d3-es@7.0.10", "", { "dependencies": { "d3": "^7.8.2", "lodash-es": "^4.17.21" } }, "sha512-qTCQmEhcynucuaZgY5/+ti3X/rnszKZhEQH/ZdWdtP1tA/y3VoHJzcVrO9pjjJCNpigfscAtoUB5ONcd2wNn0A=="],
|
|
||||||
|
|
||||||
"@excalidraw/mermaid-to-excalidraw/mermaid/dompurify": ["dompurify@3.1.6", "", {}, "sha512-cTOAhc36AalkjtBpfG6O8JimdTMWNXjiePT2xQH/ppBGi/4uIpmj8eKyIkMJErXWARyINV/sB38yf8JCLF5pbQ=="],
|
|
||||||
|
|
||||||
"@excalidraw/mermaid-to-excalidraw/mermaid/uuid": ["uuid@9.0.1", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA=="],
|
|
||||||
|
|
||||||
"@radix-ui/react-roving-focus/@radix-ui/react-id/@radix-ui/react-use-layout-effect": ["@radix-ui/react-use-layout-effect@1.0.0", "", { "dependencies": { "@babel/runtime": "^7.13.10" }, "peerDependencies": { "react": "^16.8 || ^17.0 || ^18.0" } }, "sha512-6Tpkq+R6LOlmQb1R5NNETLG0B4YP0wc+klfXafpUCj6JGyaUc8il7/kUZ7m59rGbXGczE9Bs+iz2qloqsZBduQ=="],
|
"@radix-ui/react-roving-focus/@radix-ui/react-id/@radix-ui/react-use-layout-effect": ["@radix-ui/react-use-layout-effect@1.0.0", "", { "dependencies": { "@babel/runtime": "^7.13.10" }, "peerDependencies": { "react": "^16.8 || ^17.0 || ^18.0" } }, "sha512-6Tpkq+R6LOlmQb1R5NNETLG0B4YP0wc+klfXafpUCj6JGyaUc8il7/kUZ7m59rGbXGczE9Bs+iz2qloqsZBduQ=="],
|
||||||
|
|
||||||
"@radix-ui/react-roving-focus/@radix-ui/react-primitive/@radix-ui/react-slot": ["@radix-ui/react-slot@1.0.1", "", { "dependencies": { "@babel/runtime": "^7.13.10", "@radix-ui/react-compose-refs": "1.0.0" }, "peerDependencies": { "react": "^16.8 || ^17.0 || ^18.0" } }, "sha512-avutXAFL1ehGvAXtPquu0YK5oz6ctS474iM3vNGQIkswrVhdrS52e3uoMQBzZhNRAIE0jBnUyXWNmSjGHhCFcw=="],
|
"@radix-ui/react-roving-focus/@radix-ui/react-primitive/@radix-ui/react-slot": ["@radix-ui/react-slot@1.0.1", "", { "dependencies": { "@babel/runtime": "^7.13.10", "@radix-ui/react-compose-refs": "1.0.0" }, "peerDependencies": { "react": "^16.8 || ^17.0 || ^18.0" } }, "sha512-avutXAFL1ehGvAXtPquu0YK5oz6ctS474iM3vNGQIkswrVhdrS52e3uoMQBzZhNRAIE0jBnUyXWNmSjGHhCFcw=="],
|
||||||
|
|||||||
+6
-6
@@ -1,13 +1,13 @@
|
|||||||
{
|
{
|
||||||
"name": "gstack-diagram-render",
|
"name": "gstack-diagram-render",
|
||||||
"sha256": "da9c363071afbe79e06807bd1e67dbacc1123187db7b99e2608dd4a1a9567e94",
|
"sha256": "90148189fc8688870cbb822593112b5621bcbf265f4c44f363598390e665d329",
|
||||||
"srcSha256": "07238fae312bc0444f62b0a0a3404a8a38c45cef505aa1528c60a0ded17cbe06",
|
"srcSha256": "07238fae312bc0444f62b0a0a3404a8a38c45cef505aa1528c60a0ded17cbe06",
|
||||||
"bytes": 9645479,
|
"bytes": 7953601,
|
||||||
"bunVersion": "1.3.13",
|
"bunVersion": "1.3.14",
|
||||||
"deps": {
|
"deps": {
|
||||||
"@excalidraw/excalidraw": "0.18.0",
|
"@excalidraw/excalidraw": "0.18.1",
|
||||||
"@excalidraw/mermaid-to-excalidraw": "1.1.2",
|
"@excalidraw/mermaid-to-excalidraw": "2.2.2",
|
||||||
"mermaid": "11.12.2",
|
"mermaid": "11.16.0",
|
||||||
"react": "18.3.1",
|
"react": "18.3.1",
|
||||||
"react-dom": "18.3.1"
|
"react-dom": "18.3.1"
|
||||||
}
|
}
|
||||||
|
|||||||
+1695
-2640
File diff suppressed because one or more lines are too long
@@ -7,10 +7,15 @@
|
|||||||
"build": "bun run scripts/build.ts"
|
"build": "bun run scripts/build.ts"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@excalidraw/excalidraw": "0.18.0",
|
"@excalidraw/excalidraw": "0.18.1",
|
||||||
"@excalidraw/mermaid-to-excalidraw": "1.1.2",
|
"@excalidraw/mermaid-to-excalidraw": "2.2.2",
|
||||||
"mermaid": "11.12.2",
|
"mermaid": "11.16.0",
|
||||||
"react": "18.3.1",
|
"react": "18.3.1",
|
||||||
"react-dom": "18.3.1"
|
"react-dom": "18.3.1"
|
||||||
|
},
|
||||||
|
"overrides": {
|
||||||
|
"dompurify": "3.4.11",
|
||||||
|
"lodash-es": "4.18.1",
|
||||||
|
"nanoid": "5.0.9"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+15
-6
@@ -36,7 +36,7 @@
|
|||||||
"server": "bun run browse/src/server.ts",
|
"server": "bun run browse/src/server.ts",
|
||||||
"test": "bun run scripts/test-free-strict.ts",
|
"test": "bun run scripts/test-free-strict.ts",
|
||||||
"check:gstack2-generated": "bun run scripts/gstack2/check-generated.ts",
|
"check:gstack2-generated": "bun run scripts/gstack2/check-generated.ts",
|
||||||
"test:gstack2": "bun run gen:gstack2 && bun run check:gstack2-generated && bun test --timeout 60000 test/gstack2-*.test.ts",
|
"test:gstack2": "bun run gen:gstack2 && bun run check:gstack2-generated && bun run scripts/gstack2/test-suite.ts",
|
||||||
"test:gstack2:install": "bun run scripts/gstack2/test-install-matrix.ts --full",
|
"test:gstack2:install": "bun run scripts/gstack2/test-install-matrix.ts --full",
|
||||||
"test:gstack2:parity": "bun run ensure:gstack2-runtime && bun run scripts/gstack2/run-parity.ts",
|
"test:gstack2:parity": "bun run ensure:gstack2-runtime && bun run scripts/gstack2/run-parity.ts",
|
||||||
"test:free": "bun run scripts/test-free-shards.ts",
|
"test:free": "bun run scripts/test-free-shards.ts",
|
||||||
@@ -70,17 +70,26 @@
|
|||||||
"slop:diff": "bun run scripts/slop-diff.ts"
|
"slop:diff": "bun run scripts/slop-diff.ts"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@anthropic-ai/sdk": "^0.78.0",
|
"@anthropic-ai/sdk": "^0.112.4",
|
||||||
"@ngrok/ngrok": "^1.7.0",
|
"@ngrok/ngrok": "^1.7.0",
|
||||||
"diff": "^9.0.0",
|
"diff": "^9.0.0",
|
||||||
"html-to-docx": "1.8.0",
|
"html-to-docx": "1.8.0",
|
||||||
"marked": "^18.0.2",
|
"marked": "^18.0.6",
|
||||||
"playwright": "npm:playwright-core@^1.58.2",
|
"playwright": "npm:playwright-core@^1.58.2",
|
||||||
"sharp": "^0.34.5",
|
"sharp": "^0.34.5",
|
||||||
"socks": "^2.8.8",
|
"socks": "^2.8.9",
|
||||||
"xterm": "5",
|
"xterm": "5",
|
||||||
"xterm-addon-fit": "^0.8.0"
|
"xterm-addon-fit": "^0.8.0"
|
||||||
},
|
},
|
||||||
|
"overrides": {
|
||||||
|
"@protobufjs/utf8": "1.1.1",
|
||||||
|
"adm-zip": "0.6.0",
|
||||||
|
"fast-uri": "3.1.3",
|
||||||
|
"hono": "4.12.27",
|
||||||
|
"ip-address": "10.2.0",
|
||||||
|
"protobufjs": "7.6.5",
|
||||||
|
"qs": "6.15.2"
|
||||||
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"bun": ">=1.0.0",
|
"bun": ">=1.0.0",
|
||||||
"node": ">=18.0.0"
|
"node": ">=18.0.0"
|
||||||
@@ -96,7 +105,7 @@
|
|||||||
"devtools"
|
"devtools"
|
||||||
],
|
],
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@anthropic-ai/claude-agent-sdk": "0.2.117",
|
"@anthropic-ai/claude-agent-sdk": "0.3.216",
|
||||||
"@huggingface/transformers": "^4.1.0"
|
"@huggingface/transformers": "4.2.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+128
-12
@@ -27,7 +27,12 @@ import {
|
|||||||
runExternalEffect,
|
runExternalEffect,
|
||||||
updateRunWorkflow,
|
updateRunWorkflow,
|
||||||
} from "./state.js";
|
} from "./state.js";
|
||||||
import { runDoctor, formatDoctor } from "./doctor.js";
|
import {
|
||||||
|
CAPABILITY_READINESS_CAPABILITIES,
|
||||||
|
capabilityReadiness,
|
||||||
|
runDoctor,
|
||||||
|
formatDoctor,
|
||||||
|
} from "./doctor.js";
|
||||||
import { cleanupRuntime } from "./cleanup.js";
|
import { cleanupRuntime } from "./cleanup.js";
|
||||||
import {
|
import {
|
||||||
ContextClient,
|
ContextClient,
|
||||||
@@ -41,6 +46,11 @@ import { installManagedRuntime, uninstallManagedRuntime } from "./install.js";
|
|||||||
import { assertManagedHome, withRuntimeLifecycleLock } from "./managed-home.js";
|
import { assertManagedHome, withRuntimeLifecycleLock } from "./managed-home.js";
|
||||||
import { errorWithCode as cliError } from "./errors.js";
|
import { errorWithCode as cliError } from "./errors.js";
|
||||||
import { RUNTIME_VERSION } from "./index.js";
|
import { RUNTIME_VERSION } from "./index.js";
|
||||||
|
import {
|
||||||
|
EXECUTION_RESULT_ERROR_CODES,
|
||||||
|
executionResult,
|
||||||
|
renderExecutionResult,
|
||||||
|
} from "./execution-result.js";
|
||||||
|
|
||||||
export async function main(argv = process.argv.slice(2), options = {}) {
|
export async function main(argv = process.argv.slice(2), options = {}) {
|
||||||
const env = options.env ?? process.env;
|
const env = options.env ?? process.env;
|
||||||
@@ -90,6 +100,11 @@ export async function main(argv = process.argv.slice(2), options = {}) {
|
|||||||
throw cliError(`Unknown command: ${command}`, "USAGE");
|
throw cliError(`Unknown command: ${command}`, "USAGE");
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
const structuredResult = error?.executionResult ?? error?.cause?.executionResult;
|
||||||
|
if (structuredResult) {
|
||||||
|
write(stderr, renderExecutionResult(structuredResult, { json: true }));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
const json = args.includes("--json");
|
const json = args.includes("--json");
|
||||||
const safeMessage = redactSensitiveText(error?.message ?? String(error));
|
const safeMessage = redactSensitiveText(error?.message ?? String(error));
|
||||||
if (json) {
|
if (json) {
|
||||||
@@ -154,11 +169,53 @@ async function initCommand({ args, home, cwd, stdout, legacyAlias = false }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function doctorCommand({ args, home, cwd, stdout }) {
|
async function doctorCommand({ args, home, cwd, stdout }) {
|
||||||
const parsed = parseFlags(args, new Set(["--json", "--skill-api"]));
|
const parsed = parseFlags(args, new Set(["--json", "--skill-api", "--capability"]));
|
||||||
if (parsed.positionals.length) throw cliError("Doctor accepts only named options", "USAGE");
|
if (parsed.positionals.length) throw cliError("Doctor accepts only named options", "USAGE");
|
||||||
|
const capability = parsed.values.get("--capability");
|
||||||
|
if (capability && !CAPABILITY_READINESS_CAPABILITIES.includes(capability)) {
|
||||||
|
throw cliError(`Unknown capability: ${capability}. Choose ${CAPABILITY_READINESS_CAPABILITIES.join(", ")}.`, "USAGE");
|
||||||
|
}
|
||||||
const report = await runDoctor({ home, cwd, expectedSkillApi: parsed.values.get("--skill-api") });
|
const report = await runDoctor({ home, cwd, expectedSkillApi: parsed.values.get("--skill-api") });
|
||||||
write(stdout, parsed.flags.has("--json") ? `${JSON.stringify(report, null, 2)}\n` : formatDoctor(report));
|
const result = capability ? capabilityReadiness(report, capability) : report;
|
||||||
return report.ok ? 0 : 1;
|
if (capability) {
|
||||||
|
const envelope = capabilityExecutionResult(result);
|
||||||
|
write(stdout, renderExecutionResult(envelope, { json: parsed.flags.has("--json") }));
|
||||||
|
return envelope.status === "success" ? 0 : 1;
|
||||||
|
}
|
||||||
|
write(stdout, parsed.flags.has("--json")
|
||||||
|
? `${JSON.stringify(result, null, 2)}\n`
|
||||||
|
: formatDoctor(result));
|
||||||
|
return result.ok ? 0 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
function capabilityExecutionResult(result) {
|
||||||
|
const statusByReadiness = {
|
||||||
|
ready: "success",
|
||||||
|
degraded: "degraded",
|
||||||
|
unavailable: "degraded",
|
||||||
|
unsupported: "unsupported",
|
||||||
|
failed: "failed",
|
||||||
|
};
|
||||||
|
const codeByReadiness = {
|
||||||
|
ready: null,
|
||||||
|
degraded: EXECUTION_RESULT_ERROR_CODES.DEGRADED,
|
||||||
|
unavailable: EXECUTION_RESULT_ERROR_CODES.CAPABILITY_UNAVAILABLE,
|
||||||
|
unsupported: EXECUTION_RESULT_ERROR_CODES.CAPABILITY_UNSUPPORTED,
|
||||||
|
failed: EXECUTION_RESULT_ERROR_CODES.CAPABILITY_FAILED,
|
||||||
|
};
|
||||||
|
const readiness = result.readiness.status;
|
||||||
|
const evidence = result.readiness.evidence?.map((item) =>
|
||||||
|
`${item.id}: ${item.status} — ${item.message}`) ?? [
|
||||||
|
`platform: ${result.platform.status}`,
|
||||||
|
`judgment: ${result.judgment.status}`,
|
||||||
|
];
|
||||||
|
return executionResult({
|
||||||
|
status: statusByReadiness[readiness],
|
||||||
|
code: codeByReadiness[readiness],
|
||||||
|
summary: result.readiness.message,
|
||||||
|
evidence,
|
||||||
|
data: result,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function configCommand({ args, home, cwd, stdout }) {
|
async function configCommand({ args, home, cwd, stdout }) {
|
||||||
@@ -391,7 +448,7 @@ async function stateCommand({ args, home, cwd, env, stdout, stderr }) {
|
|||||||
"EXTERNAL_EFFECT_UNCERTAIN",
|
"EXTERNAL_EFFECT_UNCERTAIN",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
write(stdout, `${JSON.stringify({ status: result.status, effectKey, idempotencyKey: result.idempotencyKey ?? null, result: result.result })}\n`);
|
write(stdout, renderExecutionResult(result.result, { json: true }));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (action === "reconcile-not-applied") {
|
if (action === "reconcile-not-applied") {
|
||||||
@@ -423,6 +480,7 @@ async function stateCommand({ args, home, cwd, env, stdout, stderr }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function runExternalCommand(command, { cwd, env, stdout, stderr }) {
|
async function runExternalCommand(command, { cwd, env, stdout, stderr }) {
|
||||||
|
const maxCapturedBytes = 1024 * 1024;
|
||||||
const [executable, ...args] = command;
|
const [executable, ...args] = command;
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const child = spawn(executable, args, {
|
const child = spawn(executable, args, {
|
||||||
@@ -431,23 +489,81 @@ async function runExternalCommand(command, { cwd, env, stdout, stderr }) {
|
|||||||
shell: false,
|
shell: false,
|
||||||
stdio: ["inherit", "pipe", "pipe"],
|
stdio: ["inherit", "pipe", "pipe"],
|
||||||
});
|
});
|
||||||
child.stdout?.on("data", (chunk) => write(stdout, chunk));
|
const captured = { stdout: "", stderr: "", bytes: 0, truncated: false };
|
||||||
child.stderr?.on("data", (chunk) => write(stderr, chunk));
|
const capture = (key, chunk) => {
|
||||||
|
const remaining = maxCapturedBytes - captured.bytes;
|
||||||
|
if (remaining <= 0) { captured.truncated = true; return; }
|
||||||
|
const buffer = Buffer.from(chunk);
|
||||||
|
captured[key] += buffer.subarray(0, remaining).toString();
|
||||||
|
captured.bytes += Math.min(buffer.length, remaining);
|
||||||
|
if (buffer.length > remaining) captured.truncated = true;
|
||||||
|
};
|
||||||
|
child.stdout?.on("data", (chunk) => capture("stdout", chunk));
|
||||||
|
child.stderr?.on("data", (chunk) => capture("stderr", chunk));
|
||||||
child.once("error", reject);
|
child.once("error", reject);
|
||||||
child.once("close", (code, signal) => {
|
child.once("close", (code, signal) => {
|
||||||
if (code === 0) {
|
if (code === 0) {
|
||||||
resolve({ exitCode: 0, executable: path.basename(executable) });
|
if (captured.truncated) {
|
||||||
|
reject(executionResultError(
|
||||||
|
`External command ${path.basename(executable)} exceeded the ${maxCapturedBytes}-byte result limit; verify its side effect before reconciling it as applied.`,
|
||||||
|
EXECUTION_RESULT_ERROR_CODES.DEGRADED,
|
||||||
|
"degraded",
|
||||||
|
["output exceeded 1048576-byte capture limit"],
|
||||||
|
{ executable: path.basename(executable), exitCode: 0, truncated: true },
|
||||||
|
));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const evidence = [];
|
||||||
|
if (captured.stdout.trim()) evidence.push("non-empty stdout");
|
||||||
|
if (captured.stderr.trim()) evidence.push("non-empty stderr");
|
||||||
|
const name = path.basename(executable);
|
||||||
|
if (evidence.length === 0) {
|
||||||
|
reject(executionResultError(
|
||||||
|
`External command ${name} exited 0 but produced no output; verify its side effect before reconciling it as applied.`,
|
||||||
|
EXECUTION_RESULT_ERROR_CODES.EMPTY,
|
||||||
|
"degraded",
|
||||||
|
["exit code 0", "stdout and stderr were empty"],
|
||||||
|
{ executable: name, exitCode: 0, stdout: "", stderr: "" },
|
||||||
|
));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
resolve(executionResult({
|
||||||
|
status: "success",
|
||||||
|
summary: `External command ${name} completed`,
|
||||||
|
evidence: [`exit code 0`, ...evidence],
|
||||||
|
data: {
|
||||||
|
exitCode: 0,
|
||||||
|
executable: name,
|
||||||
|
stdout: captured.stdout,
|
||||||
|
stderr: captured.stderr,
|
||||||
|
},
|
||||||
|
}));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const error = cliError(
|
const error = executionResultError(
|
||||||
`External command ${path.basename(executable)} ${signal ? `ended by ${signal}` : `exited ${code}`}`,
|
`External command ${path.basename(executable)} ${signal ? `ended by ${signal}` : `exited ${code}`}`,
|
||||||
"EXTERNAL_COMMAND_FAILED",
|
EXECUTION_RESULT_ERROR_CODES.FAILED,
|
||||||
|
"failed",
|
||||||
|
[signal ? `terminated by signal ${signal}` : `exit code ${code}`],
|
||||||
|
{
|
||||||
|
executable: path.basename(executable),
|
||||||
|
exitCode: code,
|
||||||
|
signal: signal ?? null,
|
||||||
|
stdout: captured.stdout,
|
||||||
|
stderr: captured.stderr,
|
||||||
|
},
|
||||||
);
|
);
|
||||||
reject(error);
|
reject(error);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function executionResultError(summary, code, status, evidence, data) {
|
||||||
|
const error = cliError(summary, code);
|
||||||
|
error.executionResult = executionResult({ status, code, summary, evidence, data });
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
async function withOwnedRuntimeMutation(home, callback) {
|
async function withOwnedRuntimeMutation(home, callback) {
|
||||||
return withRuntimeLifecycleLock(home, async () => {
|
return withRuntimeLifecycleLock(home, async () => {
|
||||||
await assertManagedHome(home);
|
await assertManagedHome(home);
|
||||||
@@ -724,7 +840,7 @@ function parseFlags(args, allowed) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!allowed.has(arg)) throw cliError(`Unknown option: ${arg}`, "USAGE");
|
if (!allowed.has(arg)) throw cliError(`Unknown option: ${arg}`, "USAGE");
|
||||||
if (["--source", "--version", "--url", "--older-than-hours", "--max-pages", "--max-depth", "--max-links", "--skill-api"].includes(arg)) {
|
if (["--source", "--version", "--url", "--older-than-hours", "--max-pages", "--max-depth", "--max-links", "--skill-api", "--capability"].includes(arg)) {
|
||||||
const value = args[++index];
|
const value = args[++index];
|
||||||
if (value == null || value.startsWith("--")) throw cliError(`${arg} requires a value`, "USAGE");
|
if (value == null || value.startsWith("--")) throw cliError(`${arg} requires a value`, "USAGE");
|
||||||
values.set(arg, value);
|
values.set(arg, value);
|
||||||
@@ -801,7 +917,7 @@ function usage() {
|
|||||||
"Usage:\n" +
|
"Usage:\n" +
|
||||||
" gstack init # initialize state only\n" +
|
" gstack init # initialize state only\n" +
|
||||||
" gstack setup # compatibility alias for init\n" +
|
" gstack setup # compatibility alias for init\n" +
|
||||||
" gstack doctor [--skill-api <version>] [--json]\n" +
|
" gstack doctor [--capability browser|design|diagram|pdf|ios] [--skill-api <version>] [--json]\n" +
|
||||||
" gstack paths [--json|--shell]\n" +
|
" gstack paths [--json|--shell]\n" +
|
||||||
" gstack runtime path <bundle-relative-path>\n" +
|
" gstack runtime path <bundle-relative-path>\n" +
|
||||||
" gstack config get [key]\n" +
|
" gstack config get [key]\n" +
|
||||||
|
|||||||
@@ -18,6 +18,14 @@ import {
|
|||||||
managedBunRelativePath,
|
managedBunRelativePath,
|
||||||
} from "./install.js";
|
} from "./install.js";
|
||||||
|
|
||||||
|
export const CAPABILITY_READINESS_CAPABILITIES = Object.freeze([
|
||||||
|
"browser",
|
||||||
|
"design",
|
||||||
|
"diagram",
|
||||||
|
"pdf",
|
||||||
|
"ios",
|
||||||
|
]);
|
||||||
|
|
||||||
export async function runDoctor(options = {}) {
|
export async function runDoctor(options = {}) {
|
||||||
const paths = resolveRuntimePaths(options);
|
const paths = resolveRuntimePaths(options);
|
||||||
const checks = [];
|
const checks = [];
|
||||||
@@ -209,6 +217,83 @@ export async function runDoctor(options = {}) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function capabilityReadiness(report, capability, options = {}) {
|
||||||
|
if (!CAPABILITY_READINESS_CAPABILITIES.includes(capability)) {
|
||||||
|
throw new TypeError(`Unknown capability: ${capability}`);
|
||||||
|
}
|
||||||
|
const platform = options.platform ?? process.platform;
|
||||||
|
const checkedAt = report.checkedAt;
|
||||||
|
const judgment = {
|
||||||
|
status: "available",
|
||||||
|
message: "Pure-judgment skill guidance is available without the optional runtime.",
|
||||||
|
};
|
||||||
|
if (capability === "ios" && platform !== "darwin") {
|
||||||
|
return {
|
||||||
|
ok: false,
|
||||||
|
capability,
|
||||||
|
checkedAt,
|
||||||
|
judgment,
|
||||||
|
platform: { status: "unsupported", platform, message: "Physical iOS requires macOS and the existing CoreDevice harness." },
|
||||||
|
consent: {
|
||||||
|
preview: { status: "not-applicable", granted: false },
|
||||||
|
install: { status: "not-applicable", granted: false },
|
||||||
|
},
|
||||||
|
readiness: { status: "unsupported", message: "The runtime capability is unsupported on this platform." },
|
||||||
|
nextAction: "Continue with pure judgment or move the physical-iOS workflow to macOS.",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const capabilityCheck = report.checks.find((check) => check.id === `capability:${capability}`);
|
||||||
|
const runtimeCheck = report.checks.find((check) => check.id === "managed-runtime");
|
||||||
|
let status;
|
||||||
|
if (capabilityCheck?.status === "pass" && runtimeCheck?.status === "pass") status = "ready";
|
||||||
|
else if (capabilityCheck?.status === "pass" && runtimeCheck?.status === "warn") status = "degraded";
|
||||||
|
else if (capabilityCheck?.status === "pass") status = "failed";
|
||||||
|
else if (capabilityCheck?.status === "fail") status = "failed";
|
||||||
|
else status = "unavailable";
|
||||||
|
|
||||||
|
const needsSetup = status === "unavailable" || status === "failed";
|
||||||
|
const messages = {
|
||||||
|
ready: "The selected capability passed its runtime readiness checks.",
|
||||||
|
degraded: "The capability check passed, but the managed runtime reported a degraded condition.",
|
||||||
|
unavailable: "The optional runtime capability is not installed or cannot currently be inspected.",
|
||||||
|
failed: "The selected capability is installed but failed readiness checks.",
|
||||||
|
};
|
||||||
|
return {
|
||||||
|
ok: status === "ready" || status === "degraded",
|
||||||
|
capability,
|
||||||
|
checkedAt,
|
||||||
|
judgment,
|
||||||
|
platform: { status: "supported", platform },
|
||||||
|
consent: {
|
||||||
|
preview: {
|
||||||
|
status: needsSetup ? "required" : "not-required",
|
||||||
|
granted: false,
|
||||||
|
message: needsSetup
|
||||||
|
? "Consent is required before an uncached signed-manifest metadata preview; this command does not grant it."
|
||||||
|
: "No setup preview is needed for the current readiness state.",
|
||||||
|
},
|
||||||
|
install: {
|
||||||
|
status: needsSetup ? "required-after-preview" : "not-required",
|
||||||
|
granted: false,
|
||||||
|
message: needsSetup
|
||||||
|
? "Install consent is separate and may be requested only after the complete preview; this command does not grant it."
|
||||||
|
: "No install is needed for the current readiness state.",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
readiness: {
|
||||||
|
status,
|
||||||
|
message: messages[status],
|
||||||
|
evidence: [runtimeCheck, capabilityCheck].filter(Boolean),
|
||||||
|
},
|
||||||
|
nextAction: needsSetup
|
||||||
|
? `Ask for preview consent, then run the packaged bootstrap preview for ${capability}; continue judgment-only work if setup is deferred.`
|
||||||
|
: status === "degraded"
|
||||||
|
? "Review the managed-runtime warning before capability-dependent evidence work."
|
||||||
|
: "Proceed with capability-dependent work.",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
async function inspectRuntimeBun(activeRoot, manifest) {
|
async function inspectRuntimeBun(activeRoot, manifest) {
|
||||||
const relative = managedBunRelativePath();
|
const relative = managedBunRelativePath();
|
||||||
const declared = manifest?.tools?.bun;
|
const declared = manifest?.tools?.bun;
|
||||||
@@ -388,3 +473,16 @@ export function formatDoctor(report) {
|
|||||||
for (const check of report.checks) lines.push(`${symbol[check.status]} ${check.id}: ${check.message}`);
|
for (const check of report.checks) lines.push(`${symbol[check.status]} ${check.id}: ${check.message}`);
|
||||||
return `${lines.join("\n")}\n`;
|
return `${lines.join("\n")}\n`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function formatCapabilityReadiness(report) {
|
||||||
|
const lines = [
|
||||||
|
`gstack capability readiness: ${report.capability}`,
|
||||||
|
`judgment: ${report.judgment.status}`,
|
||||||
|
`platform: ${report.platform.status}`,
|
||||||
|
`preview consent: ${report.consent.preview.status}`,
|
||||||
|
`install consent: ${report.consent.install.status}`,
|
||||||
|
`readiness: ${report.readiness.status}`,
|
||||||
|
`next: ${report.nextAction}`,
|
||||||
|
];
|
||||||
|
return `${lines.join("\n")}\n`;
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,92 @@
|
|||||||
|
import { errorWithCode } from "./errors.js";
|
||||||
|
|
||||||
|
export const EXECUTION_RESULT_SCHEMA_VERSION = 1;
|
||||||
|
export const EXECUTION_RESULT_STATUSES = Object.freeze([
|
||||||
|
"success",
|
||||||
|
"degraded",
|
||||||
|
"unsupported",
|
||||||
|
"failed",
|
||||||
|
]);
|
||||||
|
|
||||||
|
export const EXECUTION_RESULT_ERROR_CODES = Object.freeze({
|
||||||
|
EMPTY: "EXECUTION_EMPTY",
|
||||||
|
MALFORMED: "EXECUTION_MALFORMED",
|
||||||
|
DEGRADED: "EXECUTION_DEGRADED",
|
||||||
|
UNSUPPORTED: "EXECUTION_UNSUPPORTED",
|
||||||
|
FAILED: "EXECUTION_FAILED",
|
||||||
|
CAPABILITY_UNAVAILABLE: "CAPABILITY_UNAVAILABLE",
|
||||||
|
CAPABILITY_UNSUPPORTED: "CAPABILITY_UNSUPPORTED",
|
||||||
|
CAPABILITY_FAILED: "CAPABILITY_FAILED",
|
||||||
|
});
|
||||||
|
|
||||||
|
export const EXECUTION_RESULT_SCHEMA = Object.freeze({
|
||||||
|
$schema: "https://json-schema.org/draft/2020-12/schema",
|
||||||
|
$id: "https://gstack.dev/schemas/execution-result-v1.json",
|
||||||
|
title: "GStack execution result",
|
||||||
|
type: "object",
|
||||||
|
additionalProperties: false,
|
||||||
|
required: ["schemaVersion", "status", "code", "summary", "evidence", "data"],
|
||||||
|
properties: {
|
||||||
|
schemaVersion: { const: EXECUTION_RESULT_SCHEMA_VERSION },
|
||||||
|
status: { enum: EXECUTION_RESULT_STATUSES },
|
||||||
|
code: { type: ["string", "null"], pattern: "^[A-Z][A-Z0-9_]{2,63}$" },
|
||||||
|
summary: { type: "string", minLength: 1 },
|
||||||
|
evidence: { type: "array", items: { type: "string", minLength: 1 } },
|
||||||
|
data: {},
|
||||||
|
},
|
||||||
|
allOf: [
|
||||||
|
{ if: { properties: { status: { const: "success" } } }, then: { properties: { code: { type: "null" }, evidence: { minItems: 1 } } } },
|
||||||
|
{ if: { properties: { status: { enum: ["degraded", "unsupported", "failed"] } } }, then: { properties: { code: { type: "string" } } } },
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
/** Validate the host-neutral result before any caller can render it as success. */
|
||||||
|
export function validateExecutionResult(value) {
|
||||||
|
if (!value || typeof value !== "object" || Array.isArray(value)) return invalid("Execution result must be an object");
|
||||||
|
const keys = Object.keys(value).sort();
|
||||||
|
const expected = ["code", "data", "evidence", "schemaVersion", "status", "summary"];
|
||||||
|
if (JSON.stringify(keys) !== JSON.stringify(expected)) return invalid("Execution result contains missing or unknown fields");
|
||||||
|
if (value.schemaVersion !== EXECUTION_RESULT_SCHEMA_VERSION) return invalid("Execution result schema version is unsupported");
|
||||||
|
if (!EXECUTION_RESULT_STATUSES.includes(value.status)) return invalid("Execution result status is unsupported");
|
||||||
|
if (typeof value.summary !== "string" || value.summary.trim().length === 0) return invalid("Execution result summary is empty");
|
||||||
|
if (!Array.isArray(value.evidence) || value.evidence.some((item) => typeof item !== "string" || item.trim().length === 0)) {
|
||||||
|
return invalid("Execution result evidence is malformed");
|
||||||
|
}
|
||||||
|
if (value.status === "success") {
|
||||||
|
if (value.code !== null) return invalid("Successful execution must not carry an error code");
|
||||||
|
if (value.evidence.length === 0) return invalid("Successful execution requires evidence", EXECUTION_RESULT_ERROR_CODES.EMPTY);
|
||||||
|
} else if (typeof value.code !== "string" || !/^[A-Z][A-Z0-9_]{2,63}$/.test(value.code)) {
|
||||||
|
return invalid("Non-success execution requires a stable error code");
|
||||||
|
}
|
||||||
|
return Object.freeze({ ...value, evidence: Object.freeze([...value.evidence]) });
|
||||||
|
}
|
||||||
|
|
||||||
|
export function executionResult(input) {
|
||||||
|
return validateExecutionResult({
|
||||||
|
schemaVersion: EXECUTION_RESULT_SCHEMA_VERSION,
|
||||||
|
status: input.status,
|
||||||
|
code: input.code ?? null,
|
||||||
|
summary: input.summary,
|
||||||
|
evidence: input.evidence ?? [],
|
||||||
|
data: input.data ?? null,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function renderExecutionResult(result, options = {}) {
|
||||||
|
const valid = validateExecutionResult(result);
|
||||||
|
if (options.json) return `${JSON.stringify(valid, null, 2)}\n`;
|
||||||
|
const label = valid.status.toUpperCase();
|
||||||
|
const code = valid.code ? ` [${valid.code}]` : "";
|
||||||
|
const evidence = valid.evidence.map((item) => `- ${item}`).join("\n");
|
||||||
|
return `${label}${code}: ${valid.summary}${evidence ? `\nEvidence:\n${evidence}` : ""}\n`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function assertSuccessfulExecution(result) {
|
||||||
|
const valid = validateExecutionResult(result);
|
||||||
|
if (valid.status === "success") return valid;
|
||||||
|
throw errorWithCode(valid.summary, valid.code);
|
||||||
|
}
|
||||||
|
|
||||||
|
function invalid(message, code = EXECUTION_RESULT_ERROR_CODES.MALFORMED) {
|
||||||
|
throw errorWithCode(message, code);
|
||||||
|
}
|
||||||
@@ -15,3 +15,4 @@ export * from "./doctor.js";
|
|||||||
export * from "./cleanup.js";
|
export * from "./cleanup.js";
|
||||||
export * from "./upgrade.js";
|
export * from "./upgrade.js";
|
||||||
export * from "./install.js";
|
export * from "./install.js";
|
||||||
|
export * from "./execution-result.js";
|
||||||
|
|||||||
@@ -288,6 +288,9 @@ export const DEFAULT_RUNTIME_BUNDLE = Object.freeze([
|
|||||||
entry("node_modules/detect-libc"),
|
entry("node_modules/detect-libc"),
|
||||||
entry("node_modules/semver"),
|
entry("node_modules/semver"),
|
||||||
entry("node_modules/@anthropic-ai/sdk"),
|
entry("node_modules/@anthropic-ai/sdk"),
|
||||||
|
entry("node_modules/standardwebhooks"),
|
||||||
|
entry("node_modules/@stablelib/base64"),
|
||||||
|
entry("node_modules/fast-sha256"),
|
||||||
entry(platformBinary("design/dist/design"), "core", true),
|
entry(platformBinary("design/dist/design"), "core", true),
|
||||||
entry("design/dist/.version", "core"),
|
entry("design/dist/.version", "core"),
|
||||||
entry(platformBinary("make-pdf/dist/pdf"), "core", true),
|
entry(platformBinary("make-pdf/dist/pdf"), "core", true),
|
||||||
|
|||||||
@@ -8,7 +8,12 @@ import {
|
|||||||
} from '../../runtime/install.js';
|
} from '../../runtime/install.js';
|
||||||
|
|
||||||
const ROOT = path.resolve(import.meta.dir, '../..');
|
const ROOT = path.resolve(import.meta.dir, '../..');
|
||||||
const REQUIRED_CAPABILITIES = ['browse', 'gstack-design', 'make-pdf'] as const;
|
const REQUIRED_CAPABILITIES = [
|
||||||
|
'browse',
|
||||||
|
'gstack-design',
|
||||||
|
'make-pdf',
|
||||||
|
...(process.platform === 'darwin' ? ['gstack-ios-qa-daemon', 'gstack-ios-qa-mint'] : []),
|
||||||
|
] as const;
|
||||||
|
|
||||||
export interface RuntimePayloadEntry {
|
export interface RuntimePayloadEntry {
|
||||||
path: string;
|
path: string;
|
||||||
|
|||||||
@@ -0,0 +1,77 @@
|
|||||||
|
import type { ExecutionProfile } from './types';
|
||||||
|
|
||||||
|
export interface ExecutionProfileContract {
|
||||||
|
profile: ExecutionProfile;
|
||||||
|
inferWhen: string;
|
||||||
|
mandatoryModules: string;
|
||||||
|
legalSkips: string;
|
||||||
|
artifacts: string;
|
||||||
|
allowedClaims: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const EXECUTION_PROFILE_CONTRACTS: Record<ExecutionProfile, ExecutionProfileContract> = {
|
||||||
|
readiness: {
|
||||||
|
profile: 'readiness',
|
||||||
|
inferWhen: 'A narrow, reversible, pre-deployment or operational readiness decision needs bounded evidence; the requested claim is readiness, not completeness.',
|
||||||
|
mandatoryModules: 'Every selected specialist module remains mandatory. Run its entry gates and the smallest source-authorized evidence path that can answer the readiness question.',
|
||||||
|
legalSkips: 'Only source-declared conditional work whose condition is demonstrably false, or evidence unavailable after a named attempt. Never skip a STOP gate, approval boundary, reproduction/root-cause gate, or required physical-device/production evidence.',
|
||||||
|
artifacts: 'A readiness record naming the exact scope, probes run, evidence and freshness, failures, skipped work with reasons, and the next standard/deep step.',
|
||||||
|
allowedClaims: 'Only ready/not-ready for the named bounded decision. Must say “Readiness profile — not a complete review.” Never claim comprehensive, fully verified, production-safe, or no issues found outside the inspected scope.',
|
||||||
|
},
|
||||||
|
standard: {
|
||||||
|
profile: 'standard',
|
||||||
|
inferWhen: 'Normal feature or change work has bounded scope and risk and needs the selected specialist’s complete default workflow.',
|
||||||
|
mandatoryModules: 'Every selected specialist module and all of its mandatory phases, gates, artifacts, and exit checks.',
|
||||||
|
legalSkips: 'Only smart skips explicitly authorized by the specialist and supported by inspected evidence; list each skipped primary module and each skipped conditional phase.',
|
||||||
|
artifacts: 'Every artifact required by the selected specialist, plus evidence provenance, unresolved decisions, and a skip ledger.',
|
||||||
|
allowedClaims: 'Complete only for the named specialist scope and evidence layer. Broader product, security, production, or device claims require those modules and evidence.',
|
||||||
|
},
|
||||||
|
deep: {
|
||||||
|
profile: 'deep',
|
||||||
|
inferWhen: 'Risk, ambiguity, blast radius, cross-system effects, irreversible mutation, security/reliability needs, or production deployment demands stronger evidence.',
|
||||||
|
mandatoryModules: 'Every selected specialist module, all mandatory phases and outside-voice/cross-consumer modules selected by the dispatcher, with unchanged STOP and approval gates.',
|
||||||
|
legalSkips: 'Only specialist-authorized smart skips proven irrelevant. Missing, stale, malformed, or contradictory evidence is a gap or blocker, never a successful skip.',
|
||||||
|
artifacts: 'All specialist artifacts plus changed-input/unchanged-consumer trace, negative and failure-path evidence, provenance/freshness, rollback or reversibility evidence where applicable, and unresolved-risk ledger.',
|
||||||
|
allowedClaims: 'Complete only across the explicitly listed modules and evidence layers. “Confirmed” requires independent supporting evidence; production/device/security claims require matching production/device/security evidence.',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Infer from structured operating conditions, never prompt text. */
|
||||||
|
export function inferExecutionProfile(
|
||||||
|
signals: Record<string, unknown>,
|
||||||
|
specialistDefault: ExecutionProfile,
|
||||||
|
): ExecutionProfile {
|
||||||
|
const highRisk = signals.risk === 'high'
|
||||||
|
|| signals.blast_radius === 'broad'
|
||||||
|
|| signals.irreversible === true
|
||||||
|
|| signals.audit_focus === 'security'
|
||||||
|
|| signals.audit_focus === 'deep'
|
||||||
|
|| signals.evidence_need === 'independent'
|
||||||
|
|| signals.failure_impact === 'critical'
|
||||||
|
|| signals.mutation_scope === 'consequential'
|
||||||
|
|| signals.external_mutation_authorized === true
|
||||||
|
|| signals.deployment_state === 'production'
|
||||||
|
|| signals.release_stage === 'approved-pr'
|
||||||
|
|| signals.release_stage === 'landed';
|
||||||
|
if (highRisk) return 'deep';
|
||||||
|
|
||||||
|
const boundedReadiness = signals.evidence_need === 'readiness'
|
||||||
|
&& signals.scope === 'narrow'
|
||||||
|
&& signals.irreversible !== true
|
||||||
|
&& signals.mutation_scope !== 'consequential'
|
||||||
|
&& signals.external_mutation_authorized !== true
|
||||||
|
&& signals.deployment_state !== 'production'
|
||||||
|
&& signals.release_stage !== 'approved-pr'
|
||||||
|
&& signals.release_stage !== 'landed';
|
||||||
|
if (boundedReadiness) return 'readiness';
|
||||||
|
|
||||||
|
return specialistDefault;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function renderExecutionProfiles(): string {
|
||||||
|
const rows = (['readiness', 'standard', 'deep'] as const).map((name) => {
|
||||||
|
const contract = EXECUTION_PROFILE_CONTRACTS[name];
|
||||||
|
return `## ${name === 'readiness' ? 'Smoke/readiness' : name[0].toUpperCase() + name.slice(1)}\n\n- Infer when: ${contract.inferWhen}\n- Mandatory modules: ${contract.mandatoryModules}\n- Legal skips: ${contract.legalSkips}\n- Artifacts: ${contract.artifacts}\n- Claims: ${contract.allowedClaims}`;
|
||||||
|
});
|
||||||
|
return `# Inferred execution profiles\n\nChoose a profile from product stage, mutation authority, risk/evidence needs, and deployment state. Prompt keywords and a request to “be quick” are not routing evidence. A profile narrows or strengthens evidence; it never overrides a specialist’s binding question order, pressure, gates, mutation boundary, or exit behavior.\n\n${rows.join('\n\n')}\n`;
|
||||||
|
}
|
||||||
@@ -4,6 +4,8 @@ import * as fs from 'fs';
|
|||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import { BUG_FIX_OVERLAYS, overlaysForSource } from './bug-fix-overlays';
|
import { BUG_FIX_OVERLAYS, overlaysForSource } from './bug-fix-overlays';
|
||||||
import { renderBrowserProviderContract } from './browser-provider-contract';
|
import { renderBrowserProviderContract } from './browser-provider-contract';
|
||||||
|
import { EXECUTION_RESULT_SCHEMA } from '../../runtime/execution-result.js';
|
||||||
|
import { renderExecutionProfiles } from './execution-profiles';
|
||||||
import { contractFor, DISPATCHERS, SOURCE_ASSIGNMENTS } from './assignments';
|
import { contractFor, DISPATCHERS, SOURCE_ASSIGNMENTS } from './assignments';
|
||||||
import { SCENARIOS } from './scenarios';
|
import { SCENARIOS } from './scenarios';
|
||||||
import { runDeterministicSemanticParity } from './semantic-parity';
|
import { runDeterministicSemanticParity } from './semantic-parity';
|
||||||
@@ -220,7 +222,7 @@ Before any substantive output, print these exact labels in this exact order. Res
|
|||||||
\`\`\`text
|
\`\`\`text
|
||||||
Target: <concrete repository, product, URL, device, PR, or artifact>
|
Target: <concrete repository, product, URL, device, PR, or artifact>
|
||||||
Mode: <selected top-level mode>
|
Mode: <selected top-level mode>
|
||||||
Depth: <quick, standard, or deep>
|
Depth: <readiness, standard, or deep>
|
||||||
Mutation: <report-only or exact authorized mutation boundary>
|
Mutation: <report-only or exact authorized mutation boundary>
|
||||||
Active modules: <comma-separated internal specialist modules>
|
Active modules: <comma-separated internal specialist modules>
|
||||||
Skipped modules: <comma-separated non-active mandatory modules with compact reasons>
|
Skipped modules: <comma-separated non-active mandatory modules with compact reasons>
|
||||||
@@ -232,7 +234,7 @@ Web context: <none, optional, local-browser, or production>
|
|||||||
1. Infer the mode from product stage, surface, requested artifact, mutation authorization, evidence needs, and deployment state. Do not route by keyword alone.
|
1. Infer the mode from product stage, surface, requested artifact, mutation authorization, evidence needs, and deployment state. Do not route by keyword alone.
|
||||||
2. Refine the public mode to the smallest applicable internal specialist set, then print the required execution header before any substantive output.
|
2. Refine the public mode to the smallest applicable internal specialist set, then print the required execution header before any substantive output.
|
||||||
3. Read each active module in full from the path shown in the mode/alias tables. Its specialist body, behavioral contract, STOP gates, and appended upstream judgment ports are binding. Read a lazy specialist phase in full only when the workflow reaches its package-local reference.
|
3. Read each active module in full from the path shown in the mode/alias tables. Its specialist body, behavioral contract, STOP gates, and appended upstream judgment ports are binding. Read a lazy specialist phase in full only when the workflow reaches its package-local reference.
|
||||||
4. Read \`references/SHARED-JUDGMENT.md\` and \`references/AUTHORITY-POLICY.md\` for every invocation. Read \`references/RUNTIME.md\` before capability-dependent work and \`references/WEB-CONTEXT.md\` before public-web work.
|
4. Read \`references/EXECUTION-PROFILES.md\`, \`references/SHARED-JUDGMENT.md\`, and \`references/AUTHORITY-POLICY.md\` for every invocation. Infer Depth from structured operating conditions, then obey its mandatory modules, legal skips, artifacts, and claim limits. Read \`references/RUNTIME.md\` before capability-dependent work and \`references/WEB-CONTEXT.md\` before public-web work.
|
||||||
5. If an old asset path is unavailable, use \`references/ASSETS.md\`. If legacy prose invokes another retired skill, resolve it through \`references/COMPATIBILITY.md\` and stay inside these six dispatchers.
|
5. If an old asset path is unavailable, use \`references/ASSETS.md\`. If legacy prose invokes another retired skill, resolve it through \`references/COMPATIBILITY.md\` and stay inside these six dispatchers.
|
||||||
6. Preserve report-only versus mutation boundaries. Missing mutation authorization fails closed: do not edit merely because a specialist can fix. Commits, pushes, PRs, merges, deploys, messages, and other external mutations still require affirmative authority from the user.
|
6. Preserve report-only versus mutation boundaries. Missing mutation authorization fails closed: do not edit merely because a specialist can fix. Commits, pushes, PRs, merges, deploys, messages, and other external mutations still require affirmative authority from the user.
|
||||||
7. Match the user's language. Keep code identifiers, commands, and source quotations original when translation would reduce accuracy.
|
7. Match the user's language. Keep code identifiers, commands, and source quotations original when translation would reduce accuracy.
|
||||||
@@ -514,6 +516,10 @@ Some retained helpers are shell scripts. \`gstack doctor\` verifies Bash and, on
|
|||||||
|
|
||||||
The package/runtime compatibility tuple is \`schemaVersion=1\`, \`runtimeVersion=2.0.0\`, and \`skillApi=2.0\`; the machine-readable copy is \`references/support/runtime-contract.json\`. An incompatible active runtime is unavailable, not permission to upgrade it.
|
The package/runtime compatibility tuple is \`schemaVersion=1\`, \`runtimeVersion=2.0.0\`, and \`skillApi=2.0\`; the machine-readable copy is \`references/support/runtime-contract.json\`. An incompatible active runtime is unavailable, not permission to upgrade it.
|
||||||
|
|
||||||
|
Every optional-runtime tool result must satisfy \`references/support/execution-result-contract.json\` before it is presented as success. Success requires non-empty evidence. Empty or malformed output and explicit degraded, unsupported, or failed statuses remain non-success with stable codes; human renderings must preserve that status and code.
|
||||||
|
|
||||||
|
Use \`gstack doctor --capability browser|design|diagram|pdf|ios\` (optionally \`--json\`) for a non-mutating, capability-specific readiness result. Its independent axes must remain distinct: pure judgment availability, platform support, preview consent, install consent, and runtime readiness. Readiness is exactly \`ready\`, \`degraded\`, \`unavailable\`, \`unsupported\`, or \`failed\`. Doctor never grants or persists consent, previews metadata, or installs anything. \`unavailable\` means setup may be offered; \`failed\` means selected runtime evidence failed; \`unsupported\` is a platform boundary; and \`degraded\` means the capability passed while the managed runtime has a warning.
|
||||||
|
|
||||||
The developer-only fallback is \`node references/support/runtime-bootstrap.mjs install --source <reviewed-checkout> --capability <name> [matching browser flags] --yes\`; show its trust warning and use it only when the user explicitly selects a checkout they reviewed. If the packaged bootstrap is unavailable, stop capability setup instead of guessing a checkout-relative command. Deferring installation records no consent and must not block pure judgment.
|
The developer-only fallback is \`node references/support/runtime-bootstrap.mjs install --source <reviewed-checkout> --capability <name> [matching browser flags] --yes\`; show its trust warning and use it only when the user explicitly selects a checkout they reviewed. If the packaged bootstrap is unavailable, stop capability setup instead of guessing a checkout-relative command. Deferring installation records no consent and must not block pure judgment.
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
@@ -567,6 +573,7 @@ function writeSharedContracts(): void {
|
|||||||
const browserChoice = fs.readFileSync(path.join(ROOT, 'runtime', 'browser-choice.mjs'));
|
const browserChoice = fs.readFileSync(path.join(ROOT, 'runtime', 'browser-choice.mjs'));
|
||||||
const browserSmoke = fs.readFileSync(path.join(ROOT, 'runtime', 'browser-provider-smoke.mjs'));
|
const browserSmoke = fs.readFileSync(path.join(ROOT, 'runtime', 'browser-provider-smoke.mjs'));
|
||||||
for (const tree of TREE_NAMES) {
|
for (const tree of TREE_NAMES) {
|
||||||
|
write(path.join(ROOT, 'skills', tree, 'references', 'EXECUTION-PROFILES.md'), `${GENERATED}\n${renderExecutionProfiles()}`);
|
||||||
write(path.join(ROOT, 'skills', tree, 'references', 'SHARED-JUDGMENT.md'), sharedJudgmentContract());
|
write(path.join(ROOT, 'skills', tree, 'references', 'SHARED-JUDGMENT.md'), sharedJudgmentContract());
|
||||||
write(path.join(ROOT, 'skills', tree, 'references', 'AUTHORITY-POLICY.md'), authorityPolicyContract());
|
write(path.join(ROOT, 'skills', tree, 'references', 'AUTHORITY-POLICY.md'), authorityPolicyContract());
|
||||||
write(path.join(ROOT, 'skills', tree, 'references', 'WEB-CONTEXT.md'), webContextContract());
|
write(path.join(ROOT, 'skills', tree, 'references', 'WEB-CONTEXT.md'), webContextContract());
|
||||||
@@ -576,6 +583,7 @@ function writeSharedContracts(): void {
|
|||||||
write(path.join(ROOT, 'skills', tree, 'references', 'support', 'browser-choice.mjs'), browserChoice);
|
write(path.join(ROOT, 'skills', tree, 'references', 'support', 'browser-choice.mjs'), browserChoice);
|
||||||
write(path.join(ROOT, 'skills', tree, 'references', 'support', 'browser-provider-smoke.mjs'), browserSmoke);
|
write(path.join(ROOT, 'skills', tree, 'references', 'support', 'browser-provider-smoke.mjs'), browserSmoke);
|
||||||
writeJson(path.join(ROOT, 'skills', tree, 'references', 'support', 'runtime-contract.json'), RUNTIME_SKILL_CONTRACT);
|
writeJson(path.join(ROOT, 'skills', tree, 'references', 'support', 'runtime-contract.json'), RUNTIME_SKILL_CONTRACT);
|
||||||
|
writeJson(path.join(ROOT, 'skills', tree, 'references', 'support', 'execution-result-contract.json'), EXECUTION_RESULT_SCHEMA);
|
||||||
}
|
}
|
||||||
write(path.join(ROOT, 'skills', 'qa', 'references', 'SYSTEM-FUNCTIONAL.md'), systemFunctionalContract());
|
write(path.join(ROOT, 'skills', 'qa', 'references', 'SYSTEM-FUNCTIONAL.md'), systemFunctionalContract());
|
||||||
write(path.join(ROOT, 'skills', 'ship', 'references', 'EXTERNAL-EFFECTS.md'), externalEffectsContract());
|
write(path.join(ROOT, 'skills', 'ship', 'references', 'EXTERNAL-EFFECTS.md'), externalEffectsContract());
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ export interface StructuredHostResult {
|
|||||||
target: string;
|
target: string;
|
||||||
skill: PublicSkill;
|
skill: PublicSkill;
|
||||||
mode: string;
|
mode: string;
|
||||||
depth: 'quick' | 'standard' | 'deep';
|
depth: 'readiness' | 'standard' | 'deep';
|
||||||
mutation: string;
|
mutation: string;
|
||||||
active_modules: string[];
|
active_modules: string[];
|
||||||
skipped_modules: string[];
|
skipped_modules: string[];
|
||||||
@@ -236,7 +236,7 @@ export const FINAL_OUTPUT_SCHEMA = {
|
|||||||
target: { type: 'string' },
|
target: { type: 'string' },
|
||||||
skill: { type: 'string', enum: [...PUBLIC_SKILLS] },
|
skill: { type: 'string', enum: [...PUBLIC_SKILLS] },
|
||||||
mode: { type: 'string' },
|
mode: { type: 'string' },
|
||||||
depth: { type: 'string', enum: ['quick', 'standard', 'deep'] },
|
depth: { type: 'string', enum: ['readiness', 'standard', 'deep'] },
|
||||||
mutation: { type: 'string' },
|
mutation: { type: 'string' },
|
||||||
active_modules: { type: 'array', items: { type: 'string' } },
|
active_modules: { type: 'array', items: { type: 'string' } },
|
||||||
skipped_modules: { type: 'array', items: { type: 'string' } },
|
skipped_modules: { type: 'array', items: { type: 'string' } },
|
||||||
@@ -625,7 +625,7 @@ export function validateStructuredResult(value: unknown): value is StructuredHos
|
|||||||
route && typeof route.target === 'string'
|
route && typeof route.target === 'string'
|
||||||
&& PUBLIC_SKILLS.includes(route.skill)
|
&& PUBLIC_SKILLS.includes(route.skill)
|
||||||
&& typeof route.mode === 'string'
|
&& typeof route.mode === 'string'
|
||||||
&& ['quick', 'standard', 'deep'].includes(route.depth)
|
&& ['readiness', 'standard', 'deep'].includes(route.depth)
|
||||||
&& typeof route.mutation === 'string'
|
&& typeof route.mutation === 'string'
|
||||||
&& isStringArray(route.active_modules)
|
&& isStringArray(route.active_modules)
|
||||||
&& isStringArray(route.skipped_modules)
|
&& isStringArray(route.skipped_modules)
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { DISPATCHERS, SOURCE_ASSIGNMENTS, assignmentBySource } from './assignments';
|
import { DISPATCHERS, SOURCE_ASSIGNMENTS, assignmentBySource } from './assignments';
|
||||||
import type { ScenarioFixture, TreeName } from './types';
|
import type { ScenarioFixture, TreeName } from './types';
|
||||||
import { evaluateAuthorityPolicy, type AdversarialAttempt } from './authority-policy';
|
import { evaluateAuthorityPolicy, type AdversarialAttempt } from './authority-policy';
|
||||||
|
import { inferExecutionProfile } from './execution-profiles';
|
||||||
|
|
||||||
export interface StructuredRoute {
|
export interface StructuredRoute {
|
||||||
tree: TreeName;
|
tree: TreeName;
|
||||||
@@ -154,7 +155,7 @@ export function routeStructured(signals: Record<string, unknown>): StructuredRou
|
|||||||
return {
|
return {
|
||||||
tree,
|
tree,
|
||||||
mode,
|
mode,
|
||||||
depth: specialist.defaultDepth,
|
depth: inferExecutionProfile(signals, specialist.defaultDepth),
|
||||||
mutation,
|
mutation,
|
||||||
active_modules: active,
|
active_modules: active,
|
||||||
skipped_modules: primary.filter((candidate) => !active.includes(candidate)),
|
skipped_modules: primary.filter((candidate) => !active.includes(candidate)),
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
#!/usr/bin/env bun
|
||||||
|
|
||||||
|
import { collectFreeTestFiles } from '../test-free-shards';
|
||||||
|
import { runStrictTestShard } from '../test-free-strict';
|
||||||
|
|
||||||
|
const GSTACK2_TEST_TIMEOUT_MS = 30_000;
|
||||||
|
const files = collectFreeTestFiles().filter((file) => /^test\/gstack2-.*\.test\.ts$/.test(file));
|
||||||
|
|
||||||
|
if (files.length === 0) {
|
||||||
|
throw new Error('No GStack 2 test files were discovered.');
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`[test:gstack2] ${files.length} files across ${files.length} isolated processes`);
|
||||||
|
for (let index = 0; index < files.length; index += 1) {
|
||||||
|
const file = files[index];
|
||||||
|
console.log(`[test:gstack2] file ${index + 1}/${files.length}: ${file}`);
|
||||||
|
const exitCode = await runStrictTestShard([file], GSTACK2_TEST_TIMEOUT_MS);
|
||||||
|
if (exitCode !== 0) {
|
||||||
|
process.exitCode = exitCode;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@ export const GSTACK2_BASE_SHA = 'bb57306d98c97011b0919c6132705a15b1579781';
|
|||||||
|
|
||||||
export const TREE_NAMES = ['plan', 'design', 'qa', 'debug', 'review', 'ship'] as const;
|
export const TREE_NAMES = ['plan', 'design', 'qa', 'debug', 'review', 'ship'] as const;
|
||||||
export type TreeName = (typeof TREE_NAMES)[number];
|
export type TreeName = (typeof TREE_NAMES)[number];
|
||||||
|
export type ExecutionProfile = 'readiness' | 'standard' | 'deep';
|
||||||
|
|
||||||
export type ModuleVisibility = 'primary' | 'internal';
|
export type ModuleVisibility = 'primary' | 'internal';
|
||||||
|
|
||||||
@@ -27,7 +28,7 @@ export interface SourceAssignment {
|
|||||||
mandatory: boolean;
|
mandatory: boolean;
|
||||||
replacement: string;
|
replacement: string;
|
||||||
summary: string;
|
summary: string;
|
||||||
defaultDepth: 'quick' | 'standard' | 'deep';
|
defaultDepth: ExecutionProfile;
|
||||||
defaultMutation: string;
|
defaultMutation: string;
|
||||||
webContext: 'none' | 'optional' | 'local-browser' | 'production';
|
webContext: 'none' | 'optional' | 'local-browser' | 'production';
|
||||||
overlays?: number[];
|
overlays?: number[];
|
||||||
@@ -39,7 +40,7 @@ export interface DispatcherMode {
|
|||||||
target: string;
|
target: string;
|
||||||
modules: string[];
|
modules: string[];
|
||||||
inferWhen: string;
|
inferWhen: string;
|
||||||
depth: 'quick' | 'standard' | 'deep';
|
depth: ExecutionProfile;
|
||||||
mutation: string;
|
mutation: string;
|
||||||
webContext: 'none' | 'optional' | 'local-browser' | 'production';
|
webContext: 'none' | 'optional' | 'local-browser' | 'production';
|
||||||
}
|
}
|
||||||
@@ -75,7 +76,7 @@ export interface ScenarioFixture {
|
|||||||
expected: {
|
expected: {
|
||||||
tree: TreeName;
|
tree: TreeName;
|
||||||
mode: string;
|
mode: string;
|
||||||
depth: 'quick' | 'standard' | 'deep';
|
depth: ExecutionProfile;
|
||||||
mutation: string;
|
mutation: string;
|
||||||
active_modules: string[];
|
active_modules: string[];
|
||||||
skipped_modules: string[];
|
skipped_modules: string[];
|
||||||
|
|||||||
@@ -302,8 +302,11 @@ export function planBoundedFreeTestShards(
|
|||||||
return shards;
|
return shards;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function buildShardArgs(files: string[]): string[] {
|
export function buildShardArgs(files: string[], timeoutMs = FREE_TEST_TIMEOUT_MS): string[] {
|
||||||
return ['test', ...files, '--max-concurrency=1', `--timeout=${FREE_TEST_TIMEOUT_MS}`];
|
if (!Number.isInteger(timeoutMs) || timeoutMs <= 0) {
|
||||||
|
throw new Error(`Test timeout must be a positive integer. Received: ${timeoutMs}`);
|
||||||
|
}
|
||||||
|
return ['test', ...files, '--max-concurrency=1', `--timeout=${timeoutMs}`];
|
||||||
}
|
}
|
||||||
|
|
||||||
type CliOptions = {
|
type CliOptions = {
|
||||||
|
|||||||
@@ -261,9 +261,12 @@ export async function runDefaultFreeTests(): Promise<number> {
|
|||||||
return slopSignal === null ? 0 : terminationSignalExitCode(slopSignal);
|
return slopSignal === null ? 0 : terminationSignalExitCode(slopSignal);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function runStrictTestShard(files: string[]): Promise<number> {
|
export async function runStrictTestShard(
|
||||||
|
files: string[],
|
||||||
|
timeoutMs?: number,
|
||||||
|
): Promise<number> {
|
||||||
if (files.length === 0) throw new Error('Cannot run an empty free-test shard.');
|
if (files.length === 0) throw new Error('Cannot run an empty free-test shard.');
|
||||||
const child = spawn(process.execPath, buildShardArgs(exactTestFileSelectors(files)), {
|
const child = spawn(process.execPath, buildShardArgs(exactTestFileSelectors(files), timeoutMs), {
|
||||||
cwd: ROOT,
|
cwd: ROOT,
|
||||||
env: process.env,
|
env: process.env,
|
||||||
stdio: ['inherit', 'pipe', 'pipe'],
|
stdio: ['inherit', 'pipe', 'pipe'],
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ Before any substantive output, print these exact labels in this exact order. Res
|
|||||||
```text
|
```text
|
||||||
Target: <concrete repository, product, URL, device, PR, or artifact>
|
Target: <concrete repository, product, URL, device, PR, or artifact>
|
||||||
Mode: <selected top-level mode>
|
Mode: <selected top-level mode>
|
||||||
Depth: <quick, standard, or deep>
|
Depth: <readiness, standard, or deep>
|
||||||
Mutation: <report-only or exact authorized mutation boundary>
|
Mutation: <report-only or exact authorized mutation boundary>
|
||||||
Active modules: <comma-separated internal specialist modules>
|
Active modules: <comma-separated internal specialist modules>
|
||||||
Skipped modules: <comma-separated non-active mandatory modules with compact reasons>
|
Skipped modules: <comma-separated non-active mandatory modules with compact reasons>
|
||||||
@@ -27,7 +27,7 @@ Web context: <none, optional, local-browser, or production>
|
|||||||
1. Infer the mode from product stage, surface, requested artifact, mutation authorization, evidence needs, and deployment state. Do not route by keyword alone.
|
1. Infer the mode from product stage, surface, requested artifact, mutation authorization, evidence needs, and deployment state. Do not route by keyword alone.
|
||||||
2. Refine the public mode to the smallest applicable internal specialist set, then print the required execution header before any substantive output.
|
2. Refine the public mode to the smallest applicable internal specialist set, then print the required execution header before any substantive output.
|
||||||
3. Read each active module in full from the path shown in the mode/alias tables. Its specialist body, behavioral contract, STOP gates, and appended upstream judgment ports are binding. Read a lazy specialist phase in full only when the workflow reaches its package-local reference.
|
3. Read each active module in full from the path shown in the mode/alias tables. Its specialist body, behavioral contract, STOP gates, and appended upstream judgment ports are binding. Read a lazy specialist phase in full only when the workflow reaches its package-local reference.
|
||||||
4. Read `references/SHARED-JUDGMENT.md` and `references/AUTHORITY-POLICY.md` for every invocation. Read `references/RUNTIME.md` before capability-dependent work and `references/WEB-CONTEXT.md` before public-web work.
|
4. Read `references/EXECUTION-PROFILES.md`, `references/SHARED-JUDGMENT.md`, and `references/AUTHORITY-POLICY.md` for every invocation. Infer Depth from structured operating conditions, then obey its mandatory modules, legal skips, artifacts, and claim limits. Read `references/RUNTIME.md` before capability-dependent work and `references/WEB-CONTEXT.md` before public-web work.
|
||||||
5. If an old asset path is unavailable, use `references/ASSETS.md`. If legacy prose invokes another retired skill, resolve it through `references/COMPATIBILITY.md` and stay inside these six dispatchers.
|
5. If an old asset path is unavailable, use `references/ASSETS.md`. If legacy prose invokes another retired skill, resolve it through `references/COMPATIBILITY.md` and stay inside these six dispatchers.
|
||||||
6. Preserve report-only versus mutation boundaries. Missing mutation authorization fails closed: do not edit merely because a specialist can fix. Commits, pushes, PRs, merges, deploys, messages, and other external mutations still require affirmative authority from the user.
|
6. Preserve report-only versus mutation boundaries. Missing mutation authorization fails closed: do not edit merely because a specialist can fix. Commits, pushes, PRs, merges, deploys, messages, and other external mutations still require affirmative authority from the user.
|
||||||
7. Match the user's language. Keep code identifiers, commands, and source quotations original when translation would reduce accuracy.
|
7. Match the user's language. Keep code identifiers, commands, and source quotations original when translation would reduce accuracy.
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
<!-- GENERATED by scripts/gstack2/generate-skill-tree.ts; do not edit. -->
|
||||||
|
# Inferred execution profiles
|
||||||
|
|
||||||
|
Choose a profile from product stage, mutation authority, risk/evidence needs, and deployment state. Prompt keywords and a request to “be quick” are not routing evidence. A profile narrows or strengthens evidence; it never overrides a specialist’s binding question order, pressure, gates, mutation boundary, or exit behavior.
|
||||||
|
|
||||||
|
## Smoke/readiness
|
||||||
|
|
||||||
|
- Infer when: A narrow, reversible, pre-deployment or operational readiness decision needs bounded evidence; the requested claim is readiness, not completeness.
|
||||||
|
- Mandatory modules: Every selected specialist module remains mandatory. Run its entry gates and the smallest source-authorized evidence path that can answer the readiness question.
|
||||||
|
- Legal skips: Only source-declared conditional work whose condition is demonstrably false, or evidence unavailable after a named attempt. Never skip a STOP gate, approval boundary, reproduction/root-cause gate, or required physical-device/production evidence.
|
||||||
|
- Artifacts: A readiness record naming the exact scope, probes run, evidence and freshness, failures, skipped work with reasons, and the next standard/deep step.
|
||||||
|
- Claims: Only ready/not-ready for the named bounded decision. Must say “Readiness profile — not a complete review.” Never claim comprehensive, fully verified, production-safe, or no issues found outside the inspected scope.
|
||||||
|
|
||||||
|
## Standard
|
||||||
|
|
||||||
|
- Infer when: Normal feature or change work has bounded scope and risk and needs the selected specialist’s complete default workflow.
|
||||||
|
- Mandatory modules: Every selected specialist module and all of its mandatory phases, gates, artifacts, and exit checks.
|
||||||
|
- Legal skips: Only smart skips explicitly authorized by the specialist and supported by inspected evidence; list each skipped primary module and each skipped conditional phase.
|
||||||
|
- Artifacts: Every artifact required by the selected specialist, plus evidence provenance, unresolved decisions, and a skip ledger.
|
||||||
|
- Claims: Complete only for the named specialist scope and evidence layer. Broader product, security, production, or device claims require those modules and evidence.
|
||||||
|
|
||||||
|
## Deep
|
||||||
|
|
||||||
|
- Infer when: Risk, ambiguity, blast radius, cross-system effects, irreversible mutation, security/reliability needs, or production deployment demands stronger evidence.
|
||||||
|
- Mandatory modules: Every selected specialist module, all mandatory phases and outside-voice/cross-consumer modules selected by the dispatcher, with unchanged STOP and approval gates.
|
||||||
|
- Legal skips: Only specialist-authorized smart skips proven irrelevant. Missing, stale, malformed, or contradictory evidence is a gap or blocker, never a successful skip.
|
||||||
|
- Artifacts: All specialist artifacts plus changed-input/unchanged-consumer trace, negative and failure-path evidence, provenance/freshness, rollback or reversibility evidence where applicable, and unresolved-risk ledger.
|
||||||
|
- Claims: Complete only across the explicitly listed modules and evidence layers. “Confirmed” requires independent supporting evidence; production/device/security claims require matching production/device/security evidence.
|
||||||
@@ -23,4 +23,8 @@ Some retained helpers are shell scripts. `gstack doctor` verifies Bash and, on W
|
|||||||
|
|
||||||
The package/runtime compatibility tuple is `schemaVersion=1`, `runtimeVersion=2.0.0`, and `skillApi=2.0`; the machine-readable copy is `references/support/runtime-contract.json`. An incompatible active runtime is unavailable, not permission to upgrade it.
|
The package/runtime compatibility tuple is `schemaVersion=1`, `runtimeVersion=2.0.0`, and `skillApi=2.0`; the machine-readable copy is `references/support/runtime-contract.json`. An incompatible active runtime is unavailable, not permission to upgrade it.
|
||||||
|
|
||||||
|
Every optional-runtime tool result must satisfy `references/support/execution-result-contract.json` before it is presented as success. Success requires non-empty evidence. Empty or malformed output and explicit degraded, unsupported, or failed statuses remain non-success with stable codes; human renderings must preserve that status and code.
|
||||||
|
|
||||||
|
Use `gstack doctor --capability browser|design|diagram|pdf|ios` (optionally `--json`) for a non-mutating, capability-specific readiness result. Its independent axes must remain distinct: pure judgment availability, platform support, preview consent, install consent, and runtime readiness. Readiness is exactly `ready`, `degraded`, `unavailable`, `unsupported`, or `failed`. Doctor never grants or persists consent, previews metadata, or installs anything. `unavailable` means setup may be offered; `failed` means selected runtime evidence failed; `unsupported` is a platform boundary; and `degraded` means the capability passed while the managed runtime has a warning.
|
||||||
|
|
||||||
The developer-only fallback is `node references/support/runtime-bootstrap.mjs install --source <reviewed-checkout> --capability <name> [matching browser flags] --yes`; show its trust warning and use it only when the user explicitly selects a checkout they reviewed. If the packaged bootstrap is unavailable, stop capability setup instead of guessing a checkout-relative command. Deferring installation records no consent and must not block pure judgment.
|
The developer-only fallback is `node references/support/runtime-bootstrap.mjs install --source <reviewed-checkout> --capability <name> [matching browser flags] --yes`; show its trust warning and use it only when the user explicitly selects a checkout they reviewed. If the packaged bootstrap is unavailable, stop capability setup instead of guessing a checkout-relative command. Deferring installation records no consent and must not block pure judgment.
|
||||||
|
|||||||
@@ -0,0 +1,88 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||||
|
"$id": "https://gstack.dev/schemas/execution-result-v1.json",
|
||||||
|
"title": "GStack execution result",
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"schemaVersion",
|
||||||
|
"status",
|
||||||
|
"code",
|
||||||
|
"summary",
|
||||||
|
"evidence",
|
||||||
|
"data"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"schemaVersion": {
|
||||||
|
"const": 1
|
||||||
|
},
|
||||||
|
"status": {
|
||||||
|
"enum": [
|
||||||
|
"success",
|
||||||
|
"degraded",
|
||||||
|
"unsupported",
|
||||||
|
"failed"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"code": {
|
||||||
|
"type": [
|
||||||
|
"string",
|
||||||
|
"null"
|
||||||
|
],
|
||||||
|
"pattern": "^[A-Z][A-Z0-9_]{2,63}$"
|
||||||
|
},
|
||||||
|
"summary": {
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 1
|
||||||
|
},
|
||||||
|
"evidence": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"data": {}
|
||||||
|
},
|
||||||
|
"allOf": [
|
||||||
|
{
|
||||||
|
"if": {
|
||||||
|
"properties": {
|
||||||
|
"status": {
|
||||||
|
"const": "success"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"then": {
|
||||||
|
"properties": {
|
||||||
|
"code": {
|
||||||
|
"type": "null"
|
||||||
|
},
|
||||||
|
"evidence": {
|
||||||
|
"minItems": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"if": {
|
||||||
|
"properties": {
|
||||||
|
"status": {
|
||||||
|
"enum": [
|
||||||
|
"degraded",
|
||||||
|
"unsupported",
|
||||||
|
"failed"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"then": {
|
||||||
|
"properties": {
|
||||||
|
"code": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -15,7 +15,7 @@ Before any substantive output, print these exact labels in this exact order. Res
|
|||||||
```text
|
```text
|
||||||
Target: <concrete repository, product, URL, device, PR, or artifact>
|
Target: <concrete repository, product, URL, device, PR, or artifact>
|
||||||
Mode: <selected top-level mode>
|
Mode: <selected top-level mode>
|
||||||
Depth: <quick, standard, or deep>
|
Depth: <readiness, standard, or deep>
|
||||||
Mutation: <report-only or exact authorized mutation boundary>
|
Mutation: <report-only or exact authorized mutation boundary>
|
||||||
Active modules: <comma-separated internal specialist modules>
|
Active modules: <comma-separated internal specialist modules>
|
||||||
Skipped modules: <comma-separated non-active mandatory modules with compact reasons>
|
Skipped modules: <comma-separated non-active mandatory modules with compact reasons>
|
||||||
@@ -27,7 +27,7 @@ Web context: <none, optional, local-browser, or production>
|
|||||||
1. Infer the mode from product stage, surface, requested artifact, mutation authorization, evidence needs, and deployment state. Do not route by keyword alone.
|
1. Infer the mode from product stage, surface, requested artifact, mutation authorization, evidence needs, and deployment state. Do not route by keyword alone.
|
||||||
2. Refine the public mode to the smallest applicable internal specialist set, then print the required execution header before any substantive output.
|
2. Refine the public mode to the smallest applicable internal specialist set, then print the required execution header before any substantive output.
|
||||||
3. Read each active module in full from the path shown in the mode/alias tables. Its specialist body, behavioral contract, STOP gates, and appended upstream judgment ports are binding. Read a lazy specialist phase in full only when the workflow reaches its package-local reference.
|
3. Read each active module in full from the path shown in the mode/alias tables. Its specialist body, behavioral contract, STOP gates, and appended upstream judgment ports are binding. Read a lazy specialist phase in full only when the workflow reaches its package-local reference.
|
||||||
4. Read `references/SHARED-JUDGMENT.md` and `references/AUTHORITY-POLICY.md` for every invocation. Read `references/RUNTIME.md` before capability-dependent work and `references/WEB-CONTEXT.md` before public-web work.
|
4. Read `references/EXECUTION-PROFILES.md`, `references/SHARED-JUDGMENT.md`, and `references/AUTHORITY-POLICY.md` for every invocation. Infer Depth from structured operating conditions, then obey its mandatory modules, legal skips, artifacts, and claim limits. Read `references/RUNTIME.md` before capability-dependent work and `references/WEB-CONTEXT.md` before public-web work.
|
||||||
5. If an old asset path is unavailable, use `references/ASSETS.md`. If legacy prose invokes another retired skill, resolve it through `references/COMPATIBILITY.md` and stay inside these six dispatchers.
|
5. If an old asset path is unavailable, use `references/ASSETS.md`. If legacy prose invokes another retired skill, resolve it through `references/COMPATIBILITY.md` and stay inside these six dispatchers.
|
||||||
6. Preserve report-only versus mutation boundaries. Missing mutation authorization fails closed: do not edit merely because a specialist can fix. Commits, pushes, PRs, merges, deploys, messages, and other external mutations still require affirmative authority from the user.
|
6. Preserve report-only versus mutation boundaries. Missing mutation authorization fails closed: do not edit merely because a specialist can fix. Commits, pushes, PRs, merges, deploys, messages, and other external mutations still require affirmative authority from the user.
|
||||||
7. Match the user's language. Keep code identifiers, commands, and source quotations original when translation would reduce accuracy.
|
7. Match the user's language. Keep code identifiers, commands, and source quotations original when translation would reduce accuracy.
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
<!-- GENERATED by scripts/gstack2/generate-skill-tree.ts; do not edit. -->
|
||||||
|
# Inferred execution profiles
|
||||||
|
|
||||||
|
Choose a profile from product stage, mutation authority, risk/evidence needs, and deployment state. Prompt keywords and a request to “be quick” are not routing evidence. A profile narrows or strengthens evidence; it never overrides a specialist’s binding question order, pressure, gates, mutation boundary, or exit behavior.
|
||||||
|
|
||||||
|
## Smoke/readiness
|
||||||
|
|
||||||
|
- Infer when: A narrow, reversible, pre-deployment or operational readiness decision needs bounded evidence; the requested claim is readiness, not completeness.
|
||||||
|
- Mandatory modules: Every selected specialist module remains mandatory. Run its entry gates and the smallest source-authorized evidence path that can answer the readiness question.
|
||||||
|
- Legal skips: Only source-declared conditional work whose condition is demonstrably false, or evidence unavailable after a named attempt. Never skip a STOP gate, approval boundary, reproduction/root-cause gate, or required physical-device/production evidence.
|
||||||
|
- Artifacts: A readiness record naming the exact scope, probes run, evidence and freshness, failures, skipped work with reasons, and the next standard/deep step.
|
||||||
|
- Claims: Only ready/not-ready for the named bounded decision. Must say “Readiness profile — not a complete review.” Never claim comprehensive, fully verified, production-safe, or no issues found outside the inspected scope.
|
||||||
|
|
||||||
|
## Standard
|
||||||
|
|
||||||
|
- Infer when: Normal feature or change work has bounded scope and risk and needs the selected specialist’s complete default workflow.
|
||||||
|
- Mandatory modules: Every selected specialist module and all of its mandatory phases, gates, artifacts, and exit checks.
|
||||||
|
- Legal skips: Only smart skips explicitly authorized by the specialist and supported by inspected evidence; list each skipped primary module and each skipped conditional phase.
|
||||||
|
- Artifacts: Every artifact required by the selected specialist, plus evidence provenance, unresolved decisions, and a skip ledger.
|
||||||
|
- Claims: Complete only for the named specialist scope and evidence layer. Broader product, security, production, or device claims require those modules and evidence.
|
||||||
|
|
||||||
|
## Deep
|
||||||
|
|
||||||
|
- Infer when: Risk, ambiguity, blast radius, cross-system effects, irreversible mutation, security/reliability needs, or production deployment demands stronger evidence.
|
||||||
|
- Mandatory modules: Every selected specialist module, all mandatory phases and outside-voice/cross-consumer modules selected by the dispatcher, with unchanged STOP and approval gates.
|
||||||
|
- Legal skips: Only specialist-authorized smart skips proven irrelevant. Missing, stale, malformed, or contradictory evidence is a gap or blocker, never a successful skip.
|
||||||
|
- Artifacts: All specialist artifacts plus changed-input/unchanged-consumer trace, negative and failure-path evidence, provenance/freshness, rollback or reversibility evidence where applicable, and unresolved-risk ledger.
|
||||||
|
- Claims: Complete only across the explicitly listed modules and evidence layers. “Confirmed” requires independent supporting evidence; production/device/security claims require matching production/device/security evidence.
|
||||||
@@ -23,4 +23,8 @@ Some retained helpers are shell scripts. `gstack doctor` verifies Bash and, on W
|
|||||||
|
|
||||||
The package/runtime compatibility tuple is `schemaVersion=1`, `runtimeVersion=2.0.0`, and `skillApi=2.0`; the machine-readable copy is `references/support/runtime-contract.json`. An incompatible active runtime is unavailable, not permission to upgrade it.
|
The package/runtime compatibility tuple is `schemaVersion=1`, `runtimeVersion=2.0.0`, and `skillApi=2.0`; the machine-readable copy is `references/support/runtime-contract.json`. An incompatible active runtime is unavailable, not permission to upgrade it.
|
||||||
|
|
||||||
|
Every optional-runtime tool result must satisfy `references/support/execution-result-contract.json` before it is presented as success. Success requires non-empty evidence. Empty or malformed output and explicit degraded, unsupported, or failed statuses remain non-success with stable codes; human renderings must preserve that status and code.
|
||||||
|
|
||||||
|
Use `gstack doctor --capability browser|design|diagram|pdf|ios` (optionally `--json`) for a non-mutating, capability-specific readiness result. Its independent axes must remain distinct: pure judgment availability, platform support, preview consent, install consent, and runtime readiness. Readiness is exactly `ready`, `degraded`, `unavailable`, `unsupported`, or `failed`. Doctor never grants or persists consent, previews metadata, or installs anything. `unavailable` means setup may be offered; `failed` means selected runtime evidence failed; `unsupported` is a platform boundary; and `degraded` means the capability passed while the managed runtime has a warning.
|
||||||
|
|
||||||
The developer-only fallback is `node references/support/runtime-bootstrap.mjs install --source <reviewed-checkout> --capability <name> [matching browser flags] --yes`; show its trust warning and use it only when the user explicitly selects a checkout they reviewed. If the packaged bootstrap is unavailable, stop capability setup instead of guessing a checkout-relative command. Deferring installation records no consent and must not block pure judgment.
|
The developer-only fallback is `node references/support/runtime-bootstrap.mjs install --source <reviewed-checkout> --capability <name> [matching browser flags] --yes`; show its trust warning and use it only when the user explicitly selects a checkout they reviewed. If the packaged bootstrap is unavailable, stop capability setup instead of guessing a checkout-relative command. Deferring installation records no consent and must not block pure judgment.
|
||||||
|
|||||||
@@ -0,0 +1,88 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||||
|
"$id": "https://gstack.dev/schemas/execution-result-v1.json",
|
||||||
|
"title": "GStack execution result",
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"schemaVersion",
|
||||||
|
"status",
|
||||||
|
"code",
|
||||||
|
"summary",
|
||||||
|
"evidence",
|
||||||
|
"data"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"schemaVersion": {
|
||||||
|
"const": 1
|
||||||
|
},
|
||||||
|
"status": {
|
||||||
|
"enum": [
|
||||||
|
"success",
|
||||||
|
"degraded",
|
||||||
|
"unsupported",
|
||||||
|
"failed"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"code": {
|
||||||
|
"type": [
|
||||||
|
"string",
|
||||||
|
"null"
|
||||||
|
],
|
||||||
|
"pattern": "^[A-Z][A-Z0-9_]{2,63}$"
|
||||||
|
},
|
||||||
|
"summary": {
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 1
|
||||||
|
},
|
||||||
|
"evidence": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"data": {}
|
||||||
|
},
|
||||||
|
"allOf": [
|
||||||
|
{
|
||||||
|
"if": {
|
||||||
|
"properties": {
|
||||||
|
"status": {
|
||||||
|
"const": "success"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"then": {
|
||||||
|
"properties": {
|
||||||
|
"code": {
|
||||||
|
"type": "null"
|
||||||
|
},
|
||||||
|
"evidence": {
|
||||||
|
"minItems": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"if": {
|
||||||
|
"properties": {
|
||||||
|
"status": {
|
||||||
|
"enum": [
|
||||||
|
"degraded",
|
||||||
|
"unsupported",
|
||||||
|
"failed"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"then": {
|
||||||
|
"properties": {
|
||||||
|
"code": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -15,7 +15,7 @@ Before any substantive output, print these exact labels in this exact order. Res
|
|||||||
```text
|
```text
|
||||||
Target: <concrete repository, product, URL, device, PR, or artifact>
|
Target: <concrete repository, product, URL, device, PR, or artifact>
|
||||||
Mode: <selected top-level mode>
|
Mode: <selected top-level mode>
|
||||||
Depth: <quick, standard, or deep>
|
Depth: <readiness, standard, or deep>
|
||||||
Mutation: <report-only or exact authorized mutation boundary>
|
Mutation: <report-only or exact authorized mutation boundary>
|
||||||
Active modules: <comma-separated internal specialist modules>
|
Active modules: <comma-separated internal specialist modules>
|
||||||
Skipped modules: <comma-separated non-active mandatory modules with compact reasons>
|
Skipped modules: <comma-separated non-active mandatory modules with compact reasons>
|
||||||
@@ -27,7 +27,7 @@ Web context: <none, optional, local-browser, or production>
|
|||||||
1. Infer the mode from product stage, surface, requested artifact, mutation authorization, evidence needs, and deployment state. Do not route by keyword alone.
|
1. Infer the mode from product stage, surface, requested artifact, mutation authorization, evidence needs, and deployment state. Do not route by keyword alone.
|
||||||
2. Refine the public mode to the smallest applicable internal specialist set, then print the required execution header before any substantive output.
|
2. Refine the public mode to the smallest applicable internal specialist set, then print the required execution header before any substantive output.
|
||||||
3. Read each active module in full from the path shown in the mode/alias tables. Its specialist body, behavioral contract, STOP gates, and appended upstream judgment ports are binding. Read a lazy specialist phase in full only when the workflow reaches its package-local reference.
|
3. Read each active module in full from the path shown in the mode/alias tables. Its specialist body, behavioral contract, STOP gates, and appended upstream judgment ports are binding. Read a lazy specialist phase in full only when the workflow reaches its package-local reference.
|
||||||
4. Read `references/SHARED-JUDGMENT.md` and `references/AUTHORITY-POLICY.md` for every invocation. Read `references/RUNTIME.md` before capability-dependent work and `references/WEB-CONTEXT.md` before public-web work.
|
4. Read `references/EXECUTION-PROFILES.md`, `references/SHARED-JUDGMENT.md`, and `references/AUTHORITY-POLICY.md` for every invocation. Infer Depth from structured operating conditions, then obey its mandatory modules, legal skips, artifacts, and claim limits. Read `references/RUNTIME.md` before capability-dependent work and `references/WEB-CONTEXT.md` before public-web work.
|
||||||
5. If an old asset path is unavailable, use `references/ASSETS.md`. If legacy prose invokes another retired skill, resolve it through `references/COMPATIBILITY.md` and stay inside these six dispatchers.
|
5. If an old asset path is unavailable, use `references/ASSETS.md`. If legacy prose invokes another retired skill, resolve it through `references/COMPATIBILITY.md` and stay inside these six dispatchers.
|
||||||
6. Preserve report-only versus mutation boundaries. Missing mutation authorization fails closed: do not edit merely because a specialist can fix. Commits, pushes, PRs, merges, deploys, messages, and other external mutations still require affirmative authority from the user.
|
6. Preserve report-only versus mutation boundaries. Missing mutation authorization fails closed: do not edit merely because a specialist can fix. Commits, pushes, PRs, merges, deploys, messages, and other external mutations still require affirmative authority from the user.
|
||||||
7. Match the user's language. Keep code identifiers, commands, and source quotations original when translation would reduce accuracy.
|
7. Match the user's language. Keep code identifiers, commands, and source quotations original when translation would reduce accuracy.
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
<!-- GENERATED by scripts/gstack2/generate-skill-tree.ts; do not edit. -->
|
||||||
|
# Inferred execution profiles
|
||||||
|
|
||||||
|
Choose a profile from product stage, mutation authority, risk/evidence needs, and deployment state. Prompt keywords and a request to “be quick” are not routing evidence. A profile narrows or strengthens evidence; it never overrides a specialist’s binding question order, pressure, gates, mutation boundary, or exit behavior.
|
||||||
|
|
||||||
|
## Smoke/readiness
|
||||||
|
|
||||||
|
- Infer when: A narrow, reversible, pre-deployment or operational readiness decision needs bounded evidence; the requested claim is readiness, not completeness.
|
||||||
|
- Mandatory modules: Every selected specialist module remains mandatory. Run its entry gates and the smallest source-authorized evidence path that can answer the readiness question.
|
||||||
|
- Legal skips: Only source-declared conditional work whose condition is demonstrably false, or evidence unavailable after a named attempt. Never skip a STOP gate, approval boundary, reproduction/root-cause gate, or required physical-device/production evidence.
|
||||||
|
- Artifacts: A readiness record naming the exact scope, probes run, evidence and freshness, failures, skipped work with reasons, and the next standard/deep step.
|
||||||
|
- Claims: Only ready/not-ready for the named bounded decision. Must say “Readiness profile — not a complete review.” Never claim comprehensive, fully verified, production-safe, or no issues found outside the inspected scope.
|
||||||
|
|
||||||
|
## Standard
|
||||||
|
|
||||||
|
- Infer when: Normal feature or change work has bounded scope and risk and needs the selected specialist’s complete default workflow.
|
||||||
|
- Mandatory modules: Every selected specialist module and all of its mandatory phases, gates, artifacts, and exit checks.
|
||||||
|
- Legal skips: Only smart skips explicitly authorized by the specialist and supported by inspected evidence; list each skipped primary module and each skipped conditional phase.
|
||||||
|
- Artifacts: Every artifact required by the selected specialist, plus evidence provenance, unresolved decisions, and a skip ledger.
|
||||||
|
- Claims: Complete only for the named specialist scope and evidence layer. Broader product, security, production, or device claims require those modules and evidence.
|
||||||
|
|
||||||
|
## Deep
|
||||||
|
|
||||||
|
- Infer when: Risk, ambiguity, blast radius, cross-system effects, irreversible mutation, security/reliability needs, or production deployment demands stronger evidence.
|
||||||
|
- Mandatory modules: Every selected specialist module, all mandatory phases and outside-voice/cross-consumer modules selected by the dispatcher, with unchanged STOP and approval gates.
|
||||||
|
- Legal skips: Only specialist-authorized smart skips proven irrelevant. Missing, stale, malformed, or contradictory evidence is a gap or blocker, never a successful skip.
|
||||||
|
- Artifacts: All specialist artifacts plus changed-input/unchanged-consumer trace, negative and failure-path evidence, provenance/freshness, rollback or reversibility evidence where applicable, and unresolved-risk ledger.
|
||||||
|
- Claims: Complete only across the explicitly listed modules and evidence layers. “Confirmed” requires independent supporting evidence; production/device/security claims require matching production/device/security evidence.
|
||||||
@@ -23,4 +23,8 @@ Some retained helpers are shell scripts. `gstack doctor` verifies Bash and, on W
|
|||||||
|
|
||||||
The package/runtime compatibility tuple is `schemaVersion=1`, `runtimeVersion=2.0.0`, and `skillApi=2.0`; the machine-readable copy is `references/support/runtime-contract.json`. An incompatible active runtime is unavailable, not permission to upgrade it.
|
The package/runtime compatibility tuple is `schemaVersion=1`, `runtimeVersion=2.0.0`, and `skillApi=2.0`; the machine-readable copy is `references/support/runtime-contract.json`. An incompatible active runtime is unavailable, not permission to upgrade it.
|
||||||
|
|
||||||
|
Every optional-runtime tool result must satisfy `references/support/execution-result-contract.json` before it is presented as success. Success requires non-empty evidence. Empty or malformed output and explicit degraded, unsupported, or failed statuses remain non-success with stable codes; human renderings must preserve that status and code.
|
||||||
|
|
||||||
|
Use `gstack doctor --capability browser|design|diagram|pdf|ios` (optionally `--json`) for a non-mutating, capability-specific readiness result. Its independent axes must remain distinct: pure judgment availability, platform support, preview consent, install consent, and runtime readiness. Readiness is exactly `ready`, `degraded`, `unavailable`, `unsupported`, or `failed`. Doctor never grants or persists consent, previews metadata, or installs anything. `unavailable` means setup may be offered; `failed` means selected runtime evidence failed; `unsupported` is a platform boundary; and `degraded` means the capability passed while the managed runtime has a warning.
|
||||||
|
|
||||||
The developer-only fallback is `node references/support/runtime-bootstrap.mjs install --source <reviewed-checkout> --capability <name> [matching browser flags] --yes`; show its trust warning and use it only when the user explicitly selects a checkout they reviewed. If the packaged bootstrap is unavailable, stop capability setup instead of guessing a checkout-relative command. Deferring installation records no consent and must not block pure judgment.
|
The developer-only fallback is `node references/support/runtime-bootstrap.mjs install --source <reviewed-checkout> --capability <name> [matching browser flags] --yes`; show its trust warning and use it only when the user explicitly selects a checkout they reviewed. If the packaged bootstrap is unavailable, stop capability setup instead of guessing a checkout-relative command. Deferring installation records no consent and must not block pure judgment.
|
||||||
|
|||||||
@@ -0,0 +1,88 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||||
|
"$id": "https://gstack.dev/schemas/execution-result-v1.json",
|
||||||
|
"title": "GStack execution result",
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"schemaVersion",
|
||||||
|
"status",
|
||||||
|
"code",
|
||||||
|
"summary",
|
||||||
|
"evidence",
|
||||||
|
"data"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"schemaVersion": {
|
||||||
|
"const": 1
|
||||||
|
},
|
||||||
|
"status": {
|
||||||
|
"enum": [
|
||||||
|
"success",
|
||||||
|
"degraded",
|
||||||
|
"unsupported",
|
||||||
|
"failed"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"code": {
|
||||||
|
"type": [
|
||||||
|
"string",
|
||||||
|
"null"
|
||||||
|
],
|
||||||
|
"pattern": "^[A-Z][A-Z0-9_]{2,63}$"
|
||||||
|
},
|
||||||
|
"summary": {
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 1
|
||||||
|
},
|
||||||
|
"evidence": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"data": {}
|
||||||
|
},
|
||||||
|
"allOf": [
|
||||||
|
{
|
||||||
|
"if": {
|
||||||
|
"properties": {
|
||||||
|
"status": {
|
||||||
|
"const": "success"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"then": {
|
||||||
|
"properties": {
|
||||||
|
"code": {
|
||||||
|
"type": "null"
|
||||||
|
},
|
||||||
|
"evidence": {
|
||||||
|
"minItems": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"if": {
|
||||||
|
"properties": {
|
||||||
|
"status": {
|
||||||
|
"enum": [
|
||||||
|
"degraded",
|
||||||
|
"unsupported",
|
||||||
|
"failed"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"then": {
|
||||||
|
"properties": {
|
||||||
|
"code": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
+2
-2
@@ -15,7 +15,7 @@ Before any substantive output, print these exact labels in this exact order. Res
|
|||||||
```text
|
```text
|
||||||
Target: <concrete repository, product, URL, device, PR, or artifact>
|
Target: <concrete repository, product, URL, device, PR, or artifact>
|
||||||
Mode: <selected top-level mode>
|
Mode: <selected top-level mode>
|
||||||
Depth: <quick, standard, or deep>
|
Depth: <readiness, standard, or deep>
|
||||||
Mutation: <report-only or exact authorized mutation boundary>
|
Mutation: <report-only or exact authorized mutation boundary>
|
||||||
Active modules: <comma-separated internal specialist modules>
|
Active modules: <comma-separated internal specialist modules>
|
||||||
Skipped modules: <comma-separated non-active mandatory modules with compact reasons>
|
Skipped modules: <comma-separated non-active mandatory modules with compact reasons>
|
||||||
@@ -27,7 +27,7 @@ Web context: <none, optional, local-browser, or production>
|
|||||||
1. Infer the mode from product stage, surface, requested artifact, mutation authorization, evidence needs, and deployment state. Do not route by keyword alone.
|
1. Infer the mode from product stage, surface, requested artifact, mutation authorization, evidence needs, and deployment state. Do not route by keyword alone.
|
||||||
2. Refine the public mode to the smallest applicable internal specialist set, then print the required execution header before any substantive output.
|
2. Refine the public mode to the smallest applicable internal specialist set, then print the required execution header before any substantive output.
|
||||||
3. Read each active module in full from the path shown in the mode/alias tables. Its specialist body, behavioral contract, STOP gates, and appended upstream judgment ports are binding. Read a lazy specialist phase in full only when the workflow reaches its package-local reference.
|
3. Read each active module in full from the path shown in the mode/alias tables. Its specialist body, behavioral contract, STOP gates, and appended upstream judgment ports are binding. Read a lazy specialist phase in full only when the workflow reaches its package-local reference.
|
||||||
4. Read `references/SHARED-JUDGMENT.md` and `references/AUTHORITY-POLICY.md` for every invocation. Read `references/RUNTIME.md` before capability-dependent work and `references/WEB-CONTEXT.md` before public-web work.
|
4. Read `references/EXECUTION-PROFILES.md`, `references/SHARED-JUDGMENT.md`, and `references/AUTHORITY-POLICY.md` for every invocation. Infer Depth from structured operating conditions, then obey its mandatory modules, legal skips, artifacts, and claim limits. Read `references/RUNTIME.md` before capability-dependent work and `references/WEB-CONTEXT.md` before public-web work.
|
||||||
5. If an old asset path is unavailable, use `references/ASSETS.md`. If legacy prose invokes another retired skill, resolve it through `references/COMPATIBILITY.md` and stay inside these six dispatchers.
|
5. If an old asset path is unavailable, use `references/ASSETS.md`. If legacy prose invokes another retired skill, resolve it through `references/COMPATIBILITY.md` and stay inside these six dispatchers.
|
||||||
6. Preserve report-only versus mutation boundaries. Missing mutation authorization fails closed: do not edit merely because a specialist can fix. Commits, pushes, PRs, merges, deploys, messages, and other external mutations still require affirmative authority from the user.
|
6. Preserve report-only versus mutation boundaries. Missing mutation authorization fails closed: do not edit merely because a specialist can fix. Commits, pushes, PRs, merges, deploys, messages, and other external mutations still require affirmative authority from the user.
|
||||||
7. Match the user's language. Keep code identifiers, commands, and source quotations original when translation would reduce accuracy.
|
7. Match the user's language. Keep code identifiers, commands, and source quotations original when translation would reduce accuracy.
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
<!-- GENERATED by scripts/gstack2/generate-skill-tree.ts; do not edit. -->
|
||||||
|
# Inferred execution profiles
|
||||||
|
|
||||||
|
Choose a profile from product stage, mutation authority, risk/evidence needs, and deployment state. Prompt keywords and a request to “be quick” are not routing evidence. A profile narrows or strengthens evidence; it never overrides a specialist’s binding question order, pressure, gates, mutation boundary, or exit behavior.
|
||||||
|
|
||||||
|
## Smoke/readiness
|
||||||
|
|
||||||
|
- Infer when: A narrow, reversible, pre-deployment or operational readiness decision needs bounded evidence; the requested claim is readiness, not completeness.
|
||||||
|
- Mandatory modules: Every selected specialist module remains mandatory. Run its entry gates and the smallest source-authorized evidence path that can answer the readiness question.
|
||||||
|
- Legal skips: Only source-declared conditional work whose condition is demonstrably false, or evidence unavailable after a named attempt. Never skip a STOP gate, approval boundary, reproduction/root-cause gate, or required physical-device/production evidence.
|
||||||
|
- Artifacts: A readiness record naming the exact scope, probes run, evidence and freshness, failures, skipped work with reasons, and the next standard/deep step.
|
||||||
|
- Claims: Only ready/not-ready for the named bounded decision. Must say “Readiness profile — not a complete review.” Never claim comprehensive, fully verified, production-safe, or no issues found outside the inspected scope.
|
||||||
|
|
||||||
|
## Standard
|
||||||
|
|
||||||
|
- Infer when: Normal feature or change work has bounded scope and risk and needs the selected specialist’s complete default workflow.
|
||||||
|
- Mandatory modules: Every selected specialist module and all of its mandatory phases, gates, artifacts, and exit checks.
|
||||||
|
- Legal skips: Only smart skips explicitly authorized by the specialist and supported by inspected evidence; list each skipped primary module and each skipped conditional phase.
|
||||||
|
- Artifacts: Every artifact required by the selected specialist, plus evidence provenance, unresolved decisions, and a skip ledger.
|
||||||
|
- Claims: Complete only for the named specialist scope and evidence layer. Broader product, security, production, or device claims require those modules and evidence.
|
||||||
|
|
||||||
|
## Deep
|
||||||
|
|
||||||
|
- Infer when: Risk, ambiguity, blast radius, cross-system effects, irreversible mutation, security/reliability needs, or production deployment demands stronger evidence.
|
||||||
|
- Mandatory modules: Every selected specialist module, all mandatory phases and outside-voice/cross-consumer modules selected by the dispatcher, with unchanged STOP and approval gates.
|
||||||
|
- Legal skips: Only specialist-authorized smart skips proven irrelevant. Missing, stale, malformed, or contradictory evidence is a gap or blocker, never a successful skip.
|
||||||
|
- Artifacts: All specialist artifacts plus changed-input/unchanged-consumer trace, negative and failure-path evidence, provenance/freshness, rollback or reversibility evidence where applicable, and unresolved-risk ledger.
|
||||||
|
- Claims: Complete only across the explicitly listed modules and evidence layers. “Confirmed” requires independent supporting evidence; production/device/security claims require matching production/device/security evidence.
|
||||||
@@ -23,4 +23,8 @@ Some retained helpers are shell scripts. `gstack doctor` verifies Bash and, on W
|
|||||||
|
|
||||||
The package/runtime compatibility tuple is `schemaVersion=1`, `runtimeVersion=2.0.0`, and `skillApi=2.0`; the machine-readable copy is `references/support/runtime-contract.json`. An incompatible active runtime is unavailable, not permission to upgrade it.
|
The package/runtime compatibility tuple is `schemaVersion=1`, `runtimeVersion=2.0.0`, and `skillApi=2.0`; the machine-readable copy is `references/support/runtime-contract.json`. An incompatible active runtime is unavailable, not permission to upgrade it.
|
||||||
|
|
||||||
|
Every optional-runtime tool result must satisfy `references/support/execution-result-contract.json` before it is presented as success. Success requires non-empty evidence. Empty or malformed output and explicit degraded, unsupported, or failed statuses remain non-success with stable codes; human renderings must preserve that status and code.
|
||||||
|
|
||||||
|
Use `gstack doctor --capability browser|design|diagram|pdf|ios` (optionally `--json`) for a non-mutating, capability-specific readiness result. Its independent axes must remain distinct: pure judgment availability, platform support, preview consent, install consent, and runtime readiness. Readiness is exactly `ready`, `degraded`, `unavailable`, `unsupported`, or `failed`. Doctor never grants or persists consent, previews metadata, or installs anything. `unavailable` means setup may be offered; `failed` means selected runtime evidence failed; `unsupported` is a platform boundary; and `degraded` means the capability passed while the managed runtime has a warning.
|
||||||
|
|
||||||
The developer-only fallback is `node references/support/runtime-bootstrap.mjs install --source <reviewed-checkout> --capability <name> [matching browser flags] --yes`; show its trust warning and use it only when the user explicitly selects a checkout they reviewed. If the packaged bootstrap is unavailable, stop capability setup instead of guessing a checkout-relative command. Deferring installation records no consent and must not block pure judgment.
|
The developer-only fallback is `node references/support/runtime-bootstrap.mjs install --source <reviewed-checkout> --capability <name> [matching browser flags] --yes`; show its trust warning and use it only when the user explicitly selects a checkout they reviewed. If the packaged bootstrap is unavailable, stop capability setup instead of guessing a checkout-relative command. Deferring installation records no consent and must not block pure judgment.
|
||||||
|
|||||||
@@ -0,0 +1,88 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||||
|
"$id": "https://gstack.dev/schemas/execution-result-v1.json",
|
||||||
|
"title": "GStack execution result",
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"schemaVersion",
|
||||||
|
"status",
|
||||||
|
"code",
|
||||||
|
"summary",
|
||||||
|
"evidence",
|
||||||
|
"data"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"schemaVersion": {
|
||||||
|
"const": 1
|
||||||
|
},
|
||||||
|
"status": {
|
||||||
|
"enum": [
|
||||||
|
"success",
|
||||||
|
"degraded",
|
||||||
|
"unsupported",
|
||||||
|
"failed"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"code": {
|
||||||
|
"type": [
|
||||||
|
"string",
|
||||||
|
"null"
|
||||||
|
],
|
||||||
|
"pattern": "^[A-Z][A-Z0-9_]{2,63}$"
|
||||||
|
},
|
||||||
|
"summary": {
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 1
|
||||||
|
},
|
||||||
|
"evidence": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"data": {}
|
||||||
|
},
|
||||||
|
"allOf": [
|
||||||
|
{
|
||||||
|
"if": {
|
||||||
|
"properties": {
|
||||||
|
"status": {
|
||||||
|
"const": "success"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"then": {
|
||||||
|
"properties": {
|
||||||
|
"code": {
|
||||||
|
"type": "null"
|
||||||
|
},
|
||||||
|
"evidence": {
|
||||||
|
"minItems": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"if": {
|
||||||
|
"properties": {
|
||||||
|
"status": {
|
||||||
|
"enum": [
|
||||||
|
"degraded",
|
||||||
|
"unsupported",
|
||||||
|
"failed"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"then": {
|
||||||
|
"properties": {
|
||||||
|
"code": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -15,7 +15,7 @@ Before any substantive output, print these exact labels in this exact order. Res
|
|||||||
```text
|
```text
|
||||||
Target: <concrete repository, product, URL, device, PR, or artifact>
|
Target: <concrete repository, product, URL, device, PR, or artifact>
|
||||||
Mode: <selected top-level mode>
|
Mode: <selected top-level mode>
|
||||||
Depth: <quick, standard, or deep>
|
Depth: <readiness, standard, or deep>
|
||||||
Mutation: <report-only or exact authorized mutation boundary>
|
Mutation: <report-only or exact authorized mutation boundary>
|
||||||
Active modules: <comma-separated internal specialist modules>
|
Active modules: <comma-separated internal specialist modules>
|
||||||
Skipped modules: <comma-separated non-active mandatory modules with compact reasons>
|
Skipped modules: <comma-separated non-active mandatory modules with compact reasons>
|
||||||
@@ -27,7 +27,7 @@ Web context: <none, optional, local-browser, or production>
|
|||||||
1. Infer the mode from product stage, surface, requested artifact, mutation authorization, evidence needs, and deployment state. Do not route by keyword alone.
|
1. Infer the mode from product stage, surface, requested artifact, mutation authorization, evidence needs, and deployment state. Do not route by keyword alone.
|
||||||
2. Refine the public mode to the smallest applicable internal specialist set, then print the required execution header before any substantive output.
|
2. Refine the public mode to the smallest applicable internal specialist set, then print the required execution header before any substantive output.
|
||||||
3. Read each active module in full from the path shown in the mode/alias tables. Its specialist body, behavioral contract, STOP gates, and appended upstream judgment ports are binding. Read a lazy specialist phase in full only when the workflow reaches its package-local reference.
|
3. Read each active module in full from the path shown in the mode/alias tables. Its specialist body, behavioral contract, STOP gates, and appended upstream judgment ports are binding. Read a lazy specialist phase in full only when the workflow reaches its package-local reference.
|
||||||
4. Read `references/SHARED-JUDGMENT.md` and `references/AUTHORITY-POLICY.md` for every invocation. Read `references/RUNTIME.md` before capability-dependent work and `references/WEB-CONTEXT.md` before public-web work.
|
4. Read `references/EXECUTION-PROFILES.md`, `references/SHARED-JUDGMENT.md`, and `references/AUTHORITY-POLICY.md` for every invocation. Infer Depth from structured operating conditions, then obey its mandatory modules, legal skips, artifacts, and claim limits. Read `references/RUNTIME.md` before capability-dependent work and `references/WEB-CONTEXT.md` before public-web work.
|
||||||
5. If an old asset path is unavailable, use `references/ASSETS.md`. If legacy prose invokes another retired skill, resolve it through `references/COMPATIBILITY.md` and stay inside these six dispatchers.
|
5. If an old asset path is unavailable, use `references/ASSETS.md`. If legacy prose invokes another retired skill, resolve it through `references/COMPATIBILITY.md` and stay inside these six dispatchers.
|
||||||
6. Preserve report-only versus mutation boundaries. Missing mutation authorization fails closed: do not edit merely because a specialist can fix. Commits, pushes, PRs, merges, deploys, messages, and other external mutations still require affirmative authority from the user.
|
6. Preserve report-only versus mutation boundaries. Missing mutation authorization fails closed: do not edit merely because a specialist can fix. Commits, pushes, PRs, merges, deploys, messages, and other external mutations still require affirmative authority from the user.
|
||||||
7. Match the user's language. Keep code identifiers, commands, and source quotations original when translation would reduce accuracy.
|
7. Match the user's language. Keep code identifiers, commands, and source quotations original when translation would reduce accuracy.
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
<!-- GENERATED by scripts/gstack2/generate-skill-tree.ts; do not edit. -->
|
||||||
|
# Inferred execution profiles
|
||||||
|
|
||||||
|
Choose a profile from product stage, mutation authority, risk/evidence needs, and deployment state. Prompt keywords and a request to “be quick” are not routing evidence. A profile narrows or strengthens evidence; it never overrides a specialist’s binding question order, pressure, gates, mutation boundary, or exit behavior.
|
||||||
|
|
||||||
|
## Smoke/readiness
|
||||||
|
|
||||||
|
- Infer when: A narrow, reversible, pre-deployment or operational readiness decision needs bounded evidence; the requested claim is readiness, not completeness.
|
||||||
|
- Mandatory modules: Every selected specialist module remains mandatory. Run its entry gates and the smallest source-authorized evidence path that can answer the readiness question.
|
||||||
|
- Legal skips: Only source-declared conditional work whose condition is demonstrably false, or evidence unavailable after a named attempt. Never skip a STOP gate, approval boundary, reproduction/root-cause gate, or required physical-device/production evidence.
|
||||||
|
- Artifacts: A readiness record naming the exact scope, probes run, evidence and freshness, failures, skipped work with reasons, and the next standard/deep step.
|
||||||
|
- Claims: Only ready/not-ready for the named bounded decision. Must say “Readiness profile — not a complete review.” Never claim comprehensive, fully verified, production-safe, or no issues found outside the inspected scope.
|
||||||
|
|
||||||
|
## Standard
|
||||||
|
|
||||||
|
- Infer when: Normal feature or change work has bounded scope and risk and needs the selected specialist’s complete default workflow.
|
||||||
|
- Mandatory modules: Every selected specialist module and all of its mandatory phases, gates, artifacts, and exit checks.
|
||||||
|
- Legal skips: Only smart skips explicitly authorized by the specialist and supported by inspected evidence; list each skipped primary module and each skipped conditional phase.
|
||||||
|
- Artifacts: Every artifact required by the selected specialist, plus evidence provenance, unresolved decisions, and a skip ledger.
|
||||||
|
- Claims: Complete only for the named specialist scope and evidence layer. Broader product, security, production, or device claims require those modules and evidence.
|
||||||
|
|
||||||
|
## Deep
|
||||||
|
|
||||||
|
- Infer when: Risk, ambiguity, blast radius, cross-system effects, irreversible mutation, security/reliability needs, or production deployment demands stronger evidence.
|
||||||
|
- Mandatory modules: Every selected specialist module, all mandatory phases and outside-voice/cross-consumer modules selected by the dispatcher, with unchanged STOP and approval gates.
|
||||||
|
- Legal skips: Only specialist-authorized smart skips proven irrelevant. Missing, stale, malformed, or contradictory evidence is a gap or blocker, never a successful skip.
|
||||||
|
- Artifacts: All specialist artifacts plus changed-input/unchanged-consumer trace, negative and failure-path evidence, provenance/freshness, rollback or reversibility evidence where applicable, and unresolved-risk ledger.
|
||||||
|
- Claims: Complete only across the explicitly listed modules and evidence layers. “Confirmed” requires independent supporting evidence; production/device/security claims require matching production/device/security evidence.
|
||||||
@@ -23,4 +23,8 @@ Some retained helpers are shell scripts. `gstack doctor` verifies Bash and, on W
|
|||||||
|
|
||||||
The package/runtime compatibility tuple is `schemaVersion=1`, `runtimeVersion=2.0.0`, and `skillApi=2.0`; the machine-readable copy is `references/support/runtime-contract.json`. An incompatible active runtime is unavailable, not permission to upgrade it.
|
The package/runtime compatibility tuple is `schemaVersion=1`, `runtimeVersion=2.0.0`, and `skillApi=2.0`; the machine-readable copy is `references/support/runtime-contract.json`. An incompatible active runtime is unavailable, not permission to upgrade it.
|
||||||
|
|
||||||
|
Every optional-runtime tool result must satisfy `references/support/execution-result-contract.json` before it is presented as success. Success requires non-empty evidence. Empty or malformed output and explicit degraded, unsupported, or failed statuses remain non-success with stable codes; human renderings must preserve that status and code.
|
||||||
|
|
||||||
|
Use `gstack doctor --capability browser|design|diagram|pdf|ios` (optionally `--json`) for a non-mutating, capability-specific readiness result. Its independent axes must remain distinct: pure judgment availability, platform support, preview consent, install consent, and runtime readiness. Readiness is exactly `ready`, `degraded`, `unavailable`, `unsupported`, or `failed`. Doctor never grants or persists consent, previews metadata, or installs anything. `unavailable` means setup may be offered; `failed` means selected runtime evidence failed; `unsupported` is a platform boundary; and `degraded` means the capability passed while the managed runtime has a warning.
|
||||||
|
|
||||||
The developer-only fallback is `node references/support/runtime-bootstrap.mjs install --source <reviewed-checkout> --capability <name> [matching browser flags] --yes`; show its trust warning and use it only when the user explicitly selects a checkout they reviewed. If the packaged bootstrap is unavailable, stop capability setup instead of guessing a checkout-relative command. Deferring installation records no consent and must not block pure judgment.
|
The developer-only fallback is `node references/support/runtime-bootstrap.mjs install --source <reviewed-checkout> --capability <name> [matching browser flags] --yes`; show its trust warning and use it only when the user explicitly selects a checkout they reviewed. If the packaged bootstrap is unavailable, stop capability setup instead of guessing a checkout-relative command. Deferring installation records no consent and must not block pure judgment.
|
||||||
|
|||||||
@@ -0,0 +1,88 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||||
|
"$id": "https://gstack.dev/schemas/execution-result-v1.json",
|
||||||
|
"title": "GStack execution result",
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"schemaVersion",
|
||||||
|
"status",
|
||||||
|
"code",
|
||||||
|
"summary",
|
||||||
|
"evidence",
|
||||||
|
"data"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"schemaVersion": {
|
||||||
|
"const": 1
|
||||||
|
},
|
||||||
|
"status": {
|
||||||
|
"enum": [
|
||||||
|
"success",
|
||||||
|
"degraded",
|
||||||
|
"unsupported",
|
||||||
|
"failed"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"code": {
|
||||||
|
"type": [
|
||||||
|
"string",
|
||||||
|
"null"
|
||||||
|
],
|
||||||
|
"pattern": "^[A-Z][A-Z0-9_]{2,63}$"
|
||||||
|
},
|
||||||
|
"summary": {
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 1
|
||||||
|
},
|
||||||
|
"evidence": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"data": {}
|
||||||
|
},
|
||||||
|
"allOf": [
|
||||||
|
{
|
||||||
|
"if": {
|
||||||
|
"properties": {
|
||||||
|
"status": {
|
||||||
|
"const": "success"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"then": {
|
||||||
|
"properties": {
|
||||||
|
"code": {
|
||||||
|
"type": "null"
|
||||||
|
},
|
||||||
|
"evidence": {
|
||||||
|
"minItems": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"if": {
|
||||||
|
"properties": {
|
||||||
|
"status": {
|
||||||
|
"enum": [
|
||||||
|
"degraded",
|
||||||
|
"unsupported",
|
||||||
|
"failed"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"then": {
|
||||||
|
"properties": {
|
||||||
|
"code": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -15,7 +15,7 @@ Before any substantive output, print these exact labels in this exact order. Res
|
|||||||
```text
|
```text
|
||||||
Target: <concrete repository, product, URL, device, PR, or artifact>
|
Target: <concrete repository, product, URL, device, PR, or artifact>
|
||||||
Mode: <selected top-level mode>
|
Mode: <selected top-level mode>
|
||||||
Depth: <quick, standard, or deep>
|
Depth: <readiness, standard, or deep>
|
||||||
Mutation: <report-only or exact authorized mutation boundary>
|
Mutation: <report-only or exact authorized mutation boundary>
|
||||||
Active modules: <comma-separated internal specialist modules>
|
Active modules: <comma-separated internal specialist modules>
|
||||||
Skipped modules: <comma-separated non-active mandatory modules with compact reasons>
|
Skipped modules: <comma-separated non-active mandatory modules with compact reasons>
|
||||||
@@ -27,7 +27,7 @@ Web context: <none, optional, local-browser, or production>
|
|||||||
1. Infer the mode from product stage, surface, requested artifact, mutation authorization, evidence needs, and deployment state. Do not route by keyword alone.
|
1. Infer the mode from product stage, surface, requested artifact, mutation authorization, evidence needs, and deployment state. Do not route by keyword alone.
|
||||||
2. Refine the public mode to the smallest applicable internal specialist set, then print the required execution header before any substantive output.
|
2. Refine the public mode to the smallest applicable internal specialist set, then print the required execution header before any substantive output.
|
||||||
3. Read each active module in full from the path shown in the mode/alias tables. Its specialist body, behavioral contract, STOP gates, and appended upstream judgment ports are binding. Read a lazy specialist phase in full only when the workflow reaches its package-local reference.
|
3. Read each active module in full from the path shown in the mode/alias tables. Its specialist body, behavioral contract, STOP gates, and appended upstream judgment ports are binding. Read a lazy specialist phase in full only when the workflow reaches its package-local reference.
|
||||||
4. Read `references/SHARED-JUDGMENT.md` and `references/AUTHORITY-POLICY.md` for every invocation. Read `references/RUNTIME.md` before capability-dependent work and `references/WEB-CONTEXT.md` before public-web work.
|
4. Read `references/EXECUTION-PROFILES.md`, `references/SHARED-JUDGMENT.md`, and `references/AUTHORITY-POLICY.md` for every invocation. Infer Depth from structured operating conditions, then obey its mandatory modules, legal skips, artifacts, and claim limits. Read `references/RUNTIME.md` before capability-dependent work and `references/WEB-CONTEXT.md` before public-web work.
|
||||||
5. If an old asset path is unavailable, use `references/ASSETS.md`. If legacy prose invokes another retired skill, resolve it through `references/COMPATIBILITY.md` and stay inside these six dispatchers.
|
5. If an old asset path is unavailable, use `references/ASSETS.md`. If legacy prose invokes another retired skill, resolve it through `references/COMPATIBILITY.md` and stay inside these six dispatchers.
|
||||||
6. Preserve report-only versus mutation boundaries. Missing mutation authorization fails closed: do not edit merely because a specialist can fix. Commits, pushes, PRs, merges, deploys, messages, and other external mutations still require affirmative authority from the user.
|
6. Preserve report-only versus mutation boundaries. Missing mutation authorization fails closed: do not edit merely because a specialist can fix. Commits, pushes, PRs, merges, deploys, messages, and other external mutations still require affirmative authority from the user.
|
||||||
7. Match the user's language. Keep code identifiers, commands, and source quotations original when translation would reduce accuracy.
|
7. Match the user's language. Keep code identifiers, commands, and source quotations original when translation would reduce accuracy.
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
<!-- GENERATED by scripts/gstack2/generate-skill-tree.ts; do not edit. -->
|
||||||
|
# Inferred execution profiles
|
||||||
|
|
||||||
|
Choose a profile from product stage, mutation authority, risk/evidence needs, and deployment state. Prompt keywords and a request to “be quick” are not routing evidence. A profile narrows or strengthens evidence; it never overrides a specialist’s binding question order, pressure, gates, mutation boundary, or exit behavior.
|
||||||
|
|
||||||
|
## Smoke/readiness
|
||||||
|
|
||||||
|
- Infer when: A narrow, reversible, pre-deployment or operational readiness decision needs bounded evidence; the requested claim is readiness, not completeness.
|
||||||
|
- Mandatory modules: Every selected specialist module remains mandatory. Run its entry gates and the smallest source-authorized evidence path that can answer the readiness question.
|
||||||
|
- Legal skips: Only source-declared conditional work whose condition is demonstrably false, or evidence unavailable after a named attempt. Never skip a STOP gate, approval boundary, reproduction/root-cause gate, or required physical-device/production evidence.
|
||||||
|
- Artifacts: A readiness record naming the exact scope, probes run, evidence and freshness, failures, skipped work with reasons, and the next standard/deep step.
|
||||||
|
- Claims: Only ready/not-ready for the named bounded decision. Must say “Readiness profile — not a complete review.” Never claim comprehensive, fully verified, production-safe, or no issues found outside the inspected scope.
|
||||||
|
|
||||||
|
## Standard
|
||||||
|
|
||||||
|
- Infer when: Normal feature or change work has bounded scope and risk and needs the selected specialist’s complete default workflow.
|
||||||
|
- Mandatory modules: Every selected specialist module and all of its mandatory phases, gates, artifacts, and exit checks.
|
||||||
|
- Legal skips: Only smart skips explicitly authorized by the specialist and supported by inspected evidence; list each skipped primary module and each skipped conditional phase.
|
||||||
|
- Artifacts: Every artifact required by the selected specialist, plus evidence provenance, unresolved decisions, and a skip ledger.
|
||||||
|
- Claims: Complete only for the named specialist scope and evidence layer. Broader product, security, production, or device claims require those modules and evidence.
|
||||||
|
|
||||||
|
## Deep
|
||||||
|
|
||||||
|
- Infer when: Risk, ambiguity, blast radius, cross-system effects, irreversible mutation, security/reliability needs, or production deployment demands stronger evidence.
|
||||||
|
- Mandatory modules: Every selected specialist module, all mandatory phases and outside-voice/cross-consumer modules selected by the dispatcher, with unchanged STOP and approval gates.
|
||||||
|
- Legal skips: Only specialist-authorized smart skips proven irrelevant. Missing, stale, malformed, or contradictory evidence is a gap or blocker, never a successful skip.
|
||||||
|
- Artifacts: All specialist artifacts plus changed-input/unchanged-consumer trace, negative and failure-path evidence, provenance/freshness, rollback or reversibility evidence where applicable, and unresolved-risk ledger.
|
||||||
|
- Claims: Complete only across the explicitly listed modules and evidence layers. “Confirmed” requires independent supporting evidence; production/device/security claims require matching production/device/security evidence.
|
||||||
@@ -23,4 +23,8 @@ Some retained helpers are shell scripts. `gstack doctor` verifies Bash and, on W
|
|||||||
|
|
||||||
The package/runtime compatibility tuple is `schemaVersion=1`, `runtimeVersion=2.0.0`, and `skillApi=2.0`; the machine-readable copy is `references/support/runtime-contract.json`. An incompatible active runtime is unavailable, not permission to upgrade it.
|
The package/runtime compatibility tuple is `schemaVersion=1`, `runtimeVersion=2.0.0`, and `skillApi=2.0`; the machine-readable copy is `references/support/runtime-contract.json`. An incompatible active runtime is unavailable, not permission to upgrade it.
|
||||||
|
|
||||||
|
Every optional-runtime tool result must satisfy `references/support/execution-result-contract.json` before it is presented as success. Success requires non-empty evidence. Empty or malformed output and explicit degraded, unsupported, or failed statuses remain non-success with stable codes; human renderings must preserve that status and code.
|
||||||
|
|
||||||
|
Use `gstack doctor --capability browser|design|diagram|pdf|ios` (optionally `--json`) for a non-mutating, capability-specific readiness result. Its independent axes must remain distinct: pure judgment availability, platform support, preview consent, install consent, and runtime readiness. Readiness is exactly `ready`, `degraded`, `unavailable`, `unsupported`, or `failed`. Doctor never grants or persists consent, previews metadata, or installs anything. `unavailable` means setup may be offered; `failed` means selected runtime evidence failed; `unsupported` is a platform boundary; and `degraded` means the capability passed while the managed runtime has a warning.
|
||||||
|
|
||||||
The developer-only fallback is `node references/support/runtime-bootstrap.mjs install --source <reviewed-checkout> --capability <name> [matching browser flags] --yes`; show its trust warning and use it only when the user explicitly selects a checkout they reviewed. If the packaged bootstrap is unavailable, stop capability setup instead of guessing a checkout-relative command. Deferring installation records no consent and must not block pure judgment.
|
The developer-only fallback is `node references/support/runtime-bootstrap.mjs install --source <reviewed-checkout> --capability <name> [matching browser flags] --yes`; show its trust warning and use it only when the user explicitly selects a checkout they reviewed. If the packaged bootstrap is unavailable, stop capability setup instead of guessing a checkout-relative command. Deferring installation records no consent and must not block pure judgment.
|
||||||
|
|||||||
@@ -0,0 +1,88 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||||
|
"$id": "https://gstack.dev/schemas/execution-result-v1.json",
|
||||||
|
"title": "GStack execution result",
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"schemaVersion",
|
||||||
|
"status",
|
||||||
|
"code",
|
||||||
|
"summary",
|
||||||
|
"evidence",
|
||||||
|
"data"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"schemaVersion": {
|
||||||
|
"const": 1
|
||||||
|
},
|
||||||
|
"status": {
|
||||||
|
"enum": [
|
||||||
|
"success",
|
||||||
|
"degraded",
|
||||||
|
"unsupported",
|
||||||
|
"failed"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"code": {
|
||||||
|
"type": [
|
||||||
|
"string",
|
||||||
|
"null"
|
||||||
|
],
|
||||||
|
"pattern": "^[A-Z][A-Z0-9_]{2,63}$"
|
||||||
|
},
|
||||||
|
"summary": {
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 1
|
||||||
|
},
|
||||||
|
"evidence": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"data": {}
|
||||||
|
},
|
||||||
|
"allOf": [
|
||||||
|
{
|
||||||
|
"if": {
|
||||||
|
"properties": {
|
||||||
|
"status": {
|
||||||
|
"const": "success"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"then": {
|
||||||
|
"properties": {
|
||||||
|
"code": {
|
||||||
|
"type": "null"
|
||||||
|
},
|
||||||
|
"evidence": {
|
||||||
|
"minItems": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"if": {
|
||||||
|
"properties": {
|
||||||
|
"status": {
|
||||||
|
"enum": [
|
||||||
|
"degraded",
|
||||||
|
"unsupported",
|
||||||
|
"failed"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"then": {
|
||||||
|
"properties": {
|
||||||
|
"code": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,125 @@
|
|||||||
|
import { describe, expect, test } from "bun:test";
|
||||||
|
import fs from "node:fs/promises";
|
||||||
|
import os from "node:os";
|
||||||
|
import path from "node:path";
|
||||||
|
import { main } from "../runtime/cli.js";
|
||||||
|
import { capabilityReadiness, formatCapabilityReadiness } from "../runtime/doctor.js";
|
||||||
|
import { setupRuntime } from "../runtime/setup.js";
|
||||||
|
|
||||||
|
function report(checks: Array<Record<string, unknown>>) {
|
||||||
|
return {
|
||||||
|
ok: !checks.some((check) => check.status === "fail"),
|
||||||
|
home: "/fixture/.gstack",
|
||||||
|
checkedAt: "2026-07-20T00:00:00.000Z",
|
||||||
|
checks,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function capture() {
|
||||||
|
let value = "";
|
||||||
|
return { stream: { write: (chunk: string) => { value += chunk; } }, value: () => value };
|
||||||
|
}
|
||||||
|
|
||||||
|
describe("capability readiness", () => {
|
||||||
|
test("keeps pure judgment, preview consent, and install consent separate when unavailable", () => {
|
||||||
|
const result = capabilityReadiness(report([
|
||||||
|
{ id: "managed-runtime", status: "fail", message: "No active managed runtime" },
|
||||||
|
{ id: "capability:pdf", status: "warn", message: "not installed" },
|
||||||
|
]), "pdf");
|
||||||
|
|
||||||
|
expect(result).toMatchObject({
|
||||||
|
ok: false,
|
||||||
|
judgment: { status: "available" },
|
||||||
|
platform: { status: "supported" },
|
||||||
|
consent: {
|
||||||
|
preview: { status: "required", granted: false },
|
||||||
|
install: { status: "required-after-preview", granted: false },
|
||||||
|
},
|
||||||
|
readiness: { status: "unavailable" },
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test("distinguishes ready, degraded, and failed runtime states", () => {
|
||||||
|
const ready = capabilityReadiness(report([
|
||||||
|
{ id: "managed-runtime", status: "pass", message: "active" },
|
||||||
|
{ id: "capability:design", status: "pass", message: "runnable" },
|
||||||
|
]), "design");
|
||||||
|
const degraded = capabilityReadiness(report([
|
||||||
|
{ id: "managed-runtime", status: "warn", message: "recovered" },
|
||||||
|
{ id: "capability:design", status: "pass", message: "runnable" },
|
||||||
|
]), "design");
|
||||||
|
const failed = capabilityReadiness(report([
|
||||||
|
{ id: "managed-runtime", status: "pass", message: "active" },
|
||||||
|
{ id: "capability:diagram", status: "fail", message: "launcher metadata missing" },
|
||||||
|
]), "diagram");
|
||||||
|
// A hard runtime failure under a launchable capability is not a warning:
|
||||||
|
// it must not report ok:true, matching plain `gstack doctor`'s exit code.
|
||||||
|
const runtimeFailed = capabilityReadiness(report([
|
||||||
|
{ id: "managed-runtime", status: "fail", message: "incompatible skill API" },
|
||||||
|
{ id: "capability:browser", status: "pass", message: "launched" },
|
||||||
|
]), "browser");
|
||||||
|
|
||||||
|
expect(ready).toMatchObject({ ok: true, readiness: { status: "ready" } });
|
||||||
|
expect(degraded).toMatchObject({ ok: true, readiness: { status: "degraded" } });
|
||||||
|
expect(failed).toMatchObject({ ok: false, readiness: { status: "failed" } });
|
||||||
|
expect(failed.consent.install.status).toBe("required-after-preview");
|
||||||
|
expect(runtimeFailed).toMatchObject({ ok: false, readiness: { status: "failed" } });
|
||||||
|
});
|
||||||
|
|
||||||
|
test("reports physical iOS as unsupported without turning off pure judgment", () => {
|
||||||
|
const result = capabilityReadiness(report([]), "ios", { platform: "linux" });
|
||||||
|
expect(result).toMatchObject({
|
||||||
|
ok: false,
|
||||||
|
judgment: { status: "available" },
|
||||||
|
platform: { status: "unsupported", platform: "linux" },
|
||||||
|
consent: {
|
||||||
|
preview: { status: "not-applicable" },
|
||||||
|
install: { status: "not-applicable" },
|
||||||
|
},
|
||||||
|
readiness: { status: "unsupported" },
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test("human output exposes every state axis", () => {
|
||||||
|
const result = capabilityReadiness(report([
|
||||||
|
{ id: "managed-runtime", status: "pass", message: "active" },
|
||||||
|
{ id: "capability:browser", status: "pass", message: "launched" },
|
||||||
|
]), "browser");
|
||||||
|
expect(formatCapabilityReadiness(result)).toContain("judgment: available");
|
||||||
|
expect(formatCapabilityReadiness(result)).toContain("preview consent: not-required");
|
||||||
|
expect(formatCapabilityReadiness(result)).toContain("install consent: not-required");
|
||||||
|
expect(formatCapabilityReadiness(result)).toContain("readiness: ready");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("doctor capability JSON is non-mutating and uses the unified result envelope", async () => {
|
||||||
|
const root = await fs.mkdtemp(path.join(os.tmpdir(), "gstack-capability-doctor-"));
|
||||||
|
const home = path.join(root, "home");
|
||||||
|
const stdout = capture();
|
||||||
|
const stderr = capture();
|
||||||
|
try {
|
||||||
|
await setupRuntime({ home, cwd: root });
|
||||||
|
const exit = await main(["doctor", "--capability", "pdf", "--json"], {
|
||||||
|
cwd: root,
|
||||||
|
env: { ...process.env, GSTACK_HOME: home },
|
||||||
|
stdout: stdout.stream,
|
||||||
|
stderr: stderr.stream,
|
||||||
|
});
|
||||||
|
const result = JSON.parse(stdout.value());
|
||||||
|
expect(exit).toBe(1);
|
||||||
|
expect(stderr.value()).toBe("");
|
||||||
|
expect(result).toMatchObject({
|
||||||
|
schemaVersion: 1,
|
||||||
|
status: "degraded",
|
||||||
|
code: "CAPABILITY_UNAVAILABLE",
|
||||||
|
data: {
|
||||||
|
ok: false,
|
||||||
|
capability: "pdf",
|
||||||
|
judgment: { status: "available" },
|
||||||
|
readiness: { status: "unavailable" },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
|
await fs.rm(root, { recursive: true, force: true });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -95,4 +95,45 @@ describe('gstack state external-effect CLI', () => {
|
|||||||
{ cwd, env, stdout: out, stderr: err },
|
{ cwd, env, stdout: out, stderr: err },
|
||||||
)).toBe(2);
|
)).toBe(2);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('an empty exit-zero tool result is uncertain, never successful', async () => {
|
||||||
|
const { cwd, env } = await fixture();
|
||||||
|
const out = sink();
|
||||||
|
const err = sink();
|
||||||
|
await main(['state', 'begin', 'ship', '--run-id', 'run_empty'], { cwd, env, stdout: out, stderr: err });
|
||||||
|
const silent = path.join(cwd, 'silent.sh');
|
||||||
|
await fs.writeFile(silent, '#!/bin/sh\nexit 0\n', { mode: 0o755 });
|
||||||
|
const code = await main([
|
||||||
|
'state', 'effect', 'run_empty', 'silent.tool', '--', silent,
|
||||||
|
], { cwd, env, stdout: out, stderr: err });
|
||||||
|
expect(code).toBe(1);
|
||||||
|
expect(JSON.parse(err.value())).toMatchObject({
|
||||||
|
status: 'degraded',
|
||||||
|
code: 'EXECUTION_EMPTY',
|
||||||
|
evidence: ['exit code 0', 'stdout and stderr were empty'],
|
||||||
|
});
|
||||||
|
expect(out.value()).not.toContain('"status":"success"');
|
||||||
|
const retryError = sink();
|
||||||
|
expect(await main([
|
||||||
|
'state', 'effect', 'run_empty', 'silent.tool', '--', silent,
|
||||||
|
], { cwd, env, stdout: out, stderr: retryError })).toBe(1);
|
||||||
|
expect(retryError.value()).toContain('was already claimed');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('a nonzero command returns a structured failed result', async () => {
|
||||||
|
const { cwd, env } = await fixture();
|
||||||
|
const out = sink();
|
||||||
|
const err = sink();
|
||||||
|
await main(['state', 'begin', 'ship', '--run-id', 'run_failed'], { cwd, env, stdout: out, stderr: err });
|
||||||
|
const code = await main([
|
||||||
|
'state', 'effect', 'run_failed', 'failed.tool', '--', process.execPath, '-e', 'process.exit(7)',
|
||||||
|
], { cwd, env, stdout: out, stderr: err });
|
||||||
|
expect(code).toBe(1);
|
||||||
|
expect(JSON.parse(err.value())).toMatchObject({
|
||||||
|
status: 'failed',
|
||||||
|
code: 'EXECUTION_FAILED',
|
||||||
|
evidence: ['exit code 7'],
|
||||||
|
data: { exitCode: 7 },
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
import { describe, expect, test } from "bun:test";
|
||||||
|
import {
|
||||||
|
EXECUTION_RESULT_ERROR_CODES,
|
||||||
|
executionResult,
|
||||||
|
renderExecutionResult,
|
||||||
|
validateExecutionResult,
|
||||||
|
} from "../runtime/execution-result.js";
|
||||||
|
|
||||||
|
describe("GStack execution-result contract", () => {
|
||||||
|
test("accepts evidenced success and preserves it in both renderings", () => {
|
||||||
|
const result = executionResult({ status: "success", summary: "Probe completed", evidence: ["exit code 0"], data: { count: 1 } });
|
||||||
|
expect(JSON.parse(renderExecutionResult(result, { json: true }))).toEqual(result);
|
||||||
|
expect(renderExecutionResult(result)).toContain("SUCCESS: Probe completed");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("rejects empty and malformed values instead of inferring success", () => {
|
||||||
|
expect(() => validateExecutionResult(null)).toThrow();
|
||||||
|
expect(() => executionResult({ status: "success", summary: "Done", evidence: [], data: null }))
|
||||||
|
.toThrow("requires evidence");
|
||||||
|
try {
|
||||||
|
executionResult({ status: "success", summary: "Done", evidence: [], data: null });
|
||||||
|
} catch (error: any) {
|
||||||
|
expect(error.code).toBe(EXECUTION_RESULT_ERROR_CODES.EMPTY);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
test.each([
|
||||||
|
["degraded", "EXECUTION_DEGRADED"],
|
||||||
|
["unsupported", "EXECUTION_UNSUPPORTED"],
|
||||||
|
["failed", "EXECUTION_FAILED"],
|
||||||
|
])("keeps %s explicitly non-success", (status, code) => {
|
||||||
|
const result = executionResult({ status, code, summary: `${status} result`, evidence: [], data: null });
|
||||||
|
expect(renderExecutionResult(result)).toStartWith(`${status.toUpperCase()} [${code}]`);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -630,6 +630,9 @@ process.stdout.write(process.env.GSTACK_CHROMIUM_PATH || "unset");
|
|||||||
"node_modules/sharp",
|
"node_modules/sharp",
|
||||||
"node_modules/detect-libc",
|
"node_modules/detect-libc",
|
||||||
"node_modules/semver",
|
"node_modules/semver",
|
||||||
|
"node_modules/standardwebhooks",
|
||||||
|
"node_modules/@stablelib/base64",
|
||||||
|
"node_modules/fast-sha256",
|
||||||
...runtimeNativePackagePaths(),
|
...runtimeNativePackagePaths(),
|
||||||
]) expect(bundlePaths.has(dependency)).toBe(true);
|
]) expect(bundlePaths.has(dependency)).toBe(true);
|
||||||
expect(bundlePaths.has("node_modules/@img")).toBe(false);
|
expect(bundlePaths.has("node_modules/@img")).toBe(false);
|
||||||
|
|||||||
@@ -45,7 +45,9 @@ describe('GStack 2 generated runtime payload prerequisites', () => {
|
|||||||
expect(result.built).toBe(true);
|
expect(result.built).toBe(true);
|
||||||
expect(calls).toHaveLength(1);
|
expect(calls).toHaveLength(1);
|
||||||
expect(calls[0].map((entry) => entry.path)).toEqual(REQUIRED_RUNTIME_PAYLOADS.map((entry) => entry.path));
|
expect(calls[0].map((entry) => entry.path)).toEqual(REQUIRED_RUNTIME_PAYLOADS.map((entry) => entry.path));
|
||||||
expect(new Set(calls[0].map((entry) => entry.build))).toEqual(new Set(['core']));
|
expect(new Set(calls[0].map((entry) => entry.build))).toEqual(
|
||||||
|
new Set(process.platform === 'darwin' ? ['core', 'ios'] : ['core']),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('does not rebuild payloads that already exist', async () => {
|
test('does not rebuild payloads that already exist', async () => {
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ describe('GStack 2 semantic parity', () => {
|
|||||||
expect(result.sections).toBe(16);
|
expect(result.sections).toBe(16);
|
||||||
expect(result.policyUnits).toBe(AUTHORITY_POLICY_CASES.length);
|
expect(result.policyUnits).toBe(AUTHORITY_POLICY_CASES.length);
|
||||||
expect(result.checks).toBeGreaterThan(250);
|
expect(result.checks).toBeGreaterThan(250);
|
||||||
});
|
}, 15_000);
|
||||||
|
|
||||||
test('authority-policy units cover evidence, trust, and routing controls', () => {
|
test('authority-policy units cover evidence, trust, and routing controls', () => {
|
||||||
expect(AUTHORITY_POLICY_CASES.length).toBeGreaterThanOrEqual(9);
|
expect(AUTHORITY_POLICY_CASES.length).toBeGreaterThanOrEqual(9);
|
||||||
|
|||||||
@@ -45,6 +45,21 @@ describe('GStack 2 canonical skill UX', () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('packages one binding inferred execution-profile contract in every dispatcher', () => {
|
||||||
|
for (const tree of TREE_NAMES) {
|
||||||
|
const dispatcher = fs.readFileSync(path.join(ROOT, 'skills', tree, 'SKILL.md'), 'utf8');
|
||||||
|
const profiles = fs.readFileSync(path.join(ROOT, 'skills', tree, 'references', 'EXECUTION-PROFILES.md'), 'utf8');
|
||||||
|
expect(dispatcher, tree).toContain('Depth: <readiness, standard, or deep>');
|
||||||
|
expect(dispatcher, tree).toContain('Read `references/EXECUTION-PROFILES.md`');
|
||||||
|
expect(profiles, tree).toContain('## Smoke/readiness');
|
||||||
|
expect(profiles, tree).toContain('Readiness profile — not a complete review.');
|
||||||
|
expect(profiles, tree).toContain('Every selected specialist module remains mandatory.');
|
||||||
|
expect(profiles, tree).toContain('## Standard');
|
||||||
|
expect(profiles, tree).toContain('## Deep');
|
||||||
|
expect(profiles, tree).toContain('never overrides a specialist’s binding question order');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
test('resolves retired user-facing recommendations without rewriting package paths', () => {
|
test('resolves retired user-facing recommendations without rewriting package paths', () => {
|
||||||
for (const assignment of SOURCE_ASSIGNMENTS) {
|
for (const assignment of SOURCE_ASSIGNMENTS) {
|
||||||
const body = fs.readFileSync(ownerModule(assignment.source), 'utf8');
|
const body = fs.readFileSync(ownerModule(assignment.source), 'utf8');
|
||||||
@@ -63,9 +78,12 @@ describe('GStack 2 canonical skill UX', () => {
|
|||||||
const bootstrap = fs.readFileSync(path.join(ROOT, 'skills', tree, 'references', 'support', 'runtime-bootstrap.mjs'));
|
const bootstrap = fs.readFileSync(path.join(ROOT, 'skills', tree, 'references', 'support', 'runtime-bootstrap.mjs'));
|
||||||
const browserChoice = fs.readFileSync(path.join(ROOT, 'skills', tree, 'references', 'support', 'browser-choice.mjs'));
|
const browserChoice = fs.readFileSync(path.join(ROOT, 'skills', tree, 'references', 'support', 'browser-choice.mjs'));
|
||||||
const contract = JSON.parse(fs.readFileSync(path.join(ROOT, 'skills', tree, 'references', 'support', 'runtime-contract.json'), 'utf8'));
|
const contract = JSON.parse(fs.readFileSync(path.join(ROOT, 'skills', tree, 'references', 'support', 'runtime-contract.json'), 'utf8'));
|
||||||
|
const resultContract = JSON.parse(fs.readFileSync(path.join(ROOT, 'skills', tree, 'references', 'support', 'execution-result-contract.json'), 'utf8'));
|
||||||
expect(bootstrap, tree).toEqual(source);
|
expect(bootstrap, tree).toEqual(source);
|
||||||
expect(browserChoice, tree).toEqual(fs.readFileSync(path.join(ROOT, 'runtime', 'browser-choice.mjs')));
|
expect(browserChoice, tree).toEqual(fs.readFileSync(path.join(ROOT, 'runtime', 'browser-choice.mjs')));
|
||||||
expect(contract, tree).toEqual({ schemaVersion: 1, runtimeVersion: '2.0.0', skillApi: '2.0' });
|
expect(contract, tree).toEqual({ schemaVersion: 1, runtimeVersion: '2.0.0', skillApi: '2.0' });
|
||||||
|
expect(resultContract.properties.status.enum, tree).toEqual(['success', 'degraded', 'unsupported', 'failed']);
|
||||||
|
expect(resultContract.allOf[0].then.properties.evidence.minItems, tree).toBe(1);
|
||||||
expect(runtime, tree).toContain('preview --capability <name>');
|
expect(runtime, tree).toContain('preview --capability <name>');
|
||||||
expect(runtime, tree).toContain('It never downloads components or mutates runtime state.');
|
expect(runtime, tree).toContain('It never downloads components or mutates runtime state.');
|
||||||
expect(runtime, tree).toContain('options --capability <name>');
|
expect(runtime, tree).toContain('options --capability <name>');
|
||||||
|
|||||||
@@ -24,6 +24,41 @@ describe('GStack 2 structured dispatch', () => {
|
|||||||
expect(routeStructured({ ...scenario.signals })).toEqual(original);
|
expect(routeStructured({ ...scenario.signals })).toEqual(original);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('infers readiness only from bounded structured operating conditions', () => {
|
||||||
|
const readiness = routeStructured({
|
||||||
|
surface: 'web',
|
||||||
|
implementation_exists: true,
|
||||||
|
evidence_need: 'readiness',
|
||||||
|
scope: 'narrow',
|
||||||
|
deployment_state: 'pre-deployment',
|
||||||
|
});
|
||||||
|
expect(readiness.depth).toBe('readiness');
|
||||||
|
expect(readiness.active_modules).toEqual(['qa-only']);
|
||||||
|
|
||||||
|
expect(routeStructured({
|
||||||
|
surface: 'web',
|
||||||
|
implementation_exists: true,
|
||||||
|
evidence_need: 'readiness',
|
||||||
|
scope: 'broad',
|
||||||
|
}).depth).not.toBe('readiness');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('risk and deployment evidence promote work to deep', () => {
|
||||||
|
expect(routeStructured({ surface: 'web', implementation_exists: true, risk: 'high' }).depth)
|
||||||
|
.toBe('deep');
|
||||||
|
expect(routeStructured({ surface: 'web', implementation_exists: true, deployment_state: 'production' }).depth)
|
||||||
|
.toBe('deep');
|
||||||
|
expect(routeStructured({ surface: 'web', implementation_exists: true, mutation_scope: 'consequential' }).depth)
|
||||||
|
.toBe('deep');
|
||||||
|
expect(routeStructured({
|
||||||
|
surface: 'web',
|
||||||
|
implementation_exists: true,
|
||||||
|
evidence_need: 'readiness',
|
||||||
|
scope: 'narrow',
|
||||||
|
irreversible: true,
|
||||||
|
}).depth).toBe('deep');
|
||||||
|
});
|
||||||
|
|
||||||
test('explicit mutation denials override otherwise mutating modes', () => {
|
test('explicit mutation denials override otherwise mutating modes', () => {
|
||||||
const review = routeStructured({ audit_focus: 'broad', mutation_authorized: false });
|
const review = routeStructured({ audit_focus: 'broad', mutation_authorized: false });
|
||||||
expect(review.mode).toBe('Normal');
|
expect(review.mode).toBe('Normal');
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ describe("release and CI hardening", () => {
|
|||||||
for (const name of fs.readdirSync(workflowRoot).filter((entry) => entry.endsWith(".yml"))) {
|
for (const name of fs.readdirSync(workflowRoot).filter((entry) => entry.endsWith(".yml"))) {
|
||||||
const source = fs.readFileSync(path.join(workflowRoot, name), "utf8");
|
const source = fs.readFileSync(path.join(workflowRoot, name), "utf8");
|
||||||
expect(source, `${name} must declare top-level permissions`).toMatch(/^permissions:\s*$/m);
|
expect(source, `${name} must declare top-level permissions`).toMatch(/^permissions:\s*$/m);
|
||||||
|
expect(source, `${name} must declare workflow concurrency`).toMatch(/^concurrency:\s*$/m);
|
||||||
for (const match of source.matchAll(/\buses:\s*[^\s@]+@([^\s#]+)/g)) {
|
for (const match of source.matchAll(/\buses:\s*[^\s@]+@([^\s#]+)/g)) {
|
||||||
expect(match[1], `${name} contains a mutable action ref`).toMatch(/^[a-f0-9]{40}$/);
|
expect(match[1], `${name} contains a mutable action ref`).toMatch(/^[a-f0-9]{40}$/);
|
||||||
}
|
}
|
||||||
@@ -24,6 +25,24 @@ describe("release and CI hardening", () => {
|
|||||||
expect(source.match(new RegExp(guard.replaceAll(".", "\\."), "g"))?.length).toBeGreaterThanOrEqual(3);
|
expect(source.match(new RegExp(guard.replaceAll(".", "\\."), "g"))?.length).toBeGreaterThanOrEqual(3);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("public dependency and repository security workflows stay enabled and least-privileged", () => {
|
||||||
|
const dependencyReview = read(".github/workflows/dependency-review.yml");
|
||||||
|
expect(dependencyReview).toContain("actions/dependency-review-action@");
|
||||||
|
expect(dependencyReview).toContain("fail-on-severity: high");
|
||||||
|
expect(dependencyReview).not.toContain("pull_request_target:");
|
||||||
|
|
||||||
|
const osv = read(".github/workflows/osv-scanner.yml");
|
||||||
|
expect(osv).toContain("google/osv-scanner-action/.github/workflows/osv-scanner-reusable.yml@");
|
||||||
|
expect(osv).toContain("security-events: write");
|
||||||
|
expect(osv).toContain("schedule:");
|
||||||
|
|
||||||
|
const scorecard = read(".github/workflows/scorecard.yml");
|
||||||
|
expect(scorecard).toContain("ossf/scorecard-action@");
|
||||||
|
expect(scorecard).toContain("github/codeql-action/upload-sarif@");
|
||||||
|
expect(scorecard).toContain("publish_results: false");
|
||||||
|
expect(scorecard).not.toContain("id-token: write");
|
||||||
|
});
|
||||||
|
|
||||||
test("npm package is an explicit small runtime-control surface", () => {
|
test("npm package is an explicit small runtime-control surface", () => {
|
||||||
const pkg = JSON.parse(read("package.json"));
|
const pkg = JSON.parse(read("package.json"));
|
||||||
expect(pkg.version).toBe(read("VERSION").trim());
|
expect(pkg.version).toBe(read("VERSION").trim());
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import * as os from 'os';
|
|||||||
import {
|
import {
|
||||||
DEFAULT_MAX_FILES_PER_SHARD,
|
DEFAULT_MAX_FILES_PER_SHARD,
|
||||||
FREE_TEST_ROOTS,
|
FREE_TEST_ROOTS,
|
||||||
|
buildShardArgs,
|
||||||
isFreeTestFile,
|
isFreeTestFile,
|
||||||
collectFreeTestFiles,
|
collectFreeTestFiles,
|
||||||
containsScheduledProcessExitZero,
|
containsScheduledProcessExitZero,
|
||||||
@@ -138,6 +139,16 @@ describe('test-free-shards: sharding', () => {
|
|||||||
expect(() => assignFilesToShards(['a.test.ts'], -1)).toThrow();
|
expect(() => assignFilesToShards(['a.test.ts'], -1)).toThrow();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('buildShardArgs accepts a suite-specific timeout without enabling file concurrency', () => {
|
||||||
|
expect(buildShardArgs(['test/gstack2-skills.test.ts'], 30_000)).toEqual([
|
||||||
|
'test',
|
||||||
|
'test/gstack2-skills.test.ts',
|
||||||
|
'--max-concurrency=1',
|
||||||
|
'--timeout=30000',
|
||||||
|
]);
|
||||||
|
expect(() => buildShardArgs(['test/example.test.ts'], 0)).toThrow();
|
||||||
|
});
|
||||||
|
|
||||||
test('shards are stable across runs (same files always land in same shard)', () => {
|
test('shards are stable across runs (same files always land in same shard)', () => {
|
||||||
const files = ['x.test.ts', 'y.test.ts', 'z.test.ts'];
|
const files = ['x.test.ts', 'y.test.ts', 'z.test.ts'];
|
||||||
const a = assignFilesToShards(files, 5);
|
const a = assignFilesToShards(files, 5);
|
||||||
|
|||||||
Reference in New Issue
Block a user