@su-record/vibe 3.2.1 → 3.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CLAUDE.md +1 -1
- package/README.en.md +4 -4
- package/README.md +4 -4
- package/dist/__tests__/skill-namespace.test.d.ts +2 -0
- package/dist/__tests__/skill-namespace.test.d.ts.map +1 -0
- package/dist/__tests__/skill-namespace.test.js +60 -0
- package/dist/__tests__/skill-namespace.test.js.map +1 -0
- package/dist/__tests__/stakes-contract.test.d.ts +2 -0
- package/dist/__tests__/stakes-contract.test.d.ts.map +1 -0
- package/dist/__tests__/stakes-contract.test.js +110 -0
- package/dist/__tests__/stakes-contract.test.js.map +1 -0
- package/dist/__tests__/wiring-integrity.test.js +5 -5
- package/dist/__tests__/wiring-integrity.test.js.map +1 -1
- package/dist/cli/generate-release-notes.d.ts +3 -0
- package/dist/cli/generate-release-notes.d.ts.map +1 -0
- package/dist/cli/generate-release-notes.js +47 -0
- package/dist/cli/generate-release-notes.js.map +1 -0
- package/dist/cli/postinstall/constants.d.ts +6 -6
- package/dist/cli/postinstall/constants.d.ts.map +1 -1
- package/dist/cli/postinstall/constants.js +114 -46
- package/dist/cli/postinstall/constants.js.map +1 -1
- package/dist/cli/postinstall/fs-utils.d.ts +1 -0
- package/dist/cli/postinstall/fs-utils.d.ts.map +1 -1
- package/dist/cli/postinstall/fs-utils.js +25 -0
- package/dist/cli/postinstall/fs-utils.js.map +1 -1
- package/dist/cli/postinstall/fs-utils.test.js +46 -11
- package/dist/cli/postinstall/fs-utils.test.js.map +1 -1
- package/dist/cli/postinstall/main.d.ts.map +1 -1
- package/dist/cli/postinstall/main.js +3 -2
- package/dist/cli/postinstall/main.js.map +1 -1
- package/dist/tests/curated-release-notes.test.d.ts +2 -0
- package/dist/tests/curated-release-notes.test.d.ts.map +1 -0
- package/dist/tests/curated-release-notes.test.js +106 -0
- package/dist/tests/curated-release-notes.test.js.map +1 -0
- package/dist/tools/release/releaseNotes.d.ts +21 -0
- package/dist/tools/release/releaseNotes.d.ts.map +1 -0
- package/dist/tools/release/releaseNotes.js +105 -0
- package/dist/tools/release/releaseNotes.js.map +1 -0
- package/hooks/scripts/__tests__/.vibe/command-log.txt +3 -3
- package/package.json +2 -2
- package/skills/vibe/SKILL.md +14 -0
- package/skills/{agents-md → vibe.agents-md}/SKILL.md +1 -1
- package/skills/{brand-assets → vibe.brand-assets}/SKILL.md +1 -1
- package/skills/{capability-loop → vibe.capability-loop}/SKILL.md +1 -1
- package/skills/{chub-usage → vibe.chub-usage}/SKILL.md +1 -1
- package/skills/vibe.clone/SKILL.md +295 -3
- package/skills/{commerce-patterns → vibe.commerce-patterns}/SKILL.md +1 -1
- package/skills/{commit-push-pr → vibe.commit-push-pr}/SKILL.md +2 -2
- package/skills/{context7-usage → vibe.context7-usage}/SKILL.md +1 -1
- package/skills/vibe.contract/SKILL.md +162 -1
- package/skills/{create-prd → vibe.create-prd}/SKILL.md +2 -2
- package/skills/{design-refine → vibe.design-refine}/SKILL.md +1 -1
- package/skills/{design-review → vibe.design-review}/SKILL.md +1 -1
- package/skills/{design-teach → vibe.design-teach}/SKILL.md +1 -1
- package/skills/{devlog → vibe.devlog}/SKILL.md +1 -1
- package/skills/vibe.docs/SKILL.md +256 -1
- package/skills/{e2e-commerce → vibe.e2e-commerce}/SKILL.md +1 -1
- package/skills/vibe.educational-content/SKILL.md +157 -0
- package/skills/vibe.educational-content/references/learning-design.md +81 -0
- package/skills/vibe.educational-content/references/output-patterns.md +109 -0
- package/skills/vibe.educational-content/references/source-method.md +40 -0
- package/skills/{event-comms → vibe.event-comms}/SKILL.md +1 -1
- package/skills/{event-ops → vibe.event-ops}/SKILL.md +1 -1
- package/skills/{event-planning → vibe.event-planning}/SKILL.md +1 -1
- package/skills/vibe.figma/SKILL.md +473 -21
- package/skills/vibe.figma/references/branch-phases.md +1 -1
- package/skills/{git-worktree → vibe.git-worktree}/SKILL.md +1 -1
- package/skills/{handoff → vibe.handoff}/SKILL.md +1 -1
- package/skills/{parallel-research → vibe.parallel-research}/SKILL.md +2 -2
- package/skills/{presentation → vibe.presentation}/SKILL.md +1 -1
- package/skills/{prioritization-frameworks → vibe.prioritization}/SKILL.md +2 -2
- package/skills/{priority-todos → vibe.priority-todos}/SKILL.md +1 -1
- package/skills/{vercel-react-best-practices → vibe.react-best-practices}/SKILL.md +1 -1
- package/skills/vibe.regress/SKILL.md +182 -2
- package/skills/vibe.review/SKILL.md +8 -0
- package/skills/vibe.run/SKILL.md +392 -1
- package/skills/{arch-guard → vibe.run/internal/arch-guard}/templates/violation-report.md +1 -1
- package/skills/{seo-checklist → vibe.seo-checklist}/SKILL.md +1 -1
- package/skills/vibe.spec/SKILL.md +123 -1
- package/skills/vibe.test/SKILL.md +138 -2
- package/skills/{tool-fallback → vibe.tool-fallback}/SKILL.md +1 -1
- package/skills/{ui-ux-pro-max → vibe.ui-ux-pro-max}/SKILL.md +6 -6
- package/skills/{user-personas → vibe.user-personas}/SKILL.md +2 -2
- package/skills/vibe.verify/SKILL.md +2 -2
- package/skills/{video-production → vibe.video-production}/SKILL.md +1 -1
- package/vibe/rules/loop-contract.md +18 -0
- package/skills/arch-guard/SKILL.md +0 -183
- package/skills/clone/SKILL.md +0 -296
- package/skills/contract/SKILL.md +0 -165
- package/skills/docs/SKILL.md +0 -259
- package/skills/exec-plan/SKILL.md +0 -151
- package/skills/figma/SKILL.md +0 -456
- package/skills/regress/SKILL.md +0 -184
- package/skills/restraint/SKILL.md +0 -72
- package/skills/spec/SKILL.md +0 -125
- package/skills/test/SKILL.md +0 -140
- /package/skills/{agents-md → vibe.agents-md}/rubrics/what-to-keep.md +0 -0
- /package/skills/{agents-md → vibe.agents-md}/templates/agents-md.md +0 -0
- /package/skills/{agents-md → vibe.agents-md}/templates/claude-md.md +0 -0
- /package/skills/{brand-assets → vibe.brand-assets}/rubrics/asset-checklist.md +0 -0
- /package/skills/{brand-assets → vibe.brand-assets}/templates/brand-guide.md +0 -0
- /package/skills/{capability-loop → vibe.capability-loop}/agents/capability-designer.md +0 -0
- /package/skills/{capability-loop → vibe.capability-loop}/agents/failure-analyst.md +0 -0
- /package/skills/{capability-loop → vibe.capability-loop}/agents/implementer.md +0 -0
- /package/skills/{capability-loop → vibe.capability-loop}/agents/tester.md +0 -0
- /package/skills/{capability-loop → vibe.capability-loop}/templates/capability-spec.md +0 -0
- /package/skills/{capability-loop → vibe.capability-loop}/templates/failure-analysis.md +0 -0
- /package/skills/{clone → vibe.clone}/references/capture-rules.md +0 -0
- /package/skills/{clone → vibe.clone}/references/legal-and-error-recovery.md +0 -0
- /package/skills/{clone → vibe.clone}/references/refine-rules.md +0 -0
- /package/skills/{clone → vibe.clone}/references/scaffold-phases.md +0 -0
- /package/skills/{clone → vibe.clone}/references/setup-and-layout.md +0 -0
- /package/skills/{commerce-patterns → vibe.commerce-patterns}/rubrics/checkout-flow.md +0 -0
- /package/skills/{commerce-patterns → vibe.commerce-patterns}/templates/product-schema.md +0 -0
- /package/skills/{commit-push-pr → vibe.commit-push-pr}/agents/change-analyzer.md +0 -0
- /package/skills/{commit-push-pr → vibe.commit-push-pr}/agents/message-writer.md +0 -0
- /package/skills/{commit-push-pr → vibe.commit-push-pr}/agents/pr-writer.md +0 -0
- /package/skills/{commit-push-pr → vibe.commit-push-pr}/agents/reviewer.md +0 -0
- /package/skills/{commit-push-pr → vibe.commit-push-pr}/rubrics/commit-message.md +0 -0
- /package/skills/{commit-push-pr → vibe.commit-push-pr}/templates/pr-body.md +0 -0
- /package/skills/{context7-usage → vibe.context7-usage}/rubrics/when-to-use.md +0 -0
- /package/skills/{create-prd → vibe.create-prd}/agents/edge-case-finder.md +0 -0
- /package/skills/{create-prd → vibe.create-prd}/agents/prioritizer.md +0 -0
- /package/skills/{create-prd → vibe.create-prd}/agents/requirements-writer.md +0 -0
- /package/skills/{create-prd → vibe.create-prd}/agents/researcher.md +0 -0
- /package/skills/{create-prd → vibe.create-prd}/agents/reviewer.md +0 -0
- /package/skills/{create-prd → vibe.create-prd}/frameworks/jobs-to-be-done.md +0 -0
- /package/skills/{create-prd → vibe.create-prd}/frameworks/rice-scoring.md +0 -0
- /package/skills/{create-prd → vibe.create-prd}/orchestrator.md +0 -0
- /package/skills/{create-prd → vibe.create-prd}/rubrics/completeness.md +0 -0
- /package/skills/{create-prd → vibe.create-prd}/templates/prd.md +0 -0
- /package/skills/{design-refine → vibe.design-refine}/rubrics/polish-checklist.md +0 -0
- /package/skills/{design-refine → vibe.design-refine}/rubrics/token-naming.md +0 -0
- /package/skills/{design-refine → vibe.design-refine}/templates/design-system.md +0 -0
- /package/skills/{design-refine → vibe.design-refine}/templates/polish-report.md +0 -0
- /package/skills/{design-refine → vibe.design-refine}/templates/token-audit.md +0 -0
- /package/skills/{design-review → vibe.design-review}/agents/a11y-auditor.md +0 -0
- /package/skills/{design-review → vibe.design-review}/agents/performance-auditor.md +0 -0
- /package/skills/{design-review → vibe.design-review}/agents/responsive-auditor.md +0 -0
- /package/skills/{design-review → vibe.design-review}/agents/scorer.md +0 -0
- /package/skills/{design-review → vibe.design-review}/agents/slop-detector.md +0 -0
- /package/skills/{design-review → vibe.design-review}/frameworks/core-web-vitals.md +0 -0
- /package/skills/{design-review → vibe.design-review}/frameworks/wcag-checklist.md +0 -0
- /package/skills/{design-review → vibe.design-review}/orchestrator.md +0 -0
- /package/skills/{design-review → vibe.design-review}/rubrics/ai-slop-patterns.md +0 -0
- /package/skills/{design-review → vibe.design-review}/rubrics/scoring.md +0 -0
- /package/skills/{design-review → vibe.design-review}/rubrics/ux-heuristics.md +0 -0
- /package/skills/{design-review → vibe.design-review}/templates/critique-report.md +0 -0
- /package/skills/{design-review → vibe.design-review}/templates/report.md +0 -0
- /package/skills/{design-teach → vibe.design-teach}/rubrics/brand-personality.md +0 -0
- /package/skills/{design-teach → vibe.design-teach}/templates/design-context.json +0 -0
- /package/skills/{docs → vibe.docs}/references/api-docs-changelog.md +0 -0
- /package/skills/{docs → vibe.docs}/references/codemaps-output.md +0 -0
- /package/skills/{docs → vibe.docs}/references/diagram-spec.md +0 -0
- /package/skills/{docs → vibe.docs}/templates/architecture.md +0 -0
- /package/skills/{docs → vibe.docs}/templates/behavioral-principles.md +0 -0
- /package/skills/{docs → vibe.docs}/templates/readme.md +0 -0
- /package/skills/{docs → vibe.docs}/templates/release-notes.md +0 -0
- /package/skills/{e2e-commerce → vibe.e2e-commerce}/templates/test-scenarios.md +0 -0
- /package/skills/{event-comms → vibe.event-comms}/templates/email-invite.md +0 -0
- /package/skills/{event-comms → vibe.event-comms}/templates/sns-post.md +0 -0
- /package/skills/{event-ops → vibe.event-ops}/rubrics/contingency.md +0 -0
- /package/skills/{event-ops → vibe.event-ops}/templates/d-day-checklist.md +0 -0
- /package/skills/{event-planning → vibe.event-planning}/rubrics/timeline.md +0 -0
- /package/skills/{event-planning → vibe.event-planning}/templates/event-plan.md +0 -0
- /package/skills/{figma → vibe.figma}/rubrics/conversion-rules.md +0 -0
- /package/skills/{figma → vibe.figma}/rubrics/css-mapping.md +0 -0
- /package/skills/{figma → vibe.figma}/rubrics/extraction-checklist.md +0 -0
- /package/skills/{figma → vibe.figma}/rubrics/image-rules.md +0 -0
- /package/skills/{figma → vibe.figma}/templates/component-index.md +0 -0
- /package/skills/{figma → vibe.figma}/templates/component-spec.md +0 -0
- /package/skills/{figma → vibe.figma}/templates/component.md +0 -0
- /package/skills/{figma → vibe.figma}/templates/figma-handoff.md +0 -0
- /package/skills/{figma → vibe.figma}/templates/remapped-tree.md +0 -0
- /package/skills/{git-worktree → vibe.git-worktree}/rubrics/when-to-use.md +0 -0
- /package/skills/{handoff → vibe.handoff}/agents/context-summarizer.md +0 -0
- /package/skills/{handoff → vibe.handoff}/agents/document-writer.md +0 -0
- /package/skills/{handoff → vibe.handoff}/agents/state-collector.md +0 -0
- /package/skills/{handoff → vibe.handoff}/agents/verifier.md +0 -0
- /package/skills/{handoff → vibe.handoff}/rubrics/completeness.md +0 -0
- /package/skills/{handoff → vibe.handoff}/templates/handoff.md +0 -0
- /package/skills/{parallel-research → vibe.parallel-research}/agents/best-practices.md +0 -0
- /package/skills/{parallel-research → vibe.parallel-research}/agents/codebase-patterns.md +0 -0
- /package/skills/{parallel-research → vibe.parallel-research}/agents/framework-docs.md +0 -0
- /package/skills/{parallel-research → vibe.parallel-research}/agents/security-advisory.md +0 -0
- /package/skills/{parallel-research → vibe.parallel-research}/agents/synthesizer.md +0 -0
- /package/skills/{parallel-research → vibe.parallel-research}/experts/best-practices.md +0 -0
- /package/skills/{parallel-research → vibe.parallel-research}/experts/codebase-patterns.md +0 -0
- /package/skills/{parallel-research → vibe.parallel-research}/experts/framework-docs.md +0 -0
- /package/skills/{parallel-research → vibe.parallel-research}/experts/security-advisory.md +0 -0
- /package/skills/{parallel-research → vibe.parallel-research}/orchestrator.md +0 -0
- /package/skills/{parallel-research → vibe.parallel-research}/templates/awesome-list.md +0 -0
- /package/skills/{parallel-research → vibe.parallel-research}/templates/paper.md +0 -0
- /package/skills/{parallel-research → vibe.parallel-research}/templates/synthesis.md +0 -0
- /package/skills/{presentation → vibe.presentation}/references/style-presets.md +0 -0
- /package/skills/{prioritization-frameworks → vibe.prioritization}/rubrics/frameworks.md +0 -0
- /package/skills/{prioritization-frameworks → vibe.prioritization}/templates/scoring-matrix.md +0 -0
- /package/skills/{priority-todos → vibe.priority-todos}/rubrics/prioritization.md +0 -0
- /package/skills/{priority-todos → vibe.priority-todos}/templates/todo-board.md +0 -0
- /package/skills/{vercel-react-best-practices → vibe.react-best-practices}/rubrics/performance.md +0 -0
- /package/skills/{vercel-react-best-practices → vibe.react-best-practices}/rubrics/server-components.md +0 -0
- /package/skills/{regress → vibe.regress}/templates/bug.md +0 -0
- /package/skills/{regress → vibe.regress}/templates/test-jest.md +0 -0
- /package/skills/{regress → vibe.regress}/templates/test-vitest.md +0 -0
- /package/skills/{arch-guard → vibe.run/internal/arch-guard}/agents/detector.md +0 -0
- /package/skills/{arch-guard → vibe.run/internal/arch-guard}/agents/reporter.md +0 -0
- /package/skills/{arch-guard → vibe.run/internal/arch-guard}/agents/rule-generator.md +0 -0
- /package/skills/{arch-guard → vibe.run/internal/arch-guard}/agents/violation-checker.md +0 -0
- /package/skills/{arch-guard → vibe.run/internal/arch-guard}/frameworks/clean-architecture.md +0 -0
- /package/skills/{arch-guard → vibe.run/internal/arch-guard}/frameworks/solid.md +0 -0
- /package/skills/{arch-guard → vibe.run/internal/arch-guard}/scripts/check-boundaries.js +0 -0
- /package/skills/{arch-guard → vibe.run/internal/arch-guard}/templates/arch-rules.json +0 -0
- /package/skills/{exec-plan → vibe.run/internal/exec-plan}/agents/decomposer.md +0 -0
- /package/skills/{exec-plan → vibe.run/internal/exec-plan}/agents/dependency-mapper.md +0 -0
- /package/skills/{exec-plan → vibe.run/internal/exec-plan}/agents/estimator.md +0 -0
- /package/skills/{exec-plan → vibe.run/internal/exec-plan}/agents/validator.md +0 -0
- /package/skills/{exec-plan → vibe.run/internal/exec-plan}/orchestrator.md +0 -0
- /package/skills/{exec-plan → vibe.run/internal/exec-plan}/rubrics/complexity-scoring.md +0 -0
- /package/skills/{exec-plan → vibe.run/internal/exec-plan}/templates/plan.md +0 -0
- /package/skills/{seo-checklist → vibe.seo-checklist}/frameworks/structured-data.md +0 -0
- /package/skills/{seo-checklist → vibe.seo-checklist}/rubrics/content-seo.md +0 -0
- /package/skills/{seo-checklist → vibe.seo-checklist}/rubrics/technical-seo.md +0 -0
- /package/skills/{tool-fallback → vibe.tool-fallback}/rubrics/fallback-chain.md +0 -0
- /package/skills/{ui-ux-pro-max → vibe.ui-ux-pro-max}/reference/color-and-contrast.md +0 -0
- /package/skills/{ui-ux-pro-max → vibe.ui-ux-pro-max}/reference/interaction-design.md +0 -0
- /package/skills/{ui-ux-pro-max → vibe.ui-ux-pro-max}/reference/motion-design.md +0 -0
- /package/skills/{ui-ux-pro-max → vibe.ui-ux-pro-max}/reference/responsive-design.md +0 -0
- /package/skills/{ui-ux-pro-max → vibe.ui-ux-pro-max}/reference/spatial-design.md +0 -0
- /package/skills/{ui-ux-pro-max → vibe.ui-ux-pro-max}/reference/typography.md +0 -0
- /package/skills/{ui-ux-pro-max → vibe.ui-ux-pro-max}/reference/ux-writing.md +0 -0
- /package/skills/{ui-ux-pro-max → vibe.ui-ux-pro-max}/rubrics/interaction-states.md +0 -0
- /package/skills/{ui-ux-pro-max → vibe.ui-ux-pro-max}/rubrics/responsive-breakpoints.md +0 -0
- /package/skills/{user-personas → vibe.user-personas}/rubrics/research-methods.md +0 -0
- /package/skills/{user-personas → vibe.user-personas}/templates/persona.md +0 -0
- /package/skills/{video-production → vibe.video-production}/rubrics/quality-checklist.md +0 -0
- /package/skills/{video-production → vibe.video-production}/templates/production-plan.md +0 -0
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import { resolve } from 'node:path';
|
|
3
|
+
import { describe, expect, it } from 'vitest';
|
|
4
|
+
import { classifyCommits, createReleaseNotes, selectPreviousSemanticTag, } from '../tools/release/releaseNotes.js';
|
|
5
|
+
const CLASSIFICATION_CASES = [
|
|
6
|
+
['feat: add packets', 'Added'],
|
|
7
|
+
['fix(parser): reject drift', 'Fixed'],
|
|
8
|
+
['docs: explain packets', 'Documentation'],
|
|
9
|
+
['refactor: split compiler', 'Internal'],
|
|
10
|
+
['chore: refresh fixtures', 'Internal'],
|
|
11
|
+
['perf: cache parsing', 'Changed'],
|
|
12
|
+
];
|
|
13
|
+
describe('selectPreviousSemanticTag', () => {
|
|
14
|
+
it('REQ-release-notes-001 uses the previous semantic version and ignores log tags', () => {
|
|
15
|
+
const tags = ['log-20260720', 'v3.1.9', 'v3.2.0', 'v3.2.1'];
|
|
16
|
+
expect(selectPreviousSemanticTag(tags, 'v3.2.1')).toBe('v3.2.0');
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
describe('REQ-release-notes-003 classifyCommits', () => {
|
|
20
|
+
it.each(CLASSIFICATION_CASES)('REQ-release-notes-003 places %s in %s', (subject, section) => {
|
|
21
|
+
const result = classifyCommits([{ subject, body: '' }]);
|
|
22
|
+
expect(result[section]).toEqual([subject.replace(/^[^:]+:\s*/, '')]);
|
|
23
|
+
});
|
|
24
|
+
it('puts breaking changes first and excludes merge and version commits', () => {
|
|
25
|
+
const result = classifyCommits([
|
|
26
|
+
{ subject: 'feat!: replace packet schema', body: '' },
|
|
27
|
+
{ subject: 'Merge pull request #45', body: '' },
|
|
28
|
+
{ subject: '3.2.1', body: '' },
|
|
29
|
+
]);
|
|
30
|
+
expect(result.Breaking).toEqual(['replace packet schema']);
|
|
31
|
+
expect(Object.values(result).flat()).not.toContain('Merge pull request #45');
|
|
32
|
+
expect(Object.values(result).flat()).not.toContain('3.2.1');
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
describe('createReleaseNotes', () => {
|
|
36
|
+
it('REQ-release-notes-002 includes the SPEC overview and every requirement', () => {
|
|
37
|
+
const spec = `# SPEC: Execution Packets
|
|
38
|
+
|
|
39
|
+
## 1. Overview / Goal
|
|
40
|
+
|
|
41
|
+
Compile canonical specifications into deterministic execution packets.
|
|
42
|
+
|
|
43
|
+
## 2. Requirements
|
|
44
|
+
|
|
45
|
+
| ID | Requirement | Done Criteria |
|
|
46
|
+
|----|-------------|---------------|
|
|
47
|
+
| REQ-packet-001 | Preserve every requirement | D1 |
|
|
48
|
+
| REQ-packet-002 | Reject stale packets | D2 |
|
|
49
|
+
`;
|
|
50
|
+
const notes = createReleaseNotes({
|
|
51
|
+
currentTag: 'v3.2.1',
|
|
52
|
+
previousTag: 'v3.2.0',
|
|
53
|
+
specs: [{ path: '.vibe/specs/execution-packet-compiler.md', content: spec }],
|
|
54
|
+
commits: [
|
|
55
|
+
{ subject: 'feat: compile execution packets', body: '' },
|
|
56
|
+
{ subject: 'fix: reject tampered evidence', body: '' },
|
|
57
|
+
],
|
|
58
|
+
});
|
|
59
|
+
expect(notes).toContain('## Highlights');
|
|
60
|
+
expect(notes).toContain('Compile canonical specifications into deterministic execution packets.');
|
|
61
|
+
expect(notes).toContain('Preserve every requirement');
|
|
62
|
+
expect(notes).toContain('Reject stale packets');
|
|
63
|
+
expect(notes).toContain('## Added');
|
|
64
|
+
expect(notes).toContain('## Fixed');
|
|
65
|
+
expect(notes).toContain('## Verification');
|
|
66
|
+
expect(notes).toContain('`v3.2.0..v3.2.1`');
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
describe('release workflow', () => {
|
|
70
|
+
it('REQ-release-notes-004 checks out full history and publishes a generated notes file', () => {
|
|
71
|
+
const workflow = readFileSync(resolve('.github/workflows/release.yml'), 'utf8');
|
|
72
|
+
expect(workflow).toMatch(/fetch-depth:\s*0/);
|
|
73
|
+
expect(workflow).toContain('generate-release-notes');
|
|
74
|
+
expect(workflow).toContain('--notes-file');
|
|
75
|
+
expect(workflow).not.toContain('--generate-notes');
|
|
76
|
+
});
|
|
77
|
+
it('REQ-release-notes-006 preserves the build and full test gates', () => {
|
|
78
|
+
const workflow = readFileSync(resolve('.github/workflows/release.yml'), 'utf8');
|
|
79
|
+
expect(workflow).toContain('pnpm build');
|
|
80
|
+
expect(workflow).toContain('pnpm test -- --reporter=default');
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
describe('published release contract', () => {
|
|
84
|
+
it('REQ-release-notes-005 renders the required public sections', () => {
|
|
85
|
+
const notes = createReleaseNotes({
|
|
86
|
+
currentTag: 'v3.2.1',
|
|
87
|
+
previousTag: 'v3.2.0',
|
|
88
|
+
specs: [{ path: 'feature.md', content: '# SPEC: Feature\n\n## Overview\nUseful change.' }],
|
|
89
|
+
commits: [
|
|
90
|
+
{ subject: 'feat: add capability', body: '' },
|
|
91
|
+
{ subject: 'fix: correct behavior', body: '' },
|
|
92
|
+
],
|
|
93
|
+
});
|
|
94
|
+
expect(notes).toContain('## Highlights');
|
|
95
|
+
expect(notes).toContain('## Added');
|
|
96
|
+
expect(notes).toContain('## Fixed');
|
|
97
|
+
expect(notes).toContain('## Verification');
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
describe('release notes CLI', () => {
|
|
101
|
+
it('excludes deleted specifications from the current tag lookup', () => {
|
|
102
|
+
const cli = readFileSync(resolve('src/cli/generate-release-notes.ts'), 'utf8');
|
|
103
|
+
expect(cli).toContain("'--diff-filter=AMR'");
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
//# sourceMappingURL=curated-release-notes.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"curated-release-notes.test.js","sourceRoot":"","sources":["../../src/tests/curated-release-notes.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export interface ReleaseCommit {
|
|
2
|
+
subject: string;
|
|
3
|
+
body: string;
|
|
4
|
+
}
|
|
5
|
+
export interface ReleaseSpec {
|
|
6
|
+
path: string;
|
|
7
|
+
content: string;
|
|
8
|
+
}
|
|
9
|
+
export interface ReleaseNotesInput {
|
|
10
|
+
currentTag: string;
|
|
11
|
+
previousTag: string;
|
|
12
|
+
specs: ReleaseSpec[];
|
|
13
|
+
commits: ReleaseCommit[];
|
|
14
|
+
}
|
|
15
|
+
type ReleaseSection = 'Breaking' | 'Added' | 'Fixed' | 'Changed' | 'Documentation' | 'Internal';
|
|
16
|
+
export type ClassifiedCommits = Record<ReleaseSection, string[]>;
|
|
17
|
+
export declare function selectPreviousSemanticTag(tags: string[], currentTag: string): string;
|
|
18
|
+
export declare function classifyCommits(commits: ReleaseCommit[]): ClassifiedCommits;
|
|
19
|
+
export declare function createReleaseNotes(input: ReleaseNotesInput): string;
|
|
20
|
+
export {};
|
|
21
|
+
//# sourceMappingURL=releaseNotes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"releaseNotes.d.ts","sourceRoot":"","sources":["../../../src/tools/release/releaseNotes.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,iBAAiB;IAChC,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,OAAO,EAAE,aAAa,EAAE,CAAC;CAC1B;AAED,KAAK,cAAc,GAAG,UAAU,GAAG,OAAO,GAAG,OAAO,GAAG,SAAS,GAAG,eAAe,GAAG,UAAU,CAAC;AAChG,MAAM,MAAM,iBAAiB,GAAG,MAAM,CAAC,cAAc,EAAE,MAAM,EAAE,CAAC,CAAC;AAmCjE,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAWpF;AAMD,wBAAgB,eAAe,CAAC,OAAO,EAAE,aAAa,EAAE,GAAG,iBAAiB,CAa3E;AA4BD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,iBAAiB,GAAG,MAAM,CAkBnE"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
const SEMANTIC_TAG = /^v(\d+)\.(\d+)\.(\d+)$/;
|
|
2
|
+
const VERSION_COMMIT = /^(?:v?\d+\.\d+\.\d+|chore(?:\(release\))?:\s*v?\d+\.\d+\.\d+)$/i;
|
|
3
|
+
const CONVENTIONAL_SUBJECT = /^([a-z]+)(?:\([^)]+\))?(!)?:\s*(.+)$/i;
|
|
4
|
+
const SECTION_ORDER = [
|
|
5
|
+
'Breaking', 'Added', 'Fixed', 'Changed', 'Documentation', 'Internal',
|
|
6
|
+
];
|
|
7
|
+
const TYPE_TO_SECTION = {
|
|
8
|
+
feat: 'Added',
|
|
9
|
+
fix: 'Fixed',
|
|
10
|
+
docs: 'Documentation',
|
|
11
|
+
refactor: 'Internal',
|
|
12
|
+
chore: 'Internal',
|
|
13
|
+
test: 'Internal',
|
|
14
|
+
ci: 'Internal',
|
|
15
|
+
build: 'Internal',
|
|
16
|
+
perf: 'Changed',
|
|
17
|
+
style: 'Changed',
|
|
18
|
+
};
|
|
19
|
+
function parseTag(tag) {
|
|
20
|
+
const match = SEMANTIC_TAG.exec(tag);
|
|
21
|
+
if (!match)
|
|
22
|
+
return undefined;
|
|
23
|
+
return [Number(match[1]), Number(match[2]), Number(match[3])];
|
|
24
|
+
}
|
|
25
|
+
function compareVersions(left, right) {
|
|
26
|
+
for (let index = 0; index < left.length; index += 1) {
|
|
27
|
+
const difference = left[index] - right[index];
|
|
28
|
+
if (difference !== 0)
|
|
29
|
+
return difference;
|
|
30
|
+
}
|
|
31
|
+
return 0;
|
|
32
|
+
}
|
|
33
|
+
export function selectPreviousSemanticTag(tags, currentTag) {
|
|
34
|
+
const current = parseTag(currentTag);
|
|
35
|
+
if (!current)
|
|
36
|
+
throw new Error(`Invalid release tag: ${currentTag}`);
|
|
37
|
+
const candidates = tags
|
|
38
|
+
.map((tag) => ({ tag, version: parseTag(tag) }))
|
|
39
|
+
.filter((item) => item.version !== undefined && compareVersions(item.version, current) < 0)
|
|
40
|
+
.sort((left, right) => compareVersions(right.version, left.version));
|
|
41
|
+
if (!candidates[0])
|
|
42
|
+
throw new Error(`No previous semantic tag found for ${currentTag}`);
|
|
43
|
+
return candidates[0].tag;
|
|
44
|
+
}
|
|
45
|
+
function emptySections() {
|
|
46
|
+
return { Breaking: [], Added: [], Fixed: [], Changed: [], Documentation: [], Internal: [] };
|
|
47
|
+
}
|
|
48
|
+
export function classifyCommits(commits) {
|
|
49
|
+
return commits.reduce((sections, commit) => {
|
|
50
|
+
if (commit.subject.startsWith('Merge ') || VERSION_COMMIT.test(commit.subject))
|
|
51
|
+
return sections;
|
|
52
|
+
const match = CONVENTIONAL_SUBJECT.exec(commit.subject);
|
|
53
|
+
if (!match) {
|
|
54
|
+
sections.Changed.push(commit.subject);
|
|
55
|
+
return sections;
|
|
56
|
+
}
|
|
57
|
+
const isBreaking = match[2] === '!' || /BREAKING[ -]CHANGE:/i.test(commit.body);
|
|
58
|
+
const section = isBreaking ? 'Breaking' : (TYPE_TO_SECTION[match[1].toLowerCase()] ?? 'Changed');
|
|
59
|
+
sections[section].push(match[3]);
|
|
60
|
+
return sections;
|
|
61
|
+
}, emptySections());
|
|
62
|
+
}
|
|
63
|
+
function extractSection(content, heading) {
|
|
64
|
+
const pattern = new RegExp(`^##\\s+[^\\n]*${heading}[^\\n]*\\n([\\s\\S]*?)(?=^##\\s+|(?![\\s\\S]))`, 'im');
|
|
65
|
+
return pattern.exec(content)?.[1]?.trim() ?? '';
|
|
66
|
+
}
|
|
67
|
+
function extractSpecHighlights(spec) {
|
|
68
|
+
const title = /^#\s+(?:SPEC:\s*)?(.+)$/m.exec(spec.content)?.[1] ?? spec.path;
|
|
69
|
+
const overview = extractSection(spec.content, 'Overview').split(/^###\s+/m)[0].trim();
|
|
70
|
+
const requirements = extractSection(spec.content, 'Requirements')
|
|
71
|
+
.split('\n')
|
|
72
|
+
.filter((line) => /^\|\s*REQ-[^|]+\|/.test(line))
|
|
73
|
+
.map((line) => line.split('|')[2]?.trim())
|
|
74
|
+
.filter((value) => Boolean(value));
|
|
75
|
+
return [`### ${title}`, overview, ...requirements.map((requirement) => `- ${requirement}`)]
|
|
76
|
+
.filter((value) => Boolean(value));
|
|
77
|
+
}
|
|
78
|
+
function renderCommitSections(sections) {
|
|
79
|
+
return SECTION_ORDER.flatMap((section) => {
|
|
80
|
+
const entries = sections[section];
|
|
81
|
+
return entries.length > 0
|
|
82
|
+
? [`## ${section}`, ...entries.map((entry) => `- ${entry}`)]
|
|
83
|
+
: [];
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
export function createReleaseNotes(input) {
|
|
87
|
+
const sections = classifyCommits(input.commits);
|
|
88
|
+
const highlights = input.specs.flatMap(extractSpecHighlights);
|
|
89
|
+
const commitSections = renderCommitSections(sections);
|
|
90
|
+
if (highlights.length === 0 && commitSections.length === 0) {
|
|
91
|
+
throw new Error(`No release changes found in ${input.previousTag}..${input.currentTag}`);
|
|
92
|
+
}
|
|
93
|
+
return [
|
|
94
|
+
`# ${input.currentTag}`,
|
|
95
|
+
'## Highlights',
|
|
96
|
+
...highlights,
|
|
97
|
+
...commitSections,
|
|
98
|
+
'## Verification',
|
|
99
|
+
`- Release range: \`${input.previousTag}..${input.currentTag}\``,
|
|
100
|
+
`- Included commits: ${input.commits.length}`,
|
|
101
|
+
'- Generated deterministically from repository history and specifications.',
|
|
102
|
+
'',
|
|
103
|
+
].join('\n\n');
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=releaseNotes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"releaseNotes.js","sourceRoot":"","sources":["../../../src/tools/release/releaseNotes.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
[2026-07-
|
|
2
|
-
[2026-07-
|
|
3
|
-
[2026-07-
|
|
1
|
+
[2026-07-22T17:14:22.091Z] rm -rf /
|
|
2
|
+
[2026-07-22T17:14:22.167Z] ls -la
|
|
3
|
+
[2026-07-22T17:14:22.264Z] rm -rf src/infra/lib/evolution/
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@su-record/vibe",
|
|
3
|
-
"version": "3.2.
|
|
4
|
-
"description": "AI Coding Framework for Claude Code — 7+ agents,
|
|
3
|
+
"version": "3.2.3",
|
|
4
|
+
"description": "AI Coding Framework for Claude Code — 7+ agents, 51 skills, multi-LLM orchestration",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/cli/index.js",
|
|
7
7
|
"exports": {
|
package/skills/vibe/SKILL.md
CHANGED
|
@@ -75,6 +75,19 @@ user-invocable: true
|
|
|
75
75
|
|
|
76
76
|
복수 의도면 우선순위: resume > figma-driven > new feature > 기타.
|
|
77
77
|
|
|
78
|
+
### Phase 1-b: Stakes 분류 (태스크 무게)
|
|
79
|
+
|
|
80
|
+
의도와 별개로 태스크의 **무게(stakes)** 를 분류한다 — 매핑 SSOT: `vibe/rules/loop-contract.md`의 Stakes 표.
|
|
81
|
+
|
|
82
|
+
| stakes | 판정 신호 | 적용 프로파일 |
|
|
83
|
+
|---|---|---|
|
|
84
|
+
| `demo` | 명시 키워드(데모·일회성·실험·테스트용·throwaway·토이), 기존 프로젝트 코드와 무관한 신규 폴더, `.vibe/config.json` 없는 임시 디렉토리 | `--max-iter 1` + 리뷰 1패스 + **검증 스크립트 신규 생성 금지** |
|
|
85
|
+
| `prototype` | 검증용 초기 버전 명시, 배포 대상 아님 | demo 와 동일 프로파일 |
|
|
86
|
+
| `production` | 기본값 — 신호 없음 | 기존 기본 동작 (수렴 루프, 기본 리뷰어 셋) |
|
|
87
|
+
|
|
88
|
+
- **불확실하면 상향한다** (production). 신호가 상충하면 SPEC 승인 메시지에 stakes 확인 질문 1개를 편승시킨다 — 별도 확인 왕복을 만들지 않는다.
|
|
89
|
+
- 판정 결과는 Phase 3 실행 계획에 `Stakes:` 줄로 명시하고 spec/run/review 체인에 전달한다.
|
|
90
|
+
|
|
78
91
|
> **⚠️ 위 표는 닫힌 화이트리스트가 아니라 "흔한 케이스 빠른 경로"다.** 표에 없는 요구사항이라도 막지 말고 **Catch-all 라우팅**(아래)으로 처리한다.
|
|
79
92
|
|
|
80
93
|
### Catch-all 라우팅 (표에 없는 의도)
|
|
@@ -125,6 +138,7 @@ user-invocable: true
|
|
|
125
138
|
Input: 자연어 ("패럴랙스 웹사이트 만들어줘")
|
|
126
139
|
Resume: 없음 (신규)
|
|
127
140
|
Keywords: 없음
|
|
141
|
+
Stakes: production (신호 없음 — 기본 상향)
|
|
128
142
|
|
|
129
143
|
Phase 1: /vibe.spec → 단일 패스 SPEC + 승인 (유일한 의무 게이트)
|
|
130
144
|
Phase 2: /vibe.figma → UI 디자인 트랙 (type=website 감지)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
name: brand-assets
|
|
2
|
+
name: vibe.brand-assets
|
|
3
3
|
invocation: [auto]
|
|
4
4
|
tier: standard
|
|
5
5
|
description: "Auto-generate app icons (iOS/Android/PWA), favicons, and OG images from SPEC brand information using the Antigravity image backend. Use when the project needs visual brand assets, when user mentions 'icon', 'favicon', 'logo', or 'brand assets', or when a SPEC defines brand colors/identity but no assets exist yet. Outputs multiple sizes and formats ready for deployment. Not for complex illustration or marketing graphics — focused on app identity assets."
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
name: chub-usage
|
|
2
|
+
name: vibe.chub-usage
|
|
3
3
|
invocation: [auto]
|
|
4
4
|
tier: optional
|
|
5
5
|
description: "Context Hub (chub) — fetch vetted, up-to-date API documentation. Write accurate code based on the latest docs instead of training data when working with external APIs/SDKs."
|
|
@@ -49,14 +49,14 @@ Step 2.5) --sub URL 확장
|
|
|
49
49
|
- 포함: 같은 origin + 같은 locale prefix의 하위 메뉴 URL
|
|
50
50
|
- 제외: 외부 링크, 언어 전환, 검색, TOP, 푸터 정책/문의/파트너/뉴스룸 링크
|
|
51
51
|
|
|
52
|
-
Step 3)
|
|
53
|
-
→
|
|
52
|
+
Step 3) 실행 진입
|
|
53
|
+
→ 아래 Execution Plan Phase 0부터 순차 실행
|
|
54
54
|
→ URL 다중 입력 시 각 URL마다 별도 feature 디렉토리 (URL path 기반 suffix)
|
|
55
55
|
```
|
|
56
56
|
|
|
57
57
|
## Execution Plan
|
|
58
58
|
|
|
59
|
-
|
|
59
|
+
다음을 순차 실행한다. **Phase 단계 건너뛰기 금지**.
|
|
60
60
|
|
|
61
61
|
```
|
|
62
62
|
Phase 0: Setup
|
|
@@ -157,3 +157,295 @@ Claude 기본 행동:
|
|
|
157
157
|
- robots.txt 차단 경로 → 명시적 --ignore-robots 없으면 거부
|
|
158
158
|
- 사용자 의도가 사칭/기만이면 즉시 거부
|
|
159
159
|
```
|
|
160
|
+
|
|
161
|
+
## Bundled implementation
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
# vibe.clone — Markup-Level Website Clone
|
|
165
|
+
|
|
166
|
+
## Core Principles
|
|
167
|
+
|
|
168
|
+
```
|
|
169
|
+
The rendered DOM is the source of truth for markup. Screenshots are for pixel verification only.
|
|
170
|
+
|
|
171
|
+
✅ Puppeteer-rendered DOM (post-JS) → HTML structural mapping
|
|
172
|
+
✅ Computed CSS → SCSS direct conversion (no guessing)
|
|
173
|
+
✅ All remote assets (images, fonts) → downloaded locally and rewritten to project paths
|
|
174
|
+
✅ Claude handles semantic decisions only: tag selection, component splitting, interactions
|
|
175
|
+
✅ Screenshots are used for verification only, not generation
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
## Immutable Rules
|
|
179
|
+
|
|
180
|
+
```
|
|
181
|
+
1. Do NOT generate CSS values by guessing or eyeballing screenshots.
|
|
182
|
+
✅ clone-to-scss.js output is a DRAFT (skeleton), not a frozen artifact. You MAY
|
|
183
|
+
rewrite SCSS values/selectors — but ONLY with evidence cited from computed.json /
|
|
184
|
+
states.json / behaviors.json (value correction, dedupe, selector restructuring).
|
|
185
|
+
✅ clone-validate.js PASS is the sole judge of value correctness — not self-report.
|
|
186
|
+
❌ Do NOT invent values with no extraction evidence ("looks like 18px" is forbidden).
|
|
187
|
+
❌ Do NOT write CSS values directly inside scoped <style> blocks — style LOCATION
|
|
188
|
+
rule: all values live in styles/{feature}/ SCSS (value authority and style
|
|
189
|
+
location are separate rules; both hold).
|
|
190
|
+
|
|
191
|
+
2. Do NOT hotlink remote assets. All images/fonts must be downloaded and rewritten.
|
|
192
|
+
|
|
193
|
+
3. Do NOT skip the pixel verification loop (Phase 5). The clone is incomplete without it.
|
|
194
|
+
|
|
195
|
+
4. Do NOT copy textual content verbatim from copyrighted sources for production use.
|
|
196
|
+
This skill is for layout/markup learning ("클론 코딩"). Replace text with placeholders
|
|
197
|
+
or user-provided copy when shipping a real product.
|
|
198
|
+
Exception: `--real-content` — the user confirms (once, explicitly) they own the site
|
|
199
|
+
or have permission. Then keep text verbatim; clone-spec.js is invoked with
|
|
200
|
+
`--real-content` so specs mark copy as verbatim.
|
|
201
|
+
|
|
202
|
+
5. Do NOT build a section without confirming its interaction model. The model in
|
|
203
|
+
sections.json is a static-DOM heuristic — verify scroll-driven vs click-driven vs
|
|
204
|
+
time-driven vs hover against the live site. Misidentifying it is the #1 clone failure mode.
|
|
205
|
+
|
|
206
|
+
6. Do NOT ship default-state-only. Implement every harvested state (hover/focus/active/open/
|
|
207
|
+
tab-switch) from states.json / the section spec.
|
|
208
|
+
|
|
209
|
+
7. Do NOT ignore behaviors.json. The ACTIVE interaction sweep (scroll-state diffs,
|
|
210
|
+
click-driven tab content-swap detection, hover diffs, in-view entrance animations,
|
|
211
|
+
time-driven mutation candidates, smooth-scroll-lib detection) catches JS-set state
|
|
212
|
+
that static CSS harvesting is blind to. When the spec's "Dynamic behaviors" block
|
|
213
|
+
conflicts with the static interaction heuristic, the active capture wins.
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
## Full Flow
|
|
217
|
+
|
|
218
|
+
```
|
|
219
|
+
Input: a URL (or multiple URLs for multi-page clones)
|
|
220
|
+
|
|
221
|
+
→ Phase 0: Setup (stack detection, feature naming, working dir)
|
|
222
|
+
→ Phase 1: Capture (Puppeteer → rendered HTML + computed CSS + screenshots + assets)
|
|
223
|
+
→ Phase 2: Refine (DOM → sections.json per breakpoint; + interaction model + states)
|
|
224
|
+
→ Phase 2.5: Foundation (fonts / favicon / OG / SVG icons — sequential, before any section)
|
|
225
|
+
→ Phase 3: Scaffold (spec gate → SCSS draft + builder dispatch, parallel per section)
|
|
226
|
+
→ Phase 3C: Responsive merge (clone-merge-responsive.js — mobile-first @media)
|
|
227
|
+
→ Phase 4: Compile gate
|
|
228
|
+
→ Phase 5: Pixel verification loop (BOTH viewports after merge)
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
> Read `references/setup-and-layout.md` for the working-directory layout and code-output paths.
|
|
232
|
+
|
|
233
|
+
---
|
|
234
|
+
|
|
235
|
+
## Phase 0: Setup
|
|
236
|
+
|
|
237
|
+
> Read `references/setup-and-layout.md` for the full Phase 0 setup steps (stack detection, feature naming, directories, component indexing, design token scan).
|
|
238
|
+
|
|
239
|
+
---
|
|
240
|
+
|
|
241
|
+
## Phase 1: Capture ← Headless browser (parallel MO/PC)
|
|
242
|
+
|
|
243
|
+
**Coordinator pattern: run MO/PC capture as parallel workers.**
|
|
244
|
+
|
|
245
|
+
### BLOCKING Command — Use only clone-extract.js for capture
|
|
246
|
+
|
|
247
|
+
```bash
|
|
248
|
+
# [CLONE_SCRIPT] = {{VIBE_PATH}}/hooks/scripts/clone-extract.js
|
|
249
|
+
|
|
250
|
+
# Mobile (375×812)
|
|
251
|
+
node {{VIBE_PATH}}/hooks/scripts/clone-extract.js capture <URL> \
|
|
252
|
+
--out=/tmp/{feature}/mo/ \
|
|
253
|
+
--viewport=375x812 \
|
|
254
|
+
--bp=mo
|
|
255
|
+
|
|
256
|
+
# Desktop (1440×900)
|
|
257
|
+
node {{VIBE_PATH}}/hooks/scripts/clone-extract.js capture <URL> \
|
|
258
|
+
--out=/tmp/{feature}/pc/ \
|
|
259
|
+
--viewport=1440x900 \
|
|
260
|
+
--bp=pc
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
⛔ **Writing custom capture scripts (puppeteer-fetch.mjs, etc.) is forbidden.**
|
|
264
|
+
⛔ **Do NOT use WebFetch or curl** — they cannot render JS-driven SPAs.
|
|
265
|
+
✅ Use clone-extract.js. If output is unsatisfactory, modify the script.
|
|
266
|
+
|
|
267
|
+
> Read `references/capture-rules.md` for the full per-breakpoint output directory listing and the deterministic capture rule set (networkidle wait, asset resolution, states/behaviors harvesting, SEO asset harvest).
|
|
268
|
+
|
|
269
|
+
---
|
|
270
|
+
|
|
271
|
+
## Phase 2: Refine ← DOM → sections.json (independent per BP)
|
|
272
|
+
|
|
273
|
+
### BLOCKING Command — Writing custom refine scripts is forbidden
|
|
274
|
+
|
|
275
|
+
```bash
|
|
276
|
+
# MO (--states is optional — auto-resolved as states.json next to computed.json)
|
|
277
|
+
node {{VIBE_PATH}}/hooks/scripts/clone-refine.js \
|
|
278
|
+
/tmp/{feature}/mo/rendered.html \
|
|
279
|
+
/tmp/{feature}/mo/computed.json \
|
|
280
|
+
--out=/tmp/{feature}/mo/sections.json \
|
|
281
|
+
--states=/tmp/{feature}/mo/states.json \
|
|
282
|
+
--bp=mo
|
|
283
|
+
|
|
284
|
+
# PC
|
|
285
|
+
node {{VIBE_PATH}}/hooks/scripts/clone-refine.js \
|
|
286
|
+
/tmp/{feature}/pc/rendered.html \
|
|
287
|
+
/tmp/{feature}/pc/computed.json \
|
|
288
|
+
--out=/tmp/{feature}/pc/sections.json \
|
|
289
|
+
--states=/tmp/{feature}/pc/states.json \
|
|
290
|
+
--bp=pc
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
⛔ **Phase 3 is blocked until refine completes for all required BPs.**
|
|
294
|
+
⛔ **Do NOT parse rendered.html with custom Python/Node scripts.**
|
|
295
|
+
✅ Use clone-refine.js output as-is. If unsatisfactory, modify the script.
|
|
296
|
+
|
|
297
|
+
> Read `references/refine-rules.md` for the full refinement rule set and the sections.json output schema.
|
|
298
|
+
|
|
299
|
+
---
|
|
300
|
+
|
|
301
|
+
## Phase 2.5: Foundation ← sequential, BEFORE any section build
|
|
302
|
+
|
|
303
|
+
Nothing renders right until the foundation exists. Do this yourself (not delegated) — it
|
|
304
|
+
touches shared files:
|
|
305
|
+
|
|
306
|
+
```
|
|
307
|
+
1. Fonts: verify _base.scss @font-face srcs point at downloaded assets/fonts/ files.
|
|
308
|
+
Next.js stack → wire via next/font/local in the layout instead of raw @font-face.
|
|
309
|
+
2. Favicon / OG / manifest: copy assets/seo/* → public/ (project convention path),
|
|
310
|
+
wire metadata (layout.tsx metadata / <head>) to the local files.
|
|
311
|
+
3. SVG icons: collect inline <svg> from rendered.html, dedupe by path data,
|
|
312
|
+
emit one stack-appropriate icon module (e.g. components/{feature}/icons.tsx).
|
|
313
|
+
Name by visual function (SearchIcon, ArrowRightIcon, LogoIcon).
|
|
314
|
+
4. Global behaviors from behaviors.json: scrollLib detected → install/wire page-level
|
|
315
|
+
(Lenis etc.); global keyframes/scroll-snap → styles/{feature}/_shared.scss.
|
|
316
|
+
5. Verify: compile passes before moving on.
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
---
|
|
320
|
+
|
|
321
|
+
## Phase 3: Scaffold ← stack-specific code generation
|
|
322
|
+
|
|
323
|
+
**⛔ Implement MO fully first → pass verification → then PC. No responsive conversion in this phase.**
|
|
324
|
+
**⛔ CSS values must use computed.json output as-is. No vw/clamp/@media in this phase.**
|
|
325
|
+
|
|
326
|
+
### BLOCKING Command — SCSS must only use script output
|
|
327
|
+
|
|
328
|
+
```bash
|
|
329
|
+
# Step 0: Generate per-section build-contract specs (run once per BP)
|
|
330
|
+
node {{VIBE_PATH}}/hooks/scripts/clone-spec.js \
|
|
331
|
+
/tmp/{feature}/{bp}/sections.json \
|
|
332
|
+
--out=/path/to/project/components/{feature}/_specs/{bp}/ \
|
|
333
|
+
--feature={feature} [--real-content]
|
|
334
|
+
|
|
335
|
+
# Step A: Auto-generate SCSS draft (run once per BP — note the per-BP out dir)
|
|
336
|
+
node {{VIBE_PATH}}/hooks/scripts/clone-to-scss.js \
|
|
337
|
+
/tmp/{feature}/{bp}/sections.json \
|
|
338
|
+
--out=/path/to/project/styles/{feature}/{bp}/ \
|
|
339
|
+
--token-file=/tmp/{feature}/project-tokens.json
|
|
340
|
+
|
|
341
|
+
# Step B: Per-section validation (after writing each section's component code)
|
|
342
|
+
node {{VIBE_PATH}}/hooks/scripts/clone-validate.js \
|
|
343
|
+
/path/to/project/styles/{feature}/{bp}/ \
|
|
344
|
+
/tmp/{feature}/{bp}/sections.json \
|
|
345
|
+
--section={SectionName}
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
⛔ **No section is built without a completed spec.** Step 0 emits `_specs/{Section}.spec.md`
|
|
349
|
+
(interaction model + **active-capture Dynamic behaviors** (scroll/tab/hover/in-view/
|
|
350
|
+
time-driven/scroll-lib) + states + computed CSS + assets + text + checklist).
|
|
351
|
+
clone-spec.js auto-loads `behaviors.json` from the sections.json dir and attaches matching
|
|
352
|
+
behaviors per section. Before dispatching a section's builder, Claude reviews its spec and
|
|
353
|
+
resolves every `TODO` (confirm interaction model, list states to implement, choose tags,
|
|
354
|
+
replace copyrighted text — skipped with --real-content). The spec is the contract AND the
|
|
355
|
+
audit trail — it forces extraction rigor before any code is written.
|
|
356
|
+
⛔ **clone-to-scss.js must run first (Step A) — its output is the DRAFT every section starts
|
|
357
|
+
from.** After that, SCSS edits are allowed per Immutable Rule 1 (evidence-cited only);
|
|
358
|
+
clone-validate.js PASS is the judge.
|
|
359
|
+
⛔ **Do NOT write custom SCSS / spec generation scripts.**
|
|
360
|
+
⛔ **Do NOT proceed past a section without a clone-validate.js PASS for it.**
|
|
361
|
+
|
|
362
|
+
Phase 3A: MO Scaffold — parallel builder dispatch
|
|
363
|
+
Input: /tmp/{feature}/mo/sections.json
|
|
364
|
+
→ Phase 4 (MO compile) → Phase 5 (MO pixel verification)
|
|
365
|
+
|
|
366
|
+
Phase 3B: PC Scaffold
|
|
367
|
+
Same process as MO, input /tmp/{feature}/pc/sections.json → styles/{feature}/pc/
|
|
368
|
+
→ Phase 4 (PC compile) → Phase 5 (PC pixel verification)
|
|
369
|
+
|
|
370
|
+
Phase 3C: Responsive Integration (after both MO+PC pass Phase 5)
|
|
371
|
+
1. node {{VIBE_PATH}}/hooks/scripts/clone-merge-responsive.js \
|
|
372
|
+
--mo=/path/to/project/styles/{feature}/mo/ \
|
|
373
|
+
--pc=/path/to/project/styles/{feature}/pc/ \
|
|
374
|
+
--out=/path/to/project/styles/{feature}/ \
|
|
375
|
+
[--breakpoint=1024]
|
|
376
|
+
→ mobile-first merge: MO declarations = base, PC diffs → @media (min-width) block
|
|
377
|
+
→ Phase 4 (compile) → Phase 5 at BOTH viewports against each BP's screenshot.
|
|
378
|
+
⛔ The clone is NOT complete until the MERGED build passes Phase 5 at both.
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
> Read `references/scaffold-phases.md` for the full Phase 3A prep/dispatch/merge builder contract (framework mapping, 150-line split rule, clone-validate.js PASS/FAIL loop detail), Phase 3C steps 2–3 (import switch, pc-only/mo-only selector review), and Claude's role checklist.
|
|
382
|
+
|
|
383
|
+
---
|
|
384
|
+
|
|
385
|
+
## Phase 4: Compile Gate
|
|
386
|
+
|
|
387
|
+
```
|
|
388
|
+
No round cap. Loop until compile succeeds (or stuck → ask user).
|
|
389
|
+
|
|
390
|
+
0. Capture baseline (before Phase 3): record existing tsc + build errors
|
|
391
|
+
→ Phase 4 only fixes NEW errors
|
|
392
|
+
|
|
393
|
+
1. TypeScript: vue-tsc / svelte-check / tsc --noEmit
|
|
394
|
+
2. Build: npm run build (120s timeout)
|
|
395
|
+
3. Dev server: npm run dev → detect port → polling
|
|
396
|
+
|
|
397
|
+
On error: parse → auto-fix → re-check
|
|
398
|
+
Termination:
|
|
399
|
+
✅ Success: all checks pass → enter Phase 5
|
|
400
|
+
⚠️ Stuck: same errors as previous round → ask user
|
|
401
|
+
1. Direct fix instructions → retry
|
|
402
|
+
2. "proceed" — record remaining errors as TODO, proceed to Phase 5
|
|
403
|
+
3. "abort" — halt
|
|
404
|
+
ultrawork mode: on stuck, record TODO without prompting and proceed
|
|
405
|
+
|
|
406
|
+
⛔ Must enter Phase 5 after Phase 4 passes. Do NOT output a "completion summary".
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
---
|
|
410
|
+
|
|
411
|
+
## Phase 5: Pixel Verification Loop ← MANDATORY
|
|
412
|
+
|
|
413
|
+
**⛔ Phase 5 is mandatory, not optional. Enter automatically after Phase 4.**
|
|
414
|
+
**⛔ Skipping Phase 5 makes the entire clone "incomplete".**
|
|
415
|
+
|
|
416
|
+
```
|
|
417
|
+
No round cap. Loop until P1=0 (or stuck → ask user).
|
|
418
|
+
Infrastructure: src/infra/lib/browser/ (Puppeteer + CDP) — same as figma Phase 6.
|
|
419
|
+
|
|
420
|
+
1. Render scaffolded page in dev server at matching viewport
|
|
421
|
+
2. Capture screenshot → pixelmatch comparison against /tmp/{feature}/{bp}/screenshot.png
|
|
422
|
+
diffRatio > 0.05 (clone target is tighter than figma) → P1
|
|
423
|
+
3. CSS comparison: live computed CSS vs /tmp/{feature}/{bp}/computed.json
|
|
424
|
+
delta > 2px → P1, ≤ 2px → P2
|
|
425
|
+
4. Asset audit: every <img>/background-image resolves to local public/images/ path → else P1
|
|
426
|
+
5. Fix P1 first (refer to computed.json, no guessing) → revalidate compile → reload
|
|
427
|
+
|
|
428
|
+
Narrowing scope:
|
|
429
|
+
Round 1: P1+P2+P3
|
|
430
|
+
Round 2: P1+P2
|
|
431
|
+
Round 3+: P1 only
|
|
432
|
+
|
|
433
|
+
Termination:
|
|
434
|
+
✅ P1=0 AND no new findings → complete
|
|
435
|
+
⚠️ Stuck: same findings → ask user (resolve / proceed / abort)
|
|
436
|
+
ultrawork mode: on stuck, record TODO without prompting and complete
|
|
437
|
+
|
|
438
|
+
Responsive: after MO verification → change viewport → repeat against PC screenshot
|
|
439
|
+
Post-merge (Phase 3C): re-run at BOTH viewports (375×812 vs mo/screenshot.png,
|
|
440
|
+
1440×900 vs pc/screenshot.png) — either failing means the merge regressed; fix the
|
|
441
|
+
merged SCSS (evidence: the per-BP sections.json), never by re-guessing values
|
|
442
|
+
Cleanup: shut down browser + dev server
|
|
443
|
+
|
|
444
|
+
⛔ "Completion summary" output only allowed after Phase 5 completes.
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
---
|
|
448
|
+
|
|
449
|
+
## Legal, Ethical & Error Recovery Reference
|
|
450
|
+
|
|
451
|
+
> Read `references/legal-and-error-recovery.md` for the full legal/ethical usage notes (intended use, prohibited use, --real-content flow) and the Error Recovery troubleshooting table.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
name: commerce-patterns
|
|
2
|
+
name: vibe.commerce-patterns
|
|
3
3
|
invocation: [auto]
|
|
4
4
|
tier: core
|
|
5
5
|
description: "E-commerce domain patterns — cart management, payment processing (Toss/Stripe/PG), inventory tracking, and order state machines with transaction safety. Use when implementing any shopping cart, checkout flow, payment integration, stock management, or order lifecycle. Covers idempotency keys, double-charge prevention, stock reservation, and refund flows. Must use this skill when the codebase involves e-commerce — even for seemingly simple 'add to cart' features."
|