@milehimikey/em 1.13.1 → 1.14.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/agents/em-critic.md +26 -0
- package/.claude/agents/em-implementer.md +34 -0
- package/.claude/agents/em-reviewer.md +31 -0
- package/.claude/agents/em-validator.md +27 -0
- package/.claude/skills/event-modeling/SKILL.md +50 -11
- package/.claude/skills/event-modeling-conform/SKILL.md +1 -1
- package/.claude/skills/event-modeling-design/SKILL.md +127 -18
- package/.claude/skills/event-modeling-discover/SKILL.md +1 -1
- package/.claude/skills/event-modeling-engagement/SKILL.md +192 -0
- package/.claude/skills/event-modeling-engagement/reference/engagement.md +143 -0
- package/.claude/skills/event-modeling-implement/SKILL.md +1 -1
- package/.claude/skills/event-modeling-implement/reference/implement.md +38 -11
- package/.claude/skills/event-modeling-review/SKILL.md +2 -2
- package/.claude/skills/event-modeling-shared/reference/em-dsl.md +279 -189
- package/.claude/skills/event-modeling-shared/reference/operating-principles.md +61 -0
- package/.claude/skills/event-modeling-shared/reference/slice-doc-schema.md +116 -5
- package/.claude/skills/event-modeling-shared/templates/constitution.md +18 -1
- package/.claude/skills/event-modeling-shared/templates/slice.md +64 -39
- package/.claude/skills/event-modeling-shared/templates/state.md +5 -1
- package/.claude-plugin/marketplace.json +14 -0
- package/README.md +25 -11
- package/dist/catalog/apiFirst.d.ts +28 -0
- package/dist/catalog/apiFirst.js +49 -0
- package/dist/catalog/apiFirst.js.map +1 -0
- package/dist/catalog/docJoin.d.ts +13 -0
- package/dist/catalog/docJoin.js +11 -0
- package/dist/catalog/docJoin.js.map +1 -1
- package/dist/catalog/docModelConsistencyValidate.js +44 -4
- package/dist/catalog/docModelConsistencyValidate.js.map +1 -1
- package/dist/catalog/invariantsValidate.d.ts +4 -0
- package/dist/catalog/invariantsValidate.js +102 -0
- package/dist/catalog/invariantsValidate.js.map +1 -0
- package/dist/catalog/scenarios.d.ts +15 -0
- package/dist/catalog/scenarios.js +97 -0
- package/dist/catalog/scenarios.js.map +1 -0
- package/dist/catalog/sliceDoc.d.ts +8 -0
- package/dist/catalog/sliceDoc.js +9 -0
- package/dist/catalog/sliceDoc.js.map +1 -1
- package/dist/catalog/sliceReadyValidate.d.ts +31 -4
- package/dist/catalog/sliceReadyValidate.js +66 -8
- package/dist/catalog/sliceReadyValidate.js.map +1 -1
- package/dist/catalog/sliceSections.d.ts +55 -0
- package/dist/catalog/sliceSections.js +317 -0
- package/dist/catalog/sliceSections.js.map +1 -0
- package/dist/cli/agentsMd.js +7 -1
- package/dist/cli/agentsMd.js.map +1 -1
- package/dist/cli/api.d.ts +90 -0
- package/dist/cli/api.js +318 -0
- package/dist/cli/api.js.map +1 -0
- package/dist/cli/ciInit.d.ts +82 -21
- package/dist/cli/ciInit.js +468 -64
- package/dist/cli/ciInit.js.map +1 -1
- package/dist/cli/conformScope.d.ts +28 -0
- package/dist/cli/conformScope.js +67 -0
- package/dist/cli/conformScope.js.map +1 -1
- package/dist/cli/coverage.d.ts +9 -0
- package/dist/cli/coverage.js +60 -8
- package/dist/cli/coverage.js.map +1 -1
- package/dist/cli/defer.d.ts +55 -0
- package/dist/cli/defer.js +244 -0
- package/dist/cli/defer.js.map +1 -0
- package/dist/cli/engagement.d.ts +210 -0
- package/dist/cli/engagement.js +444 -0
- package/dist/cli/engagement.js.map +1 -0
- package/dist/cli/engagementFile.d.ts +86 -0
- package/dist/cli/engagementFile.js +255 -0
- package/dist/cli/engagementFile.js.map +1 -0
- package/dist/cli/metrics.d.ts +10 -0
- package/dist/cli/metrics.js +49 -1
- package/dist/cli/metrics.js.map +1 -1
- package/dist/cli/pluginPin.d.ts +55 -0
- package/dist/cli/pluginPin.js +188 -0
- package/dist/cli/pluginPin.js.map +1 -0
- package/dist/cli/ratify.d.ts +27 -2
- package/dist/cli/ratify.js +112 -13
- package/dist/cli/ratify.js.map +1 -1
- package/dist/cli/reratify.d.ts +4 -2
- package/dist/cli/reratify.js +41 -16
- package/dist/cli/reratify.js.map +1 -1
- package/dist/cli/scopeInputs.d.ts +48 -0
- package/dist/cli/scopeInputs.js +176 -0
- package/dist/cli/scopeInputs.js.map +1 -0
- package/dist/cli/skillCheck.d.ts +15 -1
- package/dist/cli/skillCheck.js +22 -1
- package/dist/cli/skillCheck.js.map +1 -1
- package/dist/cli/skillDirs.d.ts +5 -0
- package/dist/cli/skillDirs.js +13 -1
- package/dist/cli/skillDirs.js.map +1 -1
- package/dist/cli/skillSync.d.ts +4 -0
- package/dist/cli/skillSync.js +23 -0
- package/dist/cli/skillSync.js.map +1 -1
- package/dist/cli/sliceNew.d.ts +11 -7
- package/dist/cli/sliceNew.js +91 -18
- package/dist/cli/sliceNew.js.map +1 -1
- package/dist/cli/sliceSync.d.ts +50 -0
- package/dist/cli/sliceSync.js +170 -0
- package/dist/cli/sliceSync.js.map +1 -0
- package/dist/cli/status.d.ts +24 -1
- package/dist/cli/status.js +20 -1
- package/dist/cli/status.js.map +1 -1
- package/dist/cli/systemInputs.d.ts +53 -10
- package/dist/cli/systemInputs.js +186 -11
- package/dist/cli/systemInputs.js.map +1 -1
- package/dist/cli/upgrade.d.ts +16 -3
- package/dist/cli/upgrade.js +366 -30
- package/dist/cli/upgrade.js.map +1 -1
- package/dist/cli/usageLog.d.ts +4 -2
- package/dist/cli/usageLog.js +4 -2
- package/dist/cli/usageLog.js.map +1 -1
- package/dist/cli.js +599 -94
- package/dist/cli.js.map +1 -1
- package/dist/emit/api.d.ts +29 -0
- package/dist/emit/api.js +220 -0
- package/dist/emit/api.js.map +1 -0
- package/dist/emit/apiCheckJson.d.ts +3 -0
- package/dist/emit/apiCheckJson.js +21 -0
- package/dist/emit/apiCheckJson.js.map +1 -0
- package/dist/emit/codeownersJson.d.ts +3 -0
- package/dist/emit/codeownersJson.js +19 -0
- package/dist/emit/codeownersJson.js.map +1 -0
- package/dist/emit/diffJson.d.ts +1 -1
- package/dist/emit/diffJson.js +8 -1
- package/dist/emit/diffJson.js.map +1 -1
- package/dist/emit/engagementJson.d.ts +8 -0
- package/dist/emit/engagementJson.js +46 -0
- package/dist/emit/engagementJson.js.map +1 -0
- package/dist/emit/glossaryJson.d.ts +1 -1
- package/dist/emit/glossaryJson.js +4 -1
- package/dist/emit/glossaryJson.js.map +1 -1
- package/dist/emit/json.d.ts +17 -1
- package/dist/emit/json.js +30 -1
- package/dist/emit/json.js.map +1 -1
- package/dist/emit/metricsJson.d.ts +1 -1
- package/dist/emit/metricsJson.js +4 -1
- package/dist/emit/metricsJson.js.map +1 -1
- package/dist/emit/queryJson.d.ts +1 -1
- package/dist/emit/queryJson.js +7 -1
- package/dist/emit/queryJson.js.map +1 -1
- package/dist/emit/scopeJson.d.ts +12 -0
- package/dist/emit/scopeJson.js +26 -0
- package/dist/emit/scopeJson.js.map +1 -0
- package/dist/emit/skillCheckJson.d.ts +3 -2
- package/dist/emit/skillCheckJson.js +10 -2
- package/dist/emit/skillCheckJson.js.map +1 -1
- package/dist/emit/statusJson.d.ts +1 -1
- package/dist/emit/statusJson.js +15 -1
- package/dist/emit/statusJson.js.map +1 -1
- package/dist/emit/systemJson.d.ts +15 -8
- package/dist/emit/systemJson.js +28 -13
- package/dist/emit/systemJson.js.map +1 -1
- package/dist/emit/validateJson.d.ts +3 -3
- package/dist/emit/validateJson.js +10 -4
- package/dist/emit/validateJson.js.map +1 -1
- package/dist/mcp/server.d.ts +1 -1
- package/dist/mcp/server.js +163 -31
- package/dist/mcp/server.js.map +1 -1
- package/dist/model/diff.d.ts +4 -1
- package/dist/model/diff.js +44 -8
- package/dist/model/diff.js.map +1 -1
- package/dist/model/glossary.d.ts +2 -0
- package/dist/model/glossary.js +1 -0
- package/dist/model/glossary.js.map +1 -1
- package/dist/model/model.d.ts +55 -2
- package/dist/model/model.js +57 -0
- package/dist/model/model.js.map +1 -1
- package/dist/model/qualifiedRef.d.ts +18 -0
- package/dist/model/qualifiedRef.js +26 -0
- package/dist/model/qualifiedRef.js.map +1 -1
- package/dist/model/queryIndex.d.ts +9 -1
- package/dist/model/queryIndex.js +18 -2
- package/dist/model/queryIndex.js.map +1 -1
- package/dist/model/rules.d.ts +143 -2
- package/dist/model/rules.js +162 -3
- package/dist/model/rules.js.map +1 -1
- package/dist/model/validate.d.ts +40 -0
- package/dist/model/validate.js +147 -1
- package/dist/model/validate.js.map +1 -1
- package/dist/parser/ast.d.ts +31 -3
- package/dist/parser/parser.js +148 -14
- package/dist/parser/parser.js.map +1 -1
- package/dist/query/format.js +1 -1
- package/dist/query/format.js.map +1 -1
- package/dist/query/verbs.d.ts +6 -0
- package/dist/query/verbs.js +6 -2
- package/dist/query/verbs.js.map +1 -1
- package/dist/system/adaptation.d.ts +14 -0
- package/dist/system/adaptation.js +49 -0
- package/dist/system/adaptation.js.map +1 -0
- package/dist/system/codeowners.d.ts +77 -0
- package/dist/system/codeowners.js +242 -0
- package/dist/system/codeowners.js.map +1 -0
- package/dist/system/manifest.d.ts +10 -5
- package/dist/system/manifest.js +54 -26
- package/dist/system/manifest.js.map +1 -1
- package/dist/system/migrateManifest.d.ts +28 -0
- package/dist/system/migrateManifest.js +155 -0
- package/dist/system/migrateManifest.js.map +1 -0
- package/dist/system/scope.d.ts +46 -0
- package/dist/system/scope.js +132 -0
- package/dist/system/scope.js.map +1 -0
- package/dist/system/verify.d.ts +50 -13
- package/dist/system/verify.js +179 -58
- package/dist/system/verify.js.map +1 -1
- package/dist/templates.d.ts +2 -2
- package/dist/templates.js +23 -2
- package/dist/templates.js.map +1 -1
- package/package.json +5 -2
- package/plugin/.claude-plugin/plugin.json +18 -0
- package/plugin/agents/em-critic.md +27 -0
- package/plugin/agents/em-implementer.md +35 -0
- package/plugin/agents/em-reviewer.md +32 -0
- package/plugin/agents/em-validator.md +28 -0
- package/plugin/shared/reference/em-dsl.md +871 -0
- package/plugin/shared/reference/methodology.md +329 -0
- package/plugin/shared/reference/operating-principles.md +222 -0
- package/plugin/shared/reference/slice-doc-schema.md +574 -0
- package/plugin/shared/templates/conformance-report.md +85 -0
- package/plugin/shared/templates/constitution.md +136 -0
- package/plugin/shared/templates/model-readme.md +46 -0
- package/plugin/shared/templates/slice.md +251 -0
- package/plugin/shared/templates/state.md +77 -0
- package/plugin/skills/conform/SKILL.md +93 -0
- package/plugin/skills/conform/reference/conform.md +428 -0
- package/plugin/skills/design/SKILL.md +298 -0
- package/plugin/skills/discover/SKILL.md +90 -0
- package/plugin/skills/discover/reference/extract.md +147 -0
- package/plugin/skills/engagement/SKILL.md +193 -0
- package/plugin/skills/engagement/reference/engagement.md +144 -0
- package/plugin/skills/event-modeling/SKILL.md +132 -0
- package/plugin/skills/implement/SKILL.md +61 -0
- package/plugin/skills/implement/reference/implement.md +439 -0
- package/plugin/skills/review/SKILL.md +74 -0
- package/dist/emit/typespec.d.ts +0 -26
- package/dist/emit/typespec.js +0 -356
- package/dist/emit/typespec.js.map +0 -1
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { GitRunner } from "../cli/diff-inputs.js";
|
|
2
|
+
import type { SystemExportDoc } from "./verify.js";
|
|
3
|
+
/** The managed block's marker name (`# GENERATED:em-codeowners:start` ... `:end`). */
|
|
4
|
+
export declare const CODEOWNERS_MARKER = "em-codeowners";
|
|
5
|
+
/** The doc comment written into the block: why the contract file lists every consumer. */
|
|
6
|
+
export declare const CODEOWNERS_CONTRACT_NOTE = "Contract files list every consuming team: a change to a model's public surface cannot merge without the teams that depend on it.";
|
|
7
|
+
export type CodeownersReason = "model-dir" | "contract" | "slices" | "slices-existing";
|
|
8
|
+
export interface CodeownersEntry {
|
|
9
|
+
/** CODEOWNERS pattern, anchored with a leading `/`, forward slashes. */
|
|
10
|
+
path: string;
|
|
11
|
+
owners: string[];
|
|
12
|
+
reason: CodeownersReason;
|
|
13
|
+
}
|
|
14
|
+
/** One model as the generator needs it. `dir` is the model's directory relative to the
|
|
15
|
+
* CODEOWNERS root ("" when the model sits at the root), `/`-separated. */
|
|
16
|
+
export interface CodeownersModelInput {
|
|
17
|
+
key: string;
|
|
18
|
+
dir: string;
|
|
19
|
+
/** The header's `owner` entries, as written. */
|
|
20
|
+
owner: string[];
|
|
21
|
+
doc: SystemExportDoc;
|
|
22
|
+
}
|
|
23
|
+
export interface CodeownersPlan {
|
|
24
|
+
entries: CodeownersEntry[];
|
|
25
|
+
/** Human notes (a skipped non-handle owner); stderr in the CLI, never in the JSON. */
|
|
26
|
+
notes: string[];
|
|
27
|
+
/** Refusals: a model with no usable owner. Non-empty means no entries should be written. */
|
|
28
|
+
errors: string[];
|
|
29
|
+
}
|
|
30
|
+
/** The parsed lines of an existing CODEOWNERS, outside the managed block, as `{pattern, owners}`. */
|
|
31
|
+
export declare function existingRules(text: string): Array<{
|
|
32
|
+
pattern: string;
|
|
33
|
+
owners: string[];
|
|
34
|
+
}>;
|
|
35
|
+
/** gitignore-style pattern match as CODEOWNERS applies it, for a file path relative to the
|
|
36
|
+
* root. A pattern with a slash (other than a trailing one) is anchored at the root; one
|
|
37
|
+
* without matches at any depth. `*` stops at `/`, `**` crosses it; a trailing `/` (or a
|
|
38
|
+
* pattern naming a directory) covers everything beneath. */
|
|
39
|
+
export declare function codeownersPatternMatches(pattern: string, path: string): boolean;
|
|
40
|
+
/** Build the entries. Deterministic: system order, then dir / contract / slices per model. */
|
|
41
|
+
export declare function planCodeowners(models: CodeownersModelInput[], existingText?: string): CodeownersPlan;
|
|
42
|
+
/** The block body (between the marker lines): the explanatory comments, then one line per entry. */
|
|
43
|
+
export declare function codeownersBlockBody(entries: CodeownersEntry[]): string;
|
|
44
|
+
export type CodeownersStatus = "ok" | "missing" | "stale" | "no-markers" | "created" | "updated";
|
|
45
|
+
export interface CodeownersResult {
|
|
46
|
+
/** The full file text the managed block implies (existing content untouched). */
|
|
47
|
+
text: string;
|
|
48
|
+
/** What `--check` would report; `created`/`updated` are the write-mode equivalents of
|
|
49
|
+
* `missing`/`stale`+`no-markers`. */
|
|
50
|
+
state: "ok" | "missing" | "stale" | "no-markers";
|
|
51
|
+
}
|
|
52
|
+
/** Splice the block into `existing` (`null` = no file). Unmarked content is kept byte-for-byte;
|
|
53
|
+
* a file with no markers gets the block appended after a blank line. */
|
|
54
|
+
export declare function spliceCodeowners(existing: string | null, entries: CodeownersEntry[]): CodeownersResult;
|
|
55
|
+
/** The files em looks for, in order, when no `-o` is given (GitHub's three locations). */
|
|
56
|
+
export declare const CODEOWNERS_CANDIDATES: string[];
|
|
57
|
+
export type RunCodeownersResult = {
|
|
58
|
+
ok: false;
|
|
59
|
+
message: string;
|
|
60
|
+
} | {
|
|
61
|
+
ok: true;
|
|
62
|
+
/** The CODEOWNERS path (as given with `-o`, else root-joined; never absolutized). */
|
|
63
|
+
file: string;
|
|
64
|
+
plan: CodeownersPlan;
|
|
65
|
+
status: CodeownersStatus;
|
|
66
|
+
/** The file text after the splice (what `write` puts on disk). */
|
|
67
|
+
text: string;
|
|
68
|
+
/** True when the file on disk differs from `text` (a write is needed). */
|
|
69
|
+
changed: boolean;
|
|
70
|
+
};
|
|
71
|
+
/** Load the system, plan the entries and compute the spliced file. With `write`, also puts it
|
|
72
|
+
* on disk (creating the file and its directory). `--check` callers pass `write: false` and
|
|
73
|
+
* report `status`; the MCP tool is always read-only. */
|
|
74
|
+
export declare function runCodeowners(target: string, opts: {
|
|
75
|
+
output?: string;
|
|
76
|
+
write: boolean;
|
|
77
|
+
}, runGit?: GitRunner): RunCodeownersResult;
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
// `em system codeowners` (MIL-234): turn the models' `owner` handles and the translations'
|
|
3
|
+
// `consumes` refs into a managed CODEOWNERS block, so review of a model's public surface is
|
|
4
|
+
// routed by the platform, not by convention. Three kinds of entry, per model in system order:
|
|
5
|
+
// - the model's design directory (`<modelDir>/`) -> the model's own team(s);
|
|
6
|
+
// - its contract file (`<modelDir>/contracts/<modelKey>.tsp`) -> the producer's team(s) FIRST,
|
|
7
|
+
// then every team whose model has a translation that `consumes` one of its refs (sorted).
|
|
8
|
+
// The contract carries no source hash (R12), so internal edits never touch it: only a real
|
|
9
|
+
// change of the public surface summons the consuming teams;
|
|
10
|
+
// - the model's slice docs (`<modelDir>/slices/**`) -> the model's team(s), unless the repo's
|
|
11
|
+
// own CODEOWNERS already routes them (the ratification convention, docs/ci.md) — in which
|
|
12
|
+
// case that rule is restated after the directory entry, because CODEOWNERS is last-match-
|
|
13
|
+
// wins and the directory entry would otherwise silently take the ratifiers' review away.
|
|
14
|
+
// The planning half is pure over export documents (compile isolation, MIL-194): paths are handed
|
|
15
|
+
// in CODEOWNERS-root-relative and nothing there touches the filesystem. `runCodeowners` at the
|
|
16
|
+
// bottom is the thin fs half the CLI and the MCP tool share, so both load the system, find the
|
|
17
|
+
// file and splice the block identically.
|
|
18
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync } from "node:fs";
|
|
19
|
+
import { basename, dirname, join, relative, resolve, sep } from "node:path";
|
|
20
|
+
import { realGit } from "../cli/diff-inputs.js";
|
|
21
|
+
import { loadSystem } from "../cli/systemInputs.js";
|
|
22
|
+
import { parseContractRef } from "../model/qualifiedRef.js";
|
|
23
|
+
import { isOwnerHandle } from "../model/validate.js";
|
|
24
|
+
import { applyMarker, markerPair } from "../util/markers.js";
|
|
25
|
+
/** The managed block's marker name (`# GENERATED:em-codeowners:start` ... `:end`). */
|
|
26
|
+
export const CODEOWNERS_MARKER = "em-codeowners";
|
|
27
|
+
/** The doc comment written into the block: why the contract file lists every consumer. */
|
|
28
|
+
export const CODEOWNERS_CONTRACT_NOTE = "Contract files list every consuming team: a change to a model's public surface cannot merge without the teams that depend on it.";
|
|
29
|
+
const dedupe = (xs) => [...new Set(xs)];
|
|
30
|
+
const usable = (owners) => dedupe(owners.filter(isOwnerHandle));
|
|
31
|
+
/** `/<dir>/<rest>` with the root case handled and spaces escaped the CODEOWNERS way. */
|
|
32
|
+
function patternFor(dir, rest) {
|
|
33
|
+
const joined = dir === "" ? rest : `${dir}/${rest}`;
|
|
34
|
+
return `/${joined}`.replace(/ /g, "\\ ");
|
|
35
|
+
}
|
|
36
|
+
/** The parsed lines of an existing CODEOWNERS, outside the managed block, as `{pattern, owners}`. */
|
|
37
|
+
export function existingRules(text) {
|
|
38
|
+
const out = [];
|
|
39
|
+
const outside = stripManagedBlock(text);
|
|
40
|
+
for (const raw of outside.split(/\r?\n/)) {
|
|
41
|
+
const line = raw.trim();
|
|
42
|
+
if (line === "" || line.startsWith("#"))
|
|
43
|
+
continue;
|
|
44
|
+
const parts = line.split(/\s+/);
|
|
45
|
+
if (parts.length < 2)
|
|
46
|
+
continue;
|
|
47
|
+
out.push({ pattern: parts[0], owners: parts.slice(1) });
|
|
48
|
+
}
|
|
49
|
+
return out;
|
|
50
|
+
}
|
|
51
|
+
function stripManagedBlock(text) {
|
|
52
|
+
const { start, end } = markerPair(CODEOWNERS_MARKER, "hash");
|
|
53
|
+
const s = text.indexOf(start);
|
|
54
|
+
const e = text.indexOf(end);
|
|
55
|
+
if (s < 0 || e < s)
|
|
56
|
+
return text;
|
|
57
|
+
return text.slice(0, s) + text.slice(e + end.length);
|
|
58
|
+
}
|
|
59
|
+
/** gitignore-style pattern match as CODEOWNERS applies it, for a file path relative to the
|
|
60
|
+
* root. A pattern with a slash (other than a trailing one) is anchored at the root; one
|
|
61
|
+
* without matches at any depth. `*` stops at `/`, `**` crosses it; a trailing `/` (or a
|
|
62
|
+
* pattern naming a directory) covers everything beneath. */
|
|
63
|
+
export function codeownersPatternMatches(pattern, path) {
|
|
64
|
+
let p = pattern.replace(/\\ /g, " ");
|
|
65
|
+
const anchored = p.startsWith("/") || p.slice(0, -1).includes("/");
|
|
66
|
+
p = p.replace(/^\//, "");
|
|
67
|
+
const dirOnly = p.endsWith("/");
|
|
68
|
+
if (dirOnly)
|
|
69
|
+
p = p.slice(0, -1);
|
|
70
|
+
let re = "";
|
|
71
|
+
for (let i = 0; i < p.length; i++) {
|
|
72
|
+
const c = p[i];
|
|
73
|
+
if (c === "*") {
|
|
74
|
+
if (p[i + 1] === "*") {
|
|
75
|
+
i++;
|
|
76
|
+
if (p[i + 1] === "/") {
|
|
77
|
+
i++;
|
|
78
|
+
re += "(?:.*/)?";
|
|
79
|
+
}
|
|
80
|
+
else
|
|
81
|
+
re += ".*";
|
|
82
|
+
}
|
|
83
|
+
else
|
|
84
|
+
re += "[^/]*";
|
|
85
|
+
}
|
|
86
|
+
else if (c === "?")
|
|
87
|
+
re += "[^/]";
|
|
88
|
+
else
|
|
89
|
+
re += c.replace(/[.+^${}()|[\]\\]/g, "\\$&");
|
|
90
|
+
}
|
|
91
|
+
const prefix = anchored ? "^" : "^(?:.*/)?";
|
|
92
|
+
return new RegExp(`${prefix}${re}(?:/.*)?$`).test(path);
|
|
93
|
+
}
|
|
94
|
+
/** The last existing rule that routes `path`, ignoring a bare catch-all `*` (it is a default,
|
|
95
|
+
* not a decision about slice docs). */
|
|
96
|
+
function routedBy(rules, path) {
|
|
97
|
+
let hit = null;
|
|
98
|
+
for (const r of rules) {
|
|
99
|
+
if (r.pattern === "*" || r.pattern === "/*")
|
|
100
|
+
continue;
|
|
101
|
+
if (codeownersPatternMatches(r.pattern, path))
|
|
102
|
+
hit = r;
|
|
103
|
+
}
|
|
104
|
+
return hit;
|
|
105
|
+
}
|
|
106
|
+
/** Build the entries. Deterministic: system order, then dir / contract / slices per model. */
|
|
107
|
+
export function planCodeowners(models, existingText = "") {
|
|
108
|
+
const notes = [];
|
|
109
|
+
const errors = [];
|
|
110
|
+
const rules = existingRules(existingText);
|
|
111
|
+
const ownersOf = new Map();
|
|
112
|
+
for (const m of models) {
|
|
113
|
+
const good = usable(m.owner);
|
|
114
|
+
for (const o of m.owner) {
|
|
115
|
+
if (!isOwnerHandle(o))
|
|
116
|
+
notes.push(`model "${m.key}": skipping owner "${o}" — not a CODEOWNERS handle (use "@user", "@org/team" or an email)`);
|
|
117
|
+
}
|
|
118
|
+
if (good.length === 0) {
|
|
119
|
+
errors.push(m.owner.length === 0
|
|
120
|
+
? `model "${m.key}" has no \`owner\` — add \`owner "@org/team"\` to its \`model\` header line`
|
|
121
|
+
: `model "${m.key}" has no usable owner — every \`owner\` entry is free text; use "@user", "@org/team" or an email`);
|
|
122
|
+
}
|
|
123
|
+
ownersOf.set(m.key, good);
|
|
124
|
+
}
|
|
125
|
+
// consumer teams per producing model: the owners of every model with a translation that
|
|
126
|
+
// consumes one of the producer's refs. Refs to models outside the system and self-refs
|
|
127
|
+
// route nothing (`em system` reports those).
|
|
128
|
+
const consumers = new Map();
|
|
129
|
+
for (const m of models) {
|
|
130
|
+
for (const slice of m.doc.model.slices) {
|
|
131
|
+
for (const el of slice.elements) {
|
|
132
|
+
if (el.kind !== "translation")
|
|
133
|
+
continue;
|
|
134
|
+
for (const ref of el.consumes ?? []) {
|
|
135
|
+
const parsed = parseContractRef(ref);
|
|
136
|
+
if (!parsed || parsed.modelKey === m.key)
|
|
137
|
+
continue;
|
|
138
|
+
consumers.set(parsed.modelKey, [...(consumers.get(parsed.modelKey) ?? []), ...(ownersOf.get(m.key) ?? [])]);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
const entries = [];
|
|
144
|
+
for (const m of models) {
|
|
145
|
+
const own = ownersOf.get(m.key) ?? [];
|
|
146
|
+
if (own.length === 0)
|
|
147
|
+
continue;
|
|
148
|
+
entries.push({ path: patternFor(m.dir, ""), owners: own, reason: "model-dir" });
|
|
149
|
+
const consuming = dedupe(consumers.get(m.key) ?? []).filter((o) => !own.includes(o)).sort();
|
|
150
|
+
entries.push({ path: patternFor(m.dir, `contracts/${m.key}.tsp`), owners: [...own, ...consuming], reason: "contract" });
|
|
151
|
+
const sample = m.dir === "" ? "slices/x.md" : `${m.dir}/slices/x.md`;
|
|
152
|
+
const existing = routedBy(rules, sample);
|
|
153
|
+
if (existing === null)
|
|
154
|
+
entries.push({ path: patternFor(m.dir, "slices/**"), owners: own, reason: "slices" });
|
|
155
|
+
else
|
|
156
|
+
entries.push({ path: patternFor(m.dir, "slices/**"), owners: existing.owners, reason: "slices-existing" });
|
|
157
|
+
}
|
|
158
|
+
return { entries, notes, errors };
|
|
159
|
+
}
|
|
160
|
+
/** The block body (between the marker lines): the explanatory comments, then one line per entry. */
|
|
161
|
+
export function codeownersBlockBody(entries) {
|
|
162
|
+
const lines = [
|
|
163
|
+
"# Generated by `em system codeowners` from each model's `owner` and each translation's `consumes`.",
|
|
164
|
+
"# Re-run it after changing either; `em system codeowners --check` fails on drift.",
|
|
165
|
+
`# ${CODEOWNERS_CONTRACT_NOTE}`,
|
|
166
|
+
...entries.map((e) => `${e.path} ${e.owners.join(" ")}`),
|
|
167
|
+
];
|
|
168
|
+
return lines.join("\n");
|
|
169
|
+
}
|
|
170
|
+
/** Splice the block into `existing` (`null` = no file). Unmarked content is kept byte-for-byte;
|
|
171
|
+
* a file with no markers gets the block appended after a blank line. */
|
|
172
|
+
export function spliceCodeowners(existing, entries) {
|
|
173
|
+
const { start, end } = markerPair(CODEOWNERS_MARKER, "hash");
|
|
174
|
+
const body = codeownersBlockBody(entries);
|
|
175
|
+
if (existing === null)
|
|
176
|
+
return { text: `${start}\n${body}\n${end}\n`, state: "missing" };
|
|
177
|
+
const spliced = applyMarker(existing, CODEOWNERS_MARKER, body, "hash");
|
|
178
|
+
if (spliced !== null)
|
|
179
|
+
return { text: spliced, state: spliced === existing ? "ok" : "stale" };
|
|
180
|
+
const sep = existing === "" ? "" : existing.endsWith("\n") ? "\n" : "\n\n";
|
|
181
|
+
return { text: `${existing}${sep}${start}\n${body}\n${end}\n`, state: "no-markers" };
|
|
182
|
+
}
|
|
183
|
+
/** The files em looks for, in order, when no `-o` is given (GitHub's three locations). */
|
|
184
|
+
export const CODEOWNERS_CANDIDATES = ["CODEOWNERS", ".github/CODEOWNERS", "docs/CODEOWNERS"];
|
|
185
|
+
/** The directory CODEOWNERS paths are relative to: the parent of a `.github/` or `docs/`
|
|
186
|
+
* CODEOWNERS, else the file's own directory. */
|
|
187
|
+
function rootOfCodeownersFile(file) {
|
|
188
|
+
const dir = dirname(file);
|
|
189
|
+
const name = basename(dir);
|
|
190
|
+
return name === ".github" || name === "docs" ? dirname(dir) : dir;
|
|
191
|
+
}
|
|
192
|
+
/** Load the system, plan the entries and compute the spliced file. With `write`, also puts it
|
|
193
|
+
* on disk (creating the file and its directory). `--check` callers pass `write: false` and
|
|
194
|
+
* report `status`; the MCP tool is always read-only. */
|
|
195
|
+
export function runCodeowners(target, opts, runGit = realGit) {
|
|
196
|
+
const loaded = loadSystem(target, runGit);
|
|
197
|
+
if (!loaded.ok) {
|
|
198
|
+
return {
|
|
199
|
+
ok: false,
|
|
200
|
+
message: `${target} could not be loaded — ${loaded.diagnostics.map((d) => `${d.file}${d.line ? `:${d.line}` : ""}: ${d.message}`).join("; ")}`,
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
let file;
|
|
204
|
+
let root;
|
|
205
|
+
if (opts.output !== undefined) {
|
|
206
|
+
file = opts.output;
|
|
207
|
+
root = rootOfCodeownersFile(file);
|
|
208
|
+
}
|
|
209
|
+
else {
|
|
210
|
+
const start = loaded.manifestPath !== null ? dirname(loaded.manifestPath) : loaded.discovery.root;
|
|
211
|
+
const up = runGit(["-C", start, "rev-parse", "--show-cdup"]);
|
|
212
|
+
root = up.status === 0 ? join(start, up.stdout.trim()) : start;
|
|
213
|
+
file = join(root, CODEOWNERS_CANDIDATES.find((c) => existsSync(join(root, c))) ?? "CODEOWNERS");
|
|
214
|
+
}
|
|
215
|
+
const notes = [];
|
|
216
|
+
const inputs = [];
|
|
217
|
+
for (const m of loaded.models) {
|
|
218
|
+
if (m.sourceKind !== "em") {
|
|
219
|
+
notes.push(`model "${m.key}": sourced from an export document, not a .em file — it has no design directory to route; skipped`);
|
|
220
|
+
continue;
|
|
221
|
+
}
|
|
222
|
+
const rel = relative(resolve(root), resolve(dirname(m.file)));
|
|
223
|
+
if (rel === ".." || rel.startsWith(`..${sep}`)) {
|
|
224
|
+
return { ok: false, message: `model "${m.key}" (${m.file}) lives outside the CODEOWNERS root ${root} — pass -o with a CODEOWNERS file at or above its directory` };
|
|
225
|
+
}
|
|
226
|
+
inputs.push({ key: m.key, dir: rel.split(sep).join("/"), owner: m.owner, doc: m.doc });
|
|
227
|
+
}
|
|
228
|
+
const existing = existsSync(file) ? readFileSync(file, "utf8") : null;
|
|
229
|
+
const plan = planCodeowners(inputs, existing ?? "");
|
|
230
|
+
plan.notes.unshift(...notes);
|
|
231
|
+
if (plan.errors.length > 0)
|
|
232
|
+
return { ok: false, message: plan.errors.join("\n") };
|
|
233
|
+
const spliced = spliceCodeowners(existing, plan.entries);
|
|
234
|
+
const changed = spliced.state !== "ok";
|
|
235
|
+
if (opts.write && changed) {
|
|
236
|
+
mkdirSync(dirname(file), { recursive: true });
|
|
237
|
+
writeFileSync(file, spliced.text);
|
|
238
|
+
}
|
|
239
|
+
const status = opts.write && changed ? (spliced.state === "missing" ? "created" : "updated") : spliced.state;
|
|
240
|
+
return { ok: true, file, plan, status, text: spliced.text, changed };
|
|
241
|
+
}
|
|
242
|
+
//# sourceMappingURL=codeowners.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codeowners.js","sourceRoot":"","sources":["../../src/system/codeowners.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
import type { Diagnostic } from "../model/validate.js";
|
|
2
|
-
/** The
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
/** The manifest schema version em writes and expects (`systemSchemaVersion`). */
|
|
3
|
+
export declare const SYSTEM_MANIFEST_SCHEMA_VERSION = "2.0";
|
|
4
|
+
/** The previous version, still accepted for reading (with a `system-manifest-outdated`
|
|
5
|
+
* warning) until a repo runs `em upgrade`'s `system-manifest` step. */
|
|
6
|
+
export declare const LEGACY_SYSTEM_MANIFEST_SCHEMA_VERSION = "1.0";
|
|
5
7
|
export interface ManifestModel {
|
|
6
8
|
/** The manifest's own key for this model — by MIL-193's rule the kebab-slug of the declared
|
|
7
9
|
* model name, and verified against the export's `model.key` by src/system/verify.ts. */
|
|
8
10
|
key: string;
|
|
9
11
|
/** A `.em` file or an `em export --json` document, as written (relative to the manifest). */
|
|
10
12
|
source: string;
|
|
13
|
+
/** 1.0 manifests only — always `null` on a 2.0 manifest (owners live on the model header). */
|
|
11
14
|
owner: string | null;
|
|
12
15
|
/** 1-based line of the model's entry in the manifest, for diagnostics. */
|
|
13
16
|
line: number;
|
|
@@ -22,12 +25,14 @@ export interface ManifestSeam {
|
|
|
22
25
|
line: number;
|
|
23
26
|
}
|
|
24
27
|
export interface SystemManifest {
|
|
28
|
+
/** `"2.0"`, or `"1.0"` for a legacy manifest read for compatibility. */
|
|
25
29
|
systemSchemaVersion: string;
|
|
30
|
+
/** 1-based line of the `systemSchemaVersion` entry, for the `system-manifest-outdated` warning. */
|
|
31
|
+
versionLine: number;
|
|
26
32
|
name: string | null;
|
|
27
33
|
/** Manifest order — the order `em system` lists models and context-map nodes. */
|
|
28
34
|
models: ManifestModel[];
|
|
29
|
-
/**
|
|
30
|
-
* reports `dangling-public-event`). */
|
|
35
|
+
/** 1.0 manifests only (always `[]` on 2.0): the legacy declared seams, manifest order. */
|
|
31
36
|
seams: ManifestSeam[];
|
|
32
37
|
}
|
|
33
38
|
export type ParseManifestResult = {
|
package/dist/system/manifest.js
CHANGED
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
// SPDX-License-Identifier: MIT
|
|
2
|
-
// Parses a
|
|
3
|
-
// list of models in a system
|
|
4
|
-
//
|
|
5
|
-
//
|
|
2
|
+
// Parses a system manifest (`system.yaml`, MIL-194 / MIL-235) into a plain, validated shape —
|
|
3
|
+
// the declared list of models in a system. This is the one place the manifest's own schema is
|
|
4
|
+
// enforced; everything downstream (src/system/verify.ts) trusts the returned `SystemManifest`.
|
|
5
|
+
//
|
|
6
|
+
// Schema 2.0 (MIL-235) is membership ONLY: `systemSchemaVersion`, `name`, `models: {key:
|
|
7
|
+
// {source}}`. Seams moved to the consuming translation (`consumes <model>:<kind>.<slug>`) and
|
|
8
|
+
// owners to the model header (`model "Name" owner "Team"`), so a 2.0 manifest carrying
|
|
9
|
+
// `seams:`/`owner:` is invalid and the message points at `em upgrade`. Schema 1.0 (seams +
|
|
10
|
+
// owners in the manifest) is still READ — so `em system` on an unmigrated estate keeps
|
|
11
|
+
// verifying — and `verifySystem` warns `system-manifest-outdated`; nothing writes 1.0 any more.
|
|
6
12
|
//
|
|
7
13
|
// YAML because the manifest is human-authored (and JSON is a YAML subset, so a `.json` manifest
|
|
8
14
|
// parses here unchanged). Pure: text in, manifest + diagnostics out — the caller (src/cli/
|
|
@@ -11,12 +17,20 @@
|
|
|
11
17
|
// `LineCounter`, so a shape error points at the offending entry, not just "the manifest".
|
|
12
18
|
import { LineCounter, parseDocument, isMap, isSeq, isScalar } from "yaml";
|
|
13
19
|
import { pushDiag } from "../model/rules.js";
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
const
|
|
18
|
-
|
|
20
|
+
// 1.0 (MIL-194): models {source, owner?} + seams [{from, to, description?}].
|
|
21
|
+
// 2.0 (MIL-235): models {source} only — seams are `consumes` clauses, owners are model headers.
|
|
22
|
+
/** The manifest schema version em writes and expects (`systemSchemaVersion`). */
|
|
23
|
+
export const SYSTEM_MANIFEST_SCHEMA_VERSION = "2.0";
|
|
24
|
+
/** The previous version, still accepted for reading (with a `system-manifest-outdated`
|
|
25
|
+
* warning) until a repo runs `em upgrade`'s `system-manifest` step. */
|
|
26
|
+
export const LEGACY_SYSTEM_MANIFEST_SCHEMA_VERSION = "1.0";
|
|
27
|
+
const TOP_KEYS_V2 = new Set(["systemSchemaVersion", "name", "models"]);
|
|
28
|
+
const MODEL_KEYS_V2 = new Set(["source"]);
|
|
29
|
+
const TOP_KEYS_V1 = new Set(["systemSchemaVersion", "name", "models", "seams"]);
|
|
30
|
+
const MODEL_KEYS_V1 = new Set(["source", "owner"]);
|
|
19
31
|
const SEAM_KEYS = new Set(["from", "to", "description"]);
|
|
32
|
+
/** Shared tail of every "this moved out of the manifest" message. */
|
|
33
|
+
const RUN_UPGRADE = "run `em upgrade <model>.em --apply` to migrate";
|
|
20
34
|
/** Parse and shape-check manifest text. Every problem is a `system-manifest-invalid` error
|
|
21
35
|
* diagnostic (never a throw), and `ok: false` means the manifest can't be used at all — the
|
|
22
36
|
* caller refuses rather than verifying a partial system. Unknown keys are errors, not ignored:
|
|
@@ -39,23 +53,32 @@ export function parseManifest(text) {
|
|
|
39
53
|
}
|
|
40
54
|
const root = doc.contents;
|
|
41
55
|
if (!isMap(root)) {
|
|
42
|
-
invalid("manifest must be a YAML mapping with `systemSchemaVersion`, `models`, and optionally `name
|
|
56
|
+
invalid("manifest must be a YAML mapping with `systemSchemaVersion`, `models`, and optionally `name`");
|
|
43
57
|
return { ok: false, diagnostics };
|
|
44
58
|
}
|
|
45
|
-
|
|
46
|
-
const key = scalarString(pair.key);
|
|
47
|
-
if (key === undefined || !TOP_KEYS.has(key)) {
|
|
48
|
-
invalid(`unknown top-level key ${describeKey(pair.key)} — expected one of: ${[...TOP_KEYS].join(", ")}`, lineOf(pair));
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
// systemSchemaVersion — required, and exactly the one version this em understands.
|
|
59
|
+
// systemSchemaVersion — required: "2.0", or the legacy "1.0" (read-only compatibility).
|
|
52
60
|
const versionNode = root.get("systemSchemaVersion", true);
|
|
53
61
|
const version = scalarString(versionNode);
|
|
54
62
|
if (version === undefined) {
|
|
55
63
|
invalid(`missing or non-string \`systemSchemaVersion\` — set \`systemSchemaVersion: "${SYSTEM_MANIFEST_SCHEMA_VERSION}"\``, lineOf(versionNode));
|
|
56
64
|
}
|
|
57
|
-
else if (version !== SYSTEM_MANIFEST_SCHEMA_VERSION) {
|
|
58
|
-
invalid(`unsupported systemSchemaVersion "${version}" — this em accepts "${SYSTEM_MANIFEST_SCHEMA_VERSION}"
|
|
65
|
+
else if (version !== SYSTEM_MANIFEST_SCHEMA_VERSION && version !== LEGACY_SYSTEM_MANIFEST_SCHEMA_VERSION) {
|
|
66
|
+
invalid(`unsupported systemSchemaVersion "${version}" — this em accepts "${SYSTEM_MANIFEST_SCHEMA_VERSION}" ` +
|
|
67
|
+
`(and reads "${LEGACY_SYSTEM_MANIFEST_SCHEMA_VERSION}" for compatibility)`, lineOf(versionNode));
|
|
68
|
+
}
|
|
69
|
+
// An unknown/missing version is checked against 2.0's key set — the shape em writes today.
|
|
70
|
+
const legacy = version === LEGACY_SYSTEM_MANIFEST_SCHEMA_VERSION;
|
|
71
|
+
const topKeys = legacy ? TOP_KEYS_V1 : TOP_KEYS_V2;
|
|
72
|
+
const modelKeys = legacy ? MODEL_KEYS_V1 : MODEL_KEYS_V2;
|
|
73
|
+
for (const pair of root.items) {
|
|
74
|
+
const key = scalarString(pair.key);
|
|
75
|
+
if (!legacy && key === "seams") {
|
|
76
|
+
invalid(`\`seams:\` is not part of systemSchemaVersion "${SYSTEM_MANIFEST_SCHEMA_VERSION}" — a seam is declared on the consuming ` +
|
|
77
|
+
`translation (\`consumes <modelKey>:<kind>.<slug>\`); ${RUN_UPGRADE}`, lineOf(pair));
|
|
78
|
+
}
|
|
79
|
+
else if (key === undefined || !topKeys.has(key)) {
|
|
80
|
+
invalid(`unknown top-level key ${describeKey(pair.key)} — expected one of: ${[...topKeys].join(", ")}`, lineOf(pair));
|
|
81
|
+
}
|
|
59
82
|
}
|
|
60
83
|
// name — optional string.
|
|
61
84
|
const nameNode = root.get("name", true);
|
|
@@ -71,7 +94,7 @@ export function parseManifest(text) {
|
|
|
71
94
|
const models = [];
|
|
72
95
|
const modelsNode = root.get("models", true);
|
|
73
96
|
if (!isMap(modelsNode)) {
|
|
74
|
-
invalid("`models` must be a mapping of model key -> { source
|
|
97
|
+
invalid("`models` must be a mapping of model key -> { source } with at least one entry", lineOf(modelsNode ?? root));
|
|
75
98
|
}
|
|
76
99
|
else if (modelsNode.items.length === 0) {
|
|
77
100
|
invalid("`models` must declare at least one model", lineOf(modelsNode));
|
|
@@ -91,15 +114,20 @@ export function parseManifest(text) {
|
|
|
91
114
|
}
|
|
92
115
|
for (const p of entry.items) {
|
|
93
116
|
const k = scalarString(p.key);
|
|
94
|
-
if (k ===
|
|
95
|
-
invalid(`model "${key}":
|
|
117
|
+
if (!legacy && k === "owner") {
|
|
118
|
+
invalid(`model "${key}": \`owner:\` is not part of systemSchemaVersion "${SYSTEM_MANIFEST_SCHEMA_VERSION}" — owners live on the ` +
|
|
119
|
+
`model header (\`model "Name" owner "Team"\`); ${RUN_UPGRADE}`, lineOf(p));
|
|
120
|
+
}
|
|
121
|
+
else if (k === undefined || !modelKeys.has(k)) {
|
|
122
|
+
invalid(`model "${key}": unknown key ${describeKey(p.key)} — expected ${[...modelKeys].join(", ")}`, lineOf(p));
|
|
123
|
+
}
|
|
96
124
|
}
|
|
97
125
|
const source = scalarString(entry.get("source", true));
|
|
98
126
|
if (source === undefined || source.trim() === "") {
|
|
99
127
|
invalid(`model "${key}": \`source\` must be a non-empty path string`, line);
|
|
100
128
|
continue;
|
|
101
129
|
}
|
|
102
|
-
const ownerNode = entry.get("owner", true);
|
|
130
|
+
const ownerNode = legacy ? entry.get("owner", true) : undefined;
|
|
103
131
|
let owner = null;
|
|
104
132
|
if (ownerNode !== undefined) {
|
|
105
133
|
const o = scalarString(ownerNode);
|
|
@@ -111,9 +139,9 @@ export function parseManifest(text) {
|
|
|
111
139
|
models.push({ key, source, owner, line: line ?? 1 });
|
|
112
140
|
}
|
|
113
141
|
}
|
|
114
|
-
// seams — optional sequence of `{ from, to, description? }`.
|
|
142
|
+
// seams — 1.0 only: optional sequence of `{ from, to, description? }`.
|
|
115
143
|
const seams = [];
|
|
116
|
-
const seamsNode = root.get("seams", true);
|
|
144
|
+
const seamsNode = legacy ? root.get("seams", true) : undefined;
|
|
117
145
|
if (seamsNode !== undefined && !(isScalar(seamsNode) && seamsNode.value === null)) {
|
|
118
146
|
if (!isSeq(seamsNode)) {
|
|
119
147
|
invalid("`seams` must be a list of { from, to, description? } entries", lineOf(seamsNode));
|
|
@@ -155,7 +183,7 @@ export function parseManifest(text) {
|
|
|
155
183
|
return { ok: false, diagnostics };
|
|
156
184
|
return {
|
|
157
185
|
ok: true,
|
|
158
|
-
manifest: { systemSchemaVersion: version, name, models, seams },
|
|
186
|
+
manifest: { systemSchemaVersion: version, versionLine: lineOf(versionNode) ?? 1, name, models, seams },
|
|
159
187
|
diagnostics,
|
|
160
188
|
};
|
|
161
189
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../src/system/manifest.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B
|
|
1
|
+
{"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../src/system/manifest.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { SystemManifest } from "./manifest.js";
|
|
2
|
+
import type { SystemExportDoc } from "./verify.js";
|
|
3
|
+
export interface MigrationMember {
|
|
4
|
+
/** The manifest key. */
|
|
5
|
+
key: string;
|
|
6
|
+
/** Path the step reads/writes (manifest dir joined with `source`). */
|
|
7
|
+
file: string;
|
|
8
|
+
/** The `.em` source text, or `null` when the member is an `em export --json` document. */
|
|
9
|
+
text: string | null;
|
|
10
|
+
doc: SystemExportDoc;
|
|
11
|
+
}
|
|
12
|
+
export type ManifestMigrationPlan = {
|
|
13
|
+
ok: true;
|
|
14
|
+
manifestText: string;
|
|
15
|
+
/** Rewritten `.em` files, member order; only files that actually change. */
|
|
16
|
+
files: {
|
|
17
|
+
file: string;
|
|
18
|
+
text: string;
|
|
19
|
+
}[];
|
|
20
|
+
/** Human-readable summary lines (one per consumes/owner write), for the step's reason. */
|
|
21
|
+
summary: string[];
|
|
22
|
+
} | {
|
|
23
|
+
ok: false;
|
|
24
|
+
message: string;
|
|
25
|
+
};
|
|
26
|
+
/** Plan the whole migration. `manifest` must be a parsed 1.0 manifest; `members` one entry per
|
|
27
|
+
* manifest model, same order. */
|
|
28
|
+
export declare function planManifestMigration(manifestText: string, manifest: SystemManifest, members: MigrationMember[]): ManifestMigrationPlan;
|