@schneiderjoseph/devia 0.1.0
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/AGENTS.md +149 -0
- package/CHANGELOG.md +78 -0
- package/GOVERNANCE.md +51 -0
- package/LEVELS.md +78 -0
- package/LICENSE +21 -0
- package/MATURITY.md +79 -0
- package/MEMORY.md +122 -0
- package/MIGRATION.md +62 -0
- package/PRINCIPLES.md +110 -0
- package/README.md +125 -0
- package/REFERENCES.md +30 -0
- package/VERSION +5 -0
- package/bin/devia.mjs +13 -0
- package/checklists/README.md +39 -0
- package/checklists/design/accessibility-review.md +11 -0
- package/checklists/design/design-to-code-review.md +10 -0
- package/checklists/design/responsive-review.md +7 -0
- package/checklists/design/ui-review.md +8 -0
- package/checklists/design/ux-review.md +10 -0
- package/checklists/engineering/accessibility.md +8 -0
- package/checklists/engineering/api.md +12 -0
- package/checklists/engineering/architecture.md +8 -0
- package/checklists/engineering/database.md +11 -0
- package/checklists/engineering/devops.md +9 -0
- package/checklists/engineering/disaster-recovery.md +9 -0
- package/checklists/engineering/frontend.md +9 -0
- package/checklists/engineering/incident.md +9 -0
- package/checklists/engineering/performance.md +7 -0
- package/checklists/engineering/production.md +26 -0
- package/checklists/engineering/release.md +17 -0
- package/checklists/engineering/security.md +33 -0
- package/checklists/engineering/testing.md +8 -0
- package/compliance/COVERAGE.md +46 -0
- package/compliance/REQUIREMENTS.md +8 -0
- package/compliance/TRACEABILITY.md +160 -0
- package/compliance/WAIVERS.md +13 -0
- package/package.json +74 -0
- package/rules/LIFECYCLE.md +16 -0
- package/rules/README.md +166 -0
- package/rules/accessibility/A11Y-001.md +42 -0
- package/rules/accessibility/A11Y-002.md +41 -0
- package/rules/accessibility/A11Y-003.md +40 -0
- package/rules/accessibility/A11Y-004.md +40 -0
- package/rules/accessibility/A11Y-005.md +39 -0
- package/rules/accessibility/A11Y-006.md +42 -0
- package/rules/accessibility/A11Y-007.md +39 -0
- package/rules/accessibility/A11Y-008.md +40 -0
- package/rules/accessibility/A11Y-009.md +41 -0
- package/rules/accessibility/A11Y-010.md +40 -0
- package/rules/accessibility/A11Y-011.md +39 -0
- package/rules/accessibility/A11Y-012.md +39 -0
- package/rules/agent/AGT-001.md +42 -0
- package/rules/agent/AGT-002.md +39 -0
- package/rules/agent/AGT-003.md +38 -0
- package/rules/agent/AGT-004.md +39 -0
- package/rules/agent/AGT-005.md +38 -0
- package/rules/agent/AGT-006.md +38 -0
- package/rules/agent/AGT-007.md +38 -0
- package/rules/agent/AGT-008.md +38 -0
- package/rules/agent/AGT-009.md +39 -0
- package/rules/agent/AGT-010.md +38 -0
- package/rules/agent/AGT-011.md +38 -0
- package/rules/ai/AI-001.md +44 -0
- package/rules/ai/AI-002.md +39 -0
- package/rules/ai/AI-003.md +40 -0
- package/rules/ai/AI-004.md +39 -0
- package/rules/ai/AI-005.md +38 -0
- package/rules/api/API-001.md +39 -0
- package/rules/api/API-002.md +39 -0
- package/rules/api/API-003.md +39 -0
- package/rules/api/API-004.md +38 -0
- package/rules/api/API-005.md +39 -0
- package/rules/api/API-006.md +40 -0
- package/rules/architecture/ARC-001.md +41 -0
- package/rules/architecture/ARC-002.md +43 -0
- package/rules/architecture/ARC-003.md +43 -0
- package/rules/architecture/ARC-004.md +40 -0
- package/rules/architecture/ARC-005.md +39 -0
- package/rules/architecture/ARC-006.md +39 -0
- package/rules/components/CMP-001.md +39 -0
- package/rules/components/CMP-002.md +38 -0
- package/rules/components/CMP-003.md +39 -0
- package/rules/components/CMP-004.md +40 -0
- package/rules/components/CMP-005.md +39 -0
- package/rules/content/CNT-001.md +39 -0
- package/rules/data-display/DATA-001.md +39 -0
- package/rules/data-display/DATA-002.md +39 -0
- package/rules/data-display/DATA-003.md +40 -0
- package/rules/data-display/DATA-004.md +40 -0
- package/rules/database/DB-001.md +43 -0
- package/rules/database/DB-002.md +38 -0
- package/rules/database/DB-003.md +40 -0
- package/rules/database/DB-004.md +44 -0
- package/rules/database/DB-005.md +39 -0
- package/rules/database/DB-006.md +38 -0
- package/rules/database/DB-007.md +40 -0
- package/rules/database/DB-008.md +40 -0
- package/rules/design-system/DS-001.md +39 -0
- package/rules/design-system/DS-002.md +40 -0
- package/rules/design-system/DS-003.md +38 -0
- package/rules/devops/OPS-001.md +43 -0
- package/rules/devops/OPS-002.md +39 -0
- package/rules/devops/OPS-003.md +38 -0
- package/rules/devops/OPS-004.md +40 -0
- package/rules/devops/OPS-005.md +43 -0
- package/rules/devops/OPS-006.md +38 -0
- package/rules/devops/OPS-007.md +40 -0
- package/rules/interaction/INT-001.md +39 -0
- package/rules/interaction/INT-002.md +39 -0
- package/rules/localization/I18N-001.md +38 -0
- package/rules/localization/I18N-002.md +40 -0
- package/rules/localization/I18N-003.md +39 -0
- package/rules/memory/MEM-001.md +44 -0
- package/rules/memory/MEM-002.md +39 -0
- package/rules/memory/MEM-003.md +38 -0
- package/rules/memory/MEM-004.md +38 -0
- package/rules/memory/MEM-005.md +38 -0
- package/rules/memory/MEM-006.md +38 -0
- package/rules/memory/MEM-007.md +38 -0
- package/rules/memory/MEM-008.md +38 -0
- package/rules/memory/MEM-009.md +39 -0
- package/rules/memory/MEM-010.md +38 -0
- package/rules/memory/MEM-011.md +38 -0
- package/rules/motion/MOT-001.md +38 -0
- package/rules/observability/OBS-001.md +40 -0
- package/rules/observability/OBS-002.md +40 -0
- package/rules/observability/OBS-003.md +38 -0
- package/rules/observability/OBS-004.md +38 -0
- package/rules/privacy/PRIV-001.md +38 -0
- package/rules/privacy/PRIV-002.md +44 -0
- package/rules/privacy/PRIV-003.md +40 -0
- package/rules/privacy/PRIV-004.md +41 -0
- package/rules/responsive/RWD-001.md +40 -0
- package/rules/responsive/RWD-002.md +39 -0
- package/rules/responsive/RWD-003.md +39 -0
- package/rules/security/SEC-001.md +44 -0
- package/rules/security/SEC-002.md +44 -0
- package/rules/security/SEC-003.md +41 -0
- package/rules/security/SEC-004.md +40 -0
- package/rules/security/SEC-005.md +42 -0
- package/rules/security/SEC-006.md +40 -0
- package/rules/security/SEC-007.md +44 -0
- package/rules/security/SEC-008.md +39 -0
- package/rules/security/SEC-009.md +40 -0
- package/rules/security/SEC-010.md +40 -0
- package/rules/security/SEC-011.md +40 -0
- package/rules/security/SEC-012.md +40 -0
- package/rules/states/STATE-001.md +38 -0
- package/rules/states/STATE-002.md +39 -0
- package/rules/states/STATE-003.md +39 -0
- package/rules/states/STATE-004.md +38 -0
- package/rules/testing/TST-001.md +39 -0
- package/rules/testing/TST-002.md +39 -0
- package/rules/testing/TST-003.md +39 -0
- package/rules/testing/TST-004.md +38 -0
- package/rules/testing/TST-005.md +40 -0
- package/rules/testing/TST-006.md +39 -0
- package/rules/ui/UI-001.md +40 -0
- package/rules/ui/UI-002.md +38 -0
- package/rules/ui/UI-003.md +41 -0
- package/rules/ui/UI-004.md +41 -0
- package/rules/ui/UI-005.md +41 -0
- package/rules/ui/UI-006.md +40 -0
- package/rules/ui/UI-007.md +41 -0
- package/rules/ux/UX-001.md +41 -0
- package/rules/ux/UX-002.md +41 -0
- package/rules/ux/UX-003.md +39 -0
- package/rules/ux/UX-004.md +39 -0
- package/rules/ux/UX-005.md +40 -0
- package/rules/ux/UX-006.md +40 -0
- package/rules/ux/UX-007.md +44 -0
- package/rules/ux/UX-008.md +41 -0
- package/rules/ux/UX-009.md +39 -0
- package/rules/ux/UX-010.md +40 -0
- package/rules/ux/UX-011.md +40 -0
- package/rules/ux/UX-012.md +40 -0
- package/rules/ux/UX-013.md +39 -0
- package/schema/README.md +19 -0
- package/schema/checklist.schema.json +34 -0
- package/schema/component.schema.json +37 -0
- package/schema/project-config.schema.json +70 -0
- package/schema/rule.schema.json +104 -0
- package/schema/token.schema.json +15 -0
- package/schema/waiver.schema.json +33 -0
- package/scripts/build-index.mjs +178 -0
- package/scripts/validate-links.mjs +43 -0
- package/scripts/validate-rules.mjs +42 -0
- package/skills/devia/SKILL.md +114 -0
- package/src/cli.mjs +107 -0
- package/src/commands/check.mjs +483 -0
- package/src/commands/doctor.mjs +139 -0
- package/src/commands/init.mjs +186 -0
- package/src/commands/registry.mjs +154 -0
- package/src/commands/rules.mjs +101 -0
- package/src/commands/skills.mjs +97 -0
- package/src/commands/sync.mjs +83 -0
- package/src/commands/validate.mjs +194 -0
- package/src/lib/fs.mjs +89 -0
- package/src/lib/git.mjs +31 -0
- package/src/lib/rules.mjs +85 -0
- package/src/lib/ui.mjs +52 -0
- package/src/lib/vendor.mjs +74 -0
- package/src/lib/version.mjs +19 -0
- package/src/lib/yaml.mjs +152 -0
- package/standard/README.md +31 -0
- package/standard/design/README.md +51 -0
- package/standard/design/REFERENCES.md +39 -0
- package/standard/design/accessibility/aria.md +7 -0
- package/standard/design/accessibility/contrast.md +6 -0
- package/standard/design/accessibility/focus.md +6 -0
- package/standard/design/accessibility/forms.md +3 -0
- package/standard/design/accessibility/keyboard.md +6 -0
- package/standard/design/accessibility/reduced-motion.md +3 -0
- package/standard/design/accessibility/reflow.md +3 -0
- package/standard/design/accessibility/screen-readers.md +3 -0
- package/standard/design/accessibility/target-size.md +3 -0
- package/standard/design/accessibility/testing.md +3 -0
- package/standard/design/accessibility/wcag-2.2.md +16 -0
- package/standard/design/accessibility/zoom.md +3 -0
- package/standard/design/ai/ai-design-rules.md +8 -0
- package/standard/design/ai/anti-patterns.md +1 -0
- package/standard/design/ai/compliance-format.md +22 -0
- package/standard/design/ai/design-review.md +10 -0
- package/standard/design/ai/evals/README.md +1 -0
- package/standard/design/ai/instructions.md +7 -0
- package/standard/design/ai/prompts/accessibility-review.md +5 -0
- package/standard/design/ai/prompts/design-system-review.md +5 -0
- package/standard/design/ai/prompts/ui-review.md +5 -0
- package/standard/design/ai/prompts/ux-review.md +5 -0
- package/standard/design/ai/review-protocol.md +11 -0
- package/standard/design/anti-patterns/accessibility.md +7 -0
- package/standard/design/anti-patterns/ai-generated.md +6 -0
- package/standard/design/anti-patterns/dashboards.md +5 -0
- package/standard/design/anti-patterns/forms.md +5 -0
- package/standard/design/anti-patterns/responsive.md +5 -0
- package/standard/design/anti-patterns/ui.md +6 -0
- package/standard/design/anti-patterns/ux.md +5 -0
- package/standard/design/components/buttons.md +6 -0
- package/standard/design/components/dialogs.md +5 -0
- package/standard/design/components/feedback.md +3 -0
- package/standard/design/components/forms.md +3 -0
- package/standard/design/components/navigation.md +3 -0
- package/standard/design/components/tables.md +6 -0
- package/standard/design/content/error-messages.md +4 -0
- package/standard/design/content/ux-writing.md +5 -0
- package/standard/design/data-display/README.md +5 -0
- package/standard/design/data-display/currency.md +3 -0
- package/standard/design/data-display/dates.md +3 -0
- package/standard/design/data-display/density.md +3 -0
- package/standard/design/data-display/filtering.md +3 -0
- package/standard/design/data-display/localization.md +3 -0
- package/standard/design/data-display/numbers.md +3 -0
- package/standard/design/data-display/pagination.md +3 -0
- package/standard/design/data-display/percentages.md +3 -0
- package/standard/design/data-display/sorting.md +3 -0
- package/standard/design/data-display/tables.md +3 -0
- package/standard/design/data-display/time.md +3 -0
- package/standard/design/decisions/ADR-001-token-naming.md +13 -0
- package/standard/design/decisions/ADR-002-radius-scale.md +9 -0
- package/standard/design/decisions/ADR-003-color-system.md +9 -0
- package/standard/design/decisions/ADR-004-component-versioning.md +9 -0
- package/standard/design/decisions/README.md +3 -0
- package/standard/design/design-system/components.md +9 -0
- package/standard/design/design-system/naming.md +19 -0
- package/standard/design/design-system/tokens.md +7 -0
- package/standard/design/design-system/variants.md +5 -0
- package/standard/design/design-system/versioning.md +5 -0
- package/standard/design/health/coverage.md +1 -0
- package/standard/design/health/dashboard.md +14 -0
- package/standard/design/health/maturity-model.md +9 -0
- package/standard/design/health/score.md +14 -0
- package/standard/design/interaction/README.md +10 -0
- package/standard/design/interaction/keyboard.md +3 -0
- package/standard/design/interaction/mouse.md +2 -0
- package/standard/design/interaction/pen.md +1 -0
- package/standard/design/interaction/touch.md +3 -0
- package/standard/design/interaction/touchscreen.md +6 -0
- package/standard/design/interaction/voice.md +2 -0
- package/standard/design/localization/README.md +5 -0
- package/standard/design/localization/currency.md +3 -0
- package/standard/design/localization/date-time.md +3 -0
- package/standard/design/localization/i18n.md +3 -0
- package/standard/design/localization/locale-testing.md +3 -0
- package/standard/design/localization/number-formatting.md +3 -0
- package/standard/design/localization/pluralization.md +3 -0
- package/standard/design/localization/rtl.md +3 -0
- package/standard/design/localization/text-expansion.md +3 -0
- package/standard/design/motion/animation.md +6 -0
- package/standard/design/penpot/WORKFLOW.md +27 -0
- package/standard/design/platforms/README.md +12 -0
- package/standard/design/platforms/desktop/README.md +5 -0
- package/standard/design/platforms/mobile/android.md +5 -0
- package/standard/design/platforms/mobile/ios.md +5 -0
- package/standard/design/platforms/tablet/README.md +5 -0
- package/standard/design/platforms/web/README.md +1 -0
- package/standard/design/principles/design-principles.md +9 -0
- package/standard/design/principles/ui-principles.md +7 -0
- package/standard/design/principles/ux-principles.md +14 -0
- package/standard/design/references/atlassian.md +3 -0
- package/standard/design/references/carbon.md +3 -0
- package/standard/design/references/figma-sds.md +5 -0
- package/standard/design/references/govuk.md +3 -0
- package/standard/design/references/material.md +3 -0
- package/standard/design/references/nng.md +3 -0
- package/standard/design/references/openui.md +3 -0
- package/standard/design/references/primer.md +5 -0
- package/standard/design/references/storybook.md +3 -0
- package/standard/design/references/uswds.md +3 -0
- package/standard/design/references/w3c.md +3 -0
- package/standard/design/responsive/desktop.md +4 -0
- package/standard/design/responsive/mobile.md +6 -0
- package/standard/design/responsive/tablet.md +3 -0
- package/standard/design/states/async.md +3 -0
- package/standard/design/states/conflict.md +3 -0
- package/standard/design/states/empty.md +3 -0
- package/standard/design/states/error.md +3 -0
- package/standard/design/states/interaction.md +5 -0
- package/standard/design/states/loading.md +3 -0
- package/standard/design/states/offline.md +3 -0
- package/standard/design/states/optimistic.md +3 -0
- package/standard/design/states/partial.md +3 -0
- package/standard/design/states/permission-denied.md +3 -0
- package/standard/design/states/rate-limited.md +3 -0
- package/standard/design/states/read-only.md +3 -0
- package/standard/design/states/retry.md +3 -0
- package/standard/design/states/skeleton.md +3 -0
- package/standard/design/states/stale.md +3 -0
- package/standard/design/states/success.md +3 -0
- package/standard/design/states/timeout.md +3 -0
- package/standard/design/states/unsaved-changes.md +3 -0
- package/standard/design/ui/color.md +6 -0
- package/standard/design/ui/grids.md +5 -0
- package/standard/design/ui/icons.md +5 -0
- package/standard/design/ui/imagery.md +5 -0
- package/standard/design/ui/layout.md +5 -0
- package/standard/design/ui/spacing.md +5 -0
- package/standard/design/ui/typography.md +6 -0
- package/standard/design/ui/visual-design.md +7 -0
- package/standard/design/ux/cognitive-load.md +5 -0
- package/standard/design/ux/errors.md +6 -0
- package/standard/design/ux/feedback.md +5 -0
- package/standard/design/ux/forms.md +7 -0
- package/standard/design/ux/heuristics.md +14 -0
- package/standard/design/ux/information-architecture.md +6 -0
- package/standard/design/ux/navigation.md +6 -0
- package/standard/design/ux/usability.md +6 -0
- package/standard/engineering/README.md +29 -0
- package/standard/engineering/REFERENCES.md +42 -0
- package/standard/engineering/ai/AI_SECURITY.md +15 -0
- package/standard/engineering/ai/PROMPT_SECURITY.md +6 -0
- package/standard/engineering/architecture/ADR.md +11 -0
- package/standard/engineering/architecture/ARCHITECTURE.md +25 -0
- package/standard/engineering/architecture/PRINCIPLES.md +17 -0
- package/standard/engineering/architecture/THREAT_MODEL.md +14 -0
- package/standard/engineering/backend/API.md +29 -0
- package/standard/engineering/backend/BACKGROUND_JOBS.md +12 -0
- package/standard/engineering/backend/ERROR_HANDLING.md +26 -0
- package/standard/engineering/backend/LOGGING.md +12 -0
- package/standard/engineering/compliance/DATA_RETENTION.md +10 -0
- package/standard/engineering/compliance/PRIVACY.md +11 -0
- package/standard/engineering/database/BACKUPS.md +19 -0
- package/standard/engineering/database/DATABASE.md +30 -0
- package/standard/engineering/database/MIGRATIONS.md +12 -0
- package/standard/engineering/devops/BRANCH_PROTECTION.md +17 -0
- package/standard/engineering/devops/CI_CD.md +48 -0
- package/standard/engineering/devops/DEPLOYMENT.md +12 -0
- package/standard/engineering/devops/DOCKER.md +9 -0
- package/standard/engineering/devops/ENVIRONMENTS.md +12 -0
- package/standard/engineering/devops/RELEASE.md +6 -0
- package/standard/engineering/devops/ROLLBACK.md +9 -0
- package/standard/engineering/frontend/ACCESSIBILITY.md +16 -0
- package/standard/engineering/frontend/DESIGN_SYSTEM.md +10 -0
- package/standard/engineering/frontend/FRONTEND.md +17 -0
- package/standard/engineering/frontend/UX.md +15 -0
- package/standard/engineering/observability/ALERTING.md +11 -0
- package/standard/engineering/observability/INCIDENTS.md +10 -0
- package/standard/engineering/observability/MONITORING.md +17 -0
- package/standard/engineering/payments/PAYMENTS.md +15 -0
- package/standard/engineering/performance/PERFORMANCE.md +19 -0
- package/standard/engineering/security/API_SECURITY.md +22 -0
- package/standard/engineering/security/ASVS_5.0/V10_MALICIOUS_CODE.md +31 -0
- package/standard/engineering/security/ASVS_5.0/V11_BUSINESS_LOGIC.md +31 -0
- package/standard/engineering/security/ASVS_5.0/V12_FILES.md +31 -0
- package/standard/engineering/security/ASVS_5.0/V13_API.md +31 -0
- package/standard/engineering/security/ASVS_5.0/V14_CONFIGURATION.md +31 -0
- package/standard/engineering/security/ASVS_5.0/V1_ARCHITECTURE.md +31 -0
- package/standard/engineering/security/ASVS_5.0/V2_AUTHENTICATION.md +31 -0
- package/standard/engineering/security/ASVS_5.0/V3_SESSION.md +31 -0
- package/standard/engineering/security/ASVS_5.0/V4_ACCESS_CONTROL.md +31 -0
- package/standard/engineering/security/ASVS_5.0/V5_VALIDATION.md +31 -0
- package/standard/engineering/security/ASVS_5.0/V6_CRYPTOGRAPHY.md +31 -0
- package/standard/engineering/security/ASVS_5.0/V7_ERROR_HANDLING.md +31 -0
- package/standard/engineering/security/ASVS_5.0/V8_DATA_PROTECTION.md +31 -0
- package/standard/engineering/security/ASVS_5.0/V9_COMMUNICATION.md +31 -0
- package/standard/engineering/security/ASVS_REGISTRY.md +31 -0
- package/standard/engineering/security/AUTHENTICATION.md +28 -0
- package/standard/engineering/security/AUTHORIZATION.md +27 -0
- package/standard/engineering/security/DATA_SECURITY.md +14 -0
- package/standard/engineering/security/OWASP_ASVS.md +31 -0
- package/standard/engineering/security/SECRETS.md +28 -0
- package/standard/engineering/security/SECURITY.md +28 -0
- package/standard/engineering/testing/TESTING.md +27 -0
- package/templates/agents/AGENTS.md +34 -0
- package/templates/agents/CLAUDE.md +33 -0
- package/templates/agents/copilot-instructions.md +15 -0
- package/templates/agents/cursor.mdc +27 -0
- package/templates/agents/windsurfrules.md +17 -0
- package/templates/docs/ADR.md +16 -0
- package/templates/docs/FEATURE.md +19 -0
- package/templates/docs/SECURITY_REPORT.md +15 -0
- package/templates/docs/accessibility-review.md +9 -0
- package/templates/docs/component.md +9 -0
- package/templates/docs/decision-record.md +9 -0
- package/templates/docs/design-review.md +9 -0
- package/templates/docs/exception.md +9 -0
- package/templates/docs/page.md +9 -0
- package/templates/docs/pattern.md +9 -0
- package/templates/docs/user-flow.md +9 -0
- package/templates/github/workflows/app-ci.yml +91 -0
- package/templates/project/00_OVERVIEW.md +51 -0
- package/templates/project/01_ARCHITECTURE.md +37 -0
- package/templates/project/02_SURFACES.md +30 -0
- package/templates/project/03_DATA_MODEL.md +31 -0
- package/templates/project/04_PERMISSIONS.md +32 -0
- package/templates/project/05_FLOWS.md +20 -0
- package/templates/project/06_INTEGRATIONS.md +21 -0
- package/templates/project/07_DESIGN.md +33 -0
- package/templates/project/10_NEVER_ALWAYS.md +26 -0
- package/templates/project/11_GAPS.md +18 -0
- package/templates/project/12_DEBT.md +19 -0
- package/templates/project/13_RECIPES.md +35 -0
- package/templates/project/14_INDEX.md +50 -0
- package/templates/project/AGENTS.md +51 -0
- package/templates/project/README.md +49 -0
- package/templates/project/impact-map.yaml +41 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"title": "ComponentSpec",
|
|
4
|
+
"type": "object",
|
|
5
|
+
"required": [
|
|
6
|
+
"id",
|
|
7
|
+
"name",
|
|
8
|
+
"states"
|
|
9
|
+
],
|
|
10
|
+
"properties": {
|
|
11
|
+
"id": {
|
|
12
|
+
"type": "string"
|
|
13
|
+
},
|
|
14
|
+
"name": {
|
|
15
|
+
"type": "string"
|
|
16
|
+
},
|
|
17
|
+
"states": {
|
|
18
|
+
"type": "array",
|
|
19
|
+
"items": {
|
|
20
|
+
"type": "string"
|
|
21
|
+
},
|
|
22
|
+
"minItems": 1
|
|
23
|
+
},
|
|
24
|
+
"tokens": {
|
|
25
|
+
"type": "array",
|
|
26
|
+
"items": {
|
|
27
|
+
"type": "string"
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
"a11y": {
|
|
31
|
+
"type": "array",
|
|
32
|
+
"items": {
|
|
33
|
+
"type": "string"
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://github.com/schneiderjoseph/devia/schema/project-config.schema.json",
|
|
4
|
+
"title": "DeviaProjectConfig",
|
|
5
|
+
"description": "Shape of .devia/devia.json, written by `devia init` and read by validate, check, doctor and sync.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": ["standardVersion", "project", "maturity"],
|
|
8
|
+
"properties": {
|
|
9
|
+
"deviaVersion": {
|
|
10
|
+
"type": "string",
|
|
11
|
+
"description": "Version of the devia package that last wrote this file."
|
|
12
|
+
},
|
|
13
|
+
"standardVersion": {
|
|
14
|
+
"type": "string",
|
|
15
|
+
"description": "Version of the standard pinned in .devia/standard/. `devia sync` updates it."
|
|
16
|
+
},
|
|
17
|
+
"project": {
|
|
18
|
+
"type": "object",
|
|
19
|
+
"required": ["name"],
|
|
20
|
+
"properties": {
|
|
21
|
+
"name": { "type": "string", "minLength": 1 },
|
|
22
|
+
"profile": {
|
|
23
|
+
"enum": ["web-app", "service", "library", "cli", "design-system", "docs"]
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"maturity": {
|
|
28
|
+
"type": "object",
|
|
29
|
+
"description": "Declared tier. Agents must never claim a tier the checks do not support.",
|
|
30
|
+
"properties": {
|
|
31
|
+
"target": { "enum": ["bronze", "silver", "gold", "platinum"] },
|
|
32
|
+
"current": { "enum": ["bronze", "silver", "gold", "platinum"] }
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
"code": {
|
|
36
|
+
"type": "object",
|
|
37
|
+
"description": "Paths that hold the code the memory describes; `devia doctor` compares their history with .devia/.",
|
|
38
|
+
"properties": {
|
|
39
|
+
"paths": { "type": "array", "items": { "type": "string" } }
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
"modules": {
|
|
43
|
+
"type": "object",
|
|
44
|
+
"description": "Which parts of the standard apply to this project.",
|
|
45
|
+
"properties": {
|
|
46
|
+
"engineering": { "type": "boolean" },
|
|
47
|
+
"design": { "type": "boolean" },
|
|
48
|
+
"memory": { "type": "boolean" }
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
"waivers": {
|
|
52
|
+
"type": "array",
|
|
53
|
+
"description": "Time-boxed exceptions. An expired or undated waiver fails `devia check`.",
|
|
54
|
+
"items": {
|
|
55
|
+
"type": "object",
|
|
56
|
+
"required": ["rule_id", "reason", "owner", "expires"],
|
|
57
|
+
"properties": {
|
|
58
|
+
"rule_id": { "type": "string", "pattern": "^[A-Z][A-Z0-9]*(-[A-Z0-9]+)+$" },
|
|
59
|
+
"scope": { "type": "string" },
|
|
60
|
+
"reason": { "type": "string", "minLength": 10 },
|
|
61
|
+
"owner": { "type": "string" },
|
|
62
|
+
"expires": { "type": "string", "format": "date" },
|
|
63
|
+
"risk": { "enum": ["low", "medium", "high"] }
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
"initializedAt": { "type": "string", "format": "date" }
|
|
68
|
+
},
|
|
69
|
+
"additionalProperties": true
|
|
70
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://github.com/schneiderjoseph/devia/schema/rule.schema.json",
|
|
4
|
+
"title": "DeviaRule",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"required": [
|
|
7
|
+
"id",
|
|
8
|
+
"title",
|
|
9
|
+
"severity",
|
|
10
|
+
"status",
|
|
11
|
+
"domain",
|
|
12
|
+
"priority",
|
|
13
|
+
"source",
|
|
14
|
+
"requirement",
|
|
15
|
+
"validation"
|
|
16
|
+
],
|
|
17
|
+
"properties": {
|
|
18
|
+
"id": {
|
|
19
|
+
"type": "string",
|
|
20
|
+
"pattern": "^[A-Z][A-Z0-9]*(-[A-Z0-9]+)+$"
|
|
21
|
+
},
|
|
22
|
+
"title": {
|
|
23
|
+
"type": "string",
|
|
24
|
+
"minLength": 3
|
|
25
|
+
},
|
|
26
|
+
"severity": {
|
|
27
|
+
"enum": [
|
|
28
|
+
"MUST",
|
|
29
|
+
"SHOULD",
|
|
30
|
+
"MAY",
|
|
31
|
+
"MUST NOT"
|
|
32
|
+
],
|
|
33
|
+
"description": "The obligation itself."
|
|
34
|
+
},
|
|
35
|
+
"status": {
|
|
36
|
+
"enum": [
|
|
37
|
+
"draft",
|
|
38
|
+
"proposed",
|
|
39
|
+
"active",
|
|
40
|
+
"deprecated",
|
|
41
|
+
"superseded",
|
|
42
|
+
"removed"
|
|
43
|
+
]
|
|
44
|
+
},
|
|
45
|
+
"domain": {
|
|
46
|
+
"type": "string"
|
|
47
|
+
},
|
|
48
|
+
"source": {
|
|
49
|
+
"type": "array",
|
|
50
|
+
"items": {
|
|
51
|
+
"type": "string"
|
|
52
|
+
},
|
|
53
|
+
"minItems": 1
|
|
54
|
+
},
|
|
55
|
+
"applies_to": {
|
|
56
|
+
"type": "array",
|
|
57
|
+
"items": {
|
|
58
|
+
"type": "string"
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
"success_criteria": {
|
|
62
|
+
"type": "array",
|
|
63
|
+
"items": {
|
|
64
|
+
"type": "string"
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
"requirement": {
|
|
68
|
+
"type": "string",
|
|
69
|
+
"minLength": 10
|
|
70
|
+
},
|
|
71
|
+
"validation": {
|
|
72
|
+
"type": "object",
|
|
73
|
+
"required": [
|
|
74
|
+
"automated",
|
|
75
|
+
"manual"
|
|
76
|
+
],
|
|
77
|
+
"properties": {
|
|
78
|
+
"automated": {
|
|
79
|
+
"type": "boolean"
|
|
80
|
+
},
|
|
81
|
+
"manual": {
|
|
82
|
+
"type": "boolean"
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
"exceptions": {
|
|
87
|
+
"type": "string"
|
|
88
|
+
},
|
|
89
|
+
"priority": {
|
|
90
|
+
"enum": [
|
|
91
|
+
"P0",
|
|
92
|
+
"P1",
|
|
93
|
+
"P2",
|
|
94
|
+
"P3"
|
|
95
|
+
],
|
|
96
|
+
"description": "When the obligation blocks: P0 blocker, P1 required, P2 recommended, P3 optional."
|
|
97
|
+
},
|
|
98
|
+
"superseded_by": {
|
|
99
|
+
"type": "string",
|
|
100
|
+
"pattern": "^[A-Z][A-Z0-9]*(-[A-Z0-9]+)+$"
|
|
101
|
+
}
|
|
102
|
+
},
|
|
103
|
+
"additionalProperties": true
|
|
104
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"title": "DesignTokenFile",
|
|
4
|
+
"type": "object",
|
|
5
|
+
"description": "Minimal wrapper; prefer W3C DTCG token files in consuming repos.",
|
|
6
|
+
"properties": {
|
|
7
|
+
"$schema": {
|
|
8
|
+
"type": "string"
|
|
9
|
+
},
|
|
10
|
+
"tokens": {
|
|
11
|
+
"type": "object"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"additionalProperties": true
|
|
15
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"title": "RuleWaiver",
|
|
4
|
+
"type": "object",
|
|
5
|
+
"required": [
|
|
6
|
+
"rule_id",
|
|
7
|
+
"reason",
|
|
8
|
+
"owner",
|
|
9
|
+
"expires"
|
|
10
|
+
],
|
|
11
|
+
"properties": {
|
|
12
|
+
"rule_id": {
|
|
13
|
+
"type": "string"
|
|
14
|
+
},
|
|
15
|
+
"reason": {
|
|
16
|
+
"type": "string"
|
|
17
|
+
},
|
|
18
|
+
"owner": {
|
|
19
|
+
"type": "string"
|
|
20
|
+
},
|
|
21
|
+
"expires": {
|
|
22
|
+
"type": "string",
|
|
23
|
+
"format": "date"
|
|
24
|
+
},
|
|
25
|
+
"risk": {
|
|
26
|
+
"enum": [
|
|
27
|
+
"low",
|
|
28
|
+
"medium",
|
|
29
|
+
"high"
|
|
30
|
+
]
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Regenerate the files derived from the rule registry:
|
|
4
|
+
* rules/README.md — the index
|
|
5
|
+
* compliance/COVERAGE.md — counts
|
|
6
|
+
* compliance/TRACEABILITY.md — rule → source → validation matrix
|
|
7
|
+
*
|
|
8
|
+
* Run `npm run build:index` after adding or changing a rule. CI checks the result is current.
|
|
9
|
+
*/
|
|
10
|
+
import path from "node:path";
|
|
11
|
+
import process from "node:process";
|
|
12
|
+
import { loadRules, ruleStats } from "../src/lib/rules.mjs";
|
|
13
|
+
import { packageRoot, writeFile, read } from "../src/lib/fs.mjs";
|
|
14
|
+
|
|
15
|
+
const check = process.argv.includes("--check");
|
|
16
|
+
const rulesDir = path.join(packageRoot, "rules");
|
|
17
|
+
const { rules, errors } = loadRules(rulesDir);
|
|
18
|
+
|
|
19
|
+
if (errors.length) {
|
|
20
|
+
console.error("cannot build the index while rules are invalid:");
|
|
21
|
+
for (const e of errors) console.error(" -", e);
|
|
22
|
+
process.exit(1);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const GROUPS = [
|
|
26
|
+
["Agent discipline", ["agent", "memory"]],
|
|
27
|
+
["Engineering", ["architecture", "api", "database", "security", "testing", "devops", "observability", "privacy", "ai"]],
|
|
28
|
+
["Design", ["accessibility", "components", "content", "data-display", "design-system", "interaction", "localization", "motion", "responsive", "states", "ui", "ux"]],
|
|
29
|
+
];
|
|
30
|
+
|
|
31
|
+
function row(r) {
|
|
32
|
+
const auto = r.validation?.automated ? "yes" : "no";
|
|
33
|
+
return `| [${r.id}](${r.file}) | ${r.title} | ${r.severity} | ${r.priority} | ${r.domain} | ${auto} | ${r.status} |`;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function index() {
|
|
37
|
+
const stats = ruleStats(rules);
|
|
38
|
+
const out = [];
|
|
39
|
+
out.push("# Rules registry");
|
|
40
|
+
out.push("");
|
|
41
|
+
out.push("Machine-readable rules with stable IDs. Narrative guidance lives under");
|
|
42
|
+
out.push("[`standard/`](../standard/README.md); these files are what agents and reviews cite.");
|
|
43
|
+
out.push("");
|
|
44
|
+
out.push("Severity is the obligation (`MUST` · `MUST NOT` · `SHOULD` · `MAY`).");
|
|
45
|
+
out.push("Priority is when it blocks (`P0` · `P1` · `P2` · `P3` — see [`MATURITY.md`](../MATURITY.md)).");
|
|
46
|
+
out.push("");
|
|
47
|
+
out.push("> Generated by `npm run build:index`. Edit the rule files, not this page.");
|
|
48
|
+
const seen = new Set();
|
|
49
|
+
for (const [label, domains] of GROUPS) {
|
|
50
|
+
const group = rules.filter((r) => domains.includes(r.domain));
|
|
51
|
+
if (!group.length) continue;
|
|
52
|
+
out.push("");
|
|
53
|
+
out.push(`## ${label}`);
|
|
54
|
+
out.push("");
|
|
55
|
+
out.push("| ID | Title | Severity | Priority | Domain | Auto | Status |");
|
|
56
|
+
out.push("|---|---|---|---|---|---|---|");
|
|
57
|
+
for (const r of group) {
|
|
58
|
+
out.push(row(r));
|
|
59
|
+
seen.add(r.id);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
const rest = rules.filter((r) => !seen.has(r.id));
|
|
63
|
+
if (rest.length) {
|
|
64
|
+
out.push("");
|
|
65
|
+
out.push("## Other");
|
|
66
|
+
out.push("");
|
|
67
|
+
out.push("| ID | Title | Severity | Priority | Domain | Auto | Status |");
|
|
68
|
+
out.push("|---|---|---|---|---|---|---|");
|
|
69
|
+
for (const r of rest) out.push(row(r));
|
|
70
|
+
}
|
|
71
|
+
out.push("");
|
|
72
|
+
out.push(
|
|
73
|
+
`**Total:** ${stats.total} rules · ${stats.active} active · ${stats.automatable} automatable · schema v1`
|
|
74
|
+
);
|
|
75
|
+
out.push("");
|
|
76
|
+
out.push("Lifecycle and supersession: [`LIFECYCLE.md`](LIFECYCLE.md).");
|
|
77
|
+
out.push("");
|
|
78
|
+
return out.join("\n");
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function coverage() {
|
|
82
|
+
const s = ruleStats(rules);
|
|
83
|
+
const out = [];
|
|
84
|
+
out.push("# Coverage");
|
|
85
|
+
out.push("");
|
|
86
|
+
out.push("> Generated by `npm run build:index`.");
|
|
87
|
+
out.push("");
|
|
88
|
+
out.push("| Metric | Value |");
|
|
89
|
+
out.push("|---|---|");
|
|
90
|
+
out.push(`| Rules total | ${s.total} |`);
|
|
91
|
+
out.push(`| Active | ${s.active} |`);
|
|
92
|
+
for (const sev of ["MUST", "MUST NOT", "SHOULD", "MAY"]) {
|
|
93
|
+
if (s.severity[sev]) out.push(`| ${sev} | ${s.severity[sev]} |`);
|
|
94
|
+
}
|
|
95
|
+
for (const p of ["P0", "P1", "P2", "P3"]) {
|
|
96
|
+
if (s.priority[p]) out.push(`| ${p} | ${s.priority[p]} |`);
|
|
97
|
+
}
|
|
98
|
+
out.push(`| Automatable | ${s.automatable} |`);
|
|
99
|
+
out.push(`| Domains | ${Object.keys(s.domain).length} |`);
|
|
100
|
+
out.push("");
|
|
101
|
+
out.push("## By domain");
|
|
102
|
+
out.push("");
|
|
103
|
+
out.push("| Domain | Rules | P0 |");
|
|
104
|
+
out.push("|---|---|---|");
|
|
105
|
+
for (const d of Object.keys(s.domain).sort()) {
|
|
106
|
+
const p0 = rules.filter((r) => r.domain === d && r.priority === "P0").length;
|
|
107
|
+
out.push(`| ${d} | ${s.domain[d]} | ${p0} |`);
|
|
108
|
+
}
|
|
109
|
+
out.push("");
|
|
110
|
+
out.push(
|
|
111
|
+
"A domain with rules and no automatable check is not a failure — it is a backlog item for [`LEVELS.md`](../LEVELS.md) level 2."
|
|
112
|
+
);
|
|
113
|
+
out.push("");
|
|
114
|
+
return out.join("\n");
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function traceability() {
|
|
118
|
+
const out = [];
|
|
119
|
+
out.push("# Traceability");
|
|
120
|
+
out.push("");
|
|
121
|
+
out.push("Every rule maps down to something a human or a machine can check.");
|
|
122
|
+
out.push("");
|
|
123
|
+
out.push("```text");
|
|
124
|
+
out.push("Rule ID");
|
|
125
|
+
out.push(" ↓");
|
|
126
|
+
out.push("Authoritative source (REFERENCES.md)");
|
|
127
|
+
out.push(" ↓");
|
|
128
|
+
out.push("Success criterion (when the source has one)");
|
|
129
|
+
out.push(" ↓");
|
|
130
|
+
out.push("Guidance in standard/");
|
|
131
|
+
out.push(" ↓");
|
|
132
|
+
out.push("Checklist item");
|
|
133
|
+
out.push(" ↓");
|
|
134
|
+
out.push("Automated check or recorded manual review");
|
|
135
|
+
out.push("```");
|
|
136
|
+
out.push("");
|
|
137
|
+
out.push("> Generated by `npm run build:index`.");
|
|
138
|
+
out.push("");
|
|
139
|
+
out.push("| Rule | Domain | Severity | Priority | Source | Criteria | Validation |");
|
|
140
|
+
out.push("|---|---|---|---|---|---|---|");
|
|
141
|
+
for (const r of rules) {
|
|
142
|
+
const v = [];
|
|
143
|
+
if (r.validation?.automated) v.push("automated");
|
|
144
|
+
if (r.validation?.manual) v.push("manual");
|
|
145
|
+
const sc = Array.isArray(r.success_criteria) && r.success_criteria.length
|
|
146
|
+
? r.success_criteria.join(", ")
|
|
147
|
+
: "—";
|
|
148
|
+
out.push(
|
|
149
|
+
`| [${r.id}](../rules/${r.file}) | ${r.domain} | ${r.severity} | ${r.priority} | ${(r.source || []).join(", ")} | ${sc} | ${v.join(" + ") || "—"} |`
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
out.push("");
|
|
153
|
+
return out.join("\n");
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
const targets = [
|
|
157
|
+
[path.join(packageRoot, "rules", "README.md"), index()],
|
|
158
|
+
[path.join(packageRoot, "compliance", "COVERAGE.md"), coverage()],
|
|
159
|
+
[path.join(packageRoot, "compliance", "TRACEABILITY.md"), traceability()],
|
|
160
|
+
];
|
|
161
|
+
|
|
162
|
+
let stale = 0;
|
|
163
|
+
for (const [file, content] of targets) {
|
|
164
|
+
const rel = path.relative(packageRoot, file).split(path.sep).join("/");
|
|
165
|
+
if (check) {
|
|
166
|
+
const current = (read(file) ?? "").replace(/\r\n/g, "\n");
|
|
167
|
+
if (current !== content) {
|
|
168
|
+
console.error(`stale: ${rel} — run \`npm run build:index\``);
|
|
169
|
+
stale++;
|
|
170
|
+
}
|
|
171
|
+
} else {
|
|
172
|
+
writeFile(file, content);
|
|
173
|
+
console.log(`wrote ${rel}`);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
if (check && stale) process.exit(1);
|
|
178
|
+
if (check) console.log(`generated files are current (${rules.length} rules)`);
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/** Every relative markdown link in this repository must resolve to a file that exists. */
|
|
3
|
+
import fs from "node:fs";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import process from "node:process";
|
|
6
|
+
import { packageRoot, walk } from "../src/lib/fs.mjs";
|
|
7
|
+
|
|
8
|
+
const linkRe = /\[[^\]]*\]\(([^)\s]+)(?:\s+"[^"]*")?\)/g;
|
|
9
|
+
|
|
10
|
+
// `templates/` is written into a project, where its links resolve against `.devia/`.
|
|
11
|
+
// Those are checked against a materialised project in tests/cli.test.mjs instead.
|
|
12
|
+
const skipDirs = new Set([".git", "node_modules", ".devia", "templates"]);
|
|
13
|
+
|
|
14
|
+
const files = walk(packageRoot, {
|
|
15
|
+
filter: (rel) => rel.endsWith(".md"),
|
|
16
|
+
skip: (rel) => skipDirs.has(rel.split(path.sep)[0]),
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
let broken = 0;
|
|
20
|
+
let checked = 0;
|
|
21
|
+
|
|
22
|
+
for (const rel of files) {
|
|
23
|
+
const file = path.join(packageRoot, rel);
|
|
24
|
+
const text = fs.readFileSync(file, "utf8");
|
|
25
|
+
let m;
|
|
26
|
+
while ((m = linkRe.exec(text))) {
|
|
27
|
+
const target = m[1].split("#")[0].split("?")[0];
|
|
28
|
+
if (!target) continue;
|
|
29
|
+
if (/^(https?:|mailto:|tel:)/.test(target)) continue;
|
|
30
|
+
checked++;
|
|
31
|
+
const resolved = path.resolve(path.dirname(file), target);
|
|
32
|
+
if (!fs.existsSync(resolved)) {
|
|
33
|
+
console.error(`broken link ${rel.split(path.sep).join("/")} -> ${target}`);
|
|
34
|
+
broken++;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (broken) {
|
|
40
|
+
console.error(`validate-links FAILED: ${broken} broken of ${checked}`);
|
|
41
|
+
process.exit(1);
|
|
42
|
+
}
|
|
43
|
+
console.log(`validate-links OK: ${checked} links in ${files.length} files`);
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Validate the rule registry against `schema/rule.schema.json` and the invariants the schema
|
|
4
|
+
* cannot express: unique ids, filename equals id, directory equals domain, superseded rules
|
|
5
|
+
* pointing at a rule that exists.
|
|
6
|
+
*/
|
|
7
|
+
import path from "node:path";
|
|
8
|
+
import process from "node:process";
|
|
9
|
+
import { loadRules, ruleStats } from "../src/lib/rules.mjs";
|
|
10
|
+
import { packageRoot, readJSON } from "../src/lib/fs.mjs";
|
|
11
|
+
|
|
12
|
+
const schema = readJSON(path.join(packageRoot, "schema", "rule.schema.json"));
|
|
13
|
+
if (!schema) {
|
|
14
|
+
console.error("schema/rule.schema.json is missing or invalid JSON");
|
|
15
|
+
process.exit(1);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const { rules, errors } = loadRules(path.join(packageRoot, "rules"));
|
|
19
|
+
const ids = new Set(rules.map((r) => r.id));
|
|
20
|
+
|
|
21
|
+
for (const r of rules) {
|
|
22
|
+
for (const key of schema.required || []) {
|
|
23
|
+
if (r[key] === undefined || r[key] === null) errors.push(`${r.file}: missing ${key}`);
|
|
24
|
+
}
|
|
25
|
+
if (r.status === "superseded" && !ids.has(r.superseded_by)) {
|
|
26
|
+
errors.push(`${r.file}: superseded rules must name an existing superseded_by`);
|
|
27
|
+
}
|
|
28
|
+
if (r.validation && !r.validation.automated && !r.validation.manual) {
|
|
29
|
+
errors.push(`${r.file}: a rule with no validation at all cannot be enforced`);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (errors.length) {
|
|
34
|
+
console.error("validate-rules FAILED:");
|
|
35
|
+
for (const e of errors) console.error(" -", e);
|
|
36
|
+
process.exit(1);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const s = ruleStats(rules);
|
|
40
|
+
console.log(
|
|
41
|
+
`validate-rules OK: ${s.total} rules · ${s.priority.P0 || 0} P0 · ${s.automatable} automatable · ${Object.keys(s.domain).length} domains`
|
|
42
|
+
);
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: devia
|
|
3
|
+
description: >-
|
|
4
|
+
Project memory and engineering standard. Use at the START of any work on a repository:
|
|
5
|
+
initialise or read .devia/, follow the rules it pins, and update it in the same change.
|
|
6
|
+
Triggers on starting work in an unfamiliar repo, "init devia", memory or standard questions,
|
|
7
|
+
and before claiming anything is done or production ready.
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# devia
|
|
11
|
+
|
|
12
|
+
A repository worth working on has a memory. `.devia/` is that memory, and this skill is how you
|
|
13
|
+
use it.
|
|
14
|
+
|
|
15
|
+
## Step 1 — is there a memory?
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
ls .devia
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
**No `.devia/`** → initialise before writing any code:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npx devia init
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Then fill `.devia/00_OVERVIEW.md` from what the repository actually contains — stack, modules,
|
|
28
|
+
where the truth lives. Read the code to fill it; do not invent it. This is not paperwork: it is
|
|
29
|
+
the difference between a task and a guess (`AGT-002`).
|
|
30
|
+
|
|
31
|
+
**`.devia/` exists** → read, in this order:
|
|
32
|
+
|
|
33
|
+
1. `.devia/AGENTS.md` — the contract for this repository
|
|
34
|
+
2. `.devia/10_NEVER_ALWAYS.md` — what this project has already banned
|
|
35
|
+
3. `.devia/00_OVERVIEW.md` — what this project is
|
|
36
|
+
4. The memory file for the surface you are about to touch (`.devia/14_INDEX.md`)
|
|
37
|
+
|
|
38
|
+
## Step 2 — work under the rules
|
|
39
|
+
|
|
40
|
+
The rules are pinned in `.devia/standard/rules/` with stable IDs. The ones that stop most bad
|
|
41
|
+
changes:
|
|
42
|
+
|
|
43
|
+
| If you are about to… | Rule |
|
|
44
|
+
|---|---|
|
|
45
|
+
| Guess an endpoint, field, config key or business rule | `AGT-004` — do not. Ask, or record a gap |
|
|
46
|
+
| Encode an undecided policy | `MEM-001` — declare it and open a gap |
|
|
47
|
+
| Notice something broken you are not fixing | `MEM-002` — open a debt line |
|
|
48
|
+
| Refactor beyond the request | `AGT-003` — do not |
|
|
49
|
+
| Skip a hook or disable a test | `OPS-003`, `TST-003` — do not |
|
|
50
|
+
| Read user data on the server | `SEC-001`, `SEC-005` — authorize, scope, test it |
|
|
51
|
+
| Accept input from anywhere | `SEC-003` — validate at the boundary |
|
|
52
|
+
| Change the schema | `DB-001`, `DB-002` — versioned migration, never edit an applied one |
|
|
53
|
+
| Ship a screen | `A11Y-001`, `A11Y-004`, `A11Y-006`, `UX-007`, `UI-004`, `STATE-002` |
|
|
54
|
+
| Say "done" | `AGT-005`, `AGT-006` — name the checks, name what is unverified |
|
|
55
|
+
|
|
56
|
+
Look one up:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
npx devia rules --id SEC-001
|
|
60
|
+
npx devia rules --domain database --priority P0
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Step 3 — update the memory in the same change
|
|
64
|
+
|
|
65
|
+
`.devia/impact-map.yaml` maps what you changed to the memory files that must change with it
|
|
66
|
+
(`MEM-009`). New endpoint → `02_SURFACES.md`. New table → `03_DATA_MODEL.md`. Permission change
|
|
67
|
+
→ `04_PERMISSIONS.md`.
|
|
68
|
+
|
|
69
|
+
Registries:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
npx devia gap add "Should invoices round per line or per total?"
|
|
73
|
+
npx devia debt add "Refund endpoint has no idempotency key (API-004)"
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Never delete a gap or debt line you did not discharge (`MEM-011`).
|
|
77
|
+
|
|
78
|
+
## Step 4 — verify, then report
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
npx devia validate # memory integrity: structure, registries, placeholders
|
|
82
|
+
npx devia check # readiness gates — P0 failures block
|
|
83
|
+
npx devia doctor # is the memory older than the code?
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Report with:
|
|
87
|
+
|
|
88
|
+
```text
|
|
89
|
+
## Devia compliance
|
|
90
|
+
- Memory read: ...
|
|
91
|
+
- Rules applied (IDs): ...
|
|
92
|
+
- P0 status: ...
|
|
93
|
+
- Checks run / NOT run: ...
|
|
94
|
+
- .devia updated: ...
|
|
95
|
+
- Registries: gaps / debt touched
|
|
96
|
+
- Not verified: ...
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
For a non-trivial change, "Not verified" is never empty.
|
|
100
|
+
|
|
101
|
+
## Installing the contract for other agents
|
|
102
|
+
|
|
103
|
+
`devia init` writes the adapters: `AGENTS.md` (universal), `CLAUDE.md`,
|
|
104
|
+
`.cursor/rules/devia.mdc`, `.github/copilot-instructions.md`, `.windsurfrules`. To refresh them
|
|
105
|
+
later:
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
npx devia skills install --agent all
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## What this skill is not
|
|
112
|
+
|
|
113
|
+
It is not a code generator, and it is not a substitute for reading the repository. It is the
|
|
114
|
+
discipline that makes reading the repository unnecessary a second time.
|