ketatlas 0.2.0 → 0.2.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/CHANGELOG.md +6 -0
- package/README.md +4 -4
- package/docs/progress.md +11 -5
- package/package.json +1 -1
- package/skills/ketatlas/SKILL.md +2 -0
- package/src/index.d.ts +9 -0
- package/src/index.js +10 -3
- package/src/progress-ui.js +41 -1
- package/src/progress.js +24 -0
- package/src/template.js +1 -1
- package/styles/ketatlas.css +73 -0
- package/templates/basic/README.md +1 -1
- package/templates/process/README.md +1 -1
- package/templates/web/README.md +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.2.1
|
|
4
|
+
|
|
5
|
+
- Show compact numeric progress badges after workflow step counts, with status counts, checklist completion and blockers in tooltips.
|
|
6
|
+
- Place project-wide verified/checklist percentages and blockers next to Screens in the top bar.
|
|
7
|
+
- Deduplicate reused screens and variants, exclude process-only steps, and update the sidebar after saves, refreshes and flow navigation.
|
|
8
|
+
|
|
3
9
|
## 0.2.0
|
|
4
10
|
|
|
5
11
|
- Track delivery per screen in a separate progress JSON, with acceptance checks, blockers, ownership, task references and PR/test/release evidence.
|
package/README.md
CHANGED
|
@@ -17,15 +17,15 @@ https://github.com/user-attachments/assets/13f24fc8-7b8e-4bda-9e02-364c120ee163
|
|
|
17
17
|
[KetAtlas is available on npm](https://www.npmjs.com/package/ketatlas). Use Node.js 22+ and run it from any directory:
|
|
18
18
|
|
|
19
19
|
```sh
|
|
20
|
-
npx --yes ketatlas@0.2.
|
|
21
|
-
npx --yes ketatlas@0.2.
|
|
22
|
-
npx --yes ketatlas@0.2.
|
|
20
|
+
npx --yes ketatlas@0.2.1 scaffold my-atlas --template web
|
|
21
|
+
npx --yes ketatlas@0.2.1 serve my-atlas/atlas.json
|
|
22
|
+
npx --yes ketatlas@0.2.1 audit my-atlas/atlas.json --strict
|
|
23
23
|
```
|
|
24
24
|
|
|
25
25
|
Or install the CLI once for your user account:
|
|
26
26
|
|
|
27
27
|
```sh
|
|
28
|
-
npm install --global ketatlas@0.2.
|
|
28
|
+
npm install --global ketatlas@0.2.1
|
|
29
29
|
ketatlas scaffold my-atlas
|
|
30
30
|
ketatlas serve my-atlas/atlas.json
|
|
31
31
|
ketatlas audit my-atlas/atlas.json --strict
|
package/docs/progress.md
CHANGED
|
@@ -2,6 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
Open **Screens** to review delivery across the project. Counts use unique screen IDs, not repeated workflow nodes. Filter by status, workflow, blocker, or search names, IDs, tasks and owners. **View in map** focuses a screen; **Screen progress** opens its record from the node inspector. Mockup badges remain separate from implementation status.
|
|
4
4
|
|
|
5
|
+
## Sidebar and project completion
|
|
6
|
+
|
|
7
|
+
Project-wide verified/checklist percentages and blocker counts appear in the top bar beside **Screens**. The sidebar shows one compact numeric badge after each workflow’s step count (`2 steps [30%]`). **Verified %** is the number of Verified screens divided by the total unique screens in that scope. Repeated nodes and error variants count once; note/external nodes do not count. Screenless flows have no badge. Percentages round down so unfinished work cannot appear as 100%.
|
|
8
|
+
|
|
9
|
+
The badge tooltip and accessible label include status counts, blockers and **Checks %**, which counts completed recorded acceptance checks over all recorded checks, with an explicit unscoped-screen count when checklists are missing. This is not an estimate of effort, and 100% of a partial checklist does not make a screen Verified. Saving or refreshing progress updates the sidebar; changing or searching workflows preserves the current progress.
|
|
10
|
+
|
|
5
11
|
## Status and scope
|
|
6
12
|
|
|
7
13
|
| Status | Meaning |
|
|
@@ -63,11 +69,11 @@ Evidence kinds are `pr`, `test`, `release`, `reference`. Required fields: `id`,
|
|
|
63
69
|
## Editing locally and from agents
|
|
64
70
|
|
|
65
71
|
```sh
|
|
66
|
-
npx --yes ketatlas@0.2.
|
|
67
|
-
npx --yes ketatlas@0.2.
|
|
68
|
-
npx --yes ketatlas@0.2.
|
|
69
|
-
npx --yes ketatlas@0.2.
|
|
70
|
-
npx --yes ketatlas@0.2.
|
|
72
|
+
npx --yes ketatlas@0.2.1 serve atlas.json
|
|
73
|
+
npx --yes ketatlas@0.2.1 serve atlas.json --read-only
|
|
74
|
+
npx --yes ketatlas@0.2.1 progress atlas.json --init
|
|
75
|
+
npx --yes ketatlas@0.2.1 progress atlas.json --json
|
|
76
|
+
npx --yes ketatlas@0.2.1 progress atlas.json --set sign-in --record record.json --expect REVISION_FROM_READ
|
|
71
77
|
```
|
|
72
78
|
|
|
73
79
|
`--init` explicitly creates Unassessed records and refuses an existing progress file. `--set` replaces one complete screen record; preserve existing checklist IDs, evidence and state references. Read the revision with `--json` first. Do not retry a stale revision by blindly substituting a new one: reload and reconcile changes. `updatedAt` is stamped on successful record writes.
|
package/package.json
CHANGED
package/skills/ketatlas/SKILL.md
CHANGED
|
@@ -141,3 +141,5 @@ Update the project's README with flow-to-screen/state coverage, assumptions, dem
|
|
|
141
141
|
When implementing or reviewing screens, track progress in the sibling `<atlas-name>.progress.json`. Use KetAtlas 0.2.0 or newer. Keep version 1 workflow JSON unchanged. Read `ketatlas progress atlas.json --json`, preserve existing evidence/check IDs and state references, then update one record with `--set <screen-id> --record <record.json> --expect <revision>`. Re-read and reconcile conflicts instead of overwriting another writer. Run `audit` after updates.
|
|
142
142
|
|
|
143
143
|
Map task scope to screen IDs before assigning progress. Start unknown coverage at `unassessed`; a mockup is not implementation evidence. Use `planned`, `in_progress`, `in_review`, `implemented`, `verified` with a separate blocker reason/next action. Link PRs and exact merge commits, pin/release evidence, and test evidence at the revision/environment actually checked. Do not infer deployment, full screen coverage or verification from a PR merge or green aggregate CI. Completed acceptance checks need evidence; `verified` requires passed test evidence with revision and environment for every recorded check and no blocker. Track error/recovery states using check `nodes` references. Leave unrelated or unreviewed product surfaces unassessed and say why. See `docs/progress.md` in the package for the complete contract.
|
|
144
|
+
|
|
145
|
+
Sidebar percentages distinguish Verified screens from completed recorded checks. Do not assign arbitrary weights to intermediate statuses or remove unknown/unscoped screens to inflate completion. Workflow counts deduplicate screen IDs, including variants; process-only flows have no screen percentage.
|
package/src/index.d.ts
CHANGED
|
@@ -170,3 +170,12 @@ export function loadAtlas(
|
|
|
170
170
|
url: string | URL,
|
|
171
171
|
options?: AtlasOptions,
|
|
172
172
|
): Promise<AtlasInstance>;
|
|
173
|
+
|
|
174
|
+
/** Unique-screen delivery and recorded-check completion for one workflow; screenless flows return null percentages. */
|
|
175
|
+
export function summarizeFlowProgress(
|
|
176
|
+
data: AtlasProgress,
|
|
177
|
+
flow: AtlasFlow,
|
|
178
|
+
): ReturnType<typeof summarizeProgress> & {
|
|
179
|
+
verifiedPercent: number | null;
|
|
180
|
+
checks: { done: number; total: number; unscoped: number; percent: number | null };
|
|
181
|
+
};
|
package/src/index.js
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import { mountProgress } from "./progress-ui.js";
|
|
2
2
|
import { emptyProgress, requireProgress } from "./progress.js";
|
|
3
|
-
export {
|
|
3
|
+
export {
|
|
4
|
+
validateProgress,
|
|
5
|
+
summarizeProgress,
|
|
6
|
+
summarizeFlowProgress,
|
|
7
|
+
progressStatuses,
|
|
8
|
+
} from "./progress.js";
|
|
4
9
|
import { normalizeAtlas, safeURL } from "./config.js";
|
|
5
10
|
import { layoutAtlas, edgePath } from "./layout.js";
|
|
6
11
|
import { template, escapeHTML as e } from "./template.js";
|
|
@@ -117,6 +122,7 @@ export function createAtlas(container, input, options = {}) {
|
|
|
117
122
|
world.style.height = height + "px";
|
|
118
123
|
$("map-total").textContent = `${flows.length} flows · ${screens.size} screens`;
|
|
119
124
|
const groups = [...new Set(flows.map((f) => f.group))];
|
|
125
|
+
let progressUI;
|
|
120
126
|
function sidebar() {
|
|
121
127
|
const q = normalize($("flow-search").value);
|
|
122
128
|
$("flow-list").innerHTML =
|
|
@@ -130,10 +136,11 @@ export function createAtlas(container, input, options = {}) {
|
|
|
130
136
|
).includes(q),
|
|
131
137
|
);
|
|
132
138
|
return matches.length
|
|
133
|
-
? `<section><h2 class="flow-group-title">${e(group)}</h2>${matches.map((f) => `<button class="flow-link ${f === current ? "active" : ""}" data-flow="${f.id}" ${f === current ? 'aria-current="true"' : ""}><span class="flow-number">${String(f.index + 1).padStart(2, "0")}</span><span><strong>${e(f.title)}</strong><small>${f.nodes.length} steps
|
|
139
|
+
? `<section><h2 class="flow-group-title">${e(group)}</h2>${matches.map((f) => `<button class="flow-link ${f === current ? "active" : ""}" data-flow="${f.id}" ${f === current ? 'aria-current="true"' : ""}><span class="flow-number">${String(f.index + 1).padStart(2, "0")}</span><span class="flow-link-copy"><strong>${e(f.title)}</strong><small>${f.nodes.length} steps <span class="flow-progress" data-progress-flow="${f.id}"></span></small></span></button>`).join("")}</section>`
|
|
134
140
|
: "";
|
|
135
141
|
})
|
|
136
142
|
.join("") || '<p class="mock-filter-empty">No matching workflows.</p>';
|
|
143
|
+
progressUI?.paintSidebar();
|
|
137
144
|
}
|
|
138
145
|
const defs = `<defs>${[
|
|
139
146
|
["main", "--kv-accent"],
|
|
@@ -544,7 +551,7 @@ export function createAtlas(container, input, options = {}) {
|
|
|
544
551
|
const n = event.target.closest("[data-node]");
|
|
545
552
|
if (n && !event.target.closest("button")) openScreen(nodeByKey.get(n.dataset.node));
|
|
546
553
|
});
|
|
547
|
-
|
|
554
|
+
progressUI = mountProgress(root, config, progressData, options, (id) => {
|
|
548
555
|
const n = nodes.find((n) => n.screenId === id);
|
|
549
556
|
if (n) {
|
|
550
557
|
setCurrent(flowById.get(n.flowId));
|
package/src/progress-ui.js
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import { escapeHTML as e } from "./template.js";
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
progressFor,
|
|
4
|
+
progressStatuses,
|
|
5
|
+
summarizeProgress,
|
|
6
|
+
summarizeFlowProgress,
|
|
7
|
+
requireProgress,
|
|
8
|
+
} from "./progress.js";
|
|
3
9
|
import { safeURL } from "./config.js";
|
|
4
10
|
const optionsHTML = (values, selected) =>
|
|
5
11
|
Object.entries(values)
|
|
@@ -32,7 +38,40 @@ export function mountProgress(root, config, initial, options, selectScreen) {
|
|
|
32
38
|
const badge = (r) =>
|
|
33
39
|
`<span class="progress-badge" data-status="${e(r.status)}">${e(progressStatuses[r.status])}</span>${r.blocker?.trim() ? '<span class="progress-blocked">Blocked</span>' : ""}`;
|
|
34
40
|
const record = (id) => progressFor(data, id);
|
|
41
|
+
function paintSidebar() {
|
|
42
|
+
for (const el of root.querySelectorAll("[data-progress-flow], #project-progress")) {
|
|
43
|
+
const project = el.id === "project-progress";
|
|
44
|
+
const flow = project
|
|
45
|
+
? { nodes: config.screens.map((s) => ({ screen: s.id })) }
|
|
46
|
+
: config.flows.find((f) => f.id === el.dataset.progressFlow);
|
|
47
|
+
const summary = summarizeFlowProgress(data, flow);
|
|
48
|
+
el.hidden = !summary.total;
|
|
49
|
+
if (!summary.total) {
|
|
50
|
+
el.textContent = "";
|
|
51
|
+
el.removeAttribute("title");
|
|
52
|
+
el.removeAttribute("aria-label");
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
const statuses = Object.entries(progressStatuses)
|
|
56
|
+
.filter(([key]) => summary.counts[key])
|
|
57
|
+
.map(([key, label]) => `${summary.counts[key]} ${label.toLowerCase()}`)
|
|
58
|
+
.join(" · ");
|
|
59
|
+
const checks = summary.checks;
|
|
60
|
+
const details = `${summary.verifiedPercent}% verified · ${summary.counts.verified}/${summary.total} screens. ${statuses}${summary.blocked ? ` · ${summary.blocked} blocked` : ""}. ${checks.total ? `Checks ${checks.percent}% · ${checks.done}/${checks.total}` : "No checks recorded"}${checks.unscoped ? ` · ${checks.unscoped} unscoped` : ""}.`;
|
|
61
|
+
if (project) {
|
|
62
|
+
el.innerHTML = `<span><b>${summary.verifiedPercent}%</b> verified</span><span><b>${checks.percent ?? "—"}${checks.percent === null ? "" : "%"}</b> checks</span>${summary.blocked ? `<span class="project-blocked"><b>${summary.blocked}</b> blocked</span>` : ""}`;
|
|
63
|
+
} else el.textContent = `${summary.verifiedPercent}%`;
|
|
64
|
+
el.title = details;
|
|
65
|
+
el.setAttribute("aria-label", details);
|
|
66
|
+
el.dataset.tone = summary.blocked
|
|
67
|
+
? "blocked"
|
|
68
|
+
: summary.verifiedPercent === 100
|
|
69
|
+
? "complete"
|
|
70
|
+
: "pending";
|
|
71
|
+
}
|
|
72
|
+
}
|
|
35
73
|
function paint() {
|
|
74
|
+
paintSidebar();
|
|
36
75
|
for (const el of root.querySelectorAll("[data-progress-screen]"))
|
|
37
76
|
el.innerHTML = badge(record(el.dataset.progressScreen));
|
|
38
77
|
const summary = summarizeProgress(data, config.screens);
|
|
@@ -243,6 +282,7 @@ export function mountProgress(root, config, initial, options, selectScreen) {
|
|
|
243
282
|
return {
|
|
244
283
|
edit,
|
|
245
284
|
paint,
|
|
285
|
+
paintSidebar,
|
|
246
286
|
open() {
|
|
247
287
|
paint();
|
|
248
288
|
$("progress-screens").showModal();
|
package/src/progress.js
CHANGED
|
@@ -175,3 +175,27 @@ export function summarizeProgress(data, screens) {
|
|
|
175
175
|
}
|
|
176
176
|
return { total: screens.length, counts, blocked };
|
|
177
177
|
}
|
|
178
|
+
|
|
179
|
+
/** Delivery counts deduplicate reusable screens, including repeated error variants. */
|
|
180
|
+
export function summarizeFlowProgress(data, flow) {
|
|
181
|
+
const ids = [...new Set(flow.nodes.filter((n) => n.screen).map((n) => n.screen))];
|
|
182
|
+
const summary = summarizeProgress(
|
|
183
|
+
data,
|
|
184
|
+
ids.map((id) => ({ id })),
|
|
185
|
+
);
|
|
186
|
+
let done = 0,
|
|
187
|
+
total = 0,
|
|
188
|
+
unscoped = 0;
|
|
189
|
+
for (const id of ids) {
|
|
190
|
+
const checks = progressFor(data, id).checks || [];
|
|
191
|
+
if (!checks.length) unscoped++;
|
|
192
|
+
total += checks.length;
|
|
193
|
+
done += checks.filter((check) => check.done).length;
|
|
194
|
+
}
|
|
195
|
+
return {
|
|
196
|
+
...summary,
|
|
197
|
+
// Round down so unfinished work can never display as 100%.
|
|
198
|
+
verifiedPercent: ids.length ? Math.floor((summary.counts.verified * 100) / ids.length) : null,
|
|
199
|
+
checks: { done, total, unscoped, percent: total ? Math.floor((done * 100) / total) : null },
|
|
200
|
+
};
|
|
201
|
+
}
|
package/src/template.js
CHANGED
|
@@ -10,7 +10,7 @@ export function template(config) {
|
|
|
10
10
|
<button id="map-menu" class="icon-button" aria-label="Choose a flow" aria-expanded="false" aria-controls="map-sidebar"></button>
|
|
11
11
|
<div class="map-brand"><span class="brand-mark">K</span><span><strong>${escapeHTML(config.title)}</strong><small>KetAtlas · Workflow atlas</small></span></div>
|
|
12
12
|
<span id="map-total" class="map-total"></span>
|
|
13
|
-
<div class="map-header-actions"><button id="open-progress" data-ui="action" data-variant="secondary">Screens</button><button id="map-help" class="icon-button" aria-label="Help"></button></div>
|
|
13
|
+
<div class="map-header-actions"><div id="project-progress" class="project-progress" role="group" aria-label="Project progress"></div><button id="open-progress" data-ui="action" data-variant="secondary">Screens</button><button id="map-help" class="icon-button" aria-label="Help"></button></div>
|
|
14
14
|
</header>
|
|
15
15
|
<div class="map-layout">
|
|
16
16
|
<aside id="map-sidebar" class="map-sidebar">
|
package/styles/ketatlas.css
CHANGED
|
@@ -1284,3 +1284,76 @@ a svg {
|
|
|
1284
1284
|
color: var(--kv-text-muted);
|
|
1285
1285
|
font-weight: 400;
|
|
1286
1286
|
}
|
|
1287
|
+
|
|
1288
|
+
/* Compact verified-screen badges; detailed counts live in the tooltip. */
|
|
1289
|
+
.flow-link-copy {
|
|
1290
|
+
min-width: 0;
|
|
1291
|
+
flex: 1;
|
|
1292
|
+
}
|
|
1293
|
+
.flow-progress {
|
|
1294
|
+
display: inline-flex;
|
|
1295
|
+
align-items: center;
|
|
1296
|
+
justify-content: center;
|
|
1297
|
+
flex: none;
|
|
1298
|
+
min-width: 34px;
|
|
1299
|
+
height: 20px;
|
|
1300
|
+
padding: 0 var(--kv-space-1);
|
|
1301
|
+
border-radius: var(--kv-radius-full);
|
|
1302
|
+
background: var(--kv-surface-hover);
|
|
1303
|
+
color: var(--kv-text-muted);
|
|
1304
|
+
font-size: var(--kv-text-2xs);
|
|
1305
|
+
font-weight: var(--kv-weight-medium);
|
|
1306
|
+
font-variant-numeric: tabular-nums;
|
|
1307
|
+
line-height: 1;
|
|
1308
|
+
letter-spacing: normal;
|
|
1309
|
+
white-space: nowrap;
|
|
1310
|
+
vertical-align: middle;
|
|
1311
|
+
}
|
|
1312
|
+
.flow-progress[hidden] {
|
|
1313
|
+
display: none;
|
|
1314
|
+
}
|
|
1315
|
+
.flow-progress[data-tone="blocked"] {
|
|
1316
|
+
color: var(--kv-warning);
|
|
1317
|
+
}
|
|
1318
|
+
.flow-progress[data-tone="complete"] {
|
|
1319
|
+
color: var(--kv-positive);
|
|
1320
|
+
}
|
|
1321
|
+
|
|
1322
|
+
.project-progress {
|
|
1323
|
+
display: flex;
|
|
1324
|
+
align-items: center;
|
|
1325
|
+
gap: var(--kv-space-3);
|
|
1326
|
+
margin-right: var(--kv-space-2);
|
|
1327
|
+
color: var(--kv-text-muted);
|
|
1328
|
+
font-size: var(--kv-text-xs);
|
|
1329
|
+
font-variant-numeric: tabular-nums;
|
|
1330
|
+
white-space: nowrap;
|
|
1331
|
+
}
|
|
1332
|
+
.project-progress[hidden] {
|
|
1333
|
+
display: none;
|
|
1334
|
+
}
|
|
1335
|
+
.project-progress b {
|
|
1336
|
+
color: var(--kv-text-main);
|
|
1337
|
+
font-weight: var(--kv-weight-semibold);
|
|
1338
|
+
}
|
|
1339
|
+
.project-progress .project-blocked,
|
|
1340
|
+
.project-progress .project-blocked b {
|
|
1341
|
+
color: var(--kv-warning);
|
|
1342
|
+
}
|
|
1343
|
+
@container (max-width: 1000px) {
|
|
1344
|
+
.map-header {
|
|
1345
|
+
height: auto;
|
|
1346
|
+
min-height: 72px;
|
|
1347
|
+
flex-wrap: wrap;
|
|
1348
|
+
gap: var(--kv-space-2);
|
|
1349
|
+
}
|
|
1350
|
+
.map-header-actions {
|
|
1351
|
+
flex-basis: 100%;
|
|
1352
|
+
justify-content: flex-end;
|
|
1353
|
+
}
|
|
1354
|
+
.project-progress {
|
|
1355
|
+
margin-right: auto;
|
|
1356
|
+
gap: var(--kv-space-2);
|
|
1357
|
+
font-size: var(--kv-text-2xs);
|
|
1358
|
+
}
|
|
1359
|
+
}
|
|
@@ -7,7 +7,7 @@ npx ketatlas serve atlas.json
|
|
|
7
7
|
npx ketatlas audit atlas.json --strict
|
|
8
8
|
```
|
|
9
9
|
|
|
10
|
-
Edit `atlas.json` to change nodes, edges, and screen URLs. Screen URLs are relative to that file. Refresh the browser after editing. No wrapper HTML, package manifest, lockfile, node_modules, or build step is needed. Alternatively, install the CLI once with npm install --global ketatlas@0.2.
|
|
10
|
+
Edit `atlas.json` to change nodes, edges, and screen URLs. Screen URLs are relative to that file. Refresh the browser after editing. No wrapper HTML, package manifest, lockfile, node_modules, or build step is needed. Alternatively, install the CLI once with npm install --global ketatlas@0.2.1 and use ketatlas serve atlas.json.
|
|
11
11
|
|
|
12
12
|
Edit the HTML files in screens/ to replace the sample product. styles/design-system.css is generated from the pinned KetJS design system; do not manually fork its tokens.
|
|
13
13
|
|
|
@@ -7,7 +7,7 @@ npx ketatlas serve atlas.json
|
|
|
7
7
|
npx ketatlas audit atlas.json --strict
|
|
8
8
|
```
|
|
9
9
|
|
|
10
|
-
Edit `atlas.json` to change nodes, edges, and screen URLs. Screen URLs are relative to that file. Refresh the browser after editing. No wrapper HTML, package manifest, lockfile, node_modules, or build step is needed. Alternatively, install the CLI once with npm install --global ketatlas@0.2.
|
|
10
|
+
Edit `atlas.json` to change nodes, edges, and screen URLs. Screen URLs are relative to that file. Refresh the browser after editing. No wrapper HTML, package manifest, lockfile, node_modules, or build step is needed. Alternatively, install the CLI once with npm install --global ketatlas@0.2.1 and use ketatlas serve atlas.json.
|
|
11
11
|
|
|
12
12
|
This template models a process without HTML screens. Add a screen registry and screen nodes when needed.
|
|
13
13
|
|
package/templates/web/README.md
CHANGED
|
@@ -7,7 +7,7 @@ npx ketatlas serve atlas.json
|
|
|
7
7
|
npx ketatlas audit atlas.json --strict
|
|
8
8
|
```
|
|
9
9
|
|
|
10
|
-
Edit `atlas.json` to change nodes, edges, and screen URLs. Screen URLs are relative to that file. Refresh the browser after editing. No wrapper HTML, package manifest, lockfile, node_modules, or build step is needed. Alternatively, install the CLI once with npm install --global ketatlas@0.2.
|
|
10
|
+
Edit `atlas.json` to change nodes, edges, and screen URLs. Screen URLs are relative to that file. Refresh the browser after editing. No wrapper HTML, package manifest, lockfile, node_modules, or build step is needed. Alternatively, install the CLI once with npm install --global ketatlas@0.2.1 and use ketatlas serve atlas.json.
|
|
11
11
|
|
|
12
12
|
Edit the HTML files in screens/ to replace the sample product. styles/design-system.css is generated from the pinned KetJS design system; do not manually fork its tokens.
|
|
13
13
|
|