mirror of
https://github.com/garrytan/gstack.git
synced 2026-09-21 04:10:47 +02:00
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -75,9 +75,9 @@ function publicModeFor(source: string, tree: SourceAssignment['tree'], legacyMod
|
||||
export const SOURCE_ASSIGNMENTS: SourceAssignment[] = [
|
||||
// Shared catalog and planning/memory family.
|
||||
A('gstack', 'plan', 'catalog', 'Legacy catalog and top-level workflow routing.', { visibility: 'internal' }),
|
||||
A('office-hours', 'plan', 'product', 'Reframe a product idea through YC-style office hours.', { mandatory: true, overlays: [2030], defaultDepth: 'deep', defaultMutation: 'design-doc-only', webContext: 'optional' }),
|
||||
A('office-hours', 'plan', 'product', 'Reframe a product idea through YC-style office hours.', { mandatory: true, overlays: [1049, 2030], defaultDepth: 'deep', defaultMutation: 'design-doc-only', webContext: 'optional' }),
|
||||
A('plan-ceo-review', 'plan', 'ceo', 'Challenge scope, strategy, and the ten-star product shape.', { mandatory: true, overlays: [2030], defaultDepth: 'deep', defaultMutation: 'plan-only', webContext: 'optional' }),
|
||||
A('plan-eng-review', 'plan', 'eng', 'Review architecture, data flow, tests, performance, and failure modes.', { mandatory: true, overlays: [1071, 2030], defaultDepth: 'deep', defaultMutation: 'plan-only' }),
|
||||
A('plan-eng-review', 'plan', 'eng', 'Review architecture, data flow, tests, performance, and failure modes.', { mandatory: true, overlays: [592, 1071, 2030], defaultDepth: 'deep', defaultMutation: 'plan-only' }),
|
||||
A('plan-devex-review', 'plan', 'dx', 'Review developer personas, time-to-hello-world, friction, and DX measurement.', { mandatory: true, overlays: [2030], defaultDepth: 'deep', defaultMutation: 'plan-only', webContext: 'optional' }),
|
||||
A('autoplan', 'plan', 'auto', 'Run CEO, design, engineering, and DX plan reviews with an auditable decision trail.', { mandatory: true, overlays: [2014, 2023], defaultDepth: 'deep', defaultMutation: 'plan-only', webContext: 'optional' }),
|
||||
A('spec', 'plan', 'spec', 'Turn intent into a backlog-ready issue/spec and optional execution handoff.', { mandatory: true, defaultDepth: 'deep', defaultMutation: 'spec-and-issue', webContext: 'optional' }),
|
||||
@@ -94,7 +94,7 @@ export const SOURCE_ASSIGNMENTS: SourceAssignment[] = [
|
||||
A('design-shotgun', 'design', 'alternatives', 'Generate and compare multiple visual directions.', { mandatory: true, overlays: [1777], defaultDepth: 'deep', defaultMutation: 'design-artifacts', webContext: 'optional' }),
|
||||
A('design-html', 'design', 'html', 'Generate production-quality Pretext-native HTML/CSS.', { mandatory: true, defaultMutation: 'design-artifacts', webContext: 'local-browser' }),
|
||||
A('plan-design-review', 'design', 'plan-review', 'Review a plan for interaction states, visual quality, and accessibility.', { mandatory: true, overlays: [2030, 2189], defaultDepth: 'deep', defaultMutation: 'plan-only', webContext: 'optional' }),
|
||||
A('design-review', 'design', 'live-review', 'Audit, fix, and verify an implemented web UI.', { mandatory: true, overlays: [1920, 2030, 2189], defaultDepth: 'deep', defaultMutation: 'fix-safe', webContext: 'local-browser' }),
|
||||
A('design-review', 'design', 'live-review', 'Audit, fix, and verify an implemented web UI.', { mandatory: true, overlays: [696, 1920, 2030, 2189], defaultDepth: 'deep', defaultMutation: 'fix-safe', webContext: 'local-browser' }),
|
||||
A('ios-design-review', 'design', 'ios-review', 'Score and iterate a real iOS interface against Apple HIG.', { mandatory: true, defaultDepth: 'deep', defaultMutation: 'report-only', webContext: 'none' }),
|
||||
A('diagram', 'design', 'diagram', 'Render diagrams from English descriptions.', { visibility: 'internal', defaultMutation: 'design-artifacts' }),
|
||||
A('make-pdf', 'design', 'pdf', 'Render publication-quality PDFs from Markdown.', { visibility: 'internal', defaultMutation: 'design-artifacts' }),
|
||||
@@ -124,13 +124,13 @@ export const SOURCE_ASSIGNMENTS: SourceAssignment[] = [
|
||||
|
||||
// Review family.
|
||||
A('review', 'review', 'diff', 'Review a diff, validate findings, and apply safe fixes.', { mandatory: true, overlays: [610, 645, 2030, 2141], defaultDepth: 'deep', defaultMutation: 'fix-safe', webContext: 'optional' }),
|
||||
A('cso', 'review', 'security', 'Run OWASP, STRIDE, secrets, supply-chain, and infrastructure audits.', { mandatory: true, overlays: [2030], defaultDepth: 'deep', defaultMutation: 'report-only', webContext: 'optional' }),
|
||||
A('cso', 'review', 'security', 'Run OWASP, STRIDE, secrets, supply-chain, and infrastructure audits.', { mandatory: true, overlays: [1053, 1523, 2030], defaultDepth: 'deep', defaultMutation: 'report-only', webContext: 'optional' }),
|
||||
A('health', 'review', 'health', 'Run the code-quality dashboard and trend analysis.', { mandatory: true, defaultMutation: 'report-only' }),
|
||||
A('codex', 'review', 'outside-codex', 'Request an OpenAI Codex review, challenge, or consultation.', { mandatory: true, defaultMutation: 'report-only' }),
|
||||
A('claude', 'review', 'outside-claude', 'Request a read-only Claude outside voice.', { mandatory: true, defaultMutation: 'report-only' }),
|
||||
|
||||
// Ship/release family.
|
||||
A('ship', 'ship', 'ship', 'Test, review, version, document, commit, push, and open a PR.', { mandatory: true, overlays: [884, 2030, 2186], defaultDepth: 'deep', defaultMutation: 'commit-push-pr', webContext: 'optional' }),
|
||||
A('ship', 'ship', 'ship', 'Test, review, version, document, commit, push, and open a PR.', { mandatory: true, overlays: [884, 1102, 2030, 2186], defaultDepth: 'deep', defaultMutation: 'commit-push-pr', webContext: 'optional' }),
|
||||
A('land-and-deploy', 'ship', 'land', 'Merge an approved PR, deploy, verify, and offer rollback.', { mandatory: true, overlays: [884], defaultDepth: 'deep', defaultMutation: 'merge-deploy', webContext: 'production' }),
|
||||
A('landing-report', 'ship', 'queue', 'Render the workspace-aware version and landing queue.', { mandatory: true, defaultMutation: 'report-only' }),
|
||||
A('document-release', 'ship', 'docs', 'Update documentation and release narrative after shipping.', { mandatory: true, defaultDepth: 'deep', defaultMutation: 'docs-only', webContext: 'optional' }),
|
||||
|
||||
@@ -230,6 +230,90 @@ Accept a coherent design thesis expressed through product principles, visual rat
|
||||
expected: { thesis_recognized: true, literal_heading_required: false },
|
||||
},
|
||||
},
|
||||
{
|
||||
pr: 1102,
|
||||
url: 'https://github.com/garrytan/gstack/pull/1102',
|
||||
title: 'Read the test command from CLAUDE.md instead of hardcoding it',
|
||||
targets: ['ship'],
|
||||
anchor: 'GSTACK2_FIX_1102_TEST_COMMAND_FROM_CLAUDEMD',
|
||||
body: `### Project-owned test command
|
||||
|
||||
Resolve the test command from the project, never from a hardcoded stack assumption. Read the CLAUDE.md \`## Testing\` section first and use the command it declares. If that section is absent, search the project for its actual test entry point (package.json test script, Gemfile rake tasks, pytest configuration, and so on) and use what you find. If no test framework is detectable, print that Step 5 is skipped and continue. Never fall back to a baked-in Rails or Node command against a repository that does not use it.`,
|
||||
regression: {
|
||||
input: { claude_md_testing: 'bun run test:custom', has_package_json: false },
|
||||
expected: { test_command: 'bun run test:custom', source: 'CLAUDE.md', hardcoded_fallback_used: false },
|
||||
},
|
||||
},
|
||||
{
|
||||
pr: 1049,
|
||||
url: 'https://github.com/garrytan/gstack/pull/1049',
|
||||
title: 'Refuse to log success without a persisted design doc',
|
||||
targets: ['office-hours'],
|
||||
anchor: 'GSTACK2_FIX_1049_NO_DOC_OUTCOME',
|
||||
body: `### Artifact-verified outcome
|
||||
|
||||
The design doc file is the artifact of this session. Before the telemetry block runs, verify that a design doc actually persisted to disk. When no doc was written, the outcome must be \`no_doc\`, never \`success\`, no matter how productive the conversation felt. A session without a persisted artifact is not a successful session, and downstream analytics depend on that distinction to catch skipped review phases.`,
|
||||
regression: {
|
||||
input: { design_doc_written: false },
|
||||
expected: { outcome: 'no_doc', success_allowed: false },
|
||||
},
|
||||
},
|
||||
{
|
||||
pr: 592,
|
||||
url: 'https://github.com/garrytan/gstack/pull/592',
|
||||
title: 'Run a pre-mortem before challenging scope',
|
||||
targets: ['plan-eng-review'],
|
||||
anchor: 'GSTACK2_FIX_592_PRE_MORTEM',
|
||||
body: `### Pre-mortem before scope challenge
|
||||
|
||||
Before reviewing anything, run a pre-mortem: it is three months later and this plan failed, name the top three reasons why. Reason from production reality, not the plan's internal logic, and name concrete failure modes (data loss, performance cliff, security hole, team confusion), not abstract worries. Present those three failure modes to the user before the scope challenge, which follows the pre-mortem rather than opening the review.`,
|
||||
regression: {
|
||||
input: { stage: 'engineering-review' },
|
||||
expected: { premortem_first: true, failure_modes_named: 3, runs_before_scope: true },
|
||||
},
|
||||
},
|
||||
{
|
||||
pr: 696,
|
||||
url: 'https://github.com/garrytan/gstack/pull/696',
|
||||
title: 'Score each screen on a cognitive-load scale',
|
||||
targets: ['design-review'],
|
||||
anchor: 'GSTACK2_FIX_696_COGNITIVE_LOAD',
|
||||
body: `### Cognitive-load audit
|
||||
|
||||
Rate every audited screen on a System 1 to System 2 scale from 0 to 10, grounded in browse data already collected (element counts, link counts, load times), not impression. Most screens should sit at S1 (0-3); higher scores are acceptable only as intentional friction such as destructive or financial decisions. For any screen above the threshold that is not deliberate friction, name the specific UX laws it breaks (Fitts, Hick, Jakob, Miller, Peak-End, Von Restorff, Zeigarnik, Gestalt) and cite the measurement that proves it.`,
|
||||
regression: {
|
||||
input: { screen_elements: 93, threshold: 3 },
|
||||
expected: { cognitive_load_scored: true, flagged: true, names_ux_laws: true },
|
||||
},
|
||||
},
|
||||
{
|
||||
pr: 1523,
|
||||
url: 'https://github.com/garrytan/gstack/pull/1523',
|
||||
title: 'Detect the shai-hulud campaign in comprehensive mode only',
|
||||
targets: ['cso'],
|
||||
anchor: 'GSTACK2_FIX_1523_SHAI_HULUD',
|
||||
body: `### Known-campaign IOC tier
|
||||
|
||||
Add Tier 3 rules that detect the mini-shai-hulud supply-chain campaign: \`/proc/*/mem\` reads from Claude Code settings hooks, auto-run persistence bridges (folderOpen tasks or settings hooks invoking payloads), packed droppers that decrypt or decompress an embedded blob at load, and the getsession.org C2 IOCs. Every rule matches a deterministic primary-source indicator, surfaces only under comprehensive mode, and carries a TENTATIVE marking. Daily mode's zero-noise contract stays unchanged: none of these rules add findings there.`,
|
||||
regression: {
|
||||
input: { mode: 'comprehensive' },
|
||||
expected: { tier3_active: true, tentative: true, daily_noise_added: false },
|
||||
},
|
||||
},
|
||||
{
|
||||
pr: 1053,
|
||||
url: 'https://github.com/garrytan/gstack/pull/1053',
|
||||
title: 'Keep the audit report-only unless --fix is passed',
|
||||
targets: ['cso'],
|
||||
anchor: 'GSTACK2_FIX_1053_FIX_MODE',
|
||||
body: `### Opt-in auto-fix boundary
|
||||
|
||||
The default audit is strictly report-only and mutates nothing. Auto-fixes apply only under an explicit \`--fix\` flag, and only for provably safe patterns where the correct change is deterministic and the breakage risk is near-zero (additive gitignore hardening, TLS-verification flips, non-breaking dependency patches). No business logic and no guessing. Without \`--fix\`, produce findings and remediation plans and change no files.`,
|
||||
regression: {
|
||||
input: { fix_flag: false },
|
||||
expected: { mutations_allowed: false, fix_requires: '--fix' },
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
export function overlaysForSource(source: string): BugFixOverlay[] {
|
||||
@@ -365,6 +449,36 @@ export function evaluateBugFixRegression(pr: number, rawInput: unknown): Record<
|
||||
const coherent = /principles|thesis|rationale|philosophy|calm|trust|hierarchy|interaction/i.test(framing);
|
||||
return { thesis_recognized: coherent, literal_heading_required: false };
|
||||
}
|
||||
case 1102: {
|
||||
const fromClaudeMd = typeof input.claude_md_testing === 'string' && input.claude_md_testing.trim().length > 0;
|
||||
const fromProject = !fromClaudeMd && input.has_package_json === true;
|
||||
return {
|
||||
test_command: fromClaudeMd ? String(input.claude_md_testing) : fromProject ? 'project-detected' : null,
|
||||
source: fromClaudeMd ? 'CLAUDE.md' : fromProject ? 'project-search' : 'none',
|
||||
hardcoded_fallback_used: false,
|
||||
};
|
||||
}
|
||||
case 1049: {
|
||||
const docWritten = input.design_doc_written === true;
|
||||
return { outcome: docWritten ? 'success' : 'no_doc', success_allowed: docWritten };
|
||||
}
|
||||
case 592: {
|
||||
const engReview = input.stage === 'engineering-review';
|
||||
return { premortem_first: engReview, failure_modes_named: 3, runs_before_scope: engReview };
|
||||
}
|
||||
case 696: {
|
||||
const elements = Number(input.screen_elements ?? 0);
|
||||
const threshold = Number(input.threshold ?? 3);
|
||||
const score = Math.min(10, Math.round(elements / 13));
|
||||
const flagged = score > threshold;
|
||||
return { cognitive_load_scored: true, flagged, names_ux_laws: flagged };
|
||||
}
|
||||
case 1523: {
|
||||
const comprehensive = input.mode === 'comprehensive';
|
||||
return { tier3_active: comprehensive, tentative: true, daily_noise_added: false };
|
||||
}
|
||||
case 1053:
|
||||
return { mutations_allowed: input.fix_flag === true, fix_requires: '--fix' };
|
||||
default:
|
||||
throw new Error(`No executable GStack 2 regression evaluator for PR #${pr}`);
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ function assertInventory(): void {
|
||||
}
|
||||
if (legacySections().length !== 16) throw new Error(`Expected 16 section templates, found ${legacySections().length}`);
|
||||
if (SCENARIOS.length !== 25) throw new Error(`Expected 25 parity scenarios, found ${SCENARIOS.length}`);
|
||||
if (BUG_FIX_OVERLAYS.length !== 16) throw new Error(`Expected 16 upstream judgment overlays, found ${BUG_FIX_OVERLAYS.length}`);
|
||||
if (BUG_FIX_OVERLAYS.length !== 22) throw new Error(`Expected 22 upstream judgment overlays, found ${BUG_FIX_OVERLAYS.length}`);
|
||||
}
|
||||
|
||||
function toc(body: string): string {
|
||||
@@ -742,7 +742,7 @@ ${rows}
|
||||
## Mechanical versus judgment changes
|
||||
|
||||
- \`JUDGMENT_PRESERVING_CARVE\`: pinned specialist workflow with the retired shared onboarding wrapper excluded, retired invocations resolved to six public routes, host/runtime paths normalized, and large carved phases loaded lazily from package-local pinned references.
|
||||
- \`BUG_FIX\`: the canonical carved body plus a clearly delimited judgment overlay sourced from one of the 16 upstream PRs and its regression fixture.
|
||||
- \`BUG_FIX\`: the canonical carved body plus a clearly delimited judgment overlay sourced from one of the 22 upstream PRs and its regression fixture.
|
||||
- Asset relocation is byte-for-byte from the pinned Git blob and is indexed per tree.
|
||||
`;
|
||||
}
|
||||
@@ -763,7 +763,7 @@ function parityDoc(assetCount: number): string {
|
||||
|
||||
Parity is executable, not a prose claim. Run \`bun run scripts/gstack2/run-parity.ts\` or the dedicated Bun tests.
|
||||
|
||||
The pinned release inventory passes **${EXPECTED_PARITY_CHECKS.toLocaleString('en-US')} checks** across 55 specialist sources, 16 carved sections, 25 routing scenarios, 16 regression ports, and **${assetCount} assets**.
|
||||
The pinned release inventory passes **${EXPECTED_PARITY_CHECKS.toLocaleString('en-US')} checks** across 55 specialist sources, 16 carved sections, 25 routing scenarios, 22 regression ports, and **${assetCount} assets**.
|
||||
|
||||
The suite verifies:
|
||||
|
||||
@@ -772,7 +772,7 @@ The suite verifies:
|
||||
- immutable full 1.x render hashes plus canonical specialist-render equality, with the excluded onboarding wrapper and lazy section references asserted explicitly;
|
||||
- preservation of nine behavioral contract dimensions per module;
|
||||
- 25 structured non-keyword routing fixtures with active/skipped modules, depth, mutation, and web context;
|
||||
- 16 upstream judgment-port regression fixtures and anchors;
|
||||
- 22 upstream judgment-port regression fixtures and anchors;
|
||||
- all linked asset copies against their pinned Git blobs;
|
||||
- frontmatter and \`agents/openai.yaml\` schema for each public skill.
|
||||
|
||||
@@ -922,7 +922,7 @@ function main(): void {
|
||||
schema_version: 1,
|
||||
base_sha: GSTACK2_BASE_SHA,
|
||||
public_skills: [...TREE_NAMES],
|
||||
counts: { public_skills: 6, mandatory_inputs: 31, templates: 55, section_templates: 16, packaged_section_copies: sectionCopies.length, internal_execution_adapters: 1, scenarios: 25, bug_fix_ports: 16, assets: assets.length, dependency_copies: dependencyCopies.length, runtime_helpers: runtimeHelpers.length },
|
||||
counts: { public_skills: 6, mandatory_inputs: 31, templates: 55, section_templates: 16, packaged_section_copies: sectionCopies.length, internal_execution_adapters: 1, scenarios: 25, bug_fix_ports: 22, assets: assets.length, dependency_copies: dependencyCopies.length, runtime_helpers: runtimeHelpers.length },
|
||||
sources: sourceRecords,
|
||||
sections: sectionRecords,
|
||||
section_copies: sectionCopies,
|
||||
|
||||
@@ -15,8 +15,9 @@ const ALLOWED_DISPOSITIONS = new Set(['VERBATIM_PORT', 'MECHANICAL_PORT', 'JUDGM
|
||||
// Inventory history: the componentized-runtime parity expansion added 152
|
||||
// checks to the previously verified 4,681-check corpus. The first update only
|
||||
// accounted for the 16 lazy-section checks; the remaining 136 cover runtime
|
||||
// contracts, retired-invocation guards, and generated package closure.
|
||||
export const EXPECTED_PARITY_CHECKS = 4836;
|
||||
// contracts, retired-invocation guards, and generated package closure. Porting
|
||||
// six more upstream judgment overlays (16 -> 22) added 30 checks.
|
||||
export const EXPECTED_PARITY_CHECKS = 4866;
|
||||
|
||||
function sha256(value: string | Uint8Array): string {
|
||||
return createHash('sha256').update(value).digest('hex');
|
||||
@@ -251,8 +252,8 @@ export function runParity(): ParityResult {
|
||||
check(JSON.stringify(json(path.join(ROOT, 'evals', 'parity', 'scenarios', `${scenario.id}.json`))) === JSON.stringify(scenario), `${scenario.id} generated fixture drift`);
|
||||
}
|
||||
|
||||
check(BUG_FIX_OVERLAYS.length === 16, `Expected 16 regression definitions; got ${BUG_FIX_OVERLAYS.length}`);
|
||||
check(files(path.join(ROOT, 'evals', 'parity', 'regressions'), '.json').length === 16, 'Generated regression fixture count is not 16');
|
||||
check(BUG_FIX_OVERLAYS.length === 22, `Expected 22 regression definitions; got ${BUG_FIX_OVERLAYS.length}`);
|
||||
check(files(path.join(ROOT, 'evals', 'parity', 'regressions'), '.json').length === 22, 'Generated regression fixture count is not 22');
|
||||
for (const overlay of BUG_FIX_OVERLAYS) {
|
||||
const fixture = json(path.join(ROOT, 'evals', 'parity', 'regressions', `pr-${overlay.pr}.json`));
|
||||
check(JSON.stringify(fixture) === JSON.stringify(overlay), `PR #${overlay.pr} regression fixture drift`);
|
||||
|
||||
Reference in New Issue
Block a user