@ai.all/ds7 1.0.0 → 2.0.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/01-architecture/ATOMIC-DESIGN.md +48 -42
- package/01-architecture/COMPONENT-ANATOMY.md +14 -30
- package/01-architecture/MODIFIER-SYSTEM.md +24 -35
- package/02-design-system/BRANDBOOK-SANDBOX.md +34 -34
- package/02-design-system/NAMING-CONVENTIONS.md +21 -19
- package/02-design-system/TOKENS-SPEC.md +65 -51
- package/03-performance-web-vitals/ASSETS-PIPELINE.md +40 -49
- package/03-performance-web-vitals/CRITICAL-CSS.md +20 -27
- package/03-performance-web-vitals/FONTS-ZERO-CLS.md +30 -34
- package/03-performance-web-vitals/HYDRATION-STRATEGY.md +38 -21
- package/04-seo-ai-optimization/AEO-GEO-AI-SEARCH.md +28 -45
- package/04-seo-ai-optimization/GOOGLE-LOCAL-EEAT.md +20 -25
- package/04-seo-ai-optimization/STRUCTURED-DATA.md +42 -37
- package/05-internationalization/I18N-ARCHITECTURE.md +27 -25
- package/05-internationalization/LOCALE-TEMPLATE.json +23 -22
- package/06-business-conversion/B2C-B2B-MODELS.md +22 -21
- package/06-business-conversion/CONTEXTUAL-LEADS.md +17 -22
- package/06-business-conversion/EV-SOLAR-ECOSYSTEM.md +21 -21
- package/07-testing/TESTING-STRATEGY.md +45 -83
- package/08-token-optimization/TOKEN-STRATEGY.md +54 -103
- package/ALL.md +203 -52
- package/CHANGELOG.md +27 -0
- package/README.md +92 -97
- package/SPEC.md +81 -37
- package/bin/ds7.js +183 -100
- package/package.json +10 -11
- package/templates/component.vue +10 -16
- package/templates/nuxt.config.ts +19 -25
- package/templates/theme.css +17 -10
- package/ANDALUSIA.md +0 -89
- package/ff.md +0 -112
package/SPEC.md
CHANGED
|
@@ -1,58 +1,102 @@
|
|
|
1
|
-
# DS7 Technical Specification
|
|
1
|
+
# DS7 Technical Specification
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
- **i18n:** `@nuxtjs/i18n` (prefix-except-default strategy, single hub in `i18n/locales/`).
|
|
8
|
-
- **Typing:** Strict TypeScript (`typescript: { strict: true }`).
|
|
9
|
-
- **Testing:** Vitest (unit tests) + Playwright (end-to-end and visual regression).
|
|
3
|
+
> **How it fits with AI-ALL.** [AI-ALL](https://github.com/ai-all-ai/aiall) (`@ai.all/aiall`) creates the agent entrypoints and the routing file, and keeps them in sync. This document is delivered to agents as the `ds7` pack of AI-ALL. AI-ALL works without DS7; for web projects, install both.
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
Version 1.1.0. This document is the technical baseline. Rules for agents are in `ALL.md`; this file describes the stack, the layout and the quality gates.
|
|
10
7
|
|
|
11
8
|
---
|
|
12
9
|
|
|
13
|
-
##
|
|
10
|
+
## 1. Stack
|
|
11
|
+
|
|
12
|
+
- **Framework:** Nuxt 4, Vue 3.5+, Composition API with `<script setup lang="ts">`.
|
|
13
|
+
- **Styling:** Tailwind CSS v4 and CSS custom properties defined in `theme.css`.
|
|
14
|
+
- **Rendering:** static generation (`nuxt generate`), prerendered routes, `sitemap.xml`, `robots.txt`.
|
|
15
|
+
- **i18n:** `@nuxtjs/i18n`, prefix-except-default strategy, one locale hub in `i18n/locales/`.
|
|
16
|
+
- **Types:** strict TypeScript.
|
|
17
|
+
- **Tests:** Vitest for unit and composable tests; Playwright for flows and browser checks; axe for accessibility.
|
|
18
|
+
- **Quality tooling:** a single `qa` script runs the gates listed in section 5.
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## 2. Directory layout
|
|
14
23
|
|
|
15
24
|
```
|
|
16
25
|
project-root/
|
|
17
26
|
├── app/
|
|
18
|
-
│ ├── app.vue
|
|
27
|
+
│ ├── app.vue
|
|
19
28
|
│ ├── assets/css/
|
|
20
|
-
│ │ ├── main.css #
|
|
21
|
-
│ │ ├── theme.css #
|
|
22
|
-
│ │ ├── base.css #
|
|
23
|
-
│ │ └── components.css #
|
|
29
|
+
│ │ ├── main.css # entry point for styles
|
|
30
|
+
│ │ ├── theme.css # foundations: tokens
|
|
31
|
+
│ │ ├── base.css # reset and element defaults
|
|
32
|
+
│ │ └── components.css # base classes and modifiers
|
|
24
33
|
│ ├── components/
|
|
25
|
-
│ │ ├── ui/ #
|
|
26
|
-
│ │ ├── sections/ #
|
|
27
|
-
│ │ └── site/ #
|
|
28
|
-
│ ├── composables/ #
|
|
29
|
-
│ ├── data/ #
|
|
30
|
-
│ ├── domain/ #
|
|
31
|
-
│ └── pages/ #
|
|
34
|
+
│ │ ├── ui/ # atoms and molecules
|
|
35
|
+
│ │ ├── sections/ # sections and organisms
|
|
36
|
+
│ │ └── site/ # site shell: header, footer, modal host
|
|
37
|
+
│ ├── composables/ # reusable logic
|
|
38
|
+
│ ├── data/ # business data and schemas
|
|
39
|
+
│ ├── domain/ # pure business maths, no Vue imports
|
|
40
|
+
│ └── pages/ # routes: data in, sections out
|
|
32
41
|
├── i18n/
|
|
33
|
-
│ └── locales/ #
|
|
34
|
-
├── public/ #
|
|
35
|
-
├── docs/ #
|
|
36
|
-
|
|
42
|
+
│ └── locales/ # one file per language, same keys
|
|
43
|
+
├── public/ # static assets: images, fonts, favicon
|
|
44
|
+
├── docs/ # project documentation
|
|
45
|
+
│ ├── ARCHITECTURE.md # layer map and browser storage keys
|
|
46
|
+
│ ├── DECISIONS.md # dated decisions and reasons
|
|
47
|
+
│ └── METRICS.md # dated measurements, with machine and build
|
|
48
|
+
└── nuxt.config.ts
|
|
37
49
|
```
|
|
38
50
|
|
|
39
51
|
---
|
|
40
52
|
|
|
41
|
-
## 3.
|
|
53
|
+
## 3. Class naming
|
|
42
54
|
|
|
43
|
-
|
|
|
55
|
+
| Role | Format | Example |
|
|
44
56
|
|---|---|---|
|
|
45
|
-
|
|
|
46
|
-
|
|
|
47
|
-
|
|
|
48
|
-
|
|
|
49
|
-
|
|
|
57
|
+
| Base component | short kebab-case | `.p-card`, `.btn`, `.field` |
|
|
58
|
+
| Element | double underscore | `.p-card__title` |
|
|
59
|
+
| Modifier | separate class with a leading dash | `.-top`, `.-compact`, `.-lg` |
|
|
60
|
+
| State | `is-` prefix | `.is-open`, `.is-active` |
|
|
61
|
+
| Page context | class on `<body>` | `body.page-home` |
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## 4. Targets
|
|
66
|
+
|
|
67
|
+
These are design targets for a finished page on a mid-range phone over a 4G connection. They are not measured results. Measure them on the target device and record the results in `docs/METRICS.md`.
|
|
68
|
+
|
|
69
|
+
| Metric | Target |
|
|
70
|
+
|---|---|
|
|
71
|
+
| Lighthouse Performance | ≥ 95 |
|
|
72
|
+
| Lighthouse Accessibility | ≥ 95 |
|
|
73
|
+
| Lighthouse Best Practices | ≥ 95 |
|
|
74
|
+
| Lighthouse SEO | 100 |
|
|
75
|
+
| First Contentful Paint | ≤ 1.0 s |
|
|
76
|
+
| Largest Contentful Paint | ≤ 2.5 s |
|
|
77
|
+
| Cumulative Layout Shift | ≤ 0.01 (CLS 0 is the aim) |
|
|
78
|
+
| Total Blocking Time | ≤ 200 ms |
|
|
79
|
+
| Interaction to Next Paint | ≤ 200 ms |
|
|
80
|
+
|
|
81
|
+
Lab tools in CI or in a sandbox do not produce reliable LCP or INP values. Use them for regressions only, not as proof.
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## 5. Quality gates
|
|
86
|
+
|
|
87
|
+
A change is done when these pass:
|
|
88
|
+
|
|
89
|
+
1. Unit and composable tests.
|
|
90
|
+
2. Type check.
|
|
91
|
+
3. Locale parity: every key exists in every locale.
|
|
92
|
+
4. Asset references: every `/images/…` and `/fonts/…` path exists in `public/`.
|
|
93
|
+
5. HTML check: valid markup on every generated page.
|
|
94
|
+
6. Console check: no errors or warnings on load.
|
|
95
|
+
7. Accessibility: axe reports 0 violations at 390, 820 and 1440 px.
|
|
96
|
+
8. Build: `nuxt generate` completes.
|
|
50
97
|
|
|
51
98
|
---
|
|
52
99
|
|
|
53
|
-
##
|
|
100
|
+
## 6. Versioning and release
|
|
54
101
|
|
|
55
|
-
|
|
56
|
-
2. **Core Web Vitals:** FCP ≤ 0.4s, LCP ≤ 1.2s, CLS = 0.000, TBT ≤ 50ms, INP ≤ 50ms.
|
|
57
|
-
3. **A11y (Доступность):** 0 ошибок axe-core, строгий контраст текста (WCAG AA), уникальные `useId()` для SVG/фильтров.
|
|
58
|
-
4. **Bundle Size:** Нулевой избыточный JS/CSS на первом экране, 100% покрытие шрифтов прелоадом.
|
|
102
|
+
See `ALL.md` section 11 and `README.md`. Summary: semantic versions, one changelog entry per user-visible change, tag `vX.Y.Z` on release, publish by the maintainer.
|
package/bin/ds7.js
CHANGED
|
@@ -1,141 +1,224 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
-
// DS7 CLI
|
|
5
|
-
//
|
|
4
|
+
// DS7 CLI. Installs the DS7 standard into ds7/ and enables it as the `ds7`
|
|
5
|
+
// pack of AI-ALL (@ai.all/aiall). The agent entrypoints and the root ALL.md
|
|
6
|
+
// belong to AI-ALL; this CLI never writes them.
|
|
7
|
+
//
|
|
8
|
+
// Usage: npx @ai.all/ds7 [init|sync|update|--version|--help]
|
|
9
|
+
//
|
|
10
|
+
// Ownership:
|
|
11
|
+
// ds7/** the standard, vendored; overwritten by `update`
|
|
12
|
+
// ds7/aiall-pack.json pack manifest, generated from this version; overwritten by `update`
|
|
13
|
+
// ds7/VERSION installed version; written by `init` and `update`
|
|
14
|
+
// ALL.md (project root) AI-ALL routing file; its packs block is managed by AI-ALL,
|
|
15
|
+
// the text outside that block is the project's own
|
|
6
16
|
|
|
7
17
|
const fs = require('fs');
|
|
8
18
|
const path = require('path');
|
|
9
19
|
const { spawnSync } = require('child_process');
|
|
10
20
|
|
|
11
|
-
// ─── ANSI colours ──────────────────────────────────────────────────────────
|
|
12
21
|
const C = {
|
|
13
|
-
reset:
|
|
14
|
-
|
|
15
|
-
dim: '\x1b[2m',
|
|
16
|
-
green: '\x1b[32m',
|
|
17
|
-
yellow: '\x1b[33m',
|
|
18
|
-
cyan: '\x1b[36m',
|
|
19
|
-
red: '\x1b[31m',
|
|
22
|
+
reset: '\x1b[0m', bold: '\x1b[1m', dim: '\x1b[2m',
|
|
23
|
+
green: '\x1b[32m', yellow: '\x1b[33m', cyan: '\x1b[36m', red: '\x1b[31m',
|
|
20
24
|
};
|
|
21
25
|
const ok = (s) => console.log(` ${C.green}✓${C.reset} ${s}`);
|
|
22
|
-
const skip = (s) => console.log(` ${C.dim}· ${s} (exists,
|
|
26
|
+
const skip = (s) => console.log(` ${C.dim}· ${s} (exists, kept)${C.reset}`);
|
|
23
27
|
const info = (s) => console.log(` ${C.yellow}→${C.reset} ${s}`);
|
|
24
28
|
const err = (s) => console.log(` ${C.red}✗${C.reset} ${s}`);
|
|
25
29
|
|
|
26
|
-
|
|
27
|
-
const
|
|
28
|
-
const
|
|
30
|
+
const PKG = path.resolve(__dirname, '..');
|
|
31
|
+
const TARGET = process.cwd();
|
|
32
|
+
const DS7 = path.join(TARGET, 'ds7');
|
|
33
|
+
const PACK_REF = 'ds7/aiall-pack.json';
|
|
29
34
|
|
|
30
35
|
const { version } = require(path.join(PKG, 'package.json'));
|
|
31
36
|
|
|
32
|
-
//
|
|
33
|
-
function copyDir(src, dest) {
|
|
34
|
-
fs.mkdirSync(dest, { recursive: true });
|
|
35
|
-
for (const e of fs.readdirSync(src, { withFileTypes: true })) {
|
|
36
|
-
const s = path.join(src, e.name);
|
|
37
|
-
const d = path.join(dest, e.name);
|
|
38
|
-
if (e.isDirectory()) copyDir(s, d);
|
|
39
|
-
else if (!fs.existsSync(d)) { fs.copyFileSync(s, d); return true; }
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
function copyFile(src, dest) {
|
|
44
|
-
if (fs.existsSync(dest)) { skip(path.relative(TARGET, dest)); return false; }
|
|
45
|
-
fs.mkdirSync(path.dirname(dest), { recursive: true });
|
|
46
|
-
fs.copyFileSync(src, dest);
|
|
47
|
-
ok(path.relative(TARGET, dest));
|
|
48
|
-
return true;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// ─── Directories published to npm (not meta files) ──────────────────────────
|
|
37
|
+
// Folders that make up the standard (copied into ds7/).
|
|
52
38
|
const DS7_DIRS = [
|
|
53
39
|
'01-architecture', '02-design-system', '03-performance-web-vitals',
|
|
54
40
|
'04-seo-ai-optimization', '05-internationalization', '06-business-conversion',
|
|
55
41
|
'07-testing', '08-token-optimization', 'templates',
|
|
56
42
|
];
|
|
57
|
-
|
|
43
|
+
// Root-level documents of the standard (copied into ds7/).
|
|
44
|
+
const DS7_FILES = ['README.md', 'SPEC.md', 'ALL.md', 'CHANGELOG.md'];
|
|
45
|
+
|
|
46
|
+
// Collect every file under a folder of the package, as paths relative to PKG.
|
|
47
|
+
function listFiles(relDir) {
|
|
48
|
+
const out = [];
|
|
49
|
+
const walk = (abs, rel) => {
|
|
50
|
+
for (const e of fs.readdirSync(abs, { withFileTypes: true })) {
|
|
51
|
+
const a = path.join(abs, e.name);
|
|
52
|
+
const r = path.join(rel, e.name);
|
|
53
|
+
if (e.isDirectory()) walk(a, r);
|
|
54
|
+
else out.push(r);
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
walk(path.join(PKG, relDir), relDir);
|
|
58
|
+
return out;
|
|
59
|
+
}
|
|
58
60
|
|
|
59
|
-
//
|
|
60
|
-
function
|
|
61
|
-
|
|
61
|
+
// Copy one file. `overwrite` decides whether an existing file is replaced.
|
|
62
|
+
function copyOne(relFromPkg, destAbs, overwrite) {
|
|
63
|
+
const label = path.relative(TARGET, destAbs);
|
|
64
|
+
if (fs.existsSync(destAbs) && !overwrite) { skip(label); return false; }
|
|
65
|
+
fs.mkdirSync(path.dirname(destAbs), { recursive: true });
|
|
66
|
+
fs.copyFileSync(path.join(PKG, relFromPkg), destAbs);
|
|
67
|
+
ok(label);
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
62
70
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
71
|
+
// Every file of the standard, as [relative path in package, destination].
|
|
72
|
+
function standardFiles() {
|
|
73
|
+
const pairs = [];
|
|
66
74
|
for (const dir of DS7_DIRS) {
|
|
67
|
-
|
|
68
|
-
const
|
|
69
|
-
if (!fs.existsSync(src)) continue;
|
|
70
|
-
const entries = fs.readdirSync(src, { withFileTypes: true });
|
|
71
|
-
fs.mkdirSync(dest, { recursive: true });
|
|
72
|
-
for (const e of entries) {
|
|
73
|
-
const s = path.join(src, e.name);
|
|
74
|
-
const d = path.join(dest, e.name);
|
|
75
|
-
if (e.isDirectory()) {
|
|
76
|
-
if (copyDir(s, d)) copied++;
|
|
77
|
-
} else if (!fs.existsSync(d)) {
|
|
78
|
-
fs.copyFileSync(s, d);
|
|
79
|
-
ok(`ds7/${dir}/${e.name}`);
|
|
80
|
-
copied++;
|
|
81
|
-
} else {
|
|
82
|
-
skip(`ds7/${dir}/${e.name}`);
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
for (const f of DS7_FILES) {
|
|
87
|
-
if (copyFile(path.join(PKG, f), path.join(ds7Target, f))) copied++;
|
|
75
|
+
if (!fs.existsSync(path.join(PKG, dir))) continue;
|
|
76
|
+
for (const rel of listFiles(dir)) pairs.push([rel, path.join(DS7, rel)]);
|
|
88
77
|
}
|
|
78
|
+
for (const f of DS7_FILES) pairs.push([f, path.join(DS7, f)]);
|
|
79
|
+
return pairs;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// The pack manifest that AI-ALL reads. Paths are project-relative, because the
|
|
83
|
+
// standard is vendored into ds7/ and AI-ALL links to them from the project's ALL.md.
|
|
84
|
+
function packManifest() {
|
|
85
|
+
const doc = (p) => `ds7/${p}`;
|
|
86
|
+
return {
|
|
87
|
+
name: '@ai.all/ds7',
|
|
88
|
+
version,
|
|
89
|
+
title: 'DS7 web architecture standard',
|
|
90
|
+
directives: [
|
|
91
|
+
{ id: 'ds7.rules', title: 'DS7 agent rules',
|
|
92
|
+
summary: 'Read before any change in a DS7 web project: ground rules, build order, components and the pre-finish checklist.',
|
|
93
|
+
doc: doc('ALL.md') },
|
|
94
|
+
{ id: 'ds7.spec', title: 'DS7 stack and quality gates',
|
|
95
|
+
summary: 'Read for the stack, directory layout, naming, performance targets and quality gates.',
|
|
96
|
+
doc: doc('SPEC.md') },
|
|
97
|
+
{ id: 'ds7.architecture', title: 'Atomic architecture',
|
|
98
|
+
summary: 'Read before creating or changing components, variants or modifiers.',
|
|
99
|
+
doc: doc('01-architecture/COMPONENT-ANATOMY.md') },
|
|
100
|
+
{ id: 'ds7.brand', title: 'Brand tokens and brandbook',
|
|
101
|
+
summary: 'Read before changing colours, type, spacing or the brandbook page.',
|
|
102
|
+
doc: doc('02-design-system/TOKENS-SPEC.md') },
|
|
103
|
+
{ id: 'ds7.i18n', title: 'Internationalisation',
|
|
104
|
+
summary: 'Read before adding a locale, a route or a translated string.',
|
|
105
|
+
doc: doc('05-internationalization/I18N-ARCHITECTURE.md') },
|
|
106
|
+
{ id: 'ds7.testing', title: 'Testing strategy',
|
|
107
|
+
summary: 'Read before adding or changing tests or quality checks.',
|
|
108
|
+
doc: doc('07-testing/TESTING-STRATEGY.md') },
|
|
109
|
+
],
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function writePackManifest(overwrite) {
|
|
114
|
+
const dest = path.join(DS7, 'aiall-pack.json');
|
|
115
|
+
if (fs.existsSync(dest) && !overwrite) { skip(path.relative(TARGET, dest)); return; }
|
|
116
|
+
fs.mkdirSync(DS7, { recursive: true });
|
|
117
|
+
fs.writeFileSync(dest, `${JSON.stringify(packManifest(), null, 2)}\n`);
|
|
118
|
+
ok(path.relative(TARGET, dest));
|
|
119
|
+
}
|
|
89
120
|
|
|
90
|
-
|
|
91
|
-
|
|
121
|
+
function writeVersion() {
|
|
122
|
+
fs.mkdirSync(DS7, { recursive: true });
|
|
123
|
+
fs.writeFileSync(path.join(DS7, 'VERSION'), `${version}\n`);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Run an AI-ALL command with the @ai.all/aiall version this package depends on.
|
|
127
|
+
// The dependency is pinned, so the tested version is the one that runs.
|
|
128
|
+
function runAiall(args) {
|
|
129
|
+
let bin;
|
|
130
|
+
try { bin = require.resolve('@ai.all/aiall/bin/cli.js'); }
|
|
131
|
+
catch { err('@ai.all/aiall is not installed. Reinstall with: npm i -D @ai.all/ds7'); return false; }
|
|
132
|
+
const r = spawnSync(process.execPath, [bin, ...args, '--path', TARGET], { stdio: 'inherit' });
|
|
133
|
+
return r.status === 0;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// True when .ai/aiall.json already lists the DS7 pack.
|
|
137
|
+
function packEnabled() {
|
|
138
|
+
try {
|
|
139
|
+
const cfg = JSON.parse(fs.readFileSync(path.join(TARGET, '.ai', 'aiall.json'), 'utf8'));
|
|
140
|
+
return Array.isArray(cfg.packs) && cfg.packs.includes(PACK_REF);
|
|
141
|
+
} catch { return false; }
|
|
142
|
+
}
|
|
92
143
|
|
|
93
|
-
|
|
144
|
+
function enablePack() {
|
|
145
|
+
if (packEnabled()) { skip(`pack ${PACK_REF}`); return true; }
|
|
146
|
+
if (!runAiall(['packs', 'add', PACK_REF])) return false;
|
|
147
|
+
ok(`pack ${PACK_REF} enabled`);
|
|
148
|
+
return true;
|
|
149
|
+
}
|
|
94
150
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
info(
|
|
101
|
-
|
|
151
|
+
// Warn about files left by DS7 1.x. Nothing is deleted or rewritten automatically.
|
|
152
|
+
function legacyWarnings() {
|
|
153
|
+
const rootAll = path.join(TARGET, 'ALL.md');
|
|
154
|
+
if (fs.existsSync(rootAll) && fs.readFileSync(rootAll, 'utf8').includes('Agent Rules for DS7 Projects')) {
|
|
155
|
+
info('Root ALL.md still holds the DS7 1.x rules. Those rules now live in ds7/ALL.md.');
|
|
156
|
+
info('Remove the copied rules from root ALL.md and keep the aiall packs block.');
|
|
157
|
+
}
|
|
158
|
+
if (fs.existsSync(path.join(TARGET, 'ALL.project.md'))) {
|
|
159
|
+
info('ALL.project.md is from DS7 1.x and is no longer used. Move its project values into');
|
|
160
|
+
info('root ALL.md (below the aiall packs block), then delete the file.');
|
|
102
161
|
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function cmdInit() {
|
|
165
|
+
console.log(`\n${C.bold}${C.cyan}DS7 v${version} — setup${C.reset}\n`);
|
|
166
|
+
|
|
167
|
+
for (const [rel, dest] of standardFiles()) copyOne(rel, dest, false);
|
|
168
|
+
writePackManifest(false);
|
|
169
|
+
writeVersion();
|
|
170
|
+
|
|
171
|
+
console.log(`\n${C.yellow}Configuring AI-ALL…${C.reset}\n`);
|
|
172
|
+
if (!runAiall(['init'])) { err('AI-ALL init failed. Run: npx @ai.all/aiall init'); process.exitCode = 1; return; }
|
|
173
|
+
if (!enablePack()) { err(`Could not enable the pack. Run: npx @ai.all/aiall packs add ${PACK_REF}`); process.exitCode = 1; return; }
|
|
174
|
+
legacyWarnings();
|
|
103
175
|
|
|
104
|
-
console.log(`\n${C.bold}${C.green}
|
|
105
|
-
console.log(`
|
|
106
|
-
console.log(`
|
|
176
|
+
console.log(`\n${C.bold}${C.green}DS7 is installed.${C.reset}`);
|
|
177
|
+
console.log(` 1. Read ${C.cyan}ds7/README.md${C.reset} for the standard and the build order.`);
|
|
178
|
+
console.log(` 2. Add this project's values to the root ${C.cyan}ALL.md${C.reset}, below the aiall packs block.`);
|
|
179
|
+
console.log(` 3. Run ${C.cyan}npx @ai.all/ds7 update${C.reset} to get new versions of the standard.\n`);
|
|
107
180
|
}
|
|
108
181
|
|
|
109
182
|
function cmdSync() {
|
|
110
|
-
console.log(`\n${C.yellow}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
});
|
|
114
|
-
if (r.status !== 0) err('Sync failed — run npx @ai.all/aiall manually.');
|
|
115
|
-
else ok('All agent entrypoints are in sync.');
|
|
183
|
+
console.log(`\n${C.yellow}Syncing agent entrypoints…${C.reset}\n`);
|
|
184
|
+
if (runAiall(['sync'])) ok('Agent entrypoints are in sync.');
|
|
185
|
+
else { err('Sync failed. Run: npx @ai.all/aiall sync'); process.exitCode = 1; }
|
|
116
186
|
}
|
|
117
187
|
|
|
118
188
|
function cmdUpdate() {
|
|
119
|
-
console.log(`\n${C.yellow}
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
copyDir(src, path.join(ds7Target, dir));
|
|
125
|
-
ok(`ds7/${dir}/`);
|
|
189
|
+
console.log(`\n${C.yellow}Updating the standard to v${version}…${C.reset}\n`);
|
|
190
|
+
if (!fs.existsSync(DS7)) {
|
|
191
|
+
err('ds7/ not found. Run `npx @ai.all/ds7` (init) first.');
|
|
192
|
+
process.exitCode = 1;
|
|
193
|
+
return;
|
|
126
194
|
}
|
|
127
|
-
|
|
195
|
+
for (const [rel, dest] of standardFiles()) copyOne(rel, dest, true);
|
|
196
|
+
writePackManifest(true);
|
|
197
|
+
writeVersion();
|
|
198
|
+
|
|
199
|
+
if (!runAiall(['sync'])) { err('Sync failed. Run: npx @ai.all/aiall sync'); process.exitCode = 1; return; }
|
|
200
|
+
if (!enablePack()) { process.exitCode = 1; return; }
|
|
201
|
+
legacyWarnings();
|
|
202
|
+
|
|
203
|
+
console.log(`\n${C.green}Standard updated to v${version}. See ds7/CHANGELOG.md for what changed.${C.reset}`);
|
|
204
|
+
info('The root ALL.md outside the aiall packs block was not changed.\n');
|
|
128
205
|
}
|
|
129
206
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
// default: init
|
|
140
|
-
cmdInit();
|
|
207
|
+
function cmdHelp() {
|
|
208
|
+
console.log(`
|
|
209
|
+
DS7 ${version}
|
|
210
|
+
|
|
211
|
+
npx @ai.all/ds7 install the standard and enable the ds7 pack (init)
|
|
212
|
+
npx @ai.all/ds7 sync sync agent entrypoints (AI-ALL sync)
|
|
213
|
+
npx @ai.all/ds7 update update ds7/ to this version and refresh the pack
|
|
214
|
+
npx @ai.all/ds7 --version print the version
|
|
215
|
+
`);
|
|
141
216
|
}
|
|
217
|
+
|
|
218
|
+
const cmd = process.argv[2];
|
|
219
|
+
if (cmd === '--version' || cmd === '-v') console.log(version);
|
|
220
|
+
else if (cmd === '--help' || cmd === '-h' || cmd === 'help') cmdHelp();
|
|
221
|
+
else if (cmd === 'sync') cmdSync();
|
|
222
|
+
else if (cmd === 'update') cmdUpdate();
|
|
223
|
+
else if (!cmd || cmd === 'init') cmdInit();
|
|
224
|
+
else { err(`Unknown command: ${cmd}`); cmdHelp(); process.exitCode = 1; }
|
package/package.json
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai.all/ds7",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "AI-ready architecture standard for web projects
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"description": "AI-ready architecture standard for web projects: brand-first foundations, Atomic Design and agent rules in one place",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"architecture",
|
|
7
7
|
"design-system",
|
|
8
|
+
"design-tokens",
|
|
9
|
+
"brandbook",
|
|
8
10
|
"atomic-design",
|
|
9
11
|
"nuxt",
|
|
10
12
|
"vue",
|
|
@@ -13,8 +15,7 @@
|
|
|
13
15
|
"ai",
|
|
14
16
|
"agents",
|
|
15
17
|
"i18n",
|
|
16
|
-
"
|
|
17
|
-
"lighthouse"
|
|
18
|
+
"accessibility"
|
|
18
19
|
],
|
|
19
20
|
"homepage": "https://github.com/ai-all-ai/ds7#readme",
|
|
20
21
|
"repository": {
|
|
@@ -25,7 +26,7 @@
|
|
|
25
26
|
"url": "https://github.com/ai-all-ai/ds7/issues"
|
|
26
27
|
},
|
|
27
28
|
"license": "MIT",
|
|
28
|
-
"author": "Igor Orlov
|
|
29
|
+
"author": "Igor Orlov",
|
|
29
30
|
"bin": {
|
|
30
31
|
"ds7": "bin/ds7.js"
|
|
31
32
|
},
|
|
@@ -41,24 +42,22 @@
|
|
|
41
42
|
"08-token-optimization/",
|
|
42
43
|
"templates/",
|
|
43
44
|
"ALL.md",
|
|
44
|
-
"
|
|
45
|
-
"ANDALUSIA.md",
|
|
45
|
+
"CHANGELOG.md",
|
|
46
46
|
"README.md",
|
|
47
|
-
"SPEC.md"
|
|
48
|
-
"ff.md"
|
|
47
|
+
"SPEC.md"
|
|
49
48
|
],
|
|
50
49
|
"engines": {
|
|
51
50
|
"node": ">=18"
|
|
52
51
|
},
|
|
53
52
|
"dependencies": {
|
|
54
|
-
"@ai.all/aiall": "^0.
|
|
53
|
+
"@ai.all/aiall": "^0.3.0"
|
|
55
54
|
},
|
|
56
55
|
"publishConfig": {
|
|
57
56
|
"access": "public",
|
|
58
57
|
"registry": "https://registry.npmjs.org/"
|
|
59
58
|
},
|
|
60
59
|
"scripts": {
|
|
61
|
-
"test": "node bin/ds7.js --version",
|
|
60
|
+
"test": "node bin/ds7.js --version && node bin/ds7.js --help > /dev/null && node --test test/integration.test.js",
|
|
62
61
|
"prepublishOnly": "npm test"
|
|
63
62
|
}
|
|
64
63
|
}
|
package/templates/component.vue
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
/**
|
|
3
|
-
* DS7
|
|
4
|
-
*
|
|
3
|
+
* DS7 component template: product card molecule (CARD-01).
|
|
4
|
+
* Atomic level: molecule. Modifiers: -top, -new, -compact, -dark.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
interface SpecItem {
|
|
@@ -9,14 +9,12 @@ interface SpecItem {
|
|
|
9
9
|
value: string
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
// 1. Типизированные пропсы с модификаторами
|
|
13
12
|
const props = withDefaults(defineProps<{
|
|
14
13
|
title: string
|
|
15
14
|
description?: string
|
|
16
15
|
price?: number | null
|
|
17
16
|
badge?: 'top' | 'new' | 'sale'
|
|
18
17
|
specs?: SpecItem[]
|
|
19
|
-
// Булевые пропсы-модификаторы:
|
|
20
18
|
top?: boolean
|
|
21
19
|
compact?: boolean
|
|
22
20
|
dark?: boolean
|
|
@@ -26,27 +24,26 @@ const props = withDefaults(defineProps<{
|
|
|
26
24
|
specs: () => [],
|
|
27
25
|
top: false,
|
|
28
26
|
compact: false,
|
|
29
|
-
dark: false
|
|
27
|
+
dark: false,
|
|
30
28
|
})
|
|
31
29
|
|
|
32
|
-
// 2. Вычисление минималистичных классов
|
|
33
30
|
const classes = computed(() => [
|
|
34
31
|
'p-card',
|
|
35
32
|
props.top && '-top',
|
|
36
33
|
props.compact && '-compact',
|
|
37
34
|
props.dark && '-dark',
|
|
38
|
-
props.badge && `-${props.badge}
|
|
35
|
+
props.badge && `-${props.badge}`,
|
|
39
36
|
])
|
|
40
37
|
</script>
|
|
41
38
|
|
|
42
39
|
<template>
|
|
43
40
|
<article :class="classes" data-ref="CARD-01">
|
|
44
|
-
<!--
|
|
41
|
+
<!-- Artwork or logo slot -->
|
|
45
42
|
<div class="p-card__art">
|
|
46
43
|
<slot name="art" />
|
|
47
44
|
</div>
|
|
48
45
|
|
|
49
|
-
<!--
|
|
46
|
+
<!-- Text body -->
|
|
50
47
|
<div class="p-card__body">
|
|
51
48
|
<h3 class="p-card__title">{{ title }}</h3>
|
|
52
49
|
<p v-if="description" class="p-card__desc">{{ description }}</p>
|
|
@@ -59,7 +56,7 @@ const classes = computed(() => [
|
|
|
59
56
|
</dl>
|
|
60
57
|
</div>
|
|
61
58
|
|
|
62
|
-
<!--
|
|
59
|
+
<!-- Footer: price and action. The price is formatted by the project's price atom. -->
|
|
63
60
|
<div class="p-card__footer">
|
|
64
61
|
<div v-if="price !== null" class="p-card__price">
|
|
65
62
|
<span class="p-card__price-val">{{ price }} €</span>
|
|
@@ -70,8 +67,9 @@ const classes = computed(() => [
|
|
|
70
67
|
</template>
|
|
71
68
|
|
|
72
69
|
<style>
|
|
73
|
-
/*
|
|
74
|
-
*
|
|
70
|
+
/*
|
|
71
|
+
* Component styles. Not scoped: the prefix isolates them, and parents can
|
|
72
|
+
* override the custom properties. Values come from the tokens in theme.css.
|
|
75
73
|
*/
|
|
76
74
|
.p-card {
|
|
77
75
|
--card-bg: var(--color-white, #fff);
|
|
@@ -89,7 +87,6 @@ const classes = computed(() => [
|
|
|
89
87
|
transition: transform 0.2s ease, box-shadow 0.2s ease;
|
|
90
88
|
}
|
|
91
89
|
|
|
92
|
-
/* Модификатор TOP */
|
|
93
90
|
.p-card.-top {
|
|
94
91
|
--card-border: var(--color-sun, #ffd84d);
|
|
95
92
|
box-shadow: var(--shadow-lift);
|
|
@@ -98,19 +95,16 @@ const classes = computed(() => [
|
|
|
98
95
|
font-weight: 700;
|
|
99
96
|
}
|
|
100
97
|
|
|
101
|
-
/* Модификатор Dark */
|
|
102
98
|
.p-card.-dark {
|
|
103
99
|
--card-bg: var(--color-ink-950, #12100d);
|
|
104
100
|
--card-ink: #ffffff;
|
|
105
101
|
--card-border: rgba(255, 255, 255, 0.12);
|
|
106
102
|
}
|
|
107
103
|
|
|
108
|
-
/* Модификатор Compact */
|
|
109
104
|
.p-card.-compact {
|
|
110
105
|
padding: var(--space-2, 8px);
|
|
111
106
|
}
|
|
112
107
|
|
|
113
|
-
/* Контейнерная адаптивность */
|
|
114
108
|
@container (max-width: 320px) {
|
|
115
109
|
.p-card {
|
|
116
110
|
padding: var(--space-2, 8px);
|