@bonesofspring/ai-rules 0.2.22 → 0.2.23
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/CHANGELOG.md +8 -0
- package/README.md +6 -2
- package/bin/cli.js +32 -8
- package/bin/mavis-install.js +441 -0
- package/package.json +9 -2
- package/presets/_shared/core/meta/preset-pr-checklist.md +1 -0
- package/presets/_shared/core/meta/preset-twin-sync.md +16 -0
- package/presets/claude/android-kotlin/rules/tooling-and-review/preset-pr-checklist.md +1 -0
- package/presets/claude/android-kotlin/rules/tooling-and-review/preset-twin-sync.md +16 -0
- package/presets/claude/go/rules/tooling-and-review/preset-pr-checklist.md +1 -0
- package/presets/claude/go/rules/tooling-and-review/preset-twin-sync.md +16 -0
- package/presets/claude/ios-swift/rules/tooling-and-review/preset-pr-checklist.md +1 -0
- package/presets/claude/ios-swift/rules/tooling-and-review/preset-twin-sync.md +16 -0
- package/presets/claude/java/rules/tooling-and-review/preset-pr-checklist.md +1 -0
- package/presets/claude/java/rules/tooling-and-review/preset-twin-sync.md +16 -0
- package/presets/claude/mcp-ts/rules/tooling-and-review/preset-pr-checklist.md +1 -0
- package/presets/claude/mcp-ts/rules/tooling-and-review/preset-twin-sync.md +16 -0
- package/presets/claude/next/rules/tooling-and-review/preset-pr-checklist.md +1 -0
- package/presets/claude/next/rules/tooling-and-review/preset-twin-sync.md +16 -0
- package/presets/claude/nuxt/rules/tooling-and-review/preset-pr-checklist.md +1 -0
- package/presets/claude/nuxt/rules/tooling-and-review/preset-twin-sync.md +16 -0
- package/presets/claude/php-hexagonal/rules/tooling-and-review/preset-pr-checklist.md +1 -0
- package/presets/claude/php-hexagonal/rules/tooling-and-review/preset-twin-sync.md +16 -0
- package/presets/claude/php-laravel/rules/tooling-and-review/preset-pr-checklist.md +1 -0
- package/presets/claude/php-laravel/rules/tooling-and-review/preset-twin-sync.md +16 -0
- package/presets/claude/svelte/rules/tooling-and-review/preset-pr-checklist.md +1 -0
- package/presets/claude/svelte/rules/tooling-and-review/preset-twin-sync.md +16 -0
- package/presets/cursor/android-kotlin/rules/preset-pr-checklist.mdc +1 -0
- package/presets/cursor/android-kotlin/rules/preset-twin-sync.mdc +16 -0
- package/presets/cursor/go/rules/preset-pr-checklist.mdc +1 -0
- package/presets/cursor/go/rules/preset-twin-sync.mdc +16 -0
- package/presets/cursor/ios-swift/rules/preset-pr-checklist.mdc +1 -0
- package/presets/cursor/ios-swift/rules/preset-twin-sync.mdc +16 -0
- package/presets/cursor/java/rules/preset-pr-checklist.mdc +1 -0
- package/presets/cursor/java/rules/preset-twin-sync.mdc +16 -0
- package/presets/cursor/mcp-ts/rules/preset-pr-checklist.mdc +1 -0
- package/presets/cursor/mcp-ts/rules/preset-twin-sync.mdc +16 -0
- package/presets/cursor/next/rules/preset-pr-checklist.mdc +1 -0
- package/presets/cursor/next/rules/preset-twin-sync.mdc +16 -0
- package/presets/cursor/nuxt/rules/preset-pr-checklist.mdc +1 -0
- package/presets/cursor/nuxt/rules/preset-twin-sync.mdc +16 -0
- package/presets/cursor/php-hexagonal/rules/preset-pr-checklist.mdc +1 -0
- package/presets/cursor/php-hexagonal/rules/preset-twin-sync.mdc +16 -0
- package/presets/cursor/php-laravel/rules/preset-pr-checklist.mdc +1 -0
- package/presets/cursor/php-laravel/rules/preset-twin-sync.mdc +16 -0
- package/presets/cursor/svelte/rules/preset-pr-checklist.mdc +1 -0
- package/presets/cursor/svelte/rules/preset-twin-sync.mdc +16 -0
- package/presets/mavis/README.md +60 -0
- package/presets/mavis/next/MAVIS.md +67 -0
- package/presets/mavis/next/MCP.md +36 -0
- package/presets/mavis/next/README.md +15 -0
- package/presets/mavis/next/REPO_AGENTS.md +94 -0
- package/presets/mavis/next/adapter-map.json +959 -0
- package/presets/mavis/next/agents/README.md +206 -0
- package/presets/mavis/next/agents/accessibility-reviewer.md +61 -0
- package/presets/mavis/next/agents/api-contract-reviewer.md +57 -0
- package/presets/mavis/next/agents/build-verifier.md +110 -0
- package/presets/mavis/next/agents/ci-investigator.md +63 -0
- package/presets/mavis/next/agents/code-reviewer.md +61 -0
- package/presets/mavis/next/agents/codebase-analyzer.md +21 -0
- package/presets/mavis/next/agents/debugger.md +80 -0
- package/presets/mavis/next/agents/feature-developer.md +101 -0
- package/presets/mavis/next/agents/migration-specialist.md +67 -0
- package/presets/mavis/next/agents/mockup-reviewer.md +53 -0
- package/presets/mavis/next/agents/openspec-author.md +157 -0
- package/presets/mavis/next/agents/performance-auditor.md +68 -0
- package/presets/mavis/next/agents/playwright-test-generator.md +28 -0
- package/presets/mavis/next/agents/playwright-test-healer.md +28 -0
- package/presets/mavis/next/agents/playwright-test-planner.md +21 -0
- package/presets/mavis/next/agents/qa-tester.md +52 -0
- package/presets/mavis/next/agents/security-reviewer.md +54 -0
- package/presets/mavis/next/agents/solution-architect.md +68 -0
- package/presets/mavis/next/agents/task-analyst.md +166 -0
- package/presets/mavis/next/agents/task-router.md +178 -0
- package/presets/mavis/next/agents/tech-writer.md +57 -0
- package/presets/mavis/next/agents/unit-test-generator.md +31 -0
- package/presets/mavis/next/agents/unit-test-healer.md +32 -0
- package/presets/mavis/next/agents/unit-test-planner.md +54 -0
- package/presets/mavis/next/commands/README.md +49 -0
- package/presets/mavis/next/commands/spec-start.md +24 -0
- package/presets/mavis/next/commands/task-continue.md +50 -0
- package/presets/mavis/next/commands/task.md +50 -0
- package/presets/mavis/next/commands/technical-retro.md +80 -0
- package/presets/mavis/next/hooks/README.md +22 -0
- package/presets/mavis/next/hooks/chain-team-phases.sh +845 -0
- package/presets/mavis/next/mcp.json +19 -0
- package/presets/mavis/next/rules/README.md +16 -0
- package/presets/mavis/next/rules/agent-team-intake.md +11 -0
- package/presets/mavis/next/rules/agent-team-orchestrator.md +210 -0
- package/presets/mavis/next/rules/ai-local-overlay.md +37 -0
- package/presets/mavis/next/rules/anti-sycophancy-discipline.md +23 -0
- package/presets/mavis/next/rules/api-services.md +72 -0
- package/presets/mavis/next/rules/architecture-boundaries-ui.md +9 -0
- package/presets/mavis/next/rules/architecture-boundaries.md +86 -0
- package/presets/mavis/next/rules/arrow-functions.md +25 -0
- package/presets/mavis/next/rules/code-quality-and-refactoring.md +40 -0
- package/presets/mavis/next/rules/code-review-mr.md +40 -0
- package/presets/mavis/next/rules/css-property-order-stylelint.md +5 -0
- package/presets/mavis/next/rules/design-guidance.md +99 -0
- package/presets/mavis/next/rules/feature-delivery-workflow.md +49 -0
- package/presets/mavis/next/rules/http-client.md +55 -0
- package/presets/mavis/next/rules/layer-barrel-exports.md +68 -0
- package/presets/mavis/next/rules/mcp-usage.md +86 -0
- package/presets/mavis/next/rules/mockup-review.md +107 -0
- package/presets/mavis/next/rules/navigation-router-stack.md +56 -0
- package/presets/mavis/next/rules/navigation-router-ui.md +10 -0
- package/presets/mavis/next/rules/next-app-core.md +29 -0
- package/presets/mavis/next/rules/next-app-router.md +44 -0
- package/presets/mavis/next/rules/no-props-spread.md +56 -0
- package/presets/mavis/next/rules/no-type-assertion-as-import-export.md +51 -0
- package/presets/mavis/next/rules/package-manager.md +11 -0
- package/presets/mavis/next/rules/playwright-agents.md +67 -0
- package/presets/mavis/next/rules/post-change-lint.md +35 -0
- package/presets/mavis/next/rules/preset-layering.md +27 -0
- package/presets/mavis/next/rules/preset-no-cross-stack-leakage.md +90 -0
- package/presets/mavis/next/rules/preset-pr-checklist.md +35 -0
- package/presets/mavis/next/rules/preset-token-budget.md +36 -0
- package/presets/mavis/next/rules/preset-twin-sync.md +65 -0
- package/presets/mavis/next/rules/product-specs-authoring.md +112 -0
- package/presets/mavis/next/rules/product-specs.md +56 -0
- package/presets/mavis/next/rules/public-imports.md +50 -0
- package/presets/mavis/next/rules/react-a11y-coding.md +31 -0
- package/presets/mavis/next/rules/react-next-anti-hallucination.md +60 -0
- package/presets/mavis/next/rules/react-ui.md +105 -0
- package/presets/mavis/next/rules/reference-features.md +45 -0
- package/presets/mavis/next/rules/security-next.md +45 -0
- package/presets/mavis/next/rules/store-rtk.md +78 -0
- package/presets/mavis/next/rules/technical-retro.md +11 -0
- package/presets/mavis/next/rules/tests-e2e-structure.md +72 -0
- package/presets/mavis/next/rules/tests-unit.md +72 -0
- package/presets/mavis/next/rules/types-jsdoc.md +43 -0
- package/presets/mavis/next/rules/ux-design.md +99 -0
- package/presets/mavis/next/skills/README.md +21 -0
- package/presets/mavis/next/skills/ci-investigation/SKILL.md +39 -0
- package/presets/mavis/next/skills/code-review/SKILL.md +39 -0
- package/presets/mavis/next/skills/debug-investigation/SKILL.md +26 -0
- package/presets/mavis/next/skills/feature-delivery/SKILL.md +34 -0
- package/presets/mavis/next/skills/mockup-review/SKILL.md +24 -0
- package/presets/mavis/next/skills/playwright-e2e/SKILL.md +28 -0
- package/presets/mavis/next/skills/react-performance/SKILL.md +39 -0
- package/presets/mavis/next/skills/spec-authoring/SKILL.md +21 -0
- package/presets/mavis/next/skills/spec-discovery/SKILL.md +53 -0
- package/presets/mavis/next/skills/technical-retro/SKILL.md +49 -0
- package/presets/mavis/next/skills/unit-testing/SKILL.md +29 -0
- package/presets/mavis/next/skills/ux-design/SKILL.md +31 -0
- package/presets/mavis/next/skills/write-adr/SKILL.md +36 -0
- package/presets/mavis/next/team/README.md +148 -0
- package/presets/mavis/next/team/conventions.md +21 -0
- package/presets/mavis/next/team/fixtures/artifact-manifest.example.json +79 -0
- package/presets/mavis/next/team/fixtures/bugfix-standard.json +25 -0
- package/presets/mavis/next/team/fixtures/feature-full.json +29 -0
- package/presets/mavis/next/team/fixtures/feature-light.json +27 -0
- package/presets/mavis/next/team/fixtures/feature-with-figma-url.json +17 -0
- package/presets/mavis/next/team/fixtures/feature-with-ux-no-figma.json +17 -0
- package/presets/mavis/next/team/fixtures/memlog.example.md +9 -0
- package/presets/mavis/next/team/fixtures/metrics-scenarios/tasks/human-gate/metrics.json +69 -0
- package/presets/mavis/next/team/fixtures/metrics-scenarios/tasks/missing-ledger/status.json +5 -0
- package/presets/mavis/next/team/fixtures/metrics-scenarios/tasks/parallel-receipts/metrics.json +79 -0
- package/presets/mavis/next/team/fixtures/metrics-scenarios/tasks/serial-retry/metrics.json +124 -0
- package/presets/mavis/next/team/fixtures/metrics-scenarios/tasks/validation-failed/metrics.json +124 -0
- package/presets/mavis/next/team/fixtures/metrics.example.json +54 -0
- package/presets/mavis/next/team/fixtures/mockup-review-fail-embedded-status.json +8 -0
- package/presets/mavis/next/team/fixtures/mockup-review-standalone.json +14 -0
- package/presets/mavis/next/team/fixtures/ux-design-standalone.json +15 -0
- package/presets/mavis/next/team/tasks/.gitkeep +0 -0
- package/presets/mavis/platform-contract.json +131 -0
- package/scripts/capture-cli-golden.mjs +44 -0
- package/scripts/check-chain-hook-coverage.sh +1 -0
- package/scripts/check-mavis-adapter-map.mjs +294 -0
- package/scripts/check-mavis-local-overlay.mjs +56 -0
- package/scripts/check-mavis-platform-contract.mjs +388 -0
- package/scripts/check-mavis-token-budget.mjs +48 -0
- package/scripts/check-preset-leakage.sh +35 -3
- package/scripts/check-preset-structure.sh +63 -0
- package/scripts/check-shared-core-drift.sh +18 -0
- package/scripts/check-task-router-intents.sh +15 -2
- package/scripts/fixtures/cli-golden/claude/next.json +130 -0
- package/scripts/fixtures/cli-golden/cursor/next.json +132 -0
- package/scripts/fixtures/cli-golden/mavis/next.json +125 -0
- package/scripts/fixtures/mavis-adapter-map/invalid-unmapped/cursor/AGENTS.md +1 -0
- package/scripts/fixtures/mavis-adapter-map/invalid-unmapped/cursor/rules/extra.mdc +1 -0
- package/scripts/fixtures/mavis-adapter-map/invalid-unmapped/cursor/rules/sample.mdc +2 -0
- package/scripts/fixtures/mavis-adapter-map/invalid-unmapped/mavis/MAVIS.md +1 -0
- package/scripts/fixtures/mavis-adapter-map/invalid-unmapped/mavis/adapter-map.json +26 -0
- package/scripts/fixtures/mavis-adapter-map/invalid-unmapped/mavis/rules/sample.md +2 -0
- package/scripts/fixtures/mavis-adapter-map/valid/cursor/AGENTS.md +1 -0
- package/scripts/fixtures/mavis-adapter-map/valid/cursor/rules/sample.mdc +2 -0
- package/scripts/fixtures/mavis-adapter-map/valid/mavis/MAVIS.md +1 -0
- package/scripts/fixtures/mavis-adapter-map/valid/mavis/adapter-map.json +26 -0
- package/scripts/fixtures/mavis-adapter-map/valid/mavis/rules/sample.md +2 -0
- package/scripts/fixtures/mavis-platform-contract/invalid-minimax-destination.json +131 -0
- package/scripts/fixtures/mavis-platform-contract/invalid-missing-capability.json +126 -0
- package/scripts/fixtures/mavis-platform-contract/invalid-released-unknown-stack.json +133 -0
- package/scripts/fixtures/mavis-platform-contract/invalid-unknown-native-path.json +131 -0
- package/scripts/fixtures/mavis-platform-contract/invalid-version-pin.json +132 -0
- package/scripts/fixtures/mavis-platform-contract/valid.json +131 -0
- package/scripts/fixtures/mavis-probe/AGENTS.md +6 -0
- package/scripts/fixtures/mavis-probe/agents/probe-agent.md +6 -0
- package/scripts/fixtures/mavis-probe/fake-mcode.mjs +98 -0
- package/scripts/fixtures/mavis-probe/output.schema.json +28 -0
- package/scripts/fixtures/mavis-probe/rules/probe.md +5 -0
- package/scripts/fixtures/mavis-probe/skills/probe/SKILL.md +11 -0
- package/scripts/generate-mavis-next.mjs +704 -0
- package/scripts/lib/cli-golden.mjs +50 -0
- package/scripts/lib/discover-hooks.mjs +72 -0
- package/scripts/probe-mavis-capabilities.mjs +480 -0
- package/scripts/test-agent-task-metrics-hooks.mjs +22 -16
- package/scripts/test-chain-team-phases-coverage.mjs +10 -7
- package/scripts/test-cli-init-clean.mjs +256 -0
- package/scripts/test-cli-mcp-merge.mjs +23 -0
- package/scripts/test-mavis-context-budget.mjs +55 -0
- package/scripts/test-mavis-orchestration.mjs +649 -0
- package/scripts/test-probe-mavis-capabilities.mjs +205 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Do not use prop spread when passing props to components
|
|
2
|
+
|
|
3
|
+
When calling **custom** React components (PascalCase names: `IconBox`, `TextField`, your `FooBar`), **pass props explicitly**, not via spread (`{...props}`, `{...obj}`).
|
|
4
|
+
|
|
5
|
+
**For agents and review:** do not “simplify” JSX by building an object and spreading it — that violates this rule. If prop branching is long, use two explicit JSX blocks (`condition ? <A … /> : <B … />`) or separate small components, not `{...mergedProps}`.
|
|
6
|
+
|
|
7
|
+
## Why
|
|
8
|
+
|
|
9
|
+
- Explicit props make component dependencies obvious when reading code.
|
|
10
|
+
- Easier refactoring and usage search.
|
|
11
|
+
- Reduces the risk of accidentally passing extra or stale props.
|
|
12
|
+
|
|
13
|
+
## Repo enforcement
|
|
14
|
+
|
|
15
|
+
- For `app/src/ui/**/*.tsx`, ESLint rule `react/jsx-props-no-spreading` is enabled (`app/eslint.config.mjs`): linter and CI will catch violations.
|
|
16
|
+
- A legitimate local exception — a **single-line** `eslint-disable-next-line react/jsx-props-no-spreading` with a brief “why” comment; for rare wrappers, a file-level disable is acceptable (as in `PromocodeInput`).
|
|
17
|
+
|
|
18
|
+
## Examples
|
|
19
|
+
|
|
20
|
+
```tsx
|
|
21
|
+
// ❌ Bad
|
|
22
|
+
const commonProps = { a, b, c }
|
|
23
|
+
return <Child {...commonProps} />
|
|
24
|
+
|
|
25
|
+
// ❌ Bad
|
|
26
|
+
return <Child {...props} />
|
|
27
|
+
|
|
28
|
+
// ❌ Bad (spread from a neighboring styles module is not an excuse)
|
|
29
|
+
const iconProps = cond ? { name, size: 'm' } : { name, size: 'm', ...styles.IconBoxAccent }
|
|
30
|
+
return <IconBox {...iconProps} />
|
|
31
|
+
|
|
32
|
+
// ✅ Good
|
|
33
|
+
return (
|
|
34
|
+
<Child
|
|
35
|
+
a={a}
|
|
36
|
+
b={b}
|
|
37
|
+
c={c}
|
|
38
|
+
/>
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
// ✅ Good — explicit props per branch
|
|
42
|
+
return cond ? (
|
|
43
|
+
<IconBox name={name} size="m" variant="warning" />
|
|
44
|
+
) : (
|
|
45
|
+
<IconBox
|
|
46
|
+
customColors={styles.IconBoxAccent.customColors}
|
|
47
|
+
name={name}
|
|
48
|
+
size="m"
|
|
49
|
+
/>
|
|
50
|
+
)
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Exceptions
|
|
54
|
+
|
|
55
|
+
- Passing props to a **native** DOM element (`<div {...rest} />`) is allowed if `rest` contains only valid HTML attributes.
|
|
56
|
+
- Delegating props in a wrapper is allowed if explicitly documented and justified; mark the file or line via ESLint-disable as above when needed.
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Do not use `as` for type assertions on export and import (except necessary cases)
|
|
2
|
+
|
|
3
|
+
## Scope
|
|
4
|
+
|
|
5
|
+
This covers **type assertion** in TypeScript: an expression like `value as Type`.
|
|
6
|
+
|
|
7
|
+
**Out of scope** (module syntax, not assertion):
|
|
8
|
+
|
|
9
|
+
- rename on export: `export { foo as bar }`, `export { default as Baz } from '...'`;
|
|
10
|
+
- rename on import: `import { foo as bar } from '...'`;
|
|
11
|
+
- `import type { Foo as Bar }` — type alias in a type-only import.
|
|
12
|
+
|
|
13
|
+
## Requirement
|
|
14
|
+
|
|
15
|
+
- On the **public module boundary** (what is **exported** from a file / barrel, and what is immediately **assigned to imported symbols** with forced casting) **do not use** `as Type` to “fit” types when normal typing suffices.
|
|
16
|
+
|
|
17
|
+
## Prefer instead of `as`
|
|
18
|
+
|
|
19
|
+
- explicit annotation: `const x: T = ...` / `function f(): T`;
|
|
20
|
+
- **generics** on functions and classes;
|
|
21
|
+
- **`satisfies`** (when you need compatibility check without narrowing to `any`);
|
|
22
|
+
- narrowing **`unknown`** after checks (type guards, `zod`, etc.);
|
|
23
|
+
- fixing **source types/DTO/mappers**, not assertion at the output.
|
|
24
|
+
|
|
25
|
+
## When `as` is allowed
|
|
26
|
+
|
|
27
|
+
- interaction with **untyped** or incorrectly typed external modules where there is no reasonable alternative;
|
|
28
|
+
- narrow spots after **validation** when a type guard is still too noisy (prefer guard/`satisfies`);
|
|
29
|
+
- **`as const`** — when literal types are needed and wide inference breaks the contract (separate mechanism; use as needed, not as a substitute for API typing).
|
|
30
|
+
- **`catch (error)`** block after HTTP via the shared client: prefer narrowing via **`instanceof`** on the **transport error class** from `@/types` (which one — per existing implementation) and work with the narrowed type; bare **`as`** to the same type — only if `instanceof` is unavailable (different throw source) and intentional.
|
|
31
|
+
|
|
32
|
+
## Examples
|
|
33
|
+
|
|
34
|
+
```typescript
|
|
35
|
+
// ❌ Bad: assertion on exported API
|
|
36
|
+
export const config = loadRaw() as AppConfig
|
|
37
|
+
|
|
38
|
+
// ✅ Better: annotation + check or mapper
|
|
39
|
+
export const config: AppConfig = mapToAppConfig(loadRaw())
|
|
40
|
+
|
|
41
|
+
// ❌ Bad: immediately after import “breaks” the type
|
|
42
|
+
import { getData } from './api'
|
|
43
|
+
export const data = getData() as MyDto[]
|
|
44
|
+
|
|
45
|
+
// ✅ Better: type getData / wrap in a type-safe function
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Agent requirement
|
|
49
|
+
|
|
50
|
+
When reviewing and generating code **do not add** new `as Type` on exported entities and on import → export chains without explicit need; fix the type contract at the source when possible.
|
|
51
|
+
- In slices and services when handling API errors, consider **`instanceof`** on the transport error class from `@/types` first, following existing code (`http-client.md`, `store-rtk.md`).
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Package manager (terminal)
|
|
2
|
+
|
|
3
|
+
Before **`npm install` / `yarn` / `pnpm` / `bun`** and **`… run …`**, detect the repository package manager and **use only that one**.
|
|
4
|
+
|
|
5
|
+
## How to detect
|
|
6
|
+
|
|
7
|
+
1. **`packageManager`** in `package.json` (root or `app/package.json`).
|
|
8
|
+
2. **Lockfile** nearby: `yarn.lock` → yarn; `pnpm-lock.yaml` → pnpm; `package-lock.json` → npm; `bun.lock(b)` → bun.
|
|
9
|
+
3. If ambiguous — where `node_modules` lives and which lockfile CI uses.
|
|
10
|
+
|
|
11
|
+
Working directory for scripts — **`app/`**. Examples: `yarn lint`, `pnpm run test`. Do not guess — check the files.
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# Playwright Agents in this project
|
|
2
|
+
|
|
3
|
+
In this repository, Playwright Agents (planner, generator, healer) **must follow the existing e2e structure**:
|
|
4
|
+
|
|
5
|
+
- **Test directory**: `app/__tests__/e2e`
|
|
6
|
+
- **Test plans (specs)**: `*.cases.md` files under `app/__tests__/e2e/**`
|
|
7
|
+
- **Executable tests**: `*.spec.ts` files under `app/__tests__/e2e/**`
|
|
8
|
+
- **Seed test**: `app/__tests__/e2e/seed.spec.ts`
|
|
9
|
+
|
|
10
|
+
Do **not** introduce separate top-level `specs/` and `tests/` folders for real test coverage. Those may be used only as temporary sandboxes if explicitly requested.
|
|
11
|
+
|
|
12
|
+
## Planner (test plans)
|
|
13
|
+
|
|
14
|
+
When acting as a **Planner** (or working with the Playwright planner agent):
|
|
15
|
+
|
|
16
|
+
- **Treat `*.cases.md` as the canonical test plan files**, equivalent to Playwright's `specs/*.md`.
|
|
17
|
+
- **Location**:
|
|
18
|
+
- For a feature/domain, use the corresponding `*.cases.md` file under `app/__tests__/e2e`, e.g.:
|
|
19
|
+
- `app/__tests__/e2e/OrderHistory/order-history.cases.md`
|
|
20
|
+
- `app/__tests__/e2e/BillingReport/invoice-list.cases.md`
|
|
21
|
+
- **Content requirements**:
|
|
22
|
+
- Group scenarios by feature and subfeature using headings.
|
|
23
|
+
- For each scenario include:
|
|
24
|
+
- clear title,
|
|
25
|
+
- preconditions,
|
|
26
|
+
- ordered steps,
|
|
27
|
+
- expected results.
|
|
28
|
+
- Write in concise business language, but precise enough for automatic test generation.
|
|
29
|
+
- **Seed**:
|
|
30
|
+
- Assume environment is prepared by `app/__tests__/e2e/seed.spec.ts` (login, baseURL, mocks, etc.).
|
|
31
|
+
|
|
32
|
+
When asked to "generate a test plan" for a feature, **create or update the appropriate `*.cases.md` file in `app/__tests__/e2e/**`**, not in a separate `specs/` folder.
|
|
33
|
+
|
|
34
|
+
## Generator (tests from plans)
|
|
35
|
+
|
|
36
|
+
When acting as a **Generator** (or working with the Playwright generator agent):
|
|
37
|
+
|
|
38
|
+
- **Source of truth for scenarios**:
|
|
39
|
+
- Use the relevant `*.cases.md` file under `app/__tests__/e2e/**` as the test plan.
|
|
40
|
+
- **Target for tests**:
|
|
41
|
+
- Generate or update `*.spec.ts` files under the same folder, e.g.:
|
|
42
|
+
- plan: `app/__tests__/e2e/OrderHistory/order-history.cases.md`
|
|
43
|
+
- tests: `app/__tests__/e2e/OrderHistory/order-history.spec.ts` (or additional `*.spec.ts` in that folder if needed).
|
|
44
|
+
- **Structure**:
|
|
45
|
+
- Use `test.describe` to group by top-level plan sections (feature / user flow).
|
|
46
|
+
- Use `test(...)` titles that match scenario names from the plan.
|
|
47
|
+
- Prefer Page Object and fluent interfaces that already exist in this project, for example:
|
|
48
|
+
- `app/__tests__/e2e/OrderHistory/OrderHistoryPage.ts`
|
|
49
|
+
- shared helpers under `app/__tests__/e2e/_shared/`.
|
|
50
|
+
- **Seed**:
|
|
51
|
+
- If a seed test is needed, use `app/__tests__/e2e/seed.spec.ts` as the reference for environment setup.
|
|
52
|
+
|
|
53
|
+
Do **not** generate Playwright tests into a separate `tests/` folder by default. Keep all e2e tests under `app/__tests__/e2e/**` to respect project conventions.
|
|
54
|
+
|
|
55
|
+
## Healer (fixing tests)
|
|
56
|
+
|
|
57
|
+
When acting as a **Healer** (or working with the Playwright healer agent):
|
|
58
|
+
|
|
59
|
+
- Operate only on `*.spec.ts` files under `app/__tests__/e2e/**`.
|
|
60
|
+
- Use `*.cases.md` in the same folder as **documentation of the intended behavior**:
|
|
61
|
+
- Do not weaken or change business assertions in tests in a way that conflicts with the corresponding `*.cases.md`.
|
|
62
|
+
- Prefer updating locators, waits, and flow details to match the UI while keeping the scenario semantics intact.
|
|
63
|
+
- When multiple specs are involved, prioritize:
|
|
64
|
+
- the spec file in the same folder as the failing test,
|
|
65
|
+
- then shared utilities in `app/__tests__/e2e/_shared/`.
|
|
66
|
+
|
|
67
|
+
Healer should keep tests aligned with the existing test plans (`*.cases.md`) and with the page objects and helpers already used in the project.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Linters after code changes
|
|
2
|
+
|
|
3
|
+
**Requestable, but must run on code changes:** the rule is not always-on (saves context); after editing source files the agent **must** follow this checklist.
|
|
4
|
+
|
|
5
|
+
## When to apply
|
|
6
|
+
|
|
7
|
+
After **any** change to source files in `app/**` (TS/TSX/JS/MJS, CSS, styled/Linaria in `.ts`/`.tsx`).
|
|
8
|
+
|
|
9
|
+
Exceptions: documentation edits outside `app/`, CI configs, `.mavis/rules/**`, if application executable code did not change.
|
|
10
|
+
|
|
11
|
+
**Pipeline exception:** if the task runs through the agent team and the next step is `build-verifier`, the developer may limit lint/type-check to **changed files**; full run is **`build-verifier`’s** responsibility. In single-agent mode (no pipeline) — always a full run.
|
|
12
|
+
|
|
13
|
+
## Required commands
|
|
14
|
+
|
|
15
|
+
Working directory — **`app/`**. Package manager — **`package-manager.md`**.
|
|
16
|
+
|
|
17
|
+
1. **`lint:js`** — full ESLint across the project.
|
|
18
|
+
2. **`lint:css`** — full Stylelint (`**/*.{css,ts}`).
|
|
19
|
+
|
|
20
|
+
Targeted lint on one file **does not replace** a full run before completing the task (except the pipeline exception above).
|
|
21
|
+
|
|
22
|
+
## Procedure
|
|
23
|
+
|
|
24
|
+
1. Finish code edits.
|
|
25
|
+
2. Run **`lint:js`** and **`lint:css`** from `app/`.
|
|
26
|
+
3. Analyze full output; fix errors/warnings in changed files; for Stylelint — **`lint:css --fix`** if auto-fixable.
|
|
27
|
+
4. Repeat until exit code 0 or record a blocker in the user response.
|
|
28
|
+
5. **`type-check`** when TypeScript changed. CI level: **`lint`** (= `lint:js` + `lint:css` + `type-check`).
|
|
29
|
+
|
|
30
|
+
## What to fix
|
|
31
|
+
|
|
32
|
+
- **Errors** — must fix.
|
|
33
|
+
- **Warnings** — must fix in task files; out of scope — mention if they block a zero exit code.
|
|
34
|
+
|
|
35
|
+
Configs: `app/eslint.config.mjs`, `app/.stylelintrc` (CSS order — `css-property-order-stylelint.md`).
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
<!-- shared-core: meta/preset-layering.md -->
|
|
2
|
+
|
|
3
|
+
# Preset layering
|
|
4
|
+
|
|
5
|
+
Rules for **preset authors** (`packages/ai-rules/presets/**`). Not always-on in consumer apps.
|
|
6
|
+
|
|
7
|
+
## Layers
|
|
8
|
+
|
|
9
|
+
| Layer | Where | What to put |
|
|
10
|
+
|-------|-------|-------------|
|
|
11
|
+
| **Core** | `presets/_shared/core/**` | Stack-agnostic prose + checklists; no frontmatter; no paths `app/**`, `Features/**`, Playwright, xcodebuild |
|
|
12
|
+
| **Stack** | `presets/{cursor\|claude}/<stack>/` | Domain/tooling, stack always-on trio, stack examples in **Stack notes** |
|
|
13
|
+
| **Platform** | Cursor `.mdc` / Claude `.md` | Frontmatter (`alwaysApply`/`globs` vs `paths:`), platform-only (`BUGBOT.md`, `CLAUDE.md`) |
|
|
14
|
+
|
|
15
|
+
## Where to put a new rule
|
|
16
|
+
|
|
17
|
+
1. Shared principles for all stacks → **core** + adapters with `<!-- shared-core: … -->`.
|
|
18
|
+
2. Only one of the installable stacks (`next` / `nuxt` / `svelte` / `ios-swift` / `android-kotlin` / `go` / `java` / `mcp-ts` / `php-hexagonal` / `php-laravel`) → **stack-specific** (not in `_shared`).
|
|
19
|
+
3. Only Cursor or only Claude packaging → platform artifact / frontmatter; do not duplicate semantics.
|
|
20
|
+
|
|
21
|
+
## SoT
|
|
22
|
+
|
|
23
|
+
- Packages path — SoT; root `.cursor/` — dogfood sync.
|
|
24
|
+
- Per stack: **Cursor** `presets/cursor/<stack>/` → Claude twin same PR.
|
|
25
|
+
- `_shared` is **not** a `--preset` and is not copied by CLI `init`.
|
|
26
|
+
|
|
27
|
+
See also: `preset-twin-sync`, `preset-token-budget`, `preset-pr-checklist`, `preset-no-cross-stack-leakage`.
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
<!-- shared-core: meta/preset-no-cross-stack-leakage.md -->
|
|
2
|
+
|
|
3
|
+
# Preset no cross-stack leakage
|
|
4
|
+
|
|
5
|
+
Ban leakage of stack-specific names, paths, and handoff stems across presets.
|
|
6
|
+
|
|
7
|
+
## Principles
|
|
8
|
+
|
|
9
|
+
- `next` must not require iOS-only or Android-only agents/tooling (`xcuitest-*`, `instrumentation-test-*`, `xcodebuild` as required handoff, Keychain-only rules).
|
|
10
|
+
- `nuxt` must not require iOS-only or Android-only agents/tooling (`xcuitest-*`, `instrumentation-test-*`, `xcodebuild` as required handoff, Keychain-only rules).
|
|
11
|
+
- `svelte` must not require iOS-only or Android-only agents/tooling (`xcuitest-*`, `instrumentation-test-*`, `xcodebuild` as required handoff, Keychain-only rules).
|
|
12
|
+
- `ios-swift` must not ship Playwright handoffs, Android `instrumentation-test-*` handoffs, or Next lint recipes as required commands.
|
|
13
|
+
- `android-kotlin` must not ship Playwright, XCUITest, `xcodebuild`, or Next lint recipes as required handoffs.
|
|
14
|
+
- `go` / `java` / `php-hexagonal` / `php-laravel` / `mcp-ts` must not ship Playwright, XCUITest, Android instrumentation agents, Next lint recipes, or `xcodebuild`/`SwiftLint` as required handoffs.
|
|
15
|
+
- `mcp-ts` must not ship Go tool commands (`go test`, `go vet`, `golangci-lint`) or `integration-test-*` agents as required delivery gates.
|
|
16
|
+
- Shared core must not embed stack paths (`app/src/**`, `Features/**`, `playwright`, `xcodebuild`).
|
|
17
|
+
- Storybook / Chrome DevTools MCP must **not** be required handoffs or agent stems (`storybook-reviewer`) on backend or mobile stacks. Frontend overlay mentions in `MCP.md` / `mcp-usage` Stack notes are OK.
|
|
18
|
+
|
|
19
|
+
## Forbidden in ios-swift hooks/agents (FAIL)
|
|
20
|
+
|
|
21
|
+
In ios-swift `chain-team-phases.sh` / agent handoffs (Cursor + Claude):
|
|
22
|
+
|
|
23
|
+
- `playwright-test-`, `playwright-agents`, `playwright-e2e`, `user-playwright`
|
|
24
|
+
- `instrumentation-test-` as required Android handoffs
|
|
25
|
+
- `app/__tests__/e2e` as a required path
|
|
26
|
+
- Positive yarn recipes `lint:js` / `lint:css` as commands to run (negation prose alone is weak — prefer zero occurrences)
|
|
27
|
+
|
|
28
|
+
Required instead: `xcuitest-test-*` stems; build-verifier mentions `xcodebuild` or `post-change-build` / `xcode-tooling`.
|
|
29
|
+
|
|
30
|
+
## Forbidden in android-kotlin hooks/agents (FAIL)
|
|
31
|
+
|
|
32
|
+
In android-kotlin `chain-team-phases.sh` / agent handoffs (Cursor + Claude):
|
|
33
|
+
|
|
34
|
+
- `playwright-test-`, `playwright-agents`, `playwright-e2e`, `user-playwright`
|
|
35
|
+
- `app/__tests__/e2e` as a required path
|
|
36
|
+
- `xcuitest-test-`, positive `xcodebuild` / `SwiftLint` as required handoffs
|
|
37
|
+
- Positive yarn recipes `lint:js` / `lint:css` as commands to run
|
|
38
|
+
|
|
39
|
+
Required instead: `instrumentation-test-*` stems; build-verifier mentions `gradle-tooling` and/or `post-change-build` (Gradle wrapper discovery — not `xcodebuild` as the default gate).
|
|
40
|
+
|
|
41
|
+
## Forbidden in next hooks/agents (FAIL when present as required)
|
|
42
|
+
|
|
43
|
+
- `xcuitest-test-` / `instrumentation-test-` as handoff stems
|
|
44
|
+
- Requiring `xcodebuild` / SwiftLint as the default post-change gate for Next app work
|
|
45
|
+
|
|
46
|
+
## Forbidden in nuxt hooks/agents (FAIL when present as required)
|
|
47
|
+
|
|
48
|
+
- `xcuitest-test-` / `instrumentation-test-` as handoff stems
|
|
49
|
+
- Requiring `xcodebuild` / SwiftLint as the default post-change gate for Nuxt app work
|
|
50
|
+
- Frontend profile mirrors `next`: Playwright / `lint:js` / `lint:css` allowed
|
|
51
|
+
|
|
52
|
+
## Forbidden in svelte hooks/agents (FAIL when present as required)
|
|
53
|
+
|
|
54
|
+
- `xcuitest-test-` / `instrumentation-test-` as handoff stems
|
|
55
|
+
- Requiring `xcodebuild` / SwiftLint as the default post-change gate for SvelteKit app work
|
|
56
|
+
- Frontend profile mirrors `next` / `nuxt`: Playwright / `lint:js` / `lint:css` allowed
|
|
57
|
+
|
|
58
|
+
## Forbidden in go / java / php-hexagonal / php-laravel hooks/agents (FAIL)
|
|
59
|
+
|
|
60
|
+
Shared backend-stack bans (`go`, `java`, `php-hexagonal`, and `php-laravel`):
|
|
61
|
+
|
|
62
|
+
- `playwright-test-`, `playwright-e2e`, `user-playwright`, `app/__tests__/e2e`
|
|
63
|
+
- Positive yarn recipes `lint:js` / `lint:css`
|
|
64
|
+
- `xcuitest-test-`, `instrumentation-test-`, `xcodebuild`, `SwiftLint` as required handoffs
|
|
65
|
+
- Agent files `accessibility-reviewer`, `mockup-reviewer`, `ux-designer` (no UI surface)
|
|
66
|
+
- Required `skills/ux-design`, required `rules/ux-design`, or required pipeline handoff stem `ux-design`
|
|
67
|
+
|
|
68
|
+
Required instead: `integration-test-*`; build-verifier / `post-change-test` plus stack tooling — `go-tooling` (`go test`, `go vet`), `java-tooling` (`mvn test` / `./gradlew test`), or `php-tooling` (`php artisan test` / `composer test` / `vendor/bin/phpunit`).
|
|
69
|
+
|
|
70
|
+
## Forbidden in mcp-ts hooks/agents (FAIL)
|
|
71
|
+
|
|
72
|
+
Same UI/mobile bans as backend stacks, plus:
|
|
73
|
+
|
|
74
|
+
- `playwright-test-`, `playwright-agents`, `playwright-e2e`, `user-playwright`, `app/__tests__/e2e`
|
|
75
|
+
- Positive yarn recipes `lint:js` / `lint:css` as required gates
|
|
76
|
+
- `xcuitest-test-`, `instrumentation-test-`, `xcodebuild`, `SwiftLint` as required handoffs
|
|
77
|
+
- Go tool commands as required MCP delivery gates: `go test`, `go vet`, `golangci-lint`
|
|
78
|
+
- Agent files: `playwright-test-*`, `xcuitest-test-*`, `instrumentation-test-*`, `integration-test-*`, `accessibility-reviewer`, `mockup-reviewer`, `ux-designer`
|
|
79
|
+
- Required `skills/ux-design`, required `rules/ux-design`, or required pipeline handoff stem `ux-design`
|
|
80
|
+
|
|
81
|
+
Required instead: package-manager–discovered typecheck/test (`mcp-ts-tooling`, `post-change-test`); Phase 1 gates `build-verifier` + `security-reviewer`.
|
|
82
|
+
|
|
83
|
+
## Soft / document
|
|
84
|
+
|
|
85
|
+
- Mentioning the other stack in **docs** comparing presets is OK.
|
|
86
|
+
- `build-verifier` may reference other stacks when validating **preset packaging** (`scope: preset-structure-validation`).
|
|
87
|
+
|
|
88
|
+
## Chain fork
|
|
89
|
+
|
|
90
|
+
`hooks/chain-team-phases.sh` must differ **byte-wise** pairwise among `next`, `nuxt`, `svelte`, `ios-swift`, `android-kotlin`, `go`, `java`, `mcp-ts`, `php-hexagonal`, and `php-laravel` (per platform).
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
<!-- shared-core: meta/preset-pr-checklist.md -->
|
|
2
|
+
|
|
3
|
+
# Preset PR checklist
|
|
4
|
+
|
|
5
|
+
Checklist for PRs that touch `packages/ai-rules/presets/**` (and dogfood `.cursor/` sync).
|
|
6
|
+
|
|
7
|
+
## Before merge
|
|
8
|
+
|
|
9
|
+
- [ ] **SoT:** edits in `packages/…` (not only root `.cursor/`)
|
|
10
|
+
- [ ] **Core:** if `_shared/core/**` changed — all `<!-- shared-core: … -->` consumers updated (or documented intentional fork)
|
|
11
|
+
- [ ] **Twin:** Cursor change → Claude twin **same PR** (**FAIL** if missing on next, nuxt, svelte, ios-swift, android-kotlin, go, java, mcp-ts, php-hexagonal, and php-laravel — see `preset-twin-sync`)
|
|
12
|
+
- [ ] **Mavis derive:** mapped `cursor/<stack>/` change → `mavis/<stack>/` + `adapter-map.json` **same PR** when the stack is in `releasedStacks` (run `generate-mavis-next.mjs` + `check-mavis-adapter-map.mjs` for `next`; see `preset-twin-sync` § Mavis derivation)
|
|
13
|
+
- [ ] **Mapping:** `claude/<stack>/rules/README.md` mapping table is current
|
|
14
|
+
- [ ] **Token budget:** Cursor `alwaysApply` ≤ 4 (4th slot reserved for `ai-local-overlay`); Claude session-start exactly 3; meta rules not always-on
|
|
15
|
+
- [ ] **Local overlay coverage:** every installable stack ships `ai-local-overlay.mdc` (Cursor) and `ai-local-overlay.md` (Claude) with `MANDATORY` + acknowledgement format + `docs/LOCAL-OVERLAY.md` pointer; Claude twin listed in `claude/<stack>/rules/README.md` mapping table. Run `packages/ai-rules/scripts/check-local-overlay.sh`.
|
|
16
|
+
- [ ] **Leakage:** no foreign stack agent stems / handoff strings (`preset-no-cross-stack-leakage`)
|
|
17
|
+
- [ ] **Hook-only lifecycle:** `status.json` / `metrics.json` writes happen only inside `hooks/`; agents read but never rewrite lifecycle fields. Run `packages/ai-rules/scripts/check-hook-only-lifecycle.sh`.
|
|
18
|
+
- [ ] **Chain fork:** the byte-wise MD5 uniqueness of `chain-team-phases.sh` across the 10 stacks × 2 platforms (20 hooks) holds. Run `packages/ai-rules/scripts/check-chain-hook-coverage.sh` and `packages/ai-rules/scripts/test-chain-team-phases-coverage.mjs`.
|
|
19
|
+
- [ ] **Twin depth:** domain ≥15 lines; thin aliases documented
|
|
20
|
+
- [ ] **README:** stack `rules/README.md` core→stack mapping / catalog updated if stems added
|
|
21
|
+
- [ ] **CHANGELOG / package README:** note when public preset paths or install surface change
|
|
22
|
+
- [ ] **i18n anchors:** kept-marked Cyrillic fragments in `tests-unit.md(c)` stay consistent with their English counterparts. Run `packages/ai-rules/scripts/check-preset-i18n.sh`.
|
|
23
|
+
- [ ] **Dogfood:** run `packages/ai-rules/scripts/sync-dogfood-cursor.sh` (or document intentional skip) when maintaining this monorepo
|
|
24
|
+
- [ ] **shared-core drift:** for embed-mode stems, run `packages/ai-rules/scripts/check-shared-core-drift.sh` (or document intentional fork)
|
|
25
|
+
|
|
26
|
+
## Pointers
|
|
27
|
+
|
|
28
|
+
- Layering: `preset-layering`
|
|
29
|
+
- Sync: `preset-twin-sync`
|
|
30
|
+
- Budget: `preset-token-budget`
|
|
31
|
+
- Leakage: `preset-no-cross-stack-leakage`
|
|
32
|
+
- Validation: stack `agents/build-verifier.md` → preset-structure section
|
|
33
|
+
- Dogfood script: `packages/ai-rules/scripts/sync-dogfood-cursor.sh`
|
|
34
|
+
- Drift script: `packages/ai-rules/scripts/check-shared-core-drift.sh`
|
|
35
|
+
- Orchestrator: when editing presets, load this checklist + twin-sync
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
<!-- shared-core: meta/preset-token-budget.md -->
|
|
2
|
+
|
|
3
|
+
# Preset token budget
|
|
4
|
+
|
|
5
|
+
Invariants for rule loading in an **installed** preset (consumer app).
|
|
6
|
+
|
|
7
|
+
## Hard caps
|
|
8
|
+
|
|
9
|
+
| Platform | Always-on | Cap |
|
|
10
|
+
|----------|-----------|-----|
|
|
11
|
+
| Cursor | `alwaysApply: true` | **≤ 4** |
|
|
12
|
+
| Claude | rules **without** `paths:` | **exactly 3** |
|
|
13
|
+
|
|
14
|
+
**Cursor 4th slot is reserved for `ai-local-overlay`** (consumer-owned `.ai.local/` rules). If you do not need local overlay, demote that rule to `globs: ["**/.ai.local/**"]` and revert to ≤3.
|
|
15
|
+
|
|
16
|
+
**Claude Option A (README exclusion):** when counting Claude rules without `paths:` / session-start, **exclude `**/README.md`** (topic indexes are not session-start rules). The intended session-start trio remains **exactly 3**; body budget sums **only those 3** rules.
|
|
17
|
+
|
|
18
|
+
Session-start body budget:
|
|
19
|
+
- Claude trio: ≤140 lines total (stretch ≤120).
|
|
20
|
+
- Cursor 4-set: ≤170 lines total (4 rules including `ai-local-overlay`).
|
|
21
|
+
|
|
22
|
+
## Meta / author rules
|
|
23
|
+
|
|
24
|
+
Rules for preset authors (`preset-layering`, `preset-twin-sync`, …):
|
|
25
|
+
|
|
26
|
+
- **Never** `alwaysApply: true` on consumer installs.
|
|
27
|
+
- Cursor: `globs` limited to `packages/ai-rules/presets/**` (and dogfood `.cursor/**` where useful).
|
|
28
|
+
- Claude: `paths:` limited to `packages/ai-rules/presets/**` (and `.claude/**` dogfood if present).
|
|
29
|
+
|
|
30
|
+
## Heavy workflows
|
|
31
|
+
|
|
32
|
+
Orchestrator, feature-delivery, code-review, post-change gates, domain globs — **requestable / paths**, not always-on.
|
|
33
|
+
|
|
34
|
+
## Verifier
|
|
35
|
+
|
|
36
|
+
build-verifier **FAIL** if Cursor `alwaysApply` count exceeds 4, Claude session-start count exceeds 3 (Claude count **excludes `**/README.md`**), or if a `preset-*` meta rule is marked always-on.
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
<!-- shared-core: meta/preset-twin-sync.md -->
|
|
2
|
+
|
|
3
|
+
# Preset twin sync
|
|
4
|
+
|
|
5
|
+
Cursor `.mdc` — **SoT per stack**. Claude topic `.md` — derived twin.
|
|
6
|
+
|
|
7
|
+
## Matrix
|
|
8
|
+
|
|
9
|
+
| Stack | Cursor SoT | Claude derive | Mapping table |
|
|
10
|
+
|-------|------------|---------------|---------------|
|
|
11
|
+
| `next` | `presets/cursor/next/rules/*.mdc` | `presets/claude/next/rules/<topic>/` | **Required** in `claude/next/rules/README.md` |
|
|
12
|
+
| `nuxt` | `presets/cursor/nuxt/rules/*.mdc` | `presets/claude/nuxt/rules/<topic>/` | **Required** in `claude/nuxt/rules/README.md` |
|
|
13
|
+
| `svelte` | `presets/cursor/svelte/rules/*.mdc` | `presets/claude/svelte/rules/<topic>/` | **Required** in `claude/svelte/rules/README.md` |
|
|
14
|
+
| `ios-swift` | `presets/cursor/ios-swift/rules/*.mdc` | `presets/claude/ios-swift/rules/<topic>/` | Keep in `claude/ios-swift/rules/README.md` |
|
|
15
|
+
| `go` | `presets/cursor/go/rules/*.mdc` | `presets/claude/go/rules/<topic>/` | Keep in `claude/go/rules/README.md` |
|
|
16
|
+
| `java` | `presets/cursor/java/rules/*.mdc` | `presets/claude/java/rules/<topic>/` | Keep in `claude/java/rules/README.md` |
|
|
17
|
+
| `mcp-ts` | `presets/cursor/mcp-ts/rules/*.mdc` | `presets/claude/mcp-ts/rules/<topic>/` | Keep in `claude/mcp-ts/rules/README.md` |
|
|
18
|
+
| `php-hexagonal` | `presets/cursor/php-hexagonal/rules/*.mdc` | `presets/claude/php-hexagonal/rules/<topic>/` | Keep in `claude/php-hexagonal/rules/README.md` |
|
|
19
|
+
| `php-laravel` | `presets/cursor/php-laravel/rules/*.mdc` | `presets/claude/php-laravel/rules/<topic>/` | Keep in `claude/php-laravel/rules/README.md` |
|
|
20
|
+
| `android-kotlin` | `presets/cursor/android-kotlin/rules/*.mdc` | `presets/claude/android-kotlin/rules/<topic>/` | Keep in `claude/android-kotlin/rules/README.md` |
|
|
21
|
+
|
|
22
|
+
## Mavis derivation (not a Claude twin)
|
|
23
|
+
|
|
24
|
+
| Stack | Cursor SoT | Mavis derive | Manifest |
|
|
25
|
+
|-------|------------|--------------|----------|
|
|
26
|
+
| `next` | `presets/cursor/next/**` | `presets/mavis/next/**` via `generate-mavis-next.mjs` | **Required** `adapter-map.json` |
|
|
27
|
+
|
|
28
|
+
Mavis is a **third platform adapter**, not a Claude-style topic twin:
|
|
29
|
+
|
|
30
|
+
```text
|
|
31
|
+
_shared/core → cursor/<stack> → mavis/<stack>
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Regenerate with `node packages/ai-rules/scripts/generate-mavis-next.mjs`; validate with `node packages/ai-rules/scripts/check-mavis-adapter-map.mjs`.
|
|
35
|
+
|
|
36
|
+
## Same-PR checklist
|
|
37
|
+
|
|
38
|
+
1. Edit Cursor rule first (body + frontmatter).
|
|
39
|
+
2. Update Claude twin: body + `paths:` (from Cursor `globs:` / requestable triggers); drop `alwaysApply`.
|
|
40
|
+
3. Update mapping table row if stem/path changed.
|
|
41
|
+
4. If body embeds core (`<!-- shared-core: … -->`), sync core consumers across stacks when core changed.
|
|
42
|
+
5. When mapped `cursor/<stack>/` sources change, regenerate `mavis/<stack>/` and refresh `adapter-map.json` `sourceRevision` in the **same PR** (run `generate-mavis-next.mjs` + `check-mavis-adapter-map.mjs` for `next`).
|
|
43
|
+
|
|
44
|
+
## Twin depth
|
|
45
|
+
|
|
46
|
+
- **Domain** rules: ≥15 body lines (FAIL if thin without documented alias reason).
|
|
47
|
+
- **Thin aliases** (`agent-team-intake`, `technical-retro`): may be shorter (soft) if they only point to a command/skill.
|
|
48
|
+
- **Slim-companion rules** (UI-edit bundle, slim app-cores, slim tooling): may be shorter than 15 lines **if and only if** the body is a pointer into shared-core / stack-prose (no standalone prose). Examples live in stack `rules/README.md` (e.g. `cursor/next/rules/README.md` "UI-edit bundle" intent).
|
|
49
|
+
- Mechanical enforcement lives in `packages/ai-rules/scripts/check-preset-token-budget.sh` — see `SLIM_COMPANION_ALLOWLIST` (the 53 stems accepted as slim pointers) and `MIN_SLIM_BODY_LINES` (5-line floor). Slim-companion rules with a body of 6–14 lines whose stem is **not** in the allowlist are reported as slim violations by the script.
|
|
50
|
+
|
|
51
|
+
## Severity (build-verifier)
|
|
52
|
+
|
|
53
|
+
- **next:** missing Claude twin for a changed Cursor rule → **FAIL** (mapping table required).
|
|
54
|
+
- **nuxt:** missing Claude twin for a changed Cursor rule → **FAIL** (mapping table required).
|
|
55
|
+
- **svelte:** missing Claude twin for a changed Cursor rule → **FAIL** (mapping table required).
|
|
56
|
+
- **ios-swift:** missing Claude twin for a changed Cursor rule → **FAIL**.
|
|
57
|
+
- **go:** missing Claude twin for a changed Cursor rule → **FAIL** (same as next / ios-swift; mapping table required).
|
|
58
|
+
- **java:** missing Claude twin for a changed Cursor rule → **FAIL** (same as next / ios-swift / go; mapping table required).
|
|
59
|
+
- **mcp-ts:** missing Claude twin for a changed Cursor rule → **FAIL** (same as next / ios-swift / go / java; mapping table required).
|
|
60
|
+
- **php-hexagonal:** missing Claude twin for a changed Cursor rule → **FAIL** (same as next / ios-swift / go / java / mcp-ts; mapping table required).
|
|
61
|
+
- **php-laravel:** missing Claude twin for a changed Cursor rule → **FAIL** (same as next / ios-swift / go / java / mcp-ts / php-hexagonal; mapping table required).
|
|
62
|
+
- **android-kotlin:** missing Claude twin for a changed Cursor rule → **FAIL** (same as next / ios-swift / go / java / mcp-ts / php-*; mapping table required).
|
|
63
|
+
- **mavis/next:** `cursor/next` mapped source changed without mavis regeneration / `adapter-map.json` `sourceRevision` drift → **FAIL** (`check-mavis-adapter-map.mjs`).
|
|
64
|
+
|
|
65
|
+
Dogfood: sync packages → root `.cursor/` after Cursor SoT changes (not the reverse). Use `packages/ai-rules/scripts/sync-dogfood-cursor.sh`.
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
<!-- shared-core: architecture/product-specs-authoring.md -->
|
|
2
|
+
|
|
3
|
+
# Product specs authoring
|
|
4
|
+
|
|
5
|
+
Load when **Generate** or **Bootstrap** is requested (`/spec-start`, router `spec-gen`, brief AC, or analyst author mode). Discovery-only work stays on **`product-specs`**.
|
|
6
|
+
|
|
7
|
+
**Optional prefix:** when the user or AC asks **research-before-spec**, load skill **`spec-discovery`** first (subset of methods; **claim-ledger** mandatory). Not the default `/task` consume path and not a new pipeline step.
|
|
8
|
+
|
|
9
|
+
## Modes
|
|
10
|
+
|
|
11
|
+
1. **Consume** — default; never invent INDEX/specs (see `product-specs`).
|
|
12
|
+
2. **Generate** — create/update page/feature specs + INDEX rows from brief AC, user intent, Figma, or code archaeology. Inventing *product* behavior is forbidden without a stated source (AC / user / UI copy / code-observed behavior labeled `status: draft` or `inferred`).
|
|
13
|
+
3. **Bootstrap** — create `INDEX.md` + `_templates/` copies + first domain spec under greenfield policy.
|
|
14
|
+
|
|
15
|
+
## Greenfield policy
|
|
16
|
+
|
|
17
|
+
Agents **may** create INDEX + first specs **only when** one of:
|
|
18
|
+
|
|
19
|
+
1. User runs `/spec-start` or explicitly asks to bootstrap `docs/specs`.
|
|
20
|
+
2. Brief/AC includes generation or bootstrap language.
|
|
21
|
+
3. Router detects `spec-gen` intent.
|
|
22
|
+
|
|
23
|
+
Otherwise: missing INDEX → optional tree; do **not** invent INDEX merely because discovery loaded.
|
|
24
|
+
|
|
25
|
+
## Conflict precedence
|
|
26
|
+
|
|
27
|
+
1. **Human gate** decision (approved brief/spec edits).
|
|
28
|
+
2. **Current task `brief.md` AC** — if AC contradicts an existing spec, analyst must reconcile (update spec as `draft` or revise AC) before developer; no silent contradiction.
|
|
29
|
+
3. **Approved `docs/specs/**`** — behavior SoT for feature-developer once gate passed.
|
|
30
|
+
4. **Code / `.ai/context`** — discovery evidence only; never override approved spec without gate.
|
|
31
|
+
|
|
32
|
+
Label inferred-from-code lines with `status: draft` until human promotes.
|
|
33
|
+
|
|
34
|
+
## INDEX.md contract (v1)
|
|
35
|
+
|
|
36
|
+
| Column | Required | Notes |
|
|
37
|
+
|--------|----------|-------|
|
|
38
|
+
| `id` | yes | Stable kebab/id matching frontmatter `id` |
|
|
39
|
+
| `type` | yes | `page` \| `feature` |
|
|
40
|
+
| `domain` | yes | Domain folder under `docs/specs/domains/<domain>/` |
|
|
41
|
+
| `title` | yes | Human label |
|
|
42
|
+
| `path` | yes | Repo-relative path to markdown file |
|
|
43
|
+
| `routes` | no | Summary; may duplicate frontmatter |
|
|
44
|
+
| `aliases` | no | Comma-separated PageName / deep-link aliases |
|
|
45
|
+
| `status` | no | `draft` \| `active` \| `deprecated` |
|
|
46
|
+
|
|
47
|
+
Layout: `docs/specs/domains/<domain>/<id>.md` (page) and optional `docs/specs/domains/<domain>/feature.md`. Adding/renaming/removing a linked file **must** update INDEX in the **same change set**.
|
|
48
|
+
|
|
49
|
+
## Frontmatter v1
|
|
50
|
+
|
|
51
|
+
| Field | Type | Required | Notes |
|
|
52
|
+
|-------|------|----------|-------|
|
|
53
|
+
| `id` | string | yes | Unique; matches INDEX |
|
|
54
|
+
| `type` | enum `page` \| `feature` | yes | Backend/MCP: prefer `feature` |
|
|
55
|
+
| `domain` | string | yes | |
|
|
56
|
+
| `routes` | string[] | yes (may be `[]`) | Web: URL paths; mobile: deep links/screens; backend: HTTP paths; mcp-ts: tool names |
|
|
57
|
+
| `ui` | string[] | yes (may be `[]`) | Component/screen refs; empty on backend/mcp |
|
|
58
|
+
| `store` | string[] | yes (may be `[]`) | Slice/module refs; empty when N/A |
|
|
59
|
+
| `api` | string[] | yes (may be `[]`) | Services/ports/tools |
|
|
60
|
+
| `aliases` | string[] | yes (may be `[]`) | |
|
|
61
|
+
| `e2e` | string[] | yes (may be `[]`) | Stack-appropriate test paths |
|
|
62
|
+
| `status` | enum | no | default `draft` on agent generate |
|
|
63
|
+
| `owners` | string[] | no | |
|
|
64
|
+
| `related` | string[] | no | Spec ids or paths |
|
|
65
|
+
|
|
66
|
+
Arrays are **always present** (empty allowed). Do not omit keys for N/A stacks.
|
|
67
|
+
|
|
68
|
+
## Body headings (minimum)
|
|
69
|
+
|
|
70
|
+
**`page` required:** Overview; Entry / actors; Primary flows; States (loading / empty / error / success as applicable — mark N/A explicitly); Acceptance criteria (links or bullets to brief AC / product source).
|
|
71
|
+
|
|
72
|
+
**`page` optional:** Analytics, Accessibility, Edge cases, Related specs.
|
|
73
|
+
|
|
74
|
+
**`feature` required:** Overview; Shared behavior / constraints; Related pages (links).
|
|
75
|
+
|
|
76
|
+
**`feature` optional:** Cross-cutting states, Analytics.
|
|
77
|
+
|
|
78
|
+
Compliant = valid frontmatter + all required headings present (non-empty prose or explicit `N/A`) + INDEX row with resolvable `path`.
|
|
79
|
+
|
|
80
|
+
## Templates & assets
|
|
81
|
+
|
|
82
|
+
**Package SoT:** `packages/ai-rules/presets/_shared/assets/docs-specs/` (`INDEX.md` stub, `_templates/page.md`, `_templates/feature.md`; `schemas/frontmatter-v1.schema.json` is a documentation artifact — the checker does not evaluate it).
|
|
83
|
+
|
|
84
|
+
**CLI `init`:** when consumer `docs/specs/` is **absent**, copy INDEX stub + `_templates/*` (idempotent; **never overwrite** existing INDEX). When the tree already exists, skip seed entirely.
|
|
85
|
+
|
|
86
|
+
**Skill fallback:** if consumer `_templates/` missing during author mode, copy from package/skill assets before authoring.
|
|
87
|
+
|
|
88
|
+
## Author roles
|
|
89
|
+
|
|
90
|
+
| Role | Responsibility |
|
|
91
|
+
|------|----------------|
|
|
92
|
+
| **task-analyst** | Primary author (Generate + Bootstrap); INDEX bootstrap; brief **Related specs** + **Spec gaps / generation requested**; loads this stem + skill `spec-authoring`; optional skill `spec-discovery` when research-before-spec |
|
|
93
|
+
| **tech-writer** | Post-delivery sync where present; never invent product behavior without AC/code source |
|
|
94
|
+
| **feature-developer** | Consumes approved specs as SoT; mechanical INDEX/frontmatter fixes only on renames |
|
|
95
|
+
| **mcp-ts** | No tech-writer — author + post-sync via **task-analyst** only |
|
|
96
|
+
|
|
97
|
+
## Self-check before handoff (soft block)
|
|
98
|
+
|
|
99
|
+
Block handoff via `open_questions` until fixed:
|
|
100
|
+
|
|
101
|
+
- [ ] Required frontmatter keys present; arrays always present (may be `[]`)
|
|
102
|
+
- [ ] Required body headings present (or explicit `N/A`)
|
|
103
|
+
- [ ] INDEX row added/updated with resolvable `path` in the **same change set**
|
|
104
|
+
- [ ] Sources cited; invented product behavior absent (or labeled `draft` / `inferred`)
|
|
105
|
+
- [ ] Conflict with brief AC reconciled or flagged
|
|
106
|
+
|
|
107
|
+
## Related
|
|
108
|
+
|
|
109
|
+
- `product-specs` — discovery / consume
|
|
110
|
+
- Skill `spec-authoring` — procedural checklist
|
|
111
|
+
- Skill `spec-discovery` — opt-in research-before-spec (not default)
|
|
112
|
+
- Optional consumer script `scripts/check-product-specs.sh` (ships in the npm package; WARN default; `--strict` FAIL). Bash checks INDEX links, required frontmatter keys, and body headings — it does **not** evaluate `frontmatter-v1.schema.json`
|