mirror of
https://github.com/garrytan/gstack.git
synced 2026-06-27 20:20:03 +02:00
Merge remote-tracking branch 'origin/main' into garrytan/trunk-land-skill
# Conflicts: # CHANGELOG.md # VERSION # package.json
This commit is contained in:
+31
-29
@@ -383,7 +383,7 @@ describe('gen-skill-docs', () => {
|
||||
});
|
||||
|
||||
test('voice and writing-style preamble sections stay compact', () => {
|
||||
const content = fs.readFileSync(path.join(ROOT, 'plan-eng-review', 'SKILL.md'), 'utf-8');
|
||||
const content = readSkillUnion('plan-eng-review'); // carved: review body moved to section
|
||||
const voice = extractMarkdownSection(content, '## Voice');
|
||||
const writingStyle = extractMarkdownSection(content, '## Writing Style');
|
||||
|
||||
@@ -392,7 +392,7 @@ describe('gen-skill-docs', () => {
|
||||
});
|
||||
|
||||
test('slim voice section preserves the gstack voice contract', () => {
|
||||
const content = fs.readFileSync(path.join(ROOT, 'plan-eng-review', 'SKILL.md'), 'utf-8');
|
||||
const content = readSkillUnion('plan-eng-review'); // carved: review body moved to section
|
||||
const voice = extractMarkdownSection(content, '## Voice');
|
||||
|
||||
expect(voice).toMatch(/lead with the point|direct/i);
|
||||
@@ -672,7 +672,7 @@ describe('REVIEW_DASHBOARD resolver', () => {
|
||||
|
||||
for (const skill of REVIEW_SKILLS) {
|
||||
test(`review dashboard appears in ${skill} generated file`, () => {
|
||||
const content = fs.readFileSync(path.join(ROOT, skill, 'SKILL.md'), 'utf-8');
|
||||
const content = readSkillUnion(skill); // carved skills: union skeleton + sections
|
||||
expect(content).toContain('gstack-review');
|
||||
expect(content).toContain('REVIEW READINESS DASHBOARD');
|
||||
});
|
||||
@@ -693,13 +693,13 @@ describe('REVIEW_DASHBOARD resolver', () => {
|
||||
});
|
||||
|
||||
test('shared dashboard propagates review source to plan-eng-review', () => {
|
||||
const content = fs.readFileSync(path.join(ROOT, 'plan-eng-review', 'SKILL.md'), 'utf-8');
|
||||
const content = readSkillUnion('plan-eng-review'); // carved: review body moved to section
|
||||
expect(content).toContain('plan-eng-review, review, plan-design-review');
|
||||
expect(content).toContain('`review` (diff-scoped pre-landing review)');
|
||||
});
|
||||
|
||||
test('resolver output contains key dashboard elements', () => {
|
||||
const content = fs.readFileSync(path.join(ROOT, 'plan-ceo-review', 'SKILL.md'), 'utf-8');
|
||||
const content = readSkillUnion('plan-ceo-review'); // carved: dashboard moved to section
|
||||
expect(content).toContain('VERDICT');
|
||||
expect(content).toContain('CLEARED');
|
||||
expect(content).toContain('Eng Review');
|
||||
@@ -709,25 +709,25 @@ describe('REVIEW_DASHBOARD resolver', () => {
|
||||
});
|
||||
|
||||
test('dashboard bash block includes git HEAD for staleness detection', () => {
|
||||
const content = fs.readFileSync(path.join(ROOT, 'plan-ceo-review', 'SKILL.md'), 'utf-8');
|
||||
const content = readSkillUnion('plan-ceo-review'); // carved: dashboard moved to section
|
||||
expect(content).toContain('git rev-parse --short HEAD');
|
||||
expect(content).toContain('---HEAD---');
|
||||
});
|
||||
|
||||
test('dashboard includes staleness detection prose', () => {
|
||||
const content = fs.readFileSync(path.join(ROOT, 'plan-ceo-review', 'SKILL.md'), 'utf-8');
|
||||
const content = readSkillUnion('plan-ceo-review'); // carved: dashboard moved to section
|
||||
expect(content).toContain('Staleness detection');
|
||||
expect(content).toContain('commit');
|
||||
});
|
||||
|
||||
for (const skill of REVIEW_SKILLS) {
|
||||
test(`${skill} contains review chaining section`, () => {
|
||||
const content = fs.readFileSync(path.join(ROOT, skill, 'SKILL.md'), 'utf-8');
|
||||
const content = readSkillUnion(skill); // carved skills: union skeleton + sections
|
||||
expect(content).toContain('Review Chaining');
|
||||
});
|
||||
|
||||
test(`${skill} Review Log includes commit field`, () => {
|
||||
const content = fs.readFileSync(path.join(ROOT, skill, 'SKILL.md'), 'utf-8');
|
||||
const content = readSkillUnion(skill); // carved skills: union skeleton + sections
|
||||
expect(content).toContain('"commit"');
|
||||
});
|
||||
}
|
||||
@@ -739,13 +739,13 @@ describe('REVIEW_DASHBOARD resolver', () => {
|
||||
});
|
||||
|
||||
test('plan-eng-review chaining mentions design and ceo reviews', () => {
|
||||
const content = fs.readFileSync(path.join(ROOT, 'plan-eng-review', 'SKILL.md'), 'utf-8');
|
||||
const content = readSkillUnion('plan-eng-review'); // carved: review body moved to section
|
||||
expect(content).toContain('/plan-design-review');
|
||||
expect(content).toContain('/plan-ceo-review');
|
||||
});
|
||||
|
||||
test('plan-design-review chaining mentions eng, ceo, and design skills', () => {
|
||||
const content = fs.readFileSync(path.join(ROOT, 'plan-design-review', 'SKILL.md'), 'utf-8');
|
||||
const content = readSkillUnion('plan-design-review');
|
||||
expect(content).toContain('/plan-eng-review');
|
||||
expect(content).toContain('/plan-ceo-review');
|
||||
expect(content).toContain('/design-shotgun');
|
||||
@@ -761,7 +761,7 @@ describe('REVIEW_DASHBOARD resolver', () => {
|
||||
// ─── Test Coverage Audit Resolver Tests ─────────────────────
|
||||
|
||||
describe('TEST_COVERAGE_AUDIT placeholders', () => {
|
||||
const planSkill = fs.readFileSync(path.join(ROOT, 'plan-eng-review', 'SKILL.md'), 'utf-8');
|
||||
const planSkill = readSkillUnion('plan-eng-review'); // carved
|
||||
const shipSkill = readShipUnion();
|
||||
const reviewSkill = fs.readFileSync(path.join(ROOT, 'review', 'SKILL.md'), 'utf-8');
|
||||
|
||||
@@ -969,7 +969,7 @@ describe('PLAN_FILE_REVIEW_REPORT resolver', () => {
|
||||
}
|
||||
|
||||
test('resolver output contains key report elements', () => {
|
||||
const content = fs.readFileSync(path.join(ROOT, 'plan-ceo-review', 'SKILL.md'), 'utf-8');
|
||||
const content = readSkillUnion('plan-ceo-review'); // carved: report writer moved to section
|
||||
expect(content).toContain('Trigger');
|
||||
expect(content).toContain('Findings');
|
||||
expect(content).toContain('VERDICT');
|
||||
@@ -1144,7 +1144,7 @@ describe('Retro plan completion section', () => {
|
||||
describe('Plan status footer in preamble', () => {
|
||||
test('preamble contains plan status footer as neutral forward reference to EXIT PLAN MODE GATE', () => {
|
||||
// Read any skill that uses PREAMBLE
|
||||
const content = fs.readFileSync(path.join(ROOT, 'office-hours', 'SKILL.md'), 'utf-8');
|
||||
const content = readSkillUnion('office-hours'); // carved: Phase 5/6 prose moved to section
|
||||
expect(content).toContain('Plan Status Footer');
|
||||
expect(content).toContain('GSTACK REVIEW REPORT');
|
||||
expect(content).toContain('ExitPlanMode');
|
||||
@@ -1179,7 +1179,7 @@ describe('make-pdf setup ordering', () => {
|
||||
|
||||
describe('Skill invocation during plan mode in preamble', () => {
|
||||
test('preamble contains skill invocation plan mode section', () => {
|
||||
const content = fs.readFileSync(path.join(ROOT, 'office-hours', 'SKILL.md'), 'utf-8');
|
||||
const content = readSkillUnion('office-hours'); // carved: Phase 5/6 prose moved to section
|
||||
expect(content).toContain('Skill Invocation During Plan Mode');
|
||||
expect(content).toContain('precedence over generic plan mode behavior');
|
||||
expect(content).toContain('Do not continue the workflow');
|
||||
@@ -1190,7 +1190,7 @@ describe('Skill invocation during plan mode in preamble', () => {
|
||||
// --- {{SPEC_REVIEW_LOOP}} resolver tests ---
|
||||
|
||||
describe('SPEC_REVIEW_LOOP resolver', () => {
|
||||
const content = fs.readFileSync(path.join(ROOT, 'office-hours', 'SKILL.md'), 'utf-8');
|
||||
const content = readSkillUnion('office-hours'); // carved: Phase 5/6 prose moved to section
|
||||
|
||||
test('contains all 5 review dimensions', () => {
|
||||
for (const dim of ['Completeness', 'Consistency', 'Clarity', 'Scope', 'Feasibility']) {
|
||||
@@ -1226,7 +1226,7 @@ describe('SPEC_REVIEW_LOOP resolver', () => {
|
||||
// --- {{DESIGN_SKETCH}} resolver tests ---
|
||||
|
||||
describe('DESIGN_SKETCH resolver', () => {
|
||||
const content = fs.readFileSync(path.join(ROOT, 'office-hours', 'SKILL.md'), 'utf-8');
|
||||
const content = readSkillUnion('office-hours'); // carved: Phase 5/6 prose moved to section
|
||||
|
||||
test('references DESIGN.md for design system constraints', () => {
|
||||
expect(content).toContain('DESIGN.md');
|
||||
@@ -1256,7 +1256,7 @@ describe('DESIGN_SKETCH resolver', () => {
|
||||
// --- {{CODEX_SECOND_OPINION}} resolver tests ---
|
||||
|
||||
describe('CODEX_SECOND_OPINION resolver', () => {
|
||||
const content = fs.readFileSync(path.join(ROOT, 'office-hours', 'SKILL.md'), 'utf-8');
|
||||
const content = readSkillUnion('office-hours'); // carved: Phase 5/6 prose moved to section
|
||||
const codexContent = fs.readFileSync(path.join(ROOT, '.agents', 'skills', 'gstack-office-hours', 'SKILL.md'), 'utf-8');
|
||||
|
||||
test('Phase 3.5 section appears in office-hours SKILL.md', () => {
|
||||
@@ -1369,7 +1369,7 @@ describe('Codex filesystem boundary', () => {
|
||||
|
||||
describe('BENEFITS_FROM resolver', () => {
|
||||
const ceoContent = fs.readFileSync(path.join(ROOT, 'plan-ceo-review', 'SKILL.md'), 'utf-8');
|
||||
const engContent = fs.readFileSync(path.join(ROOT, 'plan-eng-review', 'SKILL.md'), 'utf-8');
|
||||
const engContent = readSkillUnion('plan-eng-review'); // carved
|
||||
|
||||
test('plan-ceo-review contains prerequisite skill offer', () => {
|
||||
expect(ceoContent).toContain('Prerequisite Skill Offer');
|
||||
@@ -1666,7 +1666,7 @@ describe('preamble routing injection', () => {
|
||||
|
||||
describe('DESIGN_OUTSIDE_VOICES resolver', () => {
|
||||
test('plan-design-review contains outside voices section', () => {
|
||||
const content = fs.readFileSync(path.join(ROOT, 'plan-design-review', 'SKILL.md'), 'utf-8');
|
||||
const content = readSkillUnion('plan-design-review');
|
||||
expect(content).toContain('Design Outside Voices');
|
||||
expect(content).toContain('CODEX_AVAILABLE');
|
||||
expect(content).toContain('LITMUS SCORECARD');
|
||||
@@ -1685,7 +1685,7 @@ describe('DESIGN_OUTSIDE_VOICES resolver', () => {
|
||||
});
|
||||
|
||||
test('branches correctly per skillName — different prompts', () => {
|
||||
const planContent = fs.readFileSync(path.join(ROOT, 'plan-design-review', 'SKILL.md'), 'utf-8');
|
||||
const planContent = readSkillUnion('plan-design-review');
|
||||
const consultContent = fs.readFileSync(path.join(ROOT, 'design-consultation', 'SKILL.md'), 'utf-8');
|
||||
// plan-design-review uses analytical prompt (high reasoning)
|
||||
expect(planContent).toContain('model_reasoning_effort="high"');
|
||||
@@ -1698,7 +1698,7 @@ describe('DESIGN_OUTSIDE_VOICES resolver', () => {
|
||||
|
||||
describe('DESIGN_HARD_RULES resolver', () => {
|
||||
test('plan-design-review Pass 4 contains hard rules', () => {
|
||||
const content = fs.readFileSync(path.join(ROOT, 'plan-design-review', 'SKILL.md'), 'utf-8');
|
||||
const content = readSkillUnion('plan-design-review');
|
||||
expect(content).toContain('Design Hard Rules');
|
||||
expect(content).toContain('Classifier');
|
||||
expect(content).toContain('MARKETING/LANDING PAGE');
|
||||
@@ -1711,26 +1711,26 @@ describe('DESIGN_HARD_RULES resolver', () => {
|
||||
});
|
||||
|
||||
test('includes all 3 rule sets', () => {
|
||||
const content = fs.readFileSync(path.join(ROOT, 'plan-design-review', 'SKILL.md'), 'utf-8');
|
||||
const content = readSkillUnion('plan-design-review');
|
||||
expect(content).toContain('Landing page rules');
|
||||
expect(content).toContain('App UI rules');
|
||||
expect(content).toContain('Universal rules');
|
||||
});
|
||||
|
||||
test('references shared AI slop blacklist items', () => {
|
||||
const content = fs.readFileSync(path.join(ROOT, 'plan-design-review', 'SKILL.md'), 'utf-8');
|
||||
const content = readSkillUnion('plan-design-review');
|
||||
expect(content).toContain('3-column feature grid');
|
||||
expect(content).toContain('Purple/violet/indigo');
|
||||
});
|
||||
|
||||
test('includes OpenAI hard rejection criteria', () => {
|
||||
const content = fs.readFileSync(path.join(ROOT, 'plan-design-review', 'SKILL.md'), 'utf-8');
|
||||
const content = readSkillUnion('plan-design-review');
|
||||
expect(content).toContain('Generic SaaS card grid');
|
||||
expect(content).toContain('Carousel with no narrative purpose');
|
||||
});
|
||||
|
||||
test('includes OpenAI litmus checks', () => {
|
||||
const content = fs.readFileSync(path.join(ROOT, 'plan-design-review', 'SKILL.md'), 'utf-8');
|
||||
const content = readSkillUnion('plan-design-review');
|
||||
expect(content).toContain('Brand/product unmistakable');
|
||||
expect(content).toContain('premium with all decorative shadows removed');
|
||||
});
|
||||
@@ -1739,7 +1739,7 @@ describe('DESIGN_HARD_RULES resolver', () => {
|
||||
// --- Extended DESIGN_SKETCH resolver tests ---
|
||||
|
||||
describe('DESIGN_SKETCH extended with outside voices', () => {
|
||||
const content = fs.readFileSync(path.join(ROOT, 'office-hours', 'SKILL.md'), 'utf-8');
|
||||
const content = readSkillUnion('office-hours'); // carved: Phase 5/6 prose moved to section
|
||||
|
||||
test('contains outside design voices step', () => {
|
||||
expect(content).toContain('Outside design voices');
|
||||
@@ -2764,7 +2764,7 @@ describe('community fixes wave', () => {
|
||||
|
||||
// #510 — Context warnings: plan-eng-review has explicit anti-warning
|
||||
test('plan-eng-review/SKILL.md contains "Do not preemptively warn"', () => {
|
||||
const content = fs.readFileSync(path.join(ROOT, 'plan-eng-review', 'SKILL.md'), 'utf-8');
|
||||
const content = readSkillUnion('plan-eng-review'); // carved: review body moved to section
|
||||
expect(content).toContain('Do not preemptively warn');
|
||||
});
|
||||
|
||||
@@ -3227,7 +3227,9 @@ describe('GSTACK REVIEW REPORT delete-then-append flow', () => {
|
||||
|
||||
for (const skill of PLAN_REVIEW_SKILLS) {
|
||||
test(`${skill}/SKILL.md prescribes delete-then-append, not in-place replace`, () => {
|
||||
const content = fs.readFileSync(path.join(ROOT, skill, 'SKILL.md'), 'utf-8');
|
||||
// Carved skills (v2 plan Phase B) relocate the review-report prose into
|
||||
// sections/*.md; readSkillUnion follows the content wherever the carve put it.
|
||||
const content = readSkillUnion(skill);
|
||||
|
||||
// The new (correct) instruction must be present.
|
||||
expect(content).toContain('delete-then-append flow');
|
||||
|
||||
Reference in New Issue
Block a user