ketatlas 0.2.4 → 0.3.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/CHANGELOG.md +10 -0
- package/README.md +17 -15
- package/bin/discovery.js +90 -0
- package/bin/ketatlas.js +45 -17
- package/docs/agent-mockups.md +9 -5
- package/docs/architecture.md +5 -4
- package/docs/authoring.md +3 -3
- package/docs/cli.md +26 -15
- package/docs/migration.md +6 -0
- package/docs/progress.md +7 -7
- package/package.json +1 -1
- package/skills/ketatlas/SKILL.md +44 -11
- package/src/index.js +29 -15
- package/src/progress-ui.js +23 -3
- package/styles/ketatlas.css +10 -0
- package/templates/basic/README.md +5 -5
- package/templates/process/README.md +5 -5
- package/templates/web/README.md +5 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.3.0
|
|
4
|
+
|
|
5
|
+
- Standardize discoverable projects as `<name>.ketatlas/atlas.json` bundles, add `discover`, accept bundle directories in Atlas commands, and teach the bundled skill to backfill legacy projects safely.
|
|
6
|
+
- Accelerate drag, wheel, keyboard and pinch camera controls while preserving pointer-anchored zoom.
|
|
7
|
+
- Require agents to confirm a design system before visual mockup work, with Auto defaulting to Két Design System and explicit Carbon, Primer, Fluent 2, no-system, and custom-source options.
|
|
8
|
+
|
|
9
|
+
## 0.2.5
|
|
10
|
+
|
|
11
|
+
- Show separate Checks and Implemented percentage badges per workflow. Implemented includes Verified screens; project verification remains separate on the top bar. Display a dash for Checks when no checklist is recorded.
|
|
12
|
+
|
|
3
13
|
## 0.2.4
|
|
4
14
|
|
|
5
15
|
- Anchor the progress detail header directly inside the modal top border and scroll only the form beneath it.
|
package/README.md
CHANGED
|
@@ -17,21 +17,22 @@ 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
|
|
21
|
-
npx --yes ketatlas
|
|
22
|
-
npx --yes ketatlas
|
|
20
|
+
npx --yes ketatlas scaffold my-atlas.ketatlas --template web
|
|
21
|
+
npx --yes ketatlas discover . --json
|
|
22
|
+
npx --yes ketatlas serve my-atlas.ketatlas
|
|
23
|
+
npx --yes ketatlas audit my-atlas.ketatlas --strict
|
|
23
24
|
```
|
|
24
25
|
|
|
25
26
|
Or install the CLI once for your user account:
|
|
26
27
|
|
|
27
28
|
```sh
|
|
28
|
-
npm install --global ketatlas
|
|
29
|
-
ketatlas scaffold my-atlas
|
|
30
|
-
ketatlas serve my-atlas
|
|
31
|
-
ketatlas audit my-atlas
|
|
29
|
+
npm install --global ketatlas
|
|
30
|
+
ketatlas scaffold my-atlas.ketatlas
|
|
31
|
+
ketatlas serve my-atlas.ketatlas
|
|
32
|
+
ketatlas audit my-atlas.ketatlas --strict
|
|
32
33
|
```
|
|
33
34
|
|
|
34
|
-
The consumer
|
|
35
|
+
The consumer bundle is named `<name>.ketatlas/` and contains `atlas.json`, its schema, product HTML/CSS/JavaScript, local assets, and documentation. The stable directory suffix lets desktop tools discover atlases without parsing unrelated JSON. A bundle needs no `package.json`, lockfile, `node_modules`, build step, or copy of the viewer. The CLI supplies scaffold, discovery, serving, and static audit from its own installation. `audit` leaves project files unchanged unless an output file is explicitly requested. Viewing with `serve` does not write; explicit **Save progress** writes the sibling progress file. Use `--read-only` to disable editing.
|
|
35
36
|
|
|
36
37
|
Pin the version in run commands or the global installation for reproducible team workflows. Product scripts implement mock screen interactions; they are authored content, not a local installation of KetAtlas. Framework tooling and tests stay in the KetAtlas repository.
|
|
37
38
|
|
|
@@ -81,12 +82,13 @@ Open **Screens** to filter screen progress, review blockers and edit acceptance
|
|
|
81
82
|
|
|
82
83
|
## Commands
|
|
83
84
|
|
|
84
|
-
| Command
|
|
85
|
-
|
|
|
86
|
-
| `scaffold <
|
|
87
|
-
| `
|
|
88
|
-
| `
|
|
89
|
-
| `
|
|
85
|
+
| Command | Purpose |
|
|
86
|
+
| -------------------------- | -------------------------------------------------------------------------------- |
|
|
87
|
+
| `scaffold <name.ketatlas>` | Create a bundle from `basic`, `web`, or `process`. Refuses existing content. |
|
|
88
|
+
| `discover <directory>` | Find valid `*.ketatlas/atlas.json` bundles and report invalid bundles. |
|
|
89
|
+
| `serve <bundle\|json>` | Start the viewer and serve local screens. Defaults to port 4178 on localhost. |
|
|
90
|
+
| `audit <bundle\|json>` | Check configuration, reachability, local files, and literal HTML/CSS references. |
|
|
91
|
+
| `validate <bundle\|json>` | Validate configuration only, without reading screen files. |
|
|
90
92
|
|
|
91
93
|
Use `--help` for options, `--root` when assets live above the JSON directory, and `audit --json` for CI reports. [Full CLI reference →](docs/cli.md)
|
|
92
94
|
|
|
@@ -114,7 +116,7 @@ npm ci
|
|
|
114
116
|
npm run dev
|
|
115
117
|
```
|
|
116
118
|
|
|
117
|
-
The playground includes mobile sign-in, desktop approval, and a fulfilment process. These development dependencies are not required in consumer projects. To try an unpublished checkout, use `npx --yes --package ~/dev/ketatlas ketatlas serve /path/to/my-atlas
|
|
119
|
+
The playground includes mobile sign-in, desktop approval, and a fulfilment process. These development dependencies are not required in consumer projects. To try an unpublished checkout, use `npx --yes --package ~/dev/ketatlas ketatlas serve /path/to/my-atlas.ketatlas`.
|
|
118
120
|
|
|
119
121
|
Stable version increases merged into `develop` are automatically published after CI verifies the package. See [Releasing](docs/releasing.md).
|
|
120
122
|
|
package/bin/discovery.js
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { readFile, readdir, realpath, stat } from "node:fs/promises";
|
|
2
|
+
import { basename, join, resolve } from "node:path";
|
|
3
|
+
import { validateAtlas } from "../src/config.js";
|
|
4
|
+
|
|
5
|
+
export const atlasDirectorySuffix = ".ketatlas";
|
|
6
|
+
export const atlasManifestName = "atlas.json";
|
|
7
|
+
|
|
8
|
+
const excludedDirectories = new Set([
|
|
9
|
+
".git",
|
|
10
|
+
".cache",
|
|
11
|
+
".next",
|
|
12
|
+
".venv",
|
|
13
|
+
"build",
|
|
14
|
+
"dist",
|
|
15
|
+
"node_modules",
|
|
16
|
+
"vendor",
|
|
17
|
+
]);
|
|
18
|
+
|
|
19
|
+
export function isAtlasDirectory(path) {
|
|
20
|
+
return basename(resolve(path)).toLowerCase().endsWith(atlasDirectorySuffix);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function requireAtlasDirectory(path) {
|
|
24
|
+
const destination = resolve(path);
|
|
25
|
+
if (!isAtlasDirectory(destination))
|
|
26
|
+
throw new Error(`Atlas directories must end in ${atlasDirectorySuffix}.`);
|
|
27
|
+
return destination;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export async function resolveAtlasFile(target) {
|
|
31
|
+
const absolute = resolve(target);
|
|
32
|
+
const info = await stat(absolute);
|
|
33
|
+
if (!info.isDirectory()) return absolute;
|
|
34
|
+
if (!isAtlasDirectory(absolute))
|
|
35
|
+
throw new Error(`Atlas directories must end in ${atlasDirectorySuffix}.`);
|
|
36
|
+
return join(absolute, atlasManifestName);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async function describe(directory) {
|
|
40
|
+
const path = join(directory, atlasManifestName);
|
|
41
|
+
let config;
|
|
42
|
+
try {
|
|
43
|
+
config = JSON.parse(await readFile(path, "utf8"));
|
|
44
|
+
} catch (error) {
|
|
45
|
+
return { error: { path, message: error.message } };
|
|
46
|
+
}
|
|
47
|
+
const validation = validateAtlas(config);
|
|
48
|
+
if (!validation.valid)
|
|
49
|
+
return {
|
|
50
|
+
error: {
|
|
51
|
+
path,
|
|
52
|
+
message: validation.errors.map((issue) => `${issue.path}: ${issue.message}`).join("; "),
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
return {
|
|
56
|
+
atlas: {
|
|
57
|
+
path,
|
|
58
|
+
directory,
|
|
59
|
+
title: config.title,
|
|
60
|
+
screens: (config.screens || []).map(({ id, title, url }) => ({ id, title, url })),
|
|
61
|
+
flowCount: config.flows.length,
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export async function discoverAtlases(root) {
|
|
67
|
+
const workspace = await realpath(resolve(root));
|
|
68
|
+
if (!(await stat(workspace)).isDirectory())
|
|
69
|
+
throw new Error("Discovery root must be a directory.");
|
|
70
|
+
const atlases = [],
|
|
71
|
+
errors = [],
|
|
72
|
+
directories = [workspace];
|
|
73
|
+
while (directories.length) {
|
|
74
|
+
const directory = directories.pop();
|
|
75
|
+
if (isAtlasDirectory(directory)) {
|
|
76
|
+
const result = await describe(directory);
|
|
77
|
+
if (result.atlas) atlases.push(result.atlas);
|
|
78
|
+
else errors.push(result.error);
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
for (const entry of await readdir(directory, { withFileTypes: true })) {
|
|
82
|
+
if (!entry.isDirectory() || entry.isSymbolicLink() || excludedDirectories.has(entry.name))
|
|
83
|
+
continue;
|
|
84
|
+
directories.push(join(directory, entry.name));
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
atlases.sort((a, b) => a.path.localeCompare(b.path));
|
|
88
|
+
errors.sort((a, b) => a.path.localeCompare(b.path));
|
|
89
|
+
return { version: 1, root: workspace, atlases, errors };
|
|
90
|
+
}
|
package/bin/ketatlas.js
CHANGED
|
@@ -8,21 +8,29 @@ import { validateAtlas } from "../src/config.js";
|
|
|
8
8
|
import { serve } from "./server.js";
|
|
9
9
|
import { serveAtlas } from "./viewer.js";
|
|
10
10
|
import { auditAtlas } from "./audit.js";
|
|
11
|
+
import {
|
|
12
|
+
discoverAtlases,
|
|
13
|
+
isAtlasDirectory,
|
|
14
|
+
requireAtlasDirectory,
|
|
15
|
+
resolveAtlasFile,
|
|
16
|
+
} from "./discovery.js";
|
|
11
17
|
const packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
|
12
18
|
const help = `KetAtlas — scaffold, serve, and audit HTML workflow maps
|
|
13
19
|
|
|
14
|
-
ketatlas scaffold <
|
|
15
|
-
ketatlas
|
|
16
|
-
ketatlas
|
|
17
|
-
ketatlas
|
|
18
|
-
ketatlas
|
|
19
|
-
ketatlas progress <atlas.json> --
|
|
20
|
+
ketatlas scaffold <name.ketatlas> [--template basic|web|process]
|
|
21
|
+
ketatlas discover <directory> [--json]
|
|
22
|
+
ketatlas serve <name.ketatlas|atlas.json> [--port 4178] [--root directory]
|
|
23
|
+
ketatlas audit <name.ketatlas|atlas.json> [--root directory] [--json] [--strict]
|
|
24
|
+
ketatlas validate <name.ketatlas|atlas.json>
|
|
25
|
+
ketatlas progress <name.ketatlas|atlas.json> [--json] [--init]
|
|
26
|
+
ketatlas progress <name.ketatlas|atlas.json> --set <screen-id> --record <record.json> --expect <revision>
|
|
20
27
|
ketatlas --version
|
|
21
28
|
|
|
22
29
|
Examples:
|
|
23
|
-
npx ketatlas scaffold my-atlas
|
|
24
|
-
npx ketatlas
|
|
25
|
-
npx ketatlas
|
|
30
|
+
npx ketatlas scaffold my-atlas.ketatlas
|
|
31
|
+
npx ketatlas discover . --json
|
|
32
|
+
npx ketatlas serve my-atlas.ketatlas
|
|
33
|
+
npx ketatlas audit my-atlas.ketatlas --strict
|
|
26
34
|
|
|
27
35
|
Serve binds to 127.0.0.1. No HTML wrapper, build, account, or backend required.
|
|
28
36
|
`;
|
|
@@ -61,7 +69,7 @@ async function main(args) {
|
|
|
61
69
|
template = options.template || "basic";
|
|
62
70
|
if (!["basic", "web", "process"].includes(template))
|
|
63
71
|
throw new Error("Templates: basic, web, process.");
|
|
64
|
-
const destination =
|
|
72
|
+
const destination = requireAtlasDirectory(target);
|
|
65
73
|
let existing;
|
|
66
74
|
try {
|
|
67
75
|
existing = await readdir(destination);
|
|
@@ -79,10 +87,25 @@ async function main(args) {
|
|
|
79
87
|
errorOnExist: true,
|
|
80
88
|
});
|
|
81
89
|
console.log(
|
|
82
|
-
`Created ${destination}\n\nNext: npx ketatlas serve "${
|
|
90
|
+
`Created ${destination}\n\nNext: npx ketatlas serve "${destination}"\nEdit atlas.json to make it yours.`,
|
|
83
91
|
);
|
|
84
92
|
return;
|
|
85
93
|
}
|
|
94
|
+
if (command === "discover") {
|
|
95
|
+
const { target, options } = parse(rest, { json: "boolean" }),
|
|
96
|
+
result = await discoverAtlases(target);
|
|
97
|
+
if (options.json) console.log(JSON.stringify(result, null, 2));
|
|
98
|
+
else {
|
|
99
|
+
for (const atlas of result.atlases)
|
|
100
|
+
console.log(`${atlas.title}\t${atlas.path}\t${atlas.screens.length} screens`);
|
|
101
|
+
for (const error of result.errors) console.error(`ERROR ${error.path}: ${error.message}`);
|
|
102
|
+
console.log(
|
|
103
|
+
`${result.atlases.length} atlas${result.atlases.length === 1 ? "" : "es"} in ${result.root}`,
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
if (result.errors.length) process.exitCode = 1;
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
86
109
|
if (command === "audit") {
|
|
87
110
|
const { target, options } = parse(rest, {
|
|
88
111
|
root: "string",
|
|
@@ -90,7 +113,7 @@ async function main(args) {
|
|
|
90
113
|
strict: "boolean",
|
|
91
114
|
output: "string",
|
|
92
115
|
});
|
|
93
|
-
const report = await auditAtlas(target, options),
|
|
116
|
+
const report = await auditAtlas(await resolveAtlasFile(target), options),
|
|
94
117
|
pass = report.valid && (!options.strict || report.warnings.length === 0);
|
|
95
118
|
if (options.output)
|
|
96
119
|
await writeFile(resolve(options.output), JSON.stringify(report, null, 2) + "\n", {
|
|
@@ -109,7 +132,7 @@ async function main(args) {
|
|
|
109
132
|
}
|
|
110
133
|
if (command === "validate") {
|
|
111
134
|
const { target } = parse(rest, {}),
|
|
112
|
-
config = JSON.parse(await readFile(
|
|
135
|
+
config = JSON.parse(await readFile(await resolveAtlasFile(target), "utf8")),
|
|
113
136
|
result = validateAtlas(config);
|
|
114
137
|
for (const issue of result.errors) console.error(`ERROR ${issue.path}: ${issue.message}`);
|
|
115
138
|
for (const issue of result.warnings) console.warn(`WARN ${issue.path}: ${issue.message}`);
|
|
@@ -130,7 +153,7 @@ async function main(args) {
|
|
|
130
153
|
record: "string",
|
|
131
154
|
expect: "string",
|
|
132
155
|
});
|
|
133
|
-
const file =
|
|
156
|
+
const file = await resolveAtlasFile(target),
|
|
134
157
|
atlas = JSON.parse(await readFile(file, "utf8"));
|
|
135
158
|
const valid = validateAtlas(atlas);
|
|
136
159
|
if (!valid.valid) throw new Error(valid.errors.map((e) => e.message).join("; "));
|
|
@@ -180,9 +203,14 @@ async function main(args) {
|
|
|
180
203
|
const directory = (await stat(resolve(target))).isDirectory();
|
|
181
204
|
if (directory && options.root)
|
|
182
205
|
throw new Error("--root is only needed when serving an atlas JSON file.");
|
|
183
|
-
const server =
|
|
184
|
-
|
|
185
|
-
|
|
206
|
+
const server =
|
|
207
|
+
directory && !isAtlasDirectory(target)
|
|
208
|
+
? await serve(target, { port })
|
|
209
|
+
: await serveAtlas(await resolveAtlasFile(target), {
|
|
210
|
+
port,
|
|
211
|
+
root: options.root,
|
|
212
|
+
readOnly: options["read-only"],
|
|
213
|
+
});
|
|
186
214
|
console.log(
|
|
187
215
|
`KetAtlas: http://127.0.0.1:${server.address().port}\nServing ${resolve(target)}\nPress Ctrl+C to stop.`,
|
|
188
216
|
);
|
package/docs/agent-mockups.md
CHANGED
|
@@ -36,10 +36,12 @@ and preview the result. Return the serve command and verification results.
|
|
|
36
36
|
|
|
37
37
|
`$ketatlas` is the explicit skill invocation in Codex. In other agents, use that agent's skill selector or explicitly ask it to use the installed KetAtlas skill. Keep the same product brief.
|
|
38
38
|
|
|
39
|
-
The deliverable is data and product screen assets: JSON/schema, HTML/CSS/JavaScript, local assets, and documentation. Do not add a package manifest, lockfile, node_modules, or copied viewer/test tooling to make the atlas runnable. Use a global KetAtlas installation or a version-pinned npx command. Browser checks can use the agent's existing tooling outside the atlas folder.
|
|
39
|
+
The deliverable is a `<name>.ketatlas/` bundle containing data and product screen assets: JSON/schema, HTML/CSS/JavaScript, local assets, and documentation. Do not add a package manifest, lockfile, node_modules, or copied viewer/test tooling to make the atlas runnable. Use a global KetAtlas installation or a version-pinned npx command. Browser checks can use the agent's existing tooling outside the atlas folder.
|
|
40
40
|
|
|
41
41
|
The agent should infer routine details and record assumptions. Provide an exact list when “all screens” means a defined inventory, so missing coverage can be checked against a source.
|
|
42
42
|
|
|
43
|
+
Before it creates or edits visual screens, the skill asks for one design-system choice: Auto (Két Design System), Két Design System, Carbon, GitHub Primer, Microsoft Fluent 2, no design system, or a repository URL/local path. A design system already named in the request counts as the answer. Auto uses [Két Design System](https://github.com/ketvietlab/ketjs/tree/develop/packages/design-system). The agent inspects and uses the selected system's actual tokens, components, assets, and patterns, then records the source and integration strategy in the atlas README.
|
|
44
|
+
|
|
43
45
|
## Use a saved brief for larger projects
|
|
44
46
|
|
|
45
47
|
Save this template as `mockup-brief.md`, fill in the relevant fields, and ask: **“Use the KetAtlas skill to implement mockup-brief.md.”** The brief stays Markdown; do not add its planning fields to `atlas.json`.
|
|
@@ -52,7 +54,8 @@ Save this template as `mockup-brief.md`, fill in the relevant fields, and ask: *
|
|
|
52
54
|
- Output directory:
|
|
53
55
|
- Target platforms and viewport sizes:
|
|
54
56
|
- Product content language:
|
|
55
|
-
- Design system
|
|
57
|
+
- Design system choice (Auto/Két/Carbon/Primer/Fluent 2/none/custom source):
|
|
58
|
+
- Existing HTML and reference files/URLs:
|
|
56
59
|
- Requested flows and screen inventory:
|
|
57
60
|
- Relevant loading, empty, validation, error, and recovery states:
|
|
58
61
|
- Interactions to demonstrate and synthetic demo inputs:
|
|
@@ -76,10 +79,11 @@ For an existing prototype, ask the agent to reuse its HTML and add or update the
|
|
|
76
79
|
## Review the result
|
|
77
80
|
|
|
78
81
|
```sh
|
|
79
|
-
npx ketatlas
|
|
80
|
-
npx ketatlas
|
|
82
|
+
npx ketatlas discover . --json
|
|
83
|
+
npx ketatlas serve ./tasks/mobile.ketatlas
|
|
84
|
+
npx ketatlas audit ./tasks/mobile.ketatlas --strict
|
|
81
85
|
```
|
|
82
86
|
|
|
83
87
|
Check the delivered flow coverage against the brief. Open **Try this screen** to test the actual HTML. A successful audit confirms structural and local-file checks, not visual quality, full product coverage, or working production integrations. Intentional remote URLs require separate verification and produce strict-audit warnings.
|
|
84
88
|
|
|
85
|
-
The skill lives in this repository so teams can review and evolve it alongside the schema and CLI. It
|
|
89
|
+
The skill lives in this repository so teams can review and evolve it alongside the schema and CLI. It also backfills legacy atlas directories into the discoverable bundle pattern before extending them.
|
package/docs/architecture.md
CHANGED
|
@@ -3,8 +3,9 @@
|
|
|
3
3
|
KetAtlas is a static browser viewer plus a Node.js command-line toolkit. There is no database, account service or runtime npm dependency. The localhost CLI has a narrow, protected API to read and save the progress sidecar; static hosting remains read-only.
|
|
4
4
|
|
|
5
5
|
```text
|
|
6
|
-
atlas.json + screen HTML
|
|
6
|
+
<name>.ketatlas/atlas.json + screen HTML
|
|
7
7
|
│
|
|
8
|
+
├── discover → workspace bundle catalog
|
|
8
9
|
├── validate / audit → diagnostics and CI exit code
|
|
9
10
|
│
|
|
10
11
|
└── serve → built-in viewer page
|
|
@@ -17,7 +18,7 @@ atlas.json + screen HTML
|
|
|
17
18
|
|
|
18
19
|
## Consumer boundary
|
|
19
20
|
|
|
20
|
-
KetAtlas is installed globally or executed through npx. Consumers provide JSON, a schema, HTML/CSS/JavaScript mock screens, assets, and documentation.
|
|
21
|
+
KetAtlas is installed globally or executed through npx. Consumers provide a `<name>.ketatlas/` bundle containing JSON, a schema, HTML/CSS/JavaScript mock screens, assets, and documentation. The suffix is the discovery boundary: tools inspect only its direct `atlas.json`, not arbitrary workspace JSON. Consumers do not need a Node package, lockfile, development dependencies, viewer implementation, or build/test scripts to scaffold, discover, serve, or audit a map.
|
|
21
22
|
|
|
22
23
|
The package owns the CLI, viewer, validation, and framework verification. A product may have its own application tests elsewhere; those are independent of the map format. Static audit does not simulate product interactions. Agent browser checks can run through external tooling without adding a test harness to the delivered atlas folder.
|
|
23
24
|
|
|
@@ -32,7 +33,7 @@ The package owns the CLI, viewer, validation, and framework verification. A prod
|
|
|
32
33
|
| `src/index.d.ts` | Public TypeScript declarations. |
|
|
33
34
|
| `styles/` | Viewer layout and generated canonical design-system bundles. |
|
|
34
35
|
| `assets/` | Local fonts, licenses and provenance manifest. |
|
|
35
|
-
| `bin/` |
|
|
36
|
+
| `bin/` | Bundle discovery, scaffold, serving, validation and audit. |
|
|
36
37
|
| `templates/` | Self-contained starting projects included in the npm package. |
|
|
37
38
|
| `examples/` | Maintainer playground with mobile, web and process flows. |
|
|
38
39
|
| `scripts/` | Reproducible assets, templates, schema and package checks. |
|
|
@@ -42,7 +43,7 @@ The package owns the CLI, viewer, validation, and framework verification. A prod
|
|
|
42
43
|
|
|
43
44
|
Flows are stacked on one canvas. A row and column grow to fit their largest node, so mobile and desktop aspect ratios can coexist. The layout respects authored grid positions. Arrows use orthogonal routes and a small lane offset; this is not an obstacle-avoiding graph-layout engine. Use nearby grid cells and concise labels for readable large diagrams.
|
|
44
45
|
|
|
45
|
-
Camera changes use an animation frame and a CSS transform. Only the nearest visible screen cards receive iframes, up to the configured cap. Below the preview threshold, all cards show placeholders. This limits embedded-page cost; every node and edge still has a DOM element. There is no claim of unlimited graph size.
|
|
46
|
+
Camera changes use an animation frame and a CSS transform. Drag, wheel, keyboard and pinch input use shared accelerated motion constants while zoom remains anchored under the pointer. Only the nearest visible screen cards receive iframes, up to the configured cap. Below the preview threshold, all cards show placeholders. This limits embedded-page cost; every node and edge still has a DOM element. There is no claim of unlimited graph size.
|
|
46
47
|
|
|
47
48
|
The inspector reuses the same screen URL at its declared viewport dimensions, with no extra side padding. Its iframe is removed when closed. Reopening a screen loads a fresh instance; editing a prototype is not persistent business state.
|
|
48
49
|
|
package/docs/authoring.md
CHANGED
|
@@ -5,8 +5,8 @@ Start with a user goal: sign in, approve a purchase, or deliver an order. Give e
|
|
|
5
5
|
## 1. Create a starting point
|
|
6
6
|
|
|
7
7
|
```sh
|
|
8
|
-
ketatlas scaffold ./customer-journeys --template basic
|
|
9
|
-
ketatlas serve ./customer-journeys
|
|
8
|
+
ketatlas scaffold ./customer-journeys.ketatlas --template basic
|
|
9
|
+
ketatlas serve ./customer-journeys.ketatlas
|
|
10
10
|
```
|
|
11
11
|
|
|
12
12
|
Open a card with a double-click. The preview is actual HTML; links and JavaScript inside it can work independently of the map. Edit those files before adding more nodes.
|
|
@@ -41,7 +41,7 @@ Click a node to highlight incoming/outgoing arrows and follow a next-step button
|
|
|
41
41
|
## 5. Audit before sharing
|
|
42
42
|
|
|
43
43
|
```sh
|
|
44
|
-
ketatlas audit ./customer-journeys
|
|
44
|
+
ketatlas audit ./customer-journeys.ketatlas --strict
|
|
45
45
|
```
|
|
46
46
|
|
|
47
47
|
Keep the JSON and screens in your project's repository. Review changes in pull requests. Share the directory or run the same serve command in the recipient's checkout. No hosted account or service state is required.
|
package/docs/cli.md
CHANGED
|
@@ -1,30 +1,41 @@
|
|
|
1
1
|
# CLI reference
|
|
2
2
|
|
|
3
|
-
Install once with `npm install --global ketatlas
|
|
3
|
+
Install once with `npm install --global ketatlas`, or prefix commands with `npx --yes ketatlas`. No dependency installation is required in the consumer directory. `node /path/to/ketatlas/bin/ketatlas.js` is also available to framework maintainers.
|
|
4
4
|
|
|
5
5
|
A consumer keeps only its JSON/schema, product HTML/CSS/JavaScript, assets, and documentation. The package manifest, lockfile, development scripts, and browser test dependencies belong to the tool. Normal `serve`, `validate`, and `audit` calls do not create files in the consumer; `audit --output` is an explicit exception.
|
|
6
6
|
|
|
7
7
|
## Scaffold
|
|
8
8
|
|
|
9
9
|
```sh
|
|
10
|
-
ketatlas scaffold ./journeys
|
|
11
|
-
ketatlas scaffold ./approvals --template web
|
|
12
|
-
ketatlas scaffold ./operations --template process
|
|
10
|
+
ketatlas scaffold ./journeys.ketatlas
|
|
11
|
+
ketatlas scaffold ./approvals.ketatlas --template web
|
|
12
|
+
ketatlas scaffold ./operations.ketatlas --template process
|
|
13
13
|
```
|
|
14
14
|
|
|
15
15
|
`basic` is the default: two interactive mobile pages and one flow. `web` contains desktop purchase approval pages. `process` contains notes and an external handoff, without HTML screens. Every template includes a local JSON Schema for editor completion and a README. Product HTML and its styles belong to the new project.
|
|
16
16
|
|
|
17
|
-
`init` is an alias for `scaffold`. The destination must be missing or empty. Existing files are never overwritten; there is no `--force` flag.
|
|
17
|
+
`init` is an alias for `scaffold`. The destination must end in `.ketatlas` and be missing or empty. Existing files are never overwritten; there is no `--force` flag.
|
|
18
|
+
|
|
19
|
+
## Discover bundles
|
|
20
|
+
|
|
21
|
+
```sh
|
|
22
|
+
ketatlas discover .
|
|
23
|
+
ketatlas discover . --json
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Discovery walks the selected workspace for exact `*.ketatlas/atlas.json` bundles. It skips dependency, generated, cache, Git and vendor directories; it does not parse unrelated JSON. The JSON report contains `version`, `root`, `atlases`, and `errors`, including each atlas title, path, directory, screens and flow count. Invalid bundle manifests are reported and produce exit code 1.
|
|
27
|
+
|
|
28
|
+
Legacy manifest paths remain valid command arguments, but discovery intentionally ignores them. Migrate a self-contained legacy directory by renaming it to `<name>.ketatlas`; see the bundled skill for mixed-directory migration safeguards.
|
|
18
29
|
|
|
19
30
|
## Serve a JSON file
|
|
20
31
|
|
|
21
32
|
```sh
|
|
22
|
-
ketatlas serve ./tasks/onboarding
|
|
23
|
-
ketatlas serve ./tasks/onboarding
|
|
24
|
-
ketatlas serve ./
|
|
33
|
+
ketatlas serve ./tasks/onboarding.ketatlas
|
|
34
|
+
ketatlas serve ./tasks/onboarding.ketatlas --port 4180
|
|
35
|
+
ketatlas serve ./legacy/atlas.json --root .
|
|
25
36
|
```
|
|
26
37
|
|
|
27
|
-
The tool supplies the viewer page. It validates the JSON at startup, serves your files, and mounts the atlas at `/`.
|
|
38
|
+
The tool supplies the viewer page. It validates the JSON at startup, serves your files, and mounts the atlas at `/`. Passing a `.ketatlas` directory resolves its `atlas.json` and uses the bundle as the file root. Explicit legacy JSON paths still support `--root` when a relative URL points outside the manifest directory.
|
|
28
39
|
|
|
29
40
|
Open the printed localhost URL. Changes appear after refreshing; there is no hot reload or authoring server state. Use `?flow=your-flow-id` or `?screen=your-screen-id` to open a specific part of the map. An unknown ID falls back to the first flow.
|
|
30
41
|
|
|
@@ -35,10 +46,10 @@ The `/__ketatlas__/` route is reserved for viewer assets. Dotfiles and paths res
|
|
|
35
46
|
## Audit
|
|
36
47
|
|
|
37
48
|
```sh
|
|
38
|
-
ketatlas audit ./
|
|
39
|
-
ketatlas audit ./
|
|
40
|
-
ketatlas audit ./
|
|
41
|
-
ketatlas audit ./
|
|
49
|
+
ketatlas audit ./tasks/onboarding.ketatlas
|
|
50
|
+
ketatlas audit ./tasks/onboarding.ketatlas --strict
|
|
51
|
+
ketatlas audit ./tasks/onboarding.ketatlas --json
|
|
52
|
+
ketatlas audit ./tasks/onboarding.ketatlas --json --output audit-report.json
|
|
42
53
|
```
|
|
43
54
|
|
|
44
55
|
Audit checks:
|
|
@@ -64,7 +75,7 @@ Exit codes:
|
|
|
64
75
|
## Validate and version
|
|
65
76
|
|
|
66
77
|
```sh
|
|
67
|
-
ketatlas validate ./
|
|
78
|
+
ketatlas validate ./tasks/onboarding.ketatlas
|
|
68
79
|
ketatlas --version
|
|
69
80
|
ketatlas --help
|
|
70
81
|
```
|
|
@@ -73,4 +84,4 @@ ketatlas --help
|
|
|
73
84
|
|
|
74
85
|
## Screen progress
|
|
75
86
|
|
|
76
|
-
`progress <atlas.json> --json` reads the progress record, content revision and unique-screen summary. `--init` creates a missing sidecar. `--set <screen-id> --record <record.json> --expect <revision>` replaces one record with conflict detection. `serve <atlas.json> --read-only` disables local progress writes. See [Screen progress](progress.md) for examples and persistence rules.
|
|
87
|
+
`progress <bundle|atlas.json> --json` reads the progress record, content revision and unique-screen summary. `--init` creates a missing sidecar. `--set <screen-id> --record <record.json> --expect <revision>` replaces one record with conflict detection. `serve <bundle|atlas.json> --read-only` disables local progress writes. See [Screen progress](progress.md) for examples and persistence rules.
|
package/docs/migration.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Migrating the KétSuite mobile map
|
|
2
2
|
|
|
3
|
+
## Bundle layout backfill
|
|
4
|
+
|
|
5
|
+
Current projects use `<name>.ketatlas/atlas.json`. For a legacy self-contained Atlas directory, rename the whole directory so relative screen, style and asset URLs remain unchanged. When `atlas.json` shares a directory with unrelated application code, create a sibling `<name>.ketatlas` bundle, move only Atlas-owned files, and update relative URLs for resources that intentionally remain outside it. Keep one canonical manifest, then run `ketatlas discover <workspace> --json`, `ketatlas validate <name>.ketatlas`, and `ketatlas audit <name>.ketatlas --strict`.
|
|
6
|
+
|
|
7
|
+
The CLI continues to accept a direct legacy JSON path so migration can be audited before and after the move. Discovery intentionally reports only the standard bundle pattern.
|
|
8
|
+
|
|
3
9
|
The original mobile map remains in its project. KetAtlas does not copy its business data or change the mobile repository. The extraction generalizes the viewer; project migration is a separate configuration change.
|
|
4
10
|
|
|
5
11
|
## Field mapping
|
package/docs/progress.md
CHANGED
|
@@ -6,9 +6,9 @@ Screen and state preview footers show the shared screen status, blockers and lin
|
|
|
6
6
|
|
|
7
7
|
## Sidebar and project completion
|
|
8
8
|
|
|
9
|
-
Project-wide verified/checklist percentages and blocker counts appear in the top bar beside **Screens**. The sidebar shows
|
|
9
|
+
Project-wide verified/checklist percentages and blocker counts appear in the top bar beside **Screens**. The sidebar shows two badges after each workflow’s step count: **Checks %** (completed recorded acceptance checks / all recorded checks for unique screens) and **Implemented %** (screens with Implemented or Verified status / all unique screens). The compact labels are `30% checks` and `20% impl.`; tooltips spell out the definitions. In progress and In review screens do not count as implemented. Repeated nodes and error variants count once; note/external nodes do not count. Screenless flows have no badge. Flows with no recorded checks show **—**, not a measured 0%. Percentages round down so unfinished checks cannot appear as 100%.
|
|
10
10
|
|
|
11
|
-
The badge tooltip and accessible label include status counts, blockers
|
|
11
|
+
The badge tooltip and accessible label include completed/total checks, status counts, blockers, verified-screen completion, and unscoped-screen counts when checklists are missing. Checklist completion is not an estimate of effort or verified screen completion: 100% of a partial checklist does not make a screen Verified. Verified % on the top bar remains the number of Verified screens divided by all unique project screens. Saving or refreshing progress updates the sidebar; changing or searching workflows preserves the current progress.
|
|
12
12
|
|
|
13
13
|
## Status and scope
|
|
14
14
|
|
|
@@ -71,11 +71,11 @@ Evidence kinds are `pr`, `test`, `release`, `reference`. Required fields: `id`,
|
|
|
71
71
|
## Editing locally and from agents
|
|
72
72
|
|
|
73
73
|
```sh
|
|
74
|
-
npx --yes ketatlas
|
|
75
|
-
npx --yes ketatlas
|
|
76
|
-
npx --yes ketatlas
|
|
77
|
-
npx --yes ketatlas
|
|
78
|
-
npx --yes ketatlas
|
|
74
|
+
npx --yes ketatlas serve ./account-access.ketatlas
|
|
75
|
+
npx --yes ketatlas serve ./account-access.ketatlas --read-only
|
|
76
|
+
npx --yes ketatlas progress ./account-access.ketatlas --init
|
|
77
|
+
npx --yes ketatlas progress ./account-access.ketatlas --json
|
|
78
|
+
npx --yes ketatlas progress ./account-access.ketatlas --set sign-in --record record.json --expect REVISION_FROM_READ
|
|
79
79
|
```
|
|
80
80
|
|
|
81
81
|
`--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
|
@@ -5,7 +5,7 @@ description: Create or update interactive HTML mockups and workflow maps in KetA
|
|
|
5
5
|
|
|
6
6
|
# KetAtlas
|
|
7
7
|
|
|
8
|
-
Deliver an editable
|
|
8
|
+
Deliver an editable `<name>.ketatlas/` bundle containing actual HTML screens and a version 1 `atlas.json` that `npx ketatlas serve` can open. KetAtlas supplies the draggable viewer; the agent authors the product mockups and their flow graph. A screenshot gallery or a Mermaid diagram alone is not this deliverable.
|
|
9
9
|
|
|
10
10
|
## Read the brief and choose the scope
|
|
11
11
|
|
|
@@ -18,24 +18,56 @@ Use the user's requirements, existing project files, and design references to de
|
|
|
18
18
|
|
|
19
19
|
A brief may be a chat message or a Markdown file; it is not another KetAtlas JSON format. If details are missing, use reasonable defaults and record assumptions. Ask only for information that materially blocks the requested result. Do not introduce unrelated flows or build a production backend to make a mockup work.
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
## Choose the design system
|
|
22
|
+
|
|
23
|
+
Before scaffolding or editing visual screens, ask the user to choose a design system unless the current request already makes the choice explicit. Present these options in one concise prompt:
|
|
24
|
+
|
|
25
|
+
1. **Auto (recommended)** — use [Két Design System](https://github.com/ketvietlab/ketjs/tree/develop/packages/design-system).
|
|
26
|
+
2. **Két Design System** — use the same canonical Két source explicitly.
|
|
27
|
+
3. **Carbon Design System**.
|
|
28
|
+
4. **GitHub Primer**.
|
|
29
|
+
5. **Microsoft Fluent 2**.
|
|
30
|
+
6. **No design system** — create product-specific shared CSS without claiming conformance to a named system.
|
|
31
|
+
7. **Custom source** — ask for a repository URL or local design-system path if it was not included with the selection.
|
|
32
|
+
|
|
33
|
+
Do not start visual screen implementation until the user answers. If the user explicitly delegates the choice to the agent, treat that as **Auto**. This selection prompt is still required for an existing atlas; its documented/current system may be offered as the likely choice. A request that already names a system or supplies a design-system source counts as an answer and must not be asked again.
|
|
34
|
+
|
|
35
|
+
Inspect the selected source, its usage documentation, tokens, components, icons, and relevant product patterns before mocking. Reuse its actual public assets and composition patterns when available; do not merely imitate its color palette. Replace incompatible starter styling rather than layering multiple design systems. For one shared iOS/Android prototype, create one HTML implementation with reusable styles and states unless separate variants were requested.
|
|
36
|
+
|
|
37
|
+
Prefer a local adapter descriptor with `schemaVersion: "ketatlas.design-system-adapter.v1"` when the selected design system provides one. Discover it from the user-supplied path, a repository `design-system.atlas.json`, or the package's documented `./atlas/profile.json` export. Read the descriptor before using its assets or commands; do not assume capabilities it does not declare. If there is no adapter, use the design system through its documented HTML/CSS interface and record that no reproducible adapter lock is available.
|
|
38
|
+
|
|
39
|
+
For Két Design System, prefer the descriptor exported at `@ketvietlab/design-system/atlas/profile.json` and its declared `ket-design-system-atlas` materializer. Read that descriptor for asset names, root attributes, slots, hooks, and state ownership instead of hard-coding them.
|
|
40
|
+
|
|
41
|
+
Keep the atlas self-contained and dependency-free. Do not add a consumer package installation or custom bundler just to use a design system. Materialize or copy permitted static assets only when the selected source supports it, preserve required notices, and do not rely on remote runtime assets when the requested mockup must work offline. Record the selected system, source URL/path, pinned version or commit when known, adapter/asset strategy, and any license or fidelity limitation in the bundle README.
|
|
22
42
|
|
|
23
43
|
## Scaffold or extend
|
|
24
44
|
|
|
25
45
|
Node.js 22 or newer is required. For a new, empty destination:
|
|
26
46
|
|
|
27
47
|
```sh
|
|
28
|
-
npx --yes ketatlas scaffold ./tasks/mockups --template basic
|
|
48
|
+
npx --yes ketatlas scaffold ./tasks/mockups.ketatlas --template basic
|
|
29
49
|
```
|
|
30
50
|
|
|
31
51
|
Choose `basic` for mobile, `web` for desktop, or `process` for steps without UI. These are starting examples, not required product flows. Replace their sample content with the requested product.
|
|
32
52
|
|
|
33
|
-
For an existing atlas, read and edit its JSON and screen files directly. Preserve useful IDs and URLs; scaffold refuses a nonempty directory and has no `--force` option. Pin the CLI version in the README commands
|
|
53
|
+
For an existing atlas, read and edit its JSON and screen files directly. Preserve useful IDs and URLs; scaffold refuses a nonempty directory and has no `--force` option. Pin the CLI version in the README commands or use a global installation. A consumer atlas does not need a local package installation.
|
|
54
|
+
|
|
55
|
+
### Backfill legacy projects
|
|
56
|
+
|
|
57
|
+
Before changing an existing atlas, run `ketatlas discover <workspace> --json`. If its manifest is not located at `<name>.ketatlas/atlas.json`, migrate it as part of the task:
|
|
58
|
+
|
|
59
|
+
1. Inventory the manifest, sibling progress file, schema, README, screens, styles and assets. Record every relative `$schema`, screen URL and node URL before moving anything.
|
|
60
|
+
2. If the containing directory is a self-contained Atlas project, rename that directory to a concise `<name>.ketatlas`; moving the whole directory preserves relative URLs.
|
|
61
|
+
3. If the manifest shares a directory with unrelated application code, create a sibling `<name>.ketatlas` bundle. Move only Atlas-owned files, preserve Git history when possible, and rewrite relative paths for resources that intentionally remain outside the bundle.
|
|
62
|
+
4. Keep one canonical manifest. Do not leave a copied legacy `atlas.json` behind or delete files whose ownership is unclear.
|
|
63
|
+
5. Run `ketatlas discover <workspace> --json`, `ketatlas validate <name>.ketatlas`, and `ketatlas audit <name>.ketatlas --strict` after migration. Fix discovery errors and broken paths before editing product flows.
|
|
64
|
+
|
|
65
|
+
Legacy JSON paths remain accepted by the CLI for migration, but new and updated deliverables must use the bundle pattern so desktop tools can discover them without scanning arbitrary JSON.
|
|
34
66
|
|
|
35
67
|
A self-contained project typically has:
|
|
36
68
|
|
|
37
69
|
```text
|
|
38
|
-
tasks/mockups/
|
|
70
|
+
tasks/mockups.ketatlas/
|
|
39
71
|
atlas.json
|
|
40
72
|
ketatlas.schema.json
|
|
41
73
|
screens/ HTML pages and shared CSS/JavaScript
|
|
@@ -45,7 +77,7 @@ tasks/mockups/
|
|
|
45
77
|
|
|
46
78
|
Keep product assets inside the served directory when practical. Deliver JSON/schema, screen HTML/CSS/JavaScript, assets, and documentation. Do not scaffold a `package.json`, lockfile, `node_modules`, asset build scripts, or a copied viewer/test harness in the atlas folder just to use KetAtlas. The installed CLI supplies scaffold, serve, validate, and audit. Browser verification can use the agent's external tooling. Preserve unrelated application tooling when extending an existing repository.
|
|
47
79
|
|
|
48
|
-
Do not create a wrapper viewer or a custom canvas: `serve
|
|
80
|
+
Do not create a wrapper viewer or a custom canvas: `serve ./tasks/mockups.ketatlas` provides it.
|
|
49
81
|
|
|
50
82
|
## Model the journey
|
|
51
83
|
|
|
@@ -123,9 +155,10 @@ The default iframe sandbox allows scripts and forms but gives the page an opaque
|
|
|
123
155
|
Run from the user's project with the same root for audit and serve:
|
|
124
156
|
|
|
125
157
|
```sh
|
|
126
|
-
npx --yes ketatlas
|
|
127
|
-
npx --yes ketatlas
|
|
128
|
-
npx --yes ketatlas
|
|
158
|
+
npx --yes ketatlas discover . --json
|
|
159
|
+
npx --yes ketatlas validate ./tasks/mockups.ketatlas
|
|
160
|
+
npx --yes ketatlas audit ./tasks/mockups.ketatlas --strict
|
|
161
|
+
npx --yes ketatlas serve ./tasks/mockups.ketatlas
|
|
129
162
|
```
|
|
130
163
|
|
|
131
164
|
Use `--root .` on both audit and serve if screens or assets intentionally live outside the atlas directory but inside the project. Use `--port 4180` or another free port when necessary. Refresh after file edits; there is no hot reload.
|
|
@@ -138,8 +171,8 @@ Update the project's README with flow-to-screen/state coverage, assumptions, dem
|
|
|
138
171
|
|
|
139
172
|
## Maintain screen delivery progress
|
|
140
173
|
|
|
141
|
-
When implementing or reviewing screens, track progress in
|
|
174
|
+
When implementing or reviewing screens, track progress in `atlas.progress.json` beside the bundle manifest. Keep version 1 workflow JSON unchanged. Read `ketatlas progress <name>.ketatlas --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
175
|
|
|
143
176
|
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
177
|
|
|
145
|
-
Sidebar
|
|
178
|
+
Sidebar badges show Checks (completed recorded checks / all recorded checks) and Implemented (Implemented + Verified screens / all unique screens). No recorded checks shows — for Checks. Verified-screen completion stays separate on the project top bar. 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.js
CHANGED
|
@@ -12,6 +12,16 @@ import { template, escapeHTML as e } from "./template.js";
|
|
|
12
12
|
import { icons } from "./icons.js";
|
|
13
13
|
export { validateAtlas, AtlasValidationError } from "./config.js";
|
|
14
14
|
|
|
15
|
+
const cameraMotion = Object.freeze({
|
|
16
|
+
dragPan: 1.35,
|
|
17
|
+
wheelPan: 1.45,
|
|
18
|
+
wheelZoom: 0.0032,
|
|
19
|
+
pinchZoom: 1.2,
|
|
20
|
+
zoomStep: 1.3,
|
|
21
|
+
keyPan: 120,
|
|
22
|
+
keyPanLarge: 260,
|
|
23
|
+
});
|
|
24
|
+
|
|
15
25
|
/** Mount an isolated viewer. Await atlas.ready before measuring or focusing it. */
|
|
16
26
|
export function createAtlas(container, input, options = {}) {
|
|
17
27
|
if (!(container instanceof HTMLElement))
|
|
@@ -136,7 +146,7 @@ export function createAtlas(container, input, options = {}) {
|
|
|
136
146
|
).includes(q),
|
|
137
147
|
);
|
|
138
148
|
return matches.length
|
|
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>`
|
|
149
|
+
? `<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-group" data-progress-flow="${f.id}"></span></small></span></button>`).join("")}</section>`
|
|
140
150
|
: "";
|
|
141
151
|
})
|
|
142
152
|
.join("") || '<p class="mock-filter-empty">No matching workflows.</p>';
|
|
@@ -429,10 +439,8 @@ export function createAtlas(container, input, options = {}) {
|
|
|
429
439
|
pointers.set(event.pointerId, point(event));
|
|
430
440
|
if (pointers.size >= 2 && pinch) {
|
|
431
441
|
const [a, b] = [...pointers.values()],
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
Math.min(2.2, (pinch.z * Math.hypot(a.x - b.x, a.y - b.y)) / Math.max(1, pinch.distance)),
|
|
435
|
-
);
|
|
442
|
+
ratio = Math.hypot(a.x - b.x, a.y - b.y) / Math.max(1, pinch.distance),
|
|
443
|
+
z = Math.max(0.18, Math.min(2.2, pinch.z * Math.pow(ratio, cameraMotion.pinchZoom)));
|
|
436
444
|
view = { z, x: (a.x + b.x) / 2 - pinch.worldX * z, y: (a.y + b.y) / 2 - pinch.worldY * z };
|
|
437
445
|
suppressClick = true;
|
|
438
446
|
schedule();
|
|
@@ -445,8 +453,8 @@ export function createAtlas(container, input, options = {}) {
|
|
|
445
453
|
if (Math.hypot(dx, dy) > 4) drag.moved = true;
|
|
446
454
|
if (drag.moved) {
|
|
447
455
|
viewport.classList.add("dragging");
|
|
448
|
-
view.x = drag.x + dx;
|
|
449
|
-
view.y = drag.y + dy;
|
|
456
|
+
view.x = drag.x + dx * cameraMotion.dragPan;
|
|
457
|
+
view.y = drag.y + dy * cameraMotion.dragPan;
|
|
450
458
|
schedule();
|
|
451
459
|
}
|
|
452
460
|
});
|
|
@@ -477,10 +485,16 @@ export function createAtlas(container, input, options = {}) {
|
|
|
477
485
|
event.preventDefault();
|
|
478
486
|
if (event.ctrlKey || event.metaKey) {
|
|
479
487
|
const p = point(event);
|
|
480
|
-
zoomTo(view.z * Math.exp(-event.deltaY *
|
|
488
|
+
zoomTo(view.z * Math.exp(-event.deltaY * cameraMotion.wheelZoom), p.x, p.y);
|
|
481
489
|
} else {
|
|
482
|
-
|
|
483
|
-
|
|
490
|
+
const unit =
|
|
491
|
+
event.deltaMode === WheelEvent.DOM_DELTA_LINE
|
|
492
|
+
? 16
|
|
493
|
+
: event.deltaMode === WheelEvent.DOM_DELTA_PAGE
|
|
494
|
+
? viewport.clientHeight
|
|
495
|
+
: 1;
|
|
496
|
+
view.x -= event.deltaX * unit * cameraMotion.wheelPan;
|
|
497
|
+
view.y -= event.deltaY * unit * cameraMotion.wheelPan;
|
|
484
498
|
syncCurrentFromPan();
|
|
485
499
|
schedule();
|
|
486
500
|
}
|
|
@@ -489,17 +503,17 @@ export function createAtlas(container, input, options = {}) {
|
|
|
489
503
|
);
|
|
490
504
|
viewport.addEventListener("keydown", (event) => {
|
|
491
505
|
if (event.target.closest("button,a,input") || $("screen-dialog").open) return;
|
|
492
|
-
const step = event.shiftKey ?
|
|
506
|
+
const step = event.shiftKey ? cameraMotion.keyPanLarge : cameraMotion.keyPan;
|
|
493
507
|
if (event.key === "ArrowLeft") view.x += step;
|
|
494
508
|
else if (event.key === "ArrowRight") view.x -= step;
|
|
495
509
|
else if (event.key === "ArrowUp") view.y += step;
|
|
496
510
|
else if (event.key === "ArrowDown") view.y -= step;
|
|
497
511
|
else if (["+", "="].includes(event.key)) {
|
|
498
|
-
zoomTo(view.z *
|
|
512
|
+
zoomTo(view.z * cameraMotion.zoomStep);
|
|
499
513
|
event.preventDefault();
|
|
500
514
|
return;
|
|
501
515
|
} else if (event.key === "-") {
|
|
502
|
-
zoomTo(view.z /
|
|
516
|
+
zoomTo(view.z / cameraMotion.zoomStep);
|
|
503
517
|
event.preventDefault();
|
|
504
518
|
return;
|
|
505
519
|
} else if (event.key.toLowerCase() === "f") {
|
|
@@ -566,8 +580,8 @@ export function createAtlas(container, input, options = {}) {
|
|
|
566
580
|
if (button) progressUI.edit(button.dataset.editProgress);
|
|
567
581
|
});
|
|
568
582
|
$("flow-search").addEventListener("input", sidebar);
|
|
569
|
-
$("zoom-in").onclick = () => zoomTo(view.z *
|
|
570
|
-
$("zoom-out").onclick = () => zoomTo(view.z /
|
|
583
|
+
$("zoom-in").onclick = () => zoomTo(view.z * cameraMotion.zoomStep);
|
|
584
|
+
$("zoom-out").onclick = () => zoomTo(view.z / cameraMotion.zoomStep);
|
|
571
585
|
$("zoom-reset").onclick = () => zoomTo(1);
|
|
572
586
|
$("zoom-fit").onclick = fitFlow;
|
|
573
587
|
$("minimap-fit").onclick = fitFlow;
|
package/src/progress-ui.js
CHANGED
|
@@ -58,15 +58,35 @@ export function mountProgress(root, config, initial, options, selectScreen) {
|
|
|
58
58
|
.map(([key, label]) => `${summary.counts[key]} ${label.toLowerCase()}`)
|
|
59
59
|
.join(" · ");
|
|
60
60
|
const checks = summary.checks;
|
|
61
|
-
const
|
|
61
|
+
const implemented = summary.counts.implemented + summary.counts.verified;
|
|
62
|
+
const implementedPercent = Math.floor((implemented / summary.total) * 100);
|
|
63
|
+
const details = `${checks.total ? `Checks ${checks.percent}% · ${checks.done}/${checks.total}. ` : "No checks recorded. "}${summary.verifiedPercent}% verified · ${summary.counts.verified}/${summary.total} screens. ${statuses}${summary.blocked ? ` · ${summary.blocked} blocked` : ""}${checks.unscoped ? ` · ${checks.unscoped} unscoped` : ""}.`;
|
|
62
64
|
if (project) {
|
|
63
65
|
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>` : ""}`;
|
|
64
|
-
} else
|
|
66
|
+
} else {
|
|
67
|
+
const metric = (name, label, percent, description) =>
|
|
68
|
+
`<span class="flow-progress" data-metric="${name}" data-tone="${summary.blocked ? "blocked" : percent === 100 ? "complete" : "pending"}" title="${e(description)}" aria-label="${e(description)}">${percent === null ? "—" : `${percent}%`} ${label}</span>`;
|
|
69
|
+
el.innerHTML =
|
|
70
|
+
metric(
|
|
71
|
+
"checks",
|
|
72
|
+
"checks",
|
|
73
|
+
checks.percent,
|
|
74
|
+
checks.total
|
|
75
|
+
? `Checks ${checks.percent}%: ${checks.done}/${checks.total} recorded checks completed`
|
|
76
|
+
: "Checks: no recorded checklist",
|
|
77
|
+
) +
|
|
78
|
+
metric(
|
|
79
|
+
"implemented",
|
|
80
|
+
"impl.",
|
|
81
|
+
implementedPercent,
|
|
82
|
+
`Implemented ${implementedPercent}%: ${implemented}/${summary.total} screens have Implemented or Verified status`,
|
|
83
|
+
);
|
|
84
|
+
}
|
|
65
85
|
el.title = details;
|
|
66
86
|
el.setAttribute("aria-label", details);
|
|
67
87
|
el.dataset.tone = summary.blocked
|
|
68
88
|
? "blocked"
|
|
69
|
-
: summary.verifiedPercent === 100
|
|
89
|
+
: (project ? summary.verifiedPercent : checks.percent) === 100
|
|
70
90
|
? "complete"
|
|
71
91
|
: "pending";
|
|
72
92
|
}
|
package/styles/ketatlas.css
CHANGED
|
@@ -1440,3 +1440,13 @@ a svg {
|
|
|
1440
1440
|
--progress-dialog-padding: var(--kv-space-3);
|
|
1441
1441
|
}
|
|
1442
1442
|
}
|
|
1443
|
+
|
|
1444
|
+
.flow-progress-group {
|
|
1445
|
+
display: inline-flex;
|
|
1446
|
+
align-items: center;
|
|
1447
|
+
gap: var(--kv-space-1);
|
|
1448
|
+
vertical-align: middle;
|
|
1449
|
+
}
|
|
1450
|
+
.flow-progress-group[hidden] {
|
|
1451
|
+
display: none;
|
|
1452
|
+
}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
# My KetAtlas project
|
|
2
2
|
|
|
3
|
-
Run with Node.js 22 or newer:
|
|
3
|
+
This directory must keep its `.ketatlas` suffix. Run with Node.js 22 or newer:
|
|
4
4
|
|
|
5
5
|
```sh
|
|
6
|
-
npx ketatlas serve
|
|
7
|
-
npx ketatlas audit
|
|
6
|
+
npx ketatlas serve .
|
|
7
|
+
npx ketatlas audit . --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
|
|
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 and use ketatlas serve .
|
|
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
|
|
|
14
|
-
Open **Screens** in the viewer to review or edit delivery progress. Saving writes atlas.progress.json beside the workflow; use --read-only to disable editing. You can initialize records with ketatlas progress
|
|
14
|
+
Open **Screens** in the viewer to review or edit delivery progress. Saving writes atlas.progress.json beside the workflow; use --read-only to disable editing. You can initialize records with ketatlas progress . --init. Keep this directory in your own project repository. The schema provides editor completion. See https://github.com/ketvietlab/ketatlas for the full API, CLI, and configuration reference.
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
# My KetAtlas project
|
|
2
2
|
|
|
3
|
-
Run with Node.js 22 or newer:
|
|
3
|
+
This directory must keep its `.ketatlas` suffix. Run with Node.js 22 or newer:
|
|
4
4
|
|
|
5
5
|
```sh
|
|
6
|
-
npx ketatlas serve
|
|
7
|
-
npx ketatlas audit
|
|
6
|
+
npx ketatlas serve .
|
|
7
|
+
npx ketatlas audit . --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
|
|
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 and use ketatlas serve .
|
|
11
11
|
|
|
12
12
|
This template models a process without HTML screens. Add a screen registry and screen nodes when needed.
|
|
13
13
|
|
|
14
|
-
Open **Screens** in the viewer to review or edit delivery progress. Saving writes atlas.progress.json beside the workflow; use --read-only to disable editing. You can initialize records with ketatlas progress
|
|
14
|
+
Open **Screens** in the viewer to review or edit delivery progress. Saving writes atlas.progress.json beside the workflow; use --read-only to disable editing. You can initialize records with ketatlas progress . --init. Keep this directory in your own project repository. The schema provides editor completion. See https://github.com/ketvietlab/ketatlas for the full API, CLI, and configuration reference.
|
package/templates/web/README.md
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
# My KetAtlas project
|
|
2
2
|
|
|
3
|
-
Run with Node.js 22 or newer:
|
|
3
|
+
This directory must keep its `.ketatlas` suffix. Run with Node.js 22 or newer:
|
|
4
4
|
|
|
5
5
|
```sh
|
|
6
|
-
npx ketatlas serve
|
|
7
|
-
npx ketatlas audit
|
|
6
|
+
npx ketatlas serve .
|
|
7
|
+
npx ketatlas audit . --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
|
|
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 and use ketatlas serve .
|
|
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
|
|
|
14
|
-
Open **Screens** in the viewer to review or edit delivery progress. Saving writes atlas.progress.json beside the workflow; use --read-only to disable editing. You can initialize records with ketatlas progress
|
|
14
|
+
Open **Screens** in the viewer to review or edit delivery progress. Saving writes atlas.progress.json beside the workflow; use --read-only to disable editing. You can initialize records with ketatlas progress . --init. Keep this directory in your own project repository. The schema provides editor completion. See https://github.com/ketvietlab/ketatlas for the full API, CLI, and configuration reference.
|