@tacuchi/agent-workflow-cli 20.26.0 → 21.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 +2 -1
- package/dist/adapters/node-file-system.js +3 -0
- package/dist/adapters/node-file-system.js.map +1 -1
- package/dist/application/capability/compose.js +161 -0
- package/dist/application/capability/compose.js.map +1 -0
- package/dist/application/capability/descriptor-loader.js +109 -0
- package/dist/application/capability/descriptor-loader.js.map +1 -0
- package/dist/application/capability/design-handler.js +299 -0
- package/dist/application/capability/design-handler.js.map +1 -0
- package/dist/application/capability/dispatcher.js +312 -0
- package/dist/application/capability/dispatcher.js.map +1 -0
- package/dist/application/capability/durable-effect.js +220 -0
- package/dist/application/capability/durable-effect.js.map +1 -0
- package/dist/application/capability/installed-inventory.js +168 -0
- package/dist/application/capability/installed-inventory.js.map +1 -0
- package/dist/application/capability/readiness.js +204 -0
- package/dist/application/capability/readiness.js.map +1 -0
- package/dist/application/capability/resolution.js +264 -0
- package/dist/application/capability/resolution.js.map +1 -0
- package/dist/application/capability/wrapper.js +187 -0
- package/dist/application/capability/wrapper.js.map +1 -0
- package/dist/application/context/manifest.js +11 -5
- package/dist/application/context/manifest.js.map +1 -1
- package/dist/application/context/measure.js +5 -2
- package/dist/application/context/measure.js.map +1 -1
- package/dist/application/context/plan-service.js +6 -6
- package/dist/application/context/plan-service.js.map +1 -1
- package/dist/application/design/design-bundle-service.js +148 -0
- package/dist/application/design/design-bundle-service.js.map +1 -0
- package/dist/application/design/design-gate-service.js +246 -0
- package/dist/application/design/design-gate-service.js.map +1 -0
- package/dist/application/design/design-graph-service.js +85 -0
- package/dist/application/design/design-graph-service.js.map +1 -0
- package/dist/application/design/design-index-service.js +132 -0
- package/dist/application/design/design-index-service.js.map +1 -0
- package/dist/application/design/design-proposal-service.js +69 -0
- package/dist/application/design/design-proposal-service.js.map +1 -0
- package/dist/application/design/design-publish-service.js +756 -0
- package/dist/application/design/design-publish-service.js.map +1 -0
- package/dist/application/design/design-record-service.js +100 -0
- package/dist/application/design/design-record-service.js.map +1 -0
- package/dist/application/design/design-resolver-service.js +165 -0
- package/dist/application/design/design-resolver-service.js.map +1 -0
- package/dist/application/flow/advance.js +533 -0
- package/dist/application/flow/advance.js.map +1 -0
- package/dist/application/flow/flow-service.js +65 -0
- package/dist/application/flow/flow-service.js.map +1 -0
- package/dist/application/flow/run-projection.js +80 -0
- package/dist/application/flow/run-projection.js.map +1 -0
- package/dist/application/flow/run-state-service.js +107 -0
- package/dist/application/flow/run-state-service.js.map +1 -0
- package/dist/application/flow/submit.js +423 -0
- package/dist/application/flow/submit.js.map +1 -0
- package/dist/application/resume-service.js +46 -14
- package/dist/application/resume-service.js.map +1 -1
- package/dist/application/self/install-skill.js +11 -0
- package/dist/application/self/install-skill.js.map +1 -1
- package/dist/application/self/uninstall.js +21 -0
- package/dist/application/self/uninstall.js.map +1 -1
- package/dist/application/semantic-operation/protocol.js +18 -12
- package/dist/application/semantic-operation/protocol.js.map +1 -1
- package/dist/application/semantic-operation/publish.js +56 -9
- package/dist/application/semantic-operation/publish.js.map +1 -1
- package/dist/application/skills-resolver-service.js +27 -6
- package/dist/application/skills-resolver-service.js.map +1 -1
- package/dist/application/status-service.js +5 -1
- package/dist/application/status-service.js.map +1 -1
- package/dist/application/workline-index-service.js +6 -0
- package/dist/application/workline-index-service.js.map +1 -1
- package/dist/application/workspace-init-service.js +22 -2
- package/dist/application/workspace-init-service.js.map +1 -1
- package/dist/cli/commands/capability.js +182 -0
- package/dist/cli/commands/capability.js.map +1 -0
- package/dist/cli/commands/designs.js +110 -0
- package/dist/cli/commands/designs.js.map +1 -0
- package/dist/cli/commands/flow.js +71 -0
- package/dist/cli/commands/flow.js.map +1 -0
- package/dist/cli/commands/index.js +6 -0
- package/dist/cli/commands/index.js.map +1 -1
- package/dist/cli/commands/resume.js +8 -0
- package/dist/cli/commands/resume.js.map +1 -1
- package/dist/cli/commands/skills.js +55 -2
- package/dist/cli/commands/skills.js.map +1 -1
- package/dist/cli/commands/status.js +50 -0
- package/dist/cli/commands/status.js.map +1 -1
- package/dist/cli/help-groups.js +9 -0
- package/dist/cli/help-groups.js.map +1 -1
- package/dist/cli/parser.js +7 -0
- package/dist/cli/parser.js.map +1 -1
- package/dist/cli/tui/data/workflow-content.js +5 -0
- package/dist/cli/tui/data/workflow-content.js.map +1 -1
- package/dist/cli/tui/tabs/workflow-tab.js +5 -1
- package/dist/cli/tui/tabs/workflow-tab.js.map +1 -1
- package/dist/domain/capability/descriptor.js +553 -0
- package/dist/domain/capability/descriptor.js.map +1 -0
- package/dist/domain/capability/effects.js +90 -0
- package/dist/domain/capability/effects.js.map +1 -0
- package/dist/domain/capability/protocol.js +494 -0
- package/dist/domain/capability/protocol.js.map +1 -0
- package/dist/domain/contract-reader.js +84 -0
- package/dist/domain/contract-reader.js.map +1 -0
- package/dist/domain/design/adapter.js +161 -0
- package/dist/domain/design/adapter.js.map +1 -0
- package/dist/domain/design/artifact-body.js +223 -0
- package/dist/domain/design/artifact-body.js.map +1 -0
- package/dist/domain/design/artifact.js +750 -0
- package/dist/domain/design/artifact.js.map +1 -0
- package/dist/domain/design/baseline.js +359 -0
- package/dist/domain/design/baseline.js.map +1 -0
- package/dist/domain/design/capability.js +310 -0
- package/dist/domain/design/capability.js.map +1 -0
- package/dist/domain/design/closure.js +161 -0
- package/dist/domain/design/closure.js.map +1 -0
- package/dist/domain/design/direct.js +108 -0
- package/dist/domain/design/direct.js.map +1 -0
- package/dist/domain/design/external-send.js +65 -0
- package/dist/domain/design/external-send.js.map +1 -0
- package/dist/domain/design/governance.js +298 -0
- package/dist/domain/design/governance.js.map +1 -0
- package/dist/domain/design/identity.js +145 -0
- package/dist/domain/design/identity.js.map +1 -0
- package/dist/domain/design/manifest.js +552 -0
- package/dist/domain/design/manifest.js.map +1 -0
- package/dist/domain/design/maturity.js +305 -0
- package/dist/domain/design/maturity.js.map +1 -0
- package/dist/domain/design/naming.js +117 -0
- package/dist/domain/design/naming.js.map +1 -0
- package/dist/domain/design/offline.js +92 -0
- package/dist/domain/design/offline.js.map +1 -0
- package/dist/domain/design/profiles.js +212 -0
- package/dist/domain/design/profiles.js.map +1 -0
- package/dist/domain/design/projections.js +165 -0
- package/dist/domain/design/projections.js.map +1 -0
- package/dist/domain/design/proposal.js +234 -0
- package/dist/domain/design/proposal.js.map +1 -0
- package/dist/domain/design/reference.js +234 -0
- package/dist/domain/design/reference.js.map +1 -0
- package/dist/domain/design/render-bundle.js +0 -0
- package/dist/domain/design/render-bundle.js.map +1 -0
- package/dist/domain/design/rendition.js +472 -0
- package/dist/domain/design/rendition.js.map +1 -0
- package/dist/domain/design/retired.js +61 -0
- package/dist/domain/design/retired.js.map +1 -0
- package/dist/domain/design/revision.js +219 -0
- package/dist/domain/design/revision.js.map +1 -0
- package/dist/domain/design/secrets.js +86 -0
- package/dist/domain/design/secrets.js.map +1 -0
- package/dist/domain/design/sources.js +180 -0
- package/dist/domain/design/sources.js.map +1 -0
- package/dist/domain/design/validation.js +19 -0
- package/dist/domain/design/validation.js.map +1 -0
- package/dist/domain/design/visual-evidence.js +155 -0
- package/dist/domain/design/visual-evidence.js.map +1 -0
- package/dist/domain/design/yaml-subset.js +390 -0
- package/dist/domain/design/yaml-subset.js.map +1 -0
- package/dist/domain/flow/answer.js +459 -0
- package/dist/domain/flow/answer.js.map +1 -0
- package/dist/domain/flow/authority.js +2276 -0
- package/dist/domain/flow/authority.js.map +1 -0
- package/dist/domain/flow/authorization.js +62 -0
- package/dist/domain/flow/authorization.js.map +1 -0
- package/dist/domain/flow/directive.js +421 -0
- package/dist/domain/flow/directive.js.map +1 -0
- package/dist/domain/flow/rules.js +140 -0
- package/dist/domain/flow/rules.js.map +1 -0
- package/dist/domain/flow/run-state.js +317 -0
- package/dist/domain/flow/run-state.js.map +1 -0
- package/dist/domain/harnesses.js +21 -0
- package/dist/domain/harnesses.js.map +1 -1
- package/dist/domain/safe-path.js +23 -0
- package/dist/domain/safe-path.js.map +1 -0
- package/dist/domain/skills.js +26 -3
- package/dist/domain/skills.js.map +1 -1
- package/package.json +1 -1
- package/skills/w/SKILL.md +15 -13
- package/skills/w/artifacts/README.md +3 -4
- package/skills/w/artifacts/artifacts-core/CHECKPOINT.md +2 -2
- package/skills/w/commands/plan-exec.md +11 -5
- package/skills/w/commands/plan-new.md +6 -2
- package/skills/w/commands/plan-refine.md +6 -3
- package/skills/w/commands/quick.md +2 -2
- package/skills/w/commands/spec-new.md +2 -2
- package/skills/w/commands/spec-refine.md +1 -0
- package/skills/w/context/MANIFEST.json +57 -9
- package/skills/w/harness/HARNESS.md +20 -0
- package/skills/w/loops/CHASSIS.md +11 -20
- package/skills/w/loops/CODE-POLICIES.md +18 -9
- package/skills/w/loops/README.md +1 -1
- package/skills/w/loops/plan-exec-loop/LOOP.md +126 -62
- package/skills/w/loops/plan-new-loop/LOOP.md +71 -73
- package/skills/w/loops/plan-refine-loop/LOOP.md +20 -10
- package/skills/w/loops/quick-loop/LOOP.md +18 -26
- package/skills/w/loops/spec-refine-loop/LOOP.md +28 -30
- package/skills/w/modules/COMPACTION.md +2 -6
- package/skills/w/modules/DB-SCRIPTS-ONLY.md +2 -0
- package/skills/w/modules/DESIGN-REFERENCES.md +113 -0
- package/skills/w/modules/IDEATION-GATE.md +3 -3
- package/skills/w/modules/PERSIST-ROUTING.md +1 -0
- package/skills/w/modules/PLAN-EXECUTION-BATCHES.md +65 -0
- package/skills/w/modules/PLAN-INPUT.md +5 -3
- package/skills/w/modules/PLAN-REFINE-SPLIT.md +3 -1
- package/skills/w/modules/PLAN-SPLIT-GATE.md +7 -5
- package/skills/w/modules/PROMPT-CONTINUITY.md +3 -1
- package/skills/w/modules/SPEC-CHANGE-SHAPE.md +4 -4
- package/skills/w/roles/README.md +9 -5
- package/skills/w/roles/design/CONTRACT.md +80 -0
- package/skills/w/roles/design/ROLE.md +224 -0
- package/skills/w/schemas/capability-descriptor.schema.json +260 -0
- package/skills/w/schemas/design/design-baseline.v1.schema.json +71 -0
- package/skills/w/schemas/design/design-manifest.v1.schema.json +322 -0
- package/skills/w/schemas/design/design-render-bundle.v1.schema.json +191 -0
- package/skills/w/schemas/design/design-rendition.v1.schema.json +232 -0
- package/skills/w/schemas/design/design-review.v1.schema.json +72 -0
- package/skills/w/schemas/design/design-revocation.v1.schema.json +54 -0
- package/skills/w/schemas/design/ui-flow.v1.schema.json +211 -0
- package/skills/w/schemas/design/ui-screen.v1.schema.json +242 -0
- package/skills/w/artifacts/artifacts-design/SPEC.md +0 -42
- package/skills/w/modules/PLAN-DESIGN-SPECS.md +0 -12
- package/skills/w/modules/PLAN-REFINE-DESIGN-SPECS.md +0 -7
- package/skills/w/roles/ui-spec/ROLE.md +0 -147
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The shared machinery every hand-written contract validator is built on.
|
|
3
|
+
*
|
|
4
|
+
* Three properties hold across every published contract — the design formats and
|
|
5
|
+
* the capability descriptor alike — and they live here so no validator can
|
|
6
|
+
* quietly drop one:
|
|
7
|
+
*
|
|
8
|
+
* - **Every diagnostic names an artifact and a corrective action.** A rejection
|
|
9
|
+
* that only says "invalid" is a dead end for whoever has to fix it.
|
|
10
|
+
* - **Objects are closed.** The published JSON Schemas declare
|
|
11
|
+
* `additionalProperties: false`, so a key the contract does not declare is a
|
|
12
|
+
* typo of a real one, never an extension.
|
|
13
|
+
* - **Coverage is measured, not promised.** Every property read is recorded, and
|
|
14
|
+
* each drift guard compares that set against its published schema. A property
|
|
15
|
+
* declared in the schema and forgotten in the validator cannot ship.
|
|
16
|
+
*
|
|
17
|
+
* The failure CODE prefix is a constructor argument rather than a literal: the
|
|
18
|
+
* design formats answer `DESIGN_*` and the capability descriptor `CAPABILITY_*`,
|
|
19
|
+
* and a caller reading a code should learn which contract rejected it. That one
|
|
20
|
+
* parameter is the whole reason this is shared instead of copied — a second copy
|
|
21
|
+
* of `closed()` is a second place for the closed-object rule to rot.
|
|
22
|
+
*/
|
|
23
|
+
export class ContractReader {
|
|
24
|
+
codePrefix;
|
|
25
|
+
allowedKeys;
|
|
26
|
+
touched = new Set();
|
|
27
|
+
failures = [];
|
|
28
|
+
constructor(codePrefix, allowedKeys) {
|
|
29
|
+
this.codePrefix = codePrefix;
|
|
30
|
+
this.allowedKeys = allowedKeys;
|
|
31
|
+
}
|
|
32
|
+
/** Read `path`'s last segment off `node`, recording the property as covered. */
|
|
33
|
+
read(node, path) {
|
|
34
|
+
this.touched.add(path);
|
|
35
|
+
const segments = path.split(".");
|
|
36
|
+
const key = segments[segments.length - 1].replace("[]", "");
|
|
37
|
+
return node[key];
|
|
38
|
+
}
|
|
39
|
+
fail(code, artifact, message, action) {
|
|
40
|
+
this.failures.push({ code, artifact, message, action });
|
|
41
|
+
}
|
|
42
|
+
invalid(artifact, message, action) {
|
|
43
|
+
this.fail(`${this.codePrefix}_FIELD_INVALID`, artifact, message, action);
|
|
44
|
+
}
|
|
45
|
+
/** Reject anything the contract does not declare at `path` (closed objects). */
|
|
46
|
+
closed(node, path, artifact) {
|
|
47
|
+
const allowed = this.allowedKeys[path];
|
|
48
|
+
if (allowed === undefined)
|
|
49
|
+
return;
|
|
50
|
+
for (const key of Object.keys(node)) {
|
|
51
|
+
if (allowed.includes(key))
|
|
52
|
+
continue;
|
|
53
|
+
this.fail(`${this.codePrefix}_KEY_UNKNOWN`, artifact, `${path === "" ? "el documento" : `'${path}'`} no admite la clave '${key}'`, `quitala o corregí el nombre; las claves válidas son: ${allowed.join(", ")}`);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Walk an array-of-objects field. Every list in every contract shares the same
|
|
59
|
+
* three failure modes — not an array, an item that is not an object, an item
|
|
60
|
+
* carrying a key the schema does not declare — so they are stated once here and
|
|
61
|
+
* each reader stays about ITS own fields.
|
|
62
|
+
*/
|
|
63
|
+
export function* eachRecord(r, node, path, artifact, emptyMeans = "") {
|
|
64
|
+
const list = r.read(node, path);
|
|
65
|
+
if (!Array.isArray(list)) {
|
|
66
|
+
r.invalid(artifact, `'${path}' debe ser un array${emptyMeans}`, `escribí '${path}': []`);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
for (const entry of list) {
|
|
70
|
+
if (!isRecord(entry)) {
|
|
71
|
+
r.invalid(artifact, `cada entrada de '${path}' debe ser un objeto`, `revisá el array '${path}'`);
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
r.closed(entry, `${path}[]`, artifact);
|
|
75
|
+
yield entry;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
export function isRecord(value) {
|
|
79
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
80
|
+
}
|
|
81
|
+
export function isNonEmptyString(value) {
|
|
82
|
+
return typeof value === "string" && value.trim().length > 0;
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=contract-reader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contract-reader.js","sourceRoot":"","sources":["../../src/domain/contract-reader.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a renderer or adapter says it can do — and the refusal to infer the rest.
|
|
3
|
+
*
|
|
4
|
+
* Every integration declares a COMPLETE matrix. That is the whole content of
|
|
5
|
+
* this module: an absent capability is never "probably fine", never "try it and
|
|
6
|
+
* see", never a call that silently does half the job. Asking for one that was
|
|
7
|
+
* not declared comes back as an explicit degradation naming what is missing and
|
|
8
|
+
* what does exist instead — or, when the caller cannot continue without it, as a
|
|
9
|
+
* failure. Never as silence.
|
|
10
|
+
*
|
|
11
|
+
* The matrix is a TYPE, not a document: `Record<RenderCapability, boolean>` is
|
|
12
|
+
* exhaustive, so a profile that forgets to answer for `compare` does not
|
|
13
|
+
* compile. There is no JSON schema here on purpose — a profile is code shipped
|
|
14
|
+
* with the CLI, and validating it at runtime would be checking a fact the
|
|
15
|
+
* compiler already proved.
|
|
16
|
+
*
|
|
17
|
+
* A one-way adapter is perfectly valid. `handoff + record` — prepare the context,
|
|
18
|
+
* register where the result ended up — is the whole Figma conformance profile of
|
|
19
|
+
* v1, and it is honest precisely because it declares the other five as absent.
|
|
20
|
+
*/
|
|
21
|
+
/**
|
|
22
|
+
* The seven capabilities, in decreasing order of how local they are.
|
|
23
|
+
*
|
|
24
|
+
* - `handoff` — hand the bundle over. The floor: no account, no network.
|
|
25
|
+
* - `record` — register where a result lives, as a rendition.
|
|
26
|
+
* - `snapshot` — keep a local, consultable copy of the result.
|
|
27
|
+
* - `generate` — create the visual result in the tool, automatically.
|
|
28
|
+
* - `push` — write Workline's semantics into the tool.
|
|
29
|
+
* - `pull` — bring the tool's state back.
|
|
30
|
+
* - `compare` — diff the tool's state against a revision.
|
|
31
|
+
*/
|
|
32
|
+
export const RENDER_CAPABILITIES = [
|
|
33
|
+
"handoff",
|
|
34
|
+
"record",
|
|
35
|
+
"snapshot",
|
|
36
|
+
"generate",
|
|
37
|
+
"push",
|
|
38
|
+
"pull",
|
|
39
|
+
"compare",
|
|
40
|
+
];
|
|
41
|
+
/**
|
|
42
|
+
* The three v1 conformance is defined in terms of. Optional means "may be
|
|
43
|
+
* declared false", never "may be left out of the matrix": the difference between
|
|
44
|
+
* those two is exactly what this contract exists to remove.
|
|
45
|
+
*/
|
|
46
|
+
export const CONFORMANCE_CAPABILITIES = ["handoff", "record", "snapshot"];
|
|
47
|
+
/** The four that no v1 profile implements, and that all of them must declare. */
|
|
48
|
+
export const OPTIONAL_CAPABILITIES = ["generate", "push", "pull", "compare"];
|
|
49
|
+
/**
|
|
50
|
+
* The nearest declared capability that answers the SAME need, so a degradation
|
|
51
|
+
* can offer a way forward instead of just a refusal. `handoff` has none below
|
|
52
|
+
* it: it is the floor, and a profile that cannot even hand the bundle over has
|
|
53
|
+
* nothing to fall back to.
|
|
54
|
+
*/
|
|
55
|
+
const FALLBACK = {
|
|
56
|
+
handoff: null,
|
|
57
|
+
record: "handoff",
|
|
58
|
+
snapshot: "record",
|
|
59
|
+
generate: "handoff",
|
|
60
|
+
push: "handoff",
|
|
61
|
+
pull: "record",
|
|
62
|
+
compare: "snapshot",
|
|
63
|
+
};
|
|
64
|
+
const HOW_TO_INSTEAD = {
|
|
65
|
+
handoff: "entregá el bundle y operá la herramienta a mano",
|
|
66
|
+
record: "registrá el resultado como rendition con su locator",
|
|
67
|
+
snapshot: "conservá una copia local del resultado y sellala con su source_digest",
|
|
68
|
+
generate: "creá el diseño en la herramienta a partir del bundle",
|
|
69
|
+
push: "aplicá los cambios en la herramienta a mano",
|
|
70
|
+
pull: "traé el resultado a mano y registralo como propuesta",
|
|
71
|
+
compare: "compará contra el snapshot local",
|
|
72
|
+
};
|
|
73
|
+
/**
|
|
74
|
+
* Resolve a request against the matrix.
|
|
75
|
+
*
|
|
76
|
+
* The two outcomes are the contract: a declared capability is exercised, an
|
|
77
|
+
* undeclared one degrades. There is no third branch where the caller guesses,
|
|
78
|
+
* and no branch at all where the answer is nothing.
|
|
79
|
+
*/
|
|
80
|
+
export function resolveCapability(adapter, capability) {
|
|
81
|
+
if (adapter.capabilities[capability])
|
|
82
|
+
return { ok: true, capability };
|
|
83
|
+
const fallback = FALLBACK[capability];
|
|
84
|
+
const alternative = fallback !== null && adapter.capabilities[fallback]
|
|
85
|
+
? fallback
|
|
86
|
+
: (RENDER_CAPABILITIES.find((c) => adapter.capabilities[c]) ?? null);
|
|
87
|
+
return {
|
|
88
|
+
ok: false,
|
|
89
|
+
degradation: {
|
|
90
|
+
adapter: adapter.id,
|
|
91
|
+
capability,
|
|
92
|
+
message: `el perfil '${adapter.id}' no declara '${capability}'`,
|
|
93
|
+
alternative,
|
|
94
|
+
action: alternative === null
|
|
95
|
+
? "este perfil no declara ninguna capacidad: elegí otro adapter, o hacé el handoff neutral local"
|
|
96
|
+
: `usá '${alternative}': ${HOW_TO_INSTEAD[alternative]}`,
|
|
97
|
+
},
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
/** The same degradation as a failure, for a caller that cannot continue without it. */
|
|
101
|
+
export function degradationFailure(degradation, artifact) {
|
|
102
|
+
return {
|
|
103
|
+
code: "DESIGN_CAPABILITY_UNDECLARED",
|
|
104
|
+
artifact,
|
|
105
|
+
message: degradation.message,
|
|
106
|
+
action: degradation.action,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
/** Look an adapter up. Null — never a guess — when the registry does not have it. */
|
|
110
|
+
export function findAdapter(id, registry) {
|
|
111
|
+
return registry[id] ?? null;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Ask for an adapter that has to be there. Separate from `findAdapter` so the
|
|
115
|
+
* diagnostic can list what IS registered: "no existe 'figma-api'" is a dead end
|
|
116
|
+
* when the answer the caller needed was "hay 'figma' y 'portable-html'".
|
|
117
|
+
*/
|
|
118
|
+
export function requireAdapter(id, registry, artifact) {
|
|
119
|
+
const found = findAdapter(id, registry);
|
|
120
|
+
if (found !== null)
|
|
121
|
+
return { ok: true, value: found };
|
|
122
|
+
const known = Object.keys(registry).sort();
|
|
123
|
+
return {
|
|
124
|
+
ok: false,
|
|
125
|
+
failure: {
|
|
126
|
+
code: "DESIGN_ADAPTER_UNKNOWN",
|
|
127
|
+
artifact,
|
|
128
|
+
message: `no hay ningún perfil de renderer/adapter '${id}'`,
|
|
129
|
+
action: known.length === 0
|
|
130
|
+
? "no hay perfiles registrados: el camino local (validar, leer y handoff neutral) no necesita ninguno"
|
|
131
|
+
: `los perfiles registrados son: ${known.join(", ")}`,
|
|
132
|
+
},
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
/** The adapter facet a bundle records. */
|
|
136
|
+
export function bundleAdapterOf(adapter) {
|
|
137
|
+
return { profile: adapter.id, version: adapter.version };
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Everything this profile cannot represent, as a bundle's loss report.
|
|
141
|
+
*
|
|
142
|
+
* Its own declared losses PLUS one entry per undeclared capability. The second
|
|
143
|
+
* half is what makes the report answer "what can this not do with my design"
|
|
144
|
+
* rather than only "what does this renderer draw badly".
|
|
145
|
+
*/
|
|
146
|
+
export function declaredLosses(adapter) {
|
|
147
|
+
return [
|
|
148
|
+
...adapter.losses,
|
|
149
|
+
...RENDER_CAPABILITIES.filter((c) => !adapter.capabilities[c]).map((c) => ({
|
|
150
|
+
subject: `capability:${c}`,
|
|
151
|
+
why: `el perfil '${adapter.id}' no declara '${c}'${FALLBACK[c] !== null && adapter.capabilities[FALLBACK[c]]
|
|
152
|
+
? `; lo más cercano que declara es '${FALLBACK[c]}'`
|
|
153
|
+
: ""}`,
|
|
154
|
+
})),
|
|
155
|
+
];
|
|
156
|
+
}
|
|
157
|
+
/** Does this profile satisfy v1 conformance for the capabilities it claims? */
|
|
158
|
+
export function conformanceOf(adapter) {
|
|
159
|
+
return CONFORMANCE_CAPABILITIES.filter((c) => adapter.capabilities[c]);
|
|
160
|
+
}
|
|
161
|
+
//# sourceMappingURL=adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter.js","sourceRoot":"","sources":["../../../src/domain/design/adapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
import { ARTIFACT_REF_GLOBAL, CRITERION_GLOBAL } from "./identity.js";
|
|
2
|
+
/** Flow v1 — once each, in this order. */
|
|
3
|
+
export const FLOW_HEADINGS = [
|
|
4
|
+
"Goal and outcome",
|
|
5
|
+
"Preconditions and entry",
|
|
6
|
+
"Main journey",
|
|
7
|
+
"Alternatives and recovery",
|
|
8
|
+
"Permissions and privacy",
|
|
9
|
+
"Traceability",
|
|
10
|
+
];
|
|
11
|
+
/** Screen v1 — once each, in this order. */
|
|
12
|
+
export const SCREEN_HEADINGS = [
|
|
13
|
+
"Purpose and context",
|
|
14
|
+
"Structure and content",
|
|
15
|
+
"Components and design-system deltas",
|
|
16
|
+
"Data, permissions and validation",
|
|
17
|
+
"States and transitions",
|
|
18
|
+
"Interaction and navigation",
|
|
19
|
+
"Responsive and adaptation",
|
|
20
|
+
"Localization",
|
|
21
|
+
"Accessibility",
|
|
22
|
+
"Edge cases and degradation",
|
|
23
|
+
"Traceability",
|
|
24
|
+
];
|
|
25
|
+
/**
|
|
26
|
+
* The sections that never accept a non-applicability claim. They carry what the
|
|
27
|
+
* artifact IS: drop them and there is nothing left to implement against.
|
|
28
|
+
*/
|
|
29
|
+
export const ESSENTIAL_HEADINGS = {
|
|
30
|
+
flow: ["Goal and outcome", "Main journey", "Traceability"],
|
|
31
|
+
screen: [
|
|
32
|
+
"Purpose and context",
|
|
33
|
+
"Structure and content",
|
|
34
|
+
"States and transitions",
|
|
35
|
+
"Interaction and navigation",
|
|
36
|
+
"Accessibility",
|
|
37
|
+
"Traceability",
|
|
38
|
+
],
|
|
39
|
+
};
|
|
40
|
+
export const HEADINGS = {
|
|
41
|
+
flow: FLOW_HEADINGS,
|
|
42
|
+
screen: SCREEN_HEADINGS,
|
|
43
|
+
};
|
|
44
|
+
/** `Data, permissions and validation` → `data_permissions_and_validation`. */
|
|
45
|
+
export function headingKey(heading) {
|
|
46
|
+
return heading
|
|
47
|
+
.toLowerCase()
|
|
48
|
+
.replace(/[^a-z0-9]+/g, "_")
|
|
49
|
+
.replace(/^_|_$/g, "");
|
|
50
|
+
}
|
|
51
|
+
/** The `not_applicable` keys each kind admits — derived from its own headings. */
|
|
52
|
+
export function conditionalKeys(kind) {
|
|
53
|
+
const essential = new Set(ESSENTIAL_HEADINGS[kind]);
|
|
54
|
+
return HEADINGS[kind].filter((h) => !essential.has(h)).map(headingKey);
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Placeholders that look like an answer and are not. A section may legitimately
|
|
58
|
+
* say "ninguno" or "none" — that is a statement about the design. `N/A`, `TBD`
|
|
59
|
+
* and a lone dash are refusals to answer, and the contract has a proper place
|
|
60
|
+
* for those: `not_applicable` with a reason.
|
|
61
|
+
*/
|
|
62
|
+
export const PLACEHOLDER = /^(n\/?a\.?|n\.a\.|tbd|todo|pendiente|\?+|[-–—*]+)$/i;
|
|
63
|
+
/** Split the body into its `##` sections. `#`/`###` are content, not structure. */
|
|
64
|
+
export function parseBody(body, firstLine) {
|
|
65
|
+
const lines = body.split(/\r?\n/);
|
|
66
|
+
const sections = [];
|
|
67
|
+
const order = [];
|
|
68
|
+
const preamble = [];
|
|
69
|
+
let current = null;
|
|
70
|
+
let fence = null;
|
|
71
|
+
const close = () => {
|
|
72
|
+
if (current === null)
|
|
73
|
+
return;
|
|
74
|
+
const text = current.text.join("\n").trim();
|
|
75
|
+
sections.push({
|
|
76
|
+
heading: current.heading,
|
|
77
|
+
key: headingKey(current.heading),
|
|
78
|
+
text,
|
|
79
|
+
prose: stripFences(current.text).join("\n").trim(),
|
|
80
|
+
line: current.line,
|
|
81
|
+
});
|
|
82
|
+
};
|
|
83
|
+
for (let i = 0; i < lines.length; i++) {
|
|
84
|
+
const line = lines[i];
|
|
85
|
+
fence = trackFence(line, fence);
|
|
86
|
+
const match = fence === null ? /^##\s+(.+?)\s*$/.exec(line) : null;
|
|
87
|
+
if (match === null) {
|
|
88
|
+
if (current !== null)
|
|
89
|
+
current.text.push(line);
|
|
90
|
+
else if (line.trim().length > 0 && !/^#\s+/.test(line))
|
|
91
|
+
preamble.push(line.trim());
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
close();
|
|
95
|
+
const heading = match[1];
|
|
96
|
+
order.push(heading);
|
|
97
|
+
current = { heading, line: firstLine + i, text: [] };
|
|
98
|
+
}
|
|
99
|
+
close();
|
|
100
|
+
return { sections, order, preamble: preamble.join("\n") };
|
|
101
|
+
}
|
|
102
|
+
/** Track ``` and ~~~ fences. Returns the open fence marker, or null outside one. */
|
|
103
|
+
function trackFence(line, open) {
|
|
104
|
+
const match = /^\s*(```+|~~~+)/.exec(line);
|
|
105
|
+
if (match === null)
|
|
106
|
+
return open;
|
|
107
|
+
const marker = match[1].slice(0, 3);
|
|
108
|
+
if (open === null)
|
|
109
|
+
return marker;
|
|
110
|
+
return marker === open ? null : open;
|
|
111
|
+
}
|
|
112
|
+
function stripFences(lines) {
|
|
113
|
+
const out = [];
|
|
114
|
+
let fence = null;
|
|
115
|
+
for (const line of lines) {
|
|
116
|
+
const next = trackFence(line, fence);
|
|
117
|
+
if (fence === null && next !== null) {
|
|
118
|
+
fence = next;
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
if (fence !== null) {
|
|
122
|
+
if (next === null)
|
|
123
|
+
fence = null;
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
out.push(line);
|
|
127
|
+
}
|
|
128
|
+
return out;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* The heading contract: the expected list, once each, in order, non-empty, with
|
|
132
|
+
* no placeholder standing in for content and no heading nobody declared.
|
|
133
|
+
*/
|
|
134
|
+
export function checkHeadings(r, parsed, kind, artifact) {
|
|
135
|
+
checkPresence(r, parsed, kind, artifact);
|
|
136
|
+
checkOrder(r, parsed, kind, artifact);
|
|
137
|
+
checkContent(r, parsed, kind, artifact);
|
|
138
|
+
}
|
|
139
|
+
/** Every expected heading exactly once, and nothing the contract does not name. */
|
|
140
|
+
function checkPresence(r, parsed, kind, artifact) {
|
|
141
|
+
const expected = HEADINGS[kind];
|
|
142
|
+
const expectedSet = new Set(expected);
|
|
143
|
+
const seen = new Map();
|
|
144
|
+
for (const heading of parsed.order) {
|
|
145
|
+
seen.set(heading, (seen.get(heading) ?? 0) + 1);
|
|
146
|
+
if (expectedSet.has(heading))
|
|
147
|
+
continue;
|
|
148
|
+
r.fail("DESIGN_HEADING_UNKNOWN", artifact, `'## ${heading}' no es una sección de ${kind} v1`, `usá solo las ${expected.length} secciones del contrato: ${expected.join(" · ")}`);
|
|
149
|
+
}
|
|
150
|
+
for (const heading of expected) {
|
|
151
|
+
const count = seen.get(heading) ?? 0;
|
|
152
|
+
if (count === 0) {
|
|
153
|
+
r.fail("DESIGN_HEADING_MISSING", artifact, `falta la sección '## ${heading}'`, "escribila con texto propio; omitirla no la vuelve no aplicable");
|
|
154
|
+
}
|
|
155
|
+
else if (count > 1) {
|
|
156
|
+
r.fail("DESIGN_HEADING_DUPLICATE", artifact, `'## ${heading}' aparece ${count} veces`, "dejá una sola y fusioná su contenido");
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Order is only meaningful over the headings actually present and expected —
|
|
162
|
+
* reporting it on top of a missing heading would be noise on top of noise.
|
|
163
|
+
*/
|
|
164
|
+
function checkOrder(r, parsed, kind, artifact) {
|
|
165
|
+
const expected = HEADINGS[kind];
|
|
166
|
+
const expectedSet = new Set(expected);
|
|
167
|
+
const present = parsed.order.filter((h) => expectedSet.has(h));
|
|
168
|
+
const canonical = expected.filter((h) => present.includes(h));
|
|
169
|
+
if (present.length !== canonical.length)
|
|
170
|
+
return;
|
|
171
|
+
if (present.join("\n") === canonical.join("\n"))
|
|
172
|
+
return;
|
|
173
|
+
r.fail("DESIGN_HEADING_ORDER", artifact, `las secciones están fuera de orden: ${present.join(" · ")}`, `el orden de ${kind} v1 es: ${canonical.join(" · ")}`);
|
|
174
|
+
}
|
|
175
|
+
/** Each section carries real text — never empty, never a placeholder. */
|
|
176
|
+
function checkContent(r, parsed, kind, artifact) {
|
|
177
|
+
const expectedSet = new Set(HEADINGS[kind]);
|
|
178
|
+
for (const section of parsed.sections) {
|
|
179
|
+
if (!expectedSet.has(section.heading))
|
|
180
|
+
continue;
|
|
181
|
+
if (section.text.length === 0) {
|
|
182
|
+
r.fail("DESIGN_SECTION_EMPTY", artifact, `'## ${section.heading}' (línea ${section.line}) no tiene texto`, "cada sección lleva texto propio coherente con el frontmatter");
|
|
183
|
+
continue;
|
|
184
|
+
}
|
|
185
|
+
if (!PLACEHOLDER.test(section.text))
|
|
186
|
+
continue;
|
|
187
|
+
r.fail("DESIGN_SECTION_PLACEHOLDER", artifact, `'## ${section.heading}' (línea ${section.line}) dice solo '${section.text}'`, isEssential(kind, section.heading)
|
|
188
|
+
? "esta sección es esencial y no admite no-aplicabilidad: escribí su contenido"
|
|
189
|
+
: `si de verdad no aplica, declaralo en 'not_applicable.${section.key}' con una razón, y explicalo acá`);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
export function isEssential(kind, heading) {
|
|
193
|
+
return ESSENTIAL_HEADINGS[kind].includes(heading);
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Canonical references the body cites, in document order and deduplicated.
|
|
197
|
+
*
|
|
198
|
+
* Only the exact `DES-NNN/XXX-NNN@rN[#anchor]` form is extracted — never prose.
|
|
199
|
+
* That is the whole point: cross-validation may not depend on reading a
|
|
200
|
+
* sentence, so anything the author writes informally is simply not a reference.
|
|
201
|
+
*/
|
|
202
|
+
export function bodyReferences(parsed) {
|
|
203
|
+
return harvest(parsed, ARTIFACT_REF_GLOBAL);
|
|
204
|
+
}
|
|
205
|
+
/** Acceptance criteria the body cites, in document order and deduplicated. */
|
|
206
|
+
export function bodyCriteria(parsed) {
|
|
207
|
+
return harvest(parsed, CRITERION_GLOBAL);
|
|
208
|
+
}
|
|
209
|
+
/** Asset digests the body cites. Same closed grammar as everywhere else. */
|
|
210
|
+
export function bodyDigests(parsed) {
|
|
211
|
+
return harvest(parsed, /sha256:[0-9a-f]{64}/g);
|
|
212
|
+
}
|
|
213
|
+
function harvest(parsed, pattern) {
|
|
214
|
+
const out = [];
|
|
215
|
+
for (const prose of [parsed.preamble, ...parsed.sections.map((s) => s.prose)]) {
|
|
216
|
+
for (const match of prose.matchAll(pattern)) {
|
|
217
|
+
if (!out.includes(match[0]))
|
|
218
|
+
out.push(match[0]);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
return out;
|
|
222
|
+
}
|
|
223
|
+
//# sourceMappingURL=artifact-body.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"artifact-body.js","sourceRoot":"","sources":["../../../src/domain/design/artifact-body.ts"],"names":[],"mappings":"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"}
|