@design-parity/baseline 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/README.md +60 -0
- package/dist/artifacts.d.ts +9 -0
- package/dist/artifacts.d.ts.map +1 -0
- package/dist/artifacts.js +15 -0
- package/dist/artifacts.js.map +1 -0
- package/dist/bootstrap.d.ts +59 -0
- package/dist/bootstrap.d.ts.map +1 -0
- package/dist/bootstrap.js +94 -0
- package/dist/bootstrap.js.map +1 -0
- package/dist/checks.d.ts +13 -0
- package/dist/checks.d.ts.map +1 -0
- package/dist/checks.js +8 -0
- package/dist/checks.js.map +1 -0
- package/dist/cli/bootstrap.d.ts +3 -0
- package/dist/cli/bootstrap.d.ts.map +1 -0
- package/dist/cli/bootstrap.js +149 -0
- package/dist/cli/bootstrap.js.map +1 -0
- package/dist/cmp.d.ts +75 -0
- package/dist/cmp.d.ts.map +1 -0
- package/dist/cmp.js +126 -0
- package/dist/cmp.js.map +1 -0
- package/dist/detect.d.ts +42 -0
- package/dist/detect.d.ts.map +1 -0
- package/dist/detect.js +150 -0
- package/dist/detect.js.map +1 -0
- package/dist/direction.d.ts +14 -0
- package/dist/direction.d.ts.map +1 -0
- package/dist/direction.js +10 -0
- package/dist/direction.js.map +1 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -0
- package/dist/seed.d.ts +25 -0
- package/dist/seed.d.ts.map +1 -0
- package/dist/seed.js +128 -0
- package/dist/seed.js.map +1 -0
- package/dist/tokens.d.ts +16 -0
- package/dist/tokens.d.ts.map +1 -0
- package/dist/tokens.js +57 -0
- package/dist/tokens.js.map +1 -0
- package/package.json +34 -0
package/README.md
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# @design-parity/baseline
|
|
2
|
+
|
|
3
|
+
Detect a repo's design-system maturity and, for a repo with no design system,
|
|
4
|
+
bootstrap an opinionated **committed** baseline. This is the one place AI
|
|
5
|
+
generates artifacts (see [docs/PRINCIPLES.md](../../docs/PRINCIPLES.md),
|
|
6
|
+
Principles 1, 3, 4, 5); the steady-state Action only runs what this writes.
|
|
7
|
+
|
|
8
|
+
## Maturity rungs
|
|
9
|
+
|
|
10
|
+
`detectMaturity(repoRoot)` classifies a repo by scanning committed files,
|
|
11
|
+
returning core's `MaturityRung`:
|
|
12
|
+
|
|
13
|
+
1. **`machine-link`** — Figma Code Connect (`figma.config.json` or
|
|
14
|
+
`*.figma.{tsx,kt,swift,…}`). → direction `design-led`.
|
|
15
|
+
2. **`manifest`** — a `design-map.json` or a design-token source
|
|
16
|
+
(`*.tokens.json`, a `tokens/` tree, Style Dictionary). → `code-led`.
|
|
17
|
+
3. **`bootstrap`** — neither. → `code-led`, and **bootstrap**.
|
|
18
|
+
|
|
19
|
+
Direction resolution is delegated to `@design-parity/policy` so setup and the
|
|
20
|
+
Action's late fallback agree.
|
|
21
|
+
|
|
22
|
+
## Bootstrap (`bootstrap` rung)
|
|
23
|
+
|
|
24
|
+
`planBootstrap` decides what to write; `applyBootstrap` writes it. Every rung
|
|
25
|
+
gets a concrete parity direction in policy's committed `.design-parity.json` —
|
|
26
|
+
`auto` is never left behind. The `bootstrap` rung additionally gets:
|
|
27
|
+
|
|
28
|
+
- `design-tokens.json` — Material 3 + WCAG AA + i18n-ready token baseline,
|
|
29
|
+
- `design-parity.checks.json` — `@design-parity/checks`'s `ChecksConfig`
|
|
30
|
+
(WCAG AA, hardcoded-string lint on),
|
|
31
|
+
- `design-map.json` — a schema-valid starter scaffold. Components discovered by
|
|
32
|
+
name convention are surfaced as **low-confidence review items** to wire to a
|
|
33
|
+
design source later.
|
|
34
|
+
|
|
35
|
+
## Compose Multiplatform (Principle 6)
|
|
36
|
+
|
|
37
|
+
`detectMaturity` also reports whether a repo is **Compose Multiplatform (CMP)
|
|
38
|
+
capable** — `cmpCapable: boolean` plus an evidence trail (`cmp.signals`) from a
|
|
39
|
+
bounded scan of Gradle build files (`build.gradle{,.kts}`, `settings.gradle*`,
|
|
40
|
+
`libs.versions.toml`). This is **orthogonal to the maturity rung**: a repo at any
|
|
41
|
+
rung may or may not be CMP-capable.
|
|
42
|
+
|
|
43
|
+
When a repo is **not** CMP-capable, `cmpSuggestion()` returns a non-blocking
|
|
44
|
+
advisory ("Compose Multiplatform would render candidates on the JVM/desktop with
|
|
45
|
+
no emulator — consider it"), surfaced via `plan.cmpSuggestion` and the CLI.
|
|
46
|
+
**Never a gate** — plain Jetpack Compose stays fully supported.
|
|
47
|
+
|
|
48
|
+
The live CMP render path (preferring `compose-preview`'s desktop/JVM render in
|
|
49
|
+
`@design-parity/candidate` when capable, plus a Compose-for-Web/wasm spike) is
|
|
50
|
+
deferred — it needs the JVM/Compose toolchain. See [docs/cmp.md](./docs/cmp.md).
|
|
51
|
+
|
|
52
|
+
## CLI
|
|
53
|
+
|
|
54
|
+
```sh
|
|
55
|
+
design-parity-bootstrap [--dir <path>] [--direction design-led|code-led] [--yes] [--force]
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Interactive setup, run once locally; commit the artifacts it writes. It refuses
|
|
59
|
+
to run in CI — the GitHub Action enforces committed artifacts, it never
|
|
60
|
+
bootstraps.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** Parity policy (`ParityConfig`) — written for every rung. Owned by `policy`. */
|
|
2
|
+
export declare const CONFIG_FILE = ".design-parity.json";
|
|
3
|
+
/** Opinionated `DesignTokens` baseline — bootstrap rung only. */
|
|
4
|
+
export declare const TOKENS_FILE = "design-tokens.json";
|
|
5
|
+
/** Starter `ChecksConfig` for `@design-parity/checks` — bootstrap rung only. */
|
|
6
|
+
export declare const CHECKS_FILE = "design-parity.checks.json";
|
|
7
|
+
/** Starter manifest correspondence — bootstrap rung only. */
|
|
8
|
+
export declare const DESIGN_MAP_FILE = "design-map.json";
|
|
9
|
+
//# sourceMappingURL=artifacts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"artifacts.d.ts","sourceRoot":"","sources":["../src/artifacts.ts"],"names":[],"mappings":"AAOA,kFAAkF;AAClF,eAAO,MAAM,WAAW,wBAAyB,CAAC;AAElD,iEAAiE;AACjE,eAAO,MAAM,WAAW,uBAAuB,CAAC;AAEhD,gFAAgF;AAChF,eAAO,MAAM,WAAW,8BAA8B,CAAC;AAEvD,6DAA6D;AAC7D,eAAO,MAAM,eAAe,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Filenames of the committed artifacts setup/bootstrap writes. Centralized so
|
|
3
|
+
* detection can ignore files this package itself produces (see {@link
|
|
4
|
+
* detectMaturity}) and the CLI and tests agree on paths.
|
|
5
|
+
*/
|
|
6
|
+
import { PARITY_CONFIG_FILENAME } from "@design-parity/policy";
|
|
7
|
+
/** Parity policy (`ParityConfig`) — written for every rung. Owned by `policy`. */
|
|
8
|
+
export const CONFIG_FILE = PARITY_CONFIG_FILENAME;
|
|
9
|
+
/** Opinionated `DesignTokens` baseline — bootstrap rung only. */
|
|
10
|
+
export const TOKENS_FILE = "design-tokens.json";
|
|
11
|
+
/** Starter `ChecksConfig` for `@design-parity/checks` — bootstrap rung only. */
|
|
12
|
+
export const CHECKS_FILE = "design-parity.checks.json";
|
|
13
|
+
/** Starter manifest correspondence — bootstrap rung only. */
|
|
14
|
+
export const DESIGN_MAP_FILE = "design-map.json";
|
|
15
|
+
//# sourceMappingURL=artifacts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"artifacts.js","sourceRoot":"","sources":["../src/artifacts.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAE/D,kFAAkF;AAClF,MAAM,CAAC,MAAM,WAAW,GAAG,sBAAsB,CAAC;AAElD,iEAAiE;AACjE,MAAM,CAAC,MAAM,WAAW,GAAG,oBAAoB,CAAC;AAEhD,gFAAgF;AAChF,MAAM,CAAC,MAAM,WAAW,GAAG,2BAA2B,CAAC;AAEvD,6DAA6D;AAC7D,MAAM,CAAC,MAAM,eAAe,GAAG,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { ResolvedDirection } from "@design-parity/core";
|
|
2
|
+
import type { MaturityResult } from "./detect.js";
|
|
3
|
+
import type { DiscoveredComponent } from "./seed.js";
|
|
4
|
+
/** One file the plan would write. */
|
|
5
|
+
export interface PlannedArtifact {
|
|
6
|
+
/** Repo-relative path. */
|
|
7
|
+
path: string;
|
|
8
|
+
/** One-line human description for the CLI summary. */
|
|
9
|
+
description: string;
|
|
10
|
+
/** Serialized contents (pretty JSON, trailing newline). */
|
|
11
|
+
contents: string;
|
|
12
|
+
/** True if a file already exists at `path` (apply skips it unless forced). */
|
|
13
|
+
exists: boolean;
|
|
14
|
+
}
|
|
15
|
+
export interface BootstrapPlan {
|
|
16
|
+
repoRoot: string;
|
|
17
|
+
maturity: MaturityResult;
|
|
18
|
+
/** Concrete direction materialized into the config — never `auto`. */
|
|
19
|
+
direction: ResolvedDirection;
|
|
20
|
+
/** Convention-discovered components to wire to a design source (rung 3). */
|
|
21
|
+
review: DiscoveredComponent[];
|
|
22
|
+
artifacts: PlannedArtifact[];
|
|
23
|
+
/**
|
|
24
|
+
* Non-blocking Compose Multiplatform promotion (Principle 6). Present only
|
|
25
|
+
* when the repo is *not* CMP-capable; `undefined` when it already is. Advisory
|
|
26
|
+
* surface text — never a gate, never an artifact.
|
|
27
|
+
*/
|
|
28
|
+
cmpSuggestion?: string;
|
|
29
|
+
}
|
|
30
|
+
export interface PlanOptions {
|
|
31
|
+
/** Override the materialized direction (e.g. the user picked design-led). */
|
|
32
|
+
direction?: ResolvedDirection;
|
|
33
|
+
/** Inject a maturity result instead of scanning (testing / re-runs). */
|
|
34
|
+
maturity?: MaturityResult;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Decide which committed artifacts a repo needs. Every rung gets a concrete
|
|
38
|
+
* parity direction; only rung 3 (no design system) is bootstrapped with a token
|
|
39
|
+
* baseline, a starter design-map, and a check config.
|
|
40
|
+
*
|
|
41
|
+
* @throws if the seeded design-map fails its own schema (a build-time bug).
|
|
42
|
+
*/
|
|
43
|
+
export declare function planBootstrap(repoRoot: string, opts?: PlanOptions): Promise<BootstrapPlan>;
|
|
44
|
+
export interface ApplyOptions {
|
|
45
|
+
/** Overwrite artifacts that already exist. Default: skip them. */
|
|
46
|
+
force?: boolean;
|
|
47
|
+
}
|
|
48
|
+
export interface ApplyResult {
|
|
49
|
+
/** Repo-relative paths written. */
|
|
50
|
+
written: string[];
|
|
51
|
+
/** Repo-relative paths skipped because they already existed. */
|
|
52
|
+
skipped: string[];
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Write a plan's artifacts to disk. Existing files are left untouched unless
|
|
56
|
+
* `force` is set, so a re-run never clobbers a human's edits by surprise.
|
|
57
|
+
*/
|
|
58
|
+
export declare function applyBootstrap(plan: BootstrapPlan, opts?: ApplyOptions): Promise<ApplyResult>;
|
|
59
|
+
//# sourceMappingURL=bootstrap.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bootstrap.d.ts","sourceRoot":"","sources":["../src/bootstrap.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAW7D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAGlD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAGrD,qCAAqC;AACrC,MAAM,WAAW,eAAe;IAC9B,0BAA0B;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,sDAAsD;IACtD,WAAW,EAAE,MAAM,CAAC;IACpB,2DAA2D;IAC3D,QAAQ,EAAE,MAAM,CAAC;IACjB,8EAA8E;IAC9E,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,cAAc,CAAC;IACzB,sEAAsE;IACtE,SAAS,EAAE,iBAAiB,CAAC;IAC7B,4EAA4E;IAC5E,MAAM,EAAE,mBAAmB,EAAE,CAAC;IAC9B,SAAS,EAAE,eAAe,EAAE,CAAC;IAC7B;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,WAAW;IAC1B,6EAA6E;IAC7E,SAAS,CAAC,EAAE,iBAAiB,CAAC;IAC9B,wEAAwE;IACxE,QAAQ,CAAC,EAAE,cAAc,CAAC;CAC3B;AAaD;;;;;;GAMG;AACH,wBAAsB,aAAa,CACjC,QAAQ,EAAE,MAAM,EAChB,IAAI,GAAE,WAAgB,GACrB,OAAO,CAAC,aAAa,CAAC,CAiDxB;AAED,MAAM,WAAW,YAAY;IAC3B,kEAAkE;IAClE,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,WAAW;IAC1B,mCAAmC;IACnC,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,gEAAgE;IAChE,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAClC,IAAI,EAAE,aAAa,EACnB,IAAI,GAAE,YAAiB,GACtB,OAAO,CAAC,WAAW,CAAC,CActB"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bootstrap orchestration — the one place AI generates committed artifacts
|
|
3
|
+
* (Principles 1, 3). `planBootstrap` is pure: it decides *what* to write from
|
|
4
|
+
* the detected maturity rung. `applyBootstrap` writes the plan to disk. Keeping
|
|
5
|
+
* the two apart makes the plan reviewable, testable, and re-runnable, and keeps
|
|
6
|
+
* generation off the unattended Action path entirely.
|
|
7
|
+
*/
|
|
8
|
+
import { access, writeFile } from "node:fs/promises";
|
|
9
|
+
import { join } from "node:path";
|
|
10
|
+
import { validateDesignMap } from "@design-parity/core";
|
|
11
|
+
import { CHECKS_FILE, CONFIG_FILE, DESIGN_MAP_FILE, TOKENS_FILE, } from "./artifacts.js";
|
|
12
|
+
import { defaultCheckConfig } from "./checks.js";
|
|
13
|
+
import { cmpSuggestion } from "./cmp.js";
|
|
14
|
+
import { detectMaturity } from "./detect.js";
|
|
15
|
+
import { directionForRung } from "./direction.js";
|
|
16
|
+
import { discoverCodeComponents, seedDesignMap } from "./seed.js";
|
|
17
|
+
import { materialBaselineTokens } from "./tokens.js";
|
|
18
|
+
const json = (value) => `${JSON.stringify(value, null, 2)}\n`;
|
|
19
|
+
async function fileExists(path) {
|
|
20
|
+
try {
|
|
21
|
+
await access(path);
|
|
22
|
+
return true;
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Decide which committed artifacts a repo needs. Every rung gets a concrete
|
|
30
|
+
* parity direction; only rung 3 (no design system) is bootstrapped with a token
|
|
31
|
+
* baseline, a starter design-map, and a check config.
|
|
32
|
+
*
|
|
33
|
+
* @throws if the seeded design-map fails its own schema (a build-time bug).
|
|
34
|
+
*/
|
|
35
|
+
export async function planBootstrap(repoRoot, opts = {}) {
|
|
36
|
+
const maturity = opts.maturity ?? (await detectMaturity(repoRoot));
|
|
37
|
+
const direction = opts.direction ?? directionForRung(maturity.rung);
|
|
38
|
+
const artifacts = [];
|
|
39
|
+
const add = async (path, description, value) => {
|
|
40
|
+
artifacts.push({
|
|
41
|
+
path,
|
|
42
|
+
description,
|
|
43
|
+
contents: json(value),
|
|
44
|
+
exists: await fileExists(join(repoRoot, path)),
|
|
45
|
+
});
|
|
46
|
+
};
|
|
47
|
+
// Every rung: materialize a concrete direction (Principle 5) and record the
|
|
48
|
+
// CMP capability so the unattended Action can promote CMP without re-scanning
|
|
49
|
+
// (Principles 1, 6) — the one CMP decision, committed once instead of re-made
|
|
50
|
+
// per PR run.
|
|
51
|
+
await add(CONFIG_FILE, `parity direction (${direction})`, {
|
|
52
|
+
direction,
|
|
53
|
+
cmpCapable: maturity.cmpCapable,
|
|
54
|
+
});
|
|
55
|
+
let review = [];
|
|
56
|
+
if (maturity.rung === "bootstrap") {
|
|
57
|
+
review = await discoverCodeComponents(repoRoot);
|
|
58
|
+
const designMap = seedDesignMap();
|
|
59
|
+
const check = validateDesignMap(designMap);
|
|
60
|
+
if (!check.valid) {
|
|
61
|
+
// The seeded map is hand-built; an invalid one is a bug in this package.
|
|
62
|
+
throw new Error(`seeded design-map failed schema validation: ${check.errors.join("; ")}`);
|
|
63
|
+
}
|
|
64
|
+
await add(TOKENS_FILE, "Material 3 + WCAG AA token baseline", materialBaselineTokens());
|
|
65
|
+
await add(CHECKS_FILE, "a11y + i18n checks config", defaultCheckConfig());
|
|
66
|
+
await add(DESIGN_MAP_FILE, "starter design-map (empty scaffold)", designMap);
|
|
67
|
+
}
|
|
68
|
+
return {
|
|
69
|
+
repoRoot,
|
|
70
|
+
maturity,
|
|
71
|
+
direction,
|
|
72
|
+
review,
|
|
73
|
+
artifacts,
|
|
74
|
+
cmpSuggestion: cmpSuggestion(maturity.cmp),
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Write a plan's artifacts to disk. Existing files are left untouched unless
|
|
79
|
+
* `force` is set, so a re-run never clobbers a human's edits by surprise.
|
|
80
|
+
*/
|
|
81
|
+
export async function applyBootstrap(plan, opts = {}) {
|
|
82
|
+
const written = [];
|
|
83
|
+
const skipped = [];
|
|
84
|
+
for (const artifact of plan.artifacts) {
|
|
85
|
+
if (artifact.exists && !opts.force) {
|
|
86
|
+
skipped.push(artifact.path);
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
await writeFile(join(plan.repoRoot, artifact.path), artifact.contents, "utf8");
|
|
90
|
+
written.push(artifact.path);
|
|
91
|
+
}
|
|
92
|
+
return { written, skipped };
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=bootstrap.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bootstrap.js","sourceRoot":"","sources":["../src/bootstrap.ts"],"names":[],"mappings":"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"}
|
package/dist/checks.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The starter check config for a bootstrapped repo.
|
|
3
|
+
*
|
|
4
|
+
* This is the committed input `@design-parity/checks` consumes — its
|
|
5
|
+
* {@link ChecksConfig}, not a parallel shape — so bootstrap emits exactly what
|
|
6
|
+
* the steady-state checks read (Principles 1, 2). The defaults are opinionated
|
|
7
|
+
* for a freshly bootstrapped repo: target WCAG AA contrast, and turn on the
|
|
8
|
+
* hardcoded-string lint so i18n drift surfaces from day one.
|
|
9
|
+
*/
|
|
10
|
+
import type { ChecksConfig } from "@design-parity/checks";
|
|
11
|
+
/** The opinionated default {@link ChecksConfig} for a bootstrapped repo. */
|
|
12
|
+
export declare function defaultCheckConfig(): ChecksConfig;
|
|
13
|
+
//# sourceMappingURL=checks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checks.d.ts","sourceRoot":"","sources":["../src/checks.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAE1D,4EAA4E;AAC5E,wBAAgB,kBAAkB,IAAI,YAAY,CAKjD"}
|
package/dist/checks.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checks.js","sourceRoot":"","sources":["../src/checks.ts"],"names":[],"mappings":"AAWA,4EAA4E;AAC5E,MAAM,UAAU,kBAAkB;IAChC,OAAO;QACL,aAAa,EAAE,IAAI;QACnB,oBAAoB,EAAE,IAAI;KAC3B,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bootstrap.d.ts","sourceRoot":"","sources":["../../src/cli/bootstrap.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* CLI: detect maturity and bootstrap a committed baseline — interactively.
|
|
4
|
+
*
|
|
5
|
+
* design-parity-bootstrap [--dir <path>] [--yes] [--force]
|
|
6
|
+
* [--direction design-led|code-led]
|
|
7
|
+
*
|
|
8
|
+
* This is the interactive setup step (Principle 4). It refuses to run on the
|
|
9
|
+
* unattended Action path: the Action enforces committed artifacts, it never
|
|
10
|
+
* generates them (Principle 1) — it points the user here instead.
|
|
11
|
+
*/
|
|
12
|
+
import { argv, env, exit, stdin, stdout } from "node:process";
|
|
13
|
+
import { createInterface } from "node:readline/promises";
|
|
14
|
+
import { applyBootstrap, planBootstrap, } from "../bootstrap.js";
|
|
15
|
+
function parseArgs(args) {
|
|
16
|
+
const out = { dir: ".", yes: false, force: false, help: false };
|
|
17
|
+
for (let i = 0; i < args.length; i++) {
|
|
18
|
+
const a = args[i];
|
|
19
|
+
switch (a) {
|
|
20
|
+
case "--yes":
|
|
21
|
+
case "-y":
|
|
22
|
+
out.yes = true;
|
|
23
|
+
break;
|
|
24
|
+
case "--force":
|
|
25
|
+
out.force = true;
|
|
26
|
+
break;
|
|
27
|
+
case "--help":
|
|
28
|
+
case "-h":
|
|
29
|
+
out.help = true;
|
|
30
|
+
break;
|
|
31
|
+
case "--dir":
|
|
32
|
+
out.dir = args[++i] ?? ".";
|
|
33
|
+
break;
|
|
34
|
+
case "--direction": {
|
|
35
|
+
const v = args[++i];
|
|
36
|
+
if (v !== "design-led" && v !== "code-led") {
|
|
37
|
+
throw new Error(`--direction must be design-led or code-led, got '${v}'`);
|
|
38
|
+
}
|
|
39
|
+
out.direction = v;
|
|
40
|
+
break;
|
|
41
|
+
}
|
|
42
|
+
default:
|
|
43
|
+
throw new Error(`unknown argument '${a}'`);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return out;
|
|
47
|
+
}
|
|
48
|
+
const HELP = `design-parity-bootstrap — detect maturity and bootstrap a committed baseline
|
|
49
|
+
|
|
50
|
+
Usage:
|
|
51
|
+
design-parity-bootstrap [options]
|
|
52
|
+
|
|
53
|
+
Options:
|
|
54
|
+
--dir <path> Repo root to bootstrap (default: current directory)
|
|
55
|
+
--direction <d> Force parity direction: design-led | code-led
|
|
56
|
+
--yes, -y Don't prompt; write the plan as-is
|
|
57
|
+
--force Overwrite artifacts that already exist
|
|
58
|
+
--help, -h Show this help
|
|
59
|
+
|
|
60
|
+
Interactive setup only. Run this once, locally; commit the artifacts it writes.
|
|
61
|
+
The GitHub Action runs those committed artifacts and never bootstraps.`;
|
|
62
|
+
function printPlan(plan) {
|
|
63
|
+
const { maturity } = plan;
|
|
64
|
+
console.log(`Detected maturity: ${maturity.rung} — ${maturity.label}`);
|
|
65
|
+
if (maturity.signals.length > 0) {
|
|
66
|
+
console.log("Evidence:");
|
|
67
|
+
for (const s of maturity.signals)
|
|
68
|
+
console.log(` • ${s.kind}: ${s.path}`);
|
|
69
|
+
}
|
|
70
|
+
console.log(`\nParity direction: ${plan.direction}`);
|
|
71
|
+
// Principle 6: prefer/promote Compose Multiplatform — advisory, never a gate.
|
|
72
|
+
if (maturity.cmpCapable) {
|
|
73
|
+
console.log("\nCompose Multiplatform: capable (candidates can render on the JVM/desktop — no emulator).");
|
|
74
|
+
for (const s of maturity.cmp.signals) {
|
|
75
|
+
console.log(` • ${s.kind}: ${s.path} (${s.match})`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
else if (plan.cmpSuggestion) {
|
|
79
|
+
console.log(`\nCompose Multiplatform suggestion:\n ${plan.cmpSuggestion}`);
|
|
80
|
+
}
|
|
81
|
+
console.log("\nArtifacts:");
|
|
82
|
+
for (const a of plan.artifacts) {
|
|
83
|
+
const tag = a.exists ? " (exists — will skip unless --force)" : "";
|
|
84
|
+
console.log(` • ${a.path} — ${a.description}${tag}`);
|
|
85
|
+
}
|
|
86
|
+
if (plan.review.length > 0) {
|
|
87
|
+
console.log(`\n${plan.review.length} UI component(s) discovered by convention (low confidence).`);
|
|
88
|
+
console.log("Wire each to a design reference in design-map.json when you adopt a design tool:");
|
|
89
|
+
for (const c of plan.review)
|
|
90
|
+
console.log(` • ${c.code}`);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
async function confirm(question) {
|
|
94
|
+
if (!stdin.isTTY)
|
|
95
|
+
return false;
|
|
96
|
+
const rl = createInterface({ input: stdin, output: stdout });
|
|
97
|
+
try {
|
|
98
|
+
const answer = (await rl.question(`${question} [y/N] `)).trim().toLowerCase();
|
|
99
|
+
return answer === "y" || answer === "yes";
|
|
100
|
+
}
|
|
101
|
+
finally {
|
|
102
|
+
rl.close();
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
async function main() {
|
|
106
|
+
let args;
|
|
107
|
+
try {
|
|
108
|
+
args = parseArgs(argv.slice(2));
|
|
109
|
+
}
|
|
110
|
+
catch (err) {
|
|
111
|
+
console.error(err.message);
|
|
112
|
+
console.error("\n" + HELP);
|
|
113
|
+
return 2;
|
|
114
|
+
}
|
|
115
|
+
if (args.help) {
|
|
116
|
+
console.log(HELP);
|
|
117
|
+
return 0;
|
|
118
|
+
}
|
|
119
|
+
// Principle 1 & 4: never bootstrap on the unattended Action path.
|
|
120
|
+
if (env.GITHUB_ACTIONS === "true" || env.CI === "true") {
|
|
121
|
+
console.error("design-parity-bootstrap is interactive setup and won't run in CI.\n" +
|
|
122
|
+
"Run it locally, review the generated artifacts, and commit them. The\n" +
|
|
123
|
+
"GitHub Action enforces those committed artifacts — it never bootstraps.");
|
|
124
|
+
return 1;
|
|
125
|
+
}
|
|
126
|
+
const plan = await planBootstrap(args.dir, { direction: args.direction });
|
|
127
|
+
printPlan(plan);
|
|
128
|
+
const toWrite = plan.artifacts.filter((a) => args.force || !a.exists);
|
|
129
|
+
if (toWrite.length === 0) {
|
|
130
|
+
console.log("\nNothing to write (all artifacts exist; pass --force to overwrite).");
|
|
131
|
+
return 0;
|
|
132
|
+
}
|
|
133
|
+
if (!args.yes) {
|
|
134
|
+
const ok = await confirm(`\nWrite ${toWrite.length} file(s) to ${args.dir}?`);
|
|
135
|
+
if (!ok) {
|
|
136
|
+
console.log("Aborted; nothing written.");
|
|
137
|
+
return 0;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
const result = await applyBootstrap(plan, { force: args.force });
|
|
141
|
+
for (const p of result.written)
|
|
142
|
+
console.log(`wrote ${p}`);
|
|
143
|
+
for (const p of result.skipped)
|
|
144
|
+
console.log(`skipped ${p} (exists)`);
|
|
145
|
+
console.log("\nReview the artifacts and commit them.");
|
|
146
|
+
return 0;
|
|
147
|
+
}
|
|
148
|
+
exit(await main());
|
|
149
|
+
//# sourceMappingURL=bootstrap.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bootstrap.js","sourceRoot":"","sources":["../../src/cli/bootstrap.ts"],"names":[],"mappings":"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"}
|
package/dist/cmp.d.ts
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compose Multiplatform (CMP) capability detection (Principle 6).
|
|
3
|
+
*
|
|
4
|
+
* The candidate side is cheapest to render when the UI is Compose
|
|
5
|
+
* Multiplatform: a CMP component renders on the JVM/desktop — and, increasingly,
|
|
6
|
+
* a headless browser via Compose for Web / wasm — with no Android emulator. So
|
|
7
|
+
* the bot *prefers* the CMP render path when a project supports it, and
|
|
8
|
+
* *promotes* CMP to projects that don't. This module supplies the deterministic
|
|
9
|
+
* half of that: scan committed Gradle build files for CMP signals and report a
|
|
10
|
+
* `cmpCapable` verdict plus the evidence behind it.
|
|
11
|
+
*
|
|
12
|
+
* This is detection + advisory only. It NEVER gates: plain Jetpack Compose stays
|
|
13
|
+
* fully supported, and a non-CMP repo gets a suggestion, not a failure
|
|
14
|
+
* (Principle 6). Detection is a bounded, deterministic, offline file scan — no
|
|
15
|
+
* model calls, no network, no toolchain — matching {@link detectMaturity}.
|
|
16
|
+
*/
|
|
17
|
+
/** What kind of CMP evidence a build file yielded. */
|
|
18
|
+
export type CmpSignalKind =
|
|
19
|
+
/** The `org.jetbrains.compose` Gradle plugin (the CMP plugin). */
|
|
20
|
+
"compose-plugin"
|
|
21
|
+
/** The Kotlin Multiplatform plugin (`kotlin("multiplatform")` / KMP id). */
|
|
22
|
+
| "kotlin-multiplatform"
|
|
23
|
+
/** A non-Android KMP target that can host a headless render (jvm/desktop/wasmJs/js). */
|
|
24
|
+
| "jvm-target"
|
|
25
|
+
/** A `compose-multiplatform` dependency or version-catalog coordinate. */
|
|
26
|
+
| "compose-dependency";
|
|
27
|
+
/** One piece of CMP evidence found in a build file. */
|
|
28
|
+
export interface CmpSignal {
|
|
29
|
+
kind: CmpSignalKind;
|
|
30
|
+
/** Repo-relative path to the build file that matched. */
|
|
31
|
+
path: string;
|
|
32
|
+
/** The literal text fragment that matched, for an auditable verdict. */
|
|
33
|
+
match: string;
|
|
34
|
+
}
|
|
35
|
+
/** The CMP capability verdict, surfaced on the maturity result. */
|
|
36
|
+
export interface CmpCapability {
|
|
37
|
+
/** True when any CMP signal was found (drives the prefer/promote choice). */
|
|
38
|
+
cmpCapable: boolean;
|
|
39
|
+
/** Every CMP signal found, in scan order — the audit trail. */
|
|
40
|
+
signals: CmpSignal[];
|
|
41
|
+
}
|
|
42
|
+
/** True if `name` is a build file this module scans. */
|
|
43
|
+
export declare function isCmpBuildFile(name: string): boolean;
|
|
44
|
+
/**
|
|
45
|
+
* Classify the contents of a single build file into CMP signals (pure).
|
|
46
|
+
*
|
|
47
|
+
* Comment lines (`//`, `#`) are skipped so a commented-out plugin block never
|
|
48
|
+
* trips a false positive. At most one signal per kind per file is reported, so
|
|
49
|
+
* the evidence stays compact.
|
|
50
|
+
*
|
|
51
|
+
* @param path repo-relative path, echoed back on each signal for the audit trail
|
|
52
|
+
* @param contents the file's text
|
|
53
|
+
*/
|
|
54
|
+
export declare function classifyBuildFile(path: string, contents: string): CmpSignal[];
|
|
55
|
+
/**
|
|
56
|
+
* Fold a set of per-file signals into a {@link CmpCapability} verdict.
|
|
57
|
+
*
|
|
58
|
+
* A repo is CMP-capable on *any* signal — the CMP plugin, the KMP plugin, a
|
|
59
|
+
* JVM/desktop/wasm/js target, or a compose-multiplatform dependency. The
|
|
60
|
+
* threshold is deliberately permissive: this is an advisory promote/prefer hint,
|
|
61
|
+
* never a gate, so a false positive merely skips a suggestion and a false
|
|
62
|
+
* negative merely shows one (Principle 6).
|
|
63
|
+
*/
|
|
64
|
+
export declare function summarizeCmp(signals: CmpSignal[]): CmpCapability;
|
|
65
|
+
/**
|
|
66
|
+
* The promotion suggestion shown to Android-only (non-CMP) projects. Returns a
|
|
67
|
+
* non-blocking advisory string when `capability.cmpCapable` is false, and
|
|
68
|
+
* `undefined` when the repo is already CMP-capable (nothing to promote).
|
|
69
|
+
*
|
|
70
|
+
* This is the "promote CMP, never require it" half of Principle 6: advisory
|
|
71
|
+
* only, surfaced in the bootstrap output and (where relevant) the PR comment —
|
|
72
|
+
* never a gate.
|
|
73
|
+
*/
|
|
74
|
+
export declare function cmpSuggestion(capability: CmpCapability): string | undefined;
|
|
75
|
+
//# sourceMappingURL=cmp.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cmp.d.ts","sourceRoot":"","sources":["../src/cmp.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,sDAAsD;AACtD,MAAM,MAAM,aAAa;AACvB,kEAAkE;AAChE,gBAAgB;AAClB,4EAA4E;GAC1E,sBAAsB;AACxB,wFAAwF;GACtF,YAAY;AACd,0EAA0E;GACxE,oBAAoB,CAAC;AAEzB,uDAAuD;AACvD,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,aAAa,CAAC;IACpB,yDAAyD;IACzD,IAAI,EAAE,MAAM,CAAC;IACb,wEAAwE;IACxE,KAAK,EAAE,MAAM,CAAC;CACf;AAED,mEAAmE;AACnE,MAAM,WAAW,aAAa;IAC5B,6EAA6E;IAC7E,UAAU,EAAE,OAAO,CAAC;IACpB,+DAA+D;IAC/D,OAAO,EAAE,SAAS,EAAE,CAAC;CACtB;AAUD,wDAAwD;AACxD,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEpD;AAwCD;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,SAAS,EAAE,CAwB7E;AAED;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,SAAS,EAAE,GAAG,aAAa,CAEhE;AAED;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,UAAU,EAAE,aAAa,GAAG,MAAM,GAAG,SAAS,CAU3E"}
|