@marver-design/marver 0.22.0 → 0.22.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 +22 -0
- package/dist/{bake-BSX4XR_U.mjs → bake-CvY8QR3L.mjs} +1 -1
- package/dist/{boards-BTGNPVMx.mjs → boards-BwKI0qWd.mjs} +1 -0
- package/dist/{build-Dd2Qm3OG.mjs → build-B1kavcpc.mjs} +4 -4
- package/dist/cli.mjs +8 -7
- package/dist/{context-DUAENlJ6.mjs → context-D4t59wDi.mjs} +1 -1
- package/dist/{daemon-BmkwErpC.mjs → daemon-PmNqoOAk.mjs} +1 -1
- package/dist/{dev-BW7a5kDF.mjs → dev-Cf4wLGe2.mjs} +11 -5
- package/dist/{init-NJ3xjLVu.mjs → init-C_K-cjBQ.mjs} +3 -2
- package/dist/{manifest-BqBcMJcd.mjs → manifest-CcdWx7ud.mjs} +24 -1
- package/dist/{plugin-8XntSCx_.mjs → plugin-C5u07Yhv.mjs} +8 -8
- package/dist/{poster-DRZDszTI.mjs → poster-BduzQBYz.mjs} +1 -1
- package/dist/{publish-bakes-CCWRV9iX.mjs → publish-bakes-b0jUwvM_.mjs} +2 -2
- package/dist/{shot-C22Ues04.mjs → shot-BAR8hmU9.mjs} +2 -2
- package/package.json +1 -1
- package/templates/AGENTS-embedded.md +11 -0
- package/templates/AGENTS-studio.md +11 -0
- package/templates/instructions/boards.md +3 -1
- package/templates/instructions/context.md +14 -5
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,28 @@
|
|
|
2
2
|
|
|
3
3
|
Notable changes to `@marver-design/marver`. Format follows [Keep a Changelog](https://keepachangelog.com); versions follow semver.
|
|
4
4
|
|
|
5
|
+
## 0.22.1 - 2026-10-06
|
|
6
|
+
|
|
7
|
+
### Changed
|
|
8
|
+
|
|
9
|
+
- **A project without `context/` hears about it.** The AGENTS contract opens with it: in a
|
|
10
|
+
repository with no `context/`, every reply in which an agent made, specced or changed a feature or
|
|
11
|
+
project board ends with one line - every feature board reads Backlog, nothing records what shipped,
|
|
12
|
+
want me to set it up? - until the human answers; a no stands for the session, and nothing is set up
|
|
13
|
+
unasked. `instructions/boards.md`, `npx marver boards`, `npx marver boards new` (feature, project),
|
|
14
|
+
`npx marver init` and `marver dev` at boot point at it. In 0.22.0 a routing row merely pointed at
|
|
15
|
+
the instruction: Claude Code and Codex, asked to spec a feature, both read it and never mentioned
|
|
16
|
+
it; with the line, both end their reply with it.
|
|
17
|
+
- `npx marver init` on an existing canvas no longer ends with the first-session hand-off - an
|
|
18
|
+
upgrade is not a first session.
|
|
19
|
+
|
|
20
|
+
### Docs
|
|
21
|
+
|
|
22
|
+
- **"Set up our context" is the whole ask.** `instructions/context.md`'s setup is now the full recipe,
|
|
23
|
+
in order: the kind (`product` or `knowledge`), the draft from evidence, the canvas reading it -
|
|
24
|
+
typed folders, feature boards named after their capability, a start board - and the check in ci.
|
|
25
|
+
After upgrading (`npx marver init`), tell your agent: "Set up our context."
|
|
26
|
+
|
|
5
27
|
## 0.22.0 - 2026-10-06
|
|
6
28
|
|
|
7
29
|
### Added
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AREA, SURFACE, pool, shotConcurrency, withBrowser } from "./shot-
|
|
1
|
+
import { AREA, SURFACE, pool, shotConcurrency, withBrowser } from "./shot-BAR8hmU9.mjs";
|
|
2
2
|
import { existsSync, mkdirSync, readFileSync, readdirSync, realpathSync, renameSync, rmSync, statSync, utimesSync, writeFileSync } from "node:fs";
|
|
3
3
|
import { join, sep } from "node:path";
|
|
4
4
|
import { createHash } from "node:crypto";
|
|
@@ -80,6 +80,7 @@ function boardsCommand(root, opts) {
|
|
|
80
80
|
if (landing) console.log(`\nlanding board: ${landing}`);
|
|
81
81
|
console.log(`registry: ${reg.state === "ok" ? "design/boards/_folders.json" : "none (no empty or ranked folders yet)"}`);
|
|
82
82
|
if (skipped.length) console.log(`skipped (not regular files): ${skipped.join(", ")}`);
|
|
83
|
+
if ([...notes.values()].filter((n) => n.status).length && !existsSync(join(root, "context"))) console.log(`\nno context/ yet - every feature and project board reads Backlog. Agent: end your reply with the context line in design/AGENTS.md ("Before the method").`);
|
|
83
84
|
}
|
|
84
85
|
/** `marver boards new <name>` - a board in its type's starting layout (spec 20): a feature's three
|
|
85
86
|
* phase scenes (spec, lo-fi, hi-fi) as three bands, a start board rendering context/INDEX.md and
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { a as ROUTE, r as NAME } from "./cli.mjs";
|
|
2
2
|
import { D as boardFields, H as isBoardName, L as buildTree, N as readRegistry, O as checkBoardsDir, R as flatten, Z as PROPOSED_PUBLISH, i as PUBLISHABLE, j as listBoardFiles, o as publishableStatus } from "./board-status-CWGHIdo_.mjs";
|
|
3
|
-
import {
|
|
3
|
+
import { i as scanFrames } from "./manifest-CcdWx7ud.mjs";
|
|
4
4
|
import { i as detectHost, n as loadConfig } from "./config-DJxMRVD8.mjs";
|
|
5
|
-
import { n as tailwind3Css, r as tailwind4Plugin, t as marverPlugin } from "./plugin-
|
|
5
|
+
import { n as tailwind3Css, r as tailwind4Plugin, t as marverPlugin } from "./plugin-C5u07Yhv.mjs";
|
|
6
6
|
import { cpSync, existsSync, mkdirSync, readFileSync, realpathSync, rmSync, writeFileSync } from "node:fs";
|
|
7
7
|
import { basename, dirname, join, sep } from "node:path";
|
|
8
8
|
import { fileURLToPath } from "node:url";
|
|
@@ -754,7 +754,7 @@ async function buildSite(root, boardsFlag, allBoardsFlag, embedSeeds, textures =
|
|
|
754
754
|
const realAssets = existsSync(assetsDir) ? realpathSync(assetsDir) : null;
|
|
755
755
|
for (const r of refs) {
|
|
756
756
|
if (!isLocalAssetRef(r) || !r.endsWith(".poster.png") || existsSync(join(assetsDir, r))) continue;
|
|
757
|
-
const { ensurePoster } = await import("./poster-
|
|
757
|
+
const { ensurePoster } = await import("./poster-BduzQBYz.mjs");
|
|
758
758
|
const g = await ensurePoster(assetsDir, r.slice(0, -11));
|
|
759
759
|
if (!g.ok) throw new Error(`design/assets/${r}: ${g.error}`);
|
|
760
760
|
console.log(` poster: rendered design/assets/${r} (${g.width}×${g.height})`);
|
|
@@ -821,7 +821,7 @@ async function buildSite(root, boardsFlag, allBoardsFlag, embedSeeds, textures =
|
|
|
821
821
|
}));
|
|
822
822
|
let textureLine = " textures: skipped (--no-textures)";
|
|
823
823
|
if (textures && bakeGen) {
|
|
824
|
-
const { bakePublished } = await import("./publish-bakes-
|
|
824
|
+
const { bakePublished } = await import("./publish-bakes-b0jUwvM_.mjs");
|
|
825
825
|
const pubFrameFile = new Map(pubFrames.map((f) => [f.id, f]));
|
|
826
826
|
const r = await bakePublished({
|
|
827
827
|
root,
|
package/dist/cli.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.mjs";
|
|
3
3
|
import { cac } from "cac";
|
|
4
|
-
import { readFileSync, realpathSync } from "node:fs";
|
|
4
|
+
import { existsSync, readFileSync, realpathSync } from "node:fs";
|
|
5
5
|
import { dirname, join, resolve } from "node:path";
|
|
6
6
|
import { fileURLToPath } from "node:url";
|
|
7
7
|
//#region src/client/const.ts
|
|
@@ -82,7 +82,7 @@ cli.command("init", "Scaffold design/ in this repo").option("--mode <mode>", "st
|
|
|
82
82
|
console.error(`[${NAME}] --kind ${opts.kind}: use product or knowledge`);
|
|
83
83
|
process.exit(1);
|
|
84
84
|
}
|
|
85
|
-
const { init } = await import("./init-
|
|
85
|
+
const { init } = await import("./init-C_K-cjBQ.mjs");
|
|
86
86
|
init(resolve$1(opts.root), {
|
|
87
87
|
mode: opts.mode === "embedded" ? "embedded" : "studio",
|
|
88
88
|
demo: opts.demo !== false,
|
|
@@ -90,7 +90,7 @@ cli.command("init", "Scaffold design/ in this repo").option("--mode <mode>", "st
|
|
|
90
90
|
});
|
|
91
91
|
});
|
|
92
92
|
for (const [name, desc] of [["dev", "Start the local canvas (everything on: hot reload, comments, Live Jam)"], ["canvas", "Start the local canvas - same as dev"]]) cli.command(name, desc).option("--root <dir>", "Host repo root", { default: "." }).option("--port <port>", "Port (default 5199)").action(async (opts) => {
|
|
93
|
-
const { dev } = await import("./dev-
|
|
93
|
+
const { dev } = await import("./dev-Cf4wLGe2.mjs");
|
|
94
94
|
let port;
|
|
95
95
|
if (opts.port !== void 0) {
|
|
96
96
|
const n = Number(opts.port);
|
|
@@ -100,7 +100,7 @@ for (const [name, desc] of [["dev", "Start the local canvas (everything on: hot
|
|
|
100
100
|
await dev(resolve$1(opts.root), port);
|
|
101
101
|
});
|
|
102
102
|
cli.command("build", "Static export → design/.dist (what ships comes from design/publish.json - publishing is default-closed)").option("--boards <names>", "Publish only these boards (comma-separated); overrides the publish policy").option("--all-boards", "Publish every board - the loud override for the default-closed policy").option("--embed-seeds", "Copy comment history INTO the web root (identifying - every event carries its author's email)").option("--no-textures", "Skip compiling the glass textures the published frames rest under (needs Chrome; a CI without one skips on its own)").option("--root <dir>", "Host repo root", { default: "." }).action(async (opts) => {
|
|
103
|
-
const { buildSite } = await import("./build-
|
|
103
|
+
const { buildSite } = await import("./build-B1kavcpc.mjs");
|
|
104
104
|
try {
|
|
105
105
|
const boards = opts.boards === void 0 ? void 0 : typeof opts.boards === "string" ? opts.boards : "";
|
|
106
106
|
await buildSite(resolve$1(opts.root), boards, opts.allBoards === true, opts.embedSeeds === true, opts.textures !== false && !process.env.MARVER_NO_TEXTURES);
|
|
@@ -146,13 +146,14 @@ cli.command("work <action> [...frames]", "Working state on the canvas: start <sc
|
|
|
146
146
|
}
|
|
147
147
|
});
|
|
148
148
|
cli.command("boards [action] [name]", "The sidebar as files: every folder and board in reading order, with types and statuses · new <name>: a board in its type's starting layout").option("--root <dir>", "Host repo root", { default: "." }).option("--json", "The tree as JSON ({ tree, boards, landing, registry })").option("--type <type>", "new: start | feature | surface | project | feedback | context | deck | archive (default: the folder's)").option("--folder <folder>", "new: the folder it sits in").option("--title <title>", "new: what humans see").option("--description <sentence>", "new: what agents read").option("--capability <slug>", "new: the capability it shows, when not its own name").action(async (action, name, opts) => {
|
|
149
|
-
const { boardsCommand, boardsNew } = await import("./boards-
|
|
149
|
+
const { boardsCommand, boardsNew } = await import("./boards-BwKI0qWd.mjs");
|
|
150
150
|
try {
|
|
151
151
|
if (action === void 0) boardsCommand(resolve$1(opts.root), opts);
|
|
152
152
|
else if (action === "new") {
|
|
153
153
|
if (!name) throw new Error("name the board: `boards new <name>`");
|
|
154
154
|
const made = boardsNew(resolve$1(opts.root), name, opts);
|
|
155
155
|
for (const c of made) console.log(` + ${c}`);
|
|
156
|
+
if (/\((feature|project)\b/.test(made[0] ?? "") && !existsSync(join(resolve$1(opts.root), "context"))) console.log(`\n note: no context/ yet - this board's status reads Backlog until there is one. Agent: end your reply with the context line in design/AGENTS.md ("Before the method").`);
|
|
156
157
|
if (made.some((c) => c.endsWith("/_brief.md")) && !made.some((c) => /\.(tsx|jsx|html)$/.test(c))) console.log(`\n next: a frame you make in these scenes shows on the board once it is pinned - a node in\n design/boards/${name}.json (an agent does this as it works: design/AGENTS.md)`);
|
|
157
158
|
} else throw new Error(`unknown action "${action}" - \`boards\` lists, \`boards new <name>\` creates`);
|
|
158
159
|
} catch (err) {
|
|
@@ -161,7 +162,7 @@ cli.command("boards [action] [name]", "The sidebar as files: every folder and bo
|
|
|
161
162
|
}
|
|
162
163
|
});
|
|
163
164
|
cli.command("folders <action> [...modules]", "The shared sidebar's typed folders · add <start|features|surfaces|projects|feedback|context|decks|archive ...>").option("--root <dir>", "Host repo root", { default: "." }).action(async (action, modules, opts) => {
|
|
164
|
-
const { foldersAdd } = await import("./boards-
|
|
165
|
+
const { foldersAdd } = await import("./boards-BwKI0qWd.mjs");
|
|
165
166
|
try {
|
|
166
167
|
if (action !== "add") throw new Error(`unknown action "${action}" - \`folders add <module ...>\``);
|
|
167
168
|
const { added, existing } = foldersAdd(resolve$1(opts.root), modules);
|
|
@@ -173,7 +174,7 @@ cli.command("folders <action> [...modules]", "The shared sidebar's typed folders
|
|
|
173
174
|
}
|
|
174
175
|
});
|
|
175
176
|
cli.command("context <action>", "The project's context/ (spec 19) · init: create it · check: keep it true (exit 0 pass, 1 fail, 2 cannot determine) · index: regenerate the index's capability table").option("--root <dir>", "Host repo root", { default: "." }).option("--base <ref>", "check: the pull request's base - a change to a contracted capability's code must change its contract or say why (in ci, read from the event)").option("--head <ref>", "check: the pull request's head (default HEAD)").option("--body-file <file>", "check: the pull request's body, for `no-contract-change: <capability> - <why>`").option("--json", "check: the findings as JSON ({ exit, failures, unsure, notes })").option("--kind <kind>", "init: product (a shipped record) or knowledge (a delivered record)", { default: "product" }).action(async (action, opts) => {
|
|
176
|
-
const ctx = await import("./context-
|
|
177
|
+
const ctx = await import("./context-D4t59wDi.mjs");
|
|
177
178
|
const root = resolve$1(opts.root);
|
|
178
179
|
try {
|
|
179
180
|
if (action === "init") {
|
|
@@ -2,7 +2,7 @@ import { r as NAME } from "./cli.mjs";
|
|
|
2
2
|
import { C as tables, S as proseLines, _ as isRecordTable, b as looseTables, c as CITED_FILE, d as LEVEL, f as availableLevels, g as hasGlob, h as globRe, k as checkRealDirs, l as EVIDENCE_COLUMN, m as frontMatter, p as capabilityTable, s as CITATION, tt as readStatusWord, u as GENERATED, v as levelsIn, w as wordCount, x as parseMap, y as lf } from "./board-status-CWGHIdo_.mjs";
|
|
3
3
|
import { pkgDir } from "./managed-HwHVNI3h.mjs";
|
|
4
4
|
import { t as writeManaged } from "./managed-write-Bo-oPc-i.mjs";
|
|
5
|
-
import {
|
|
5
|
+
import { i as scanFrames } from "./manifest-CcdWx7ud.mjs";
|
|
6
6
|
import { existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, renameSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
7
7
|
import { basename, dirname, join, normalize, relative, sep } from "node:path";
|
|
8
8
|
import { execFileSync } from "node:child_process";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { n as replay } from "./events-B3LBn74P.mjs";
|
|
2
2
|
import { i as readLog, r as listBoards, t as appendEvents } from "./comments-DZyobpxG.mjs";
|
|
3
3
|
import { n as localProfile } from "./profile-BjAPAJSb.mjs";
|
|
4
|
-
import {
|
|
4
|
+
import { o as toFrameId } from "./manifest-CcdWx7ud.mjs";
|
|
5
5
|
import { workActivity } from "./work-CLrmY-vQ.mjs";
|
|
6
6
|
import { r as deviceId, t as has } from "./ledger-Bu0BjqIe.mjs";
|
|
7
7
|
import { closeSync, existsSync, fsyncSync, mkdirSync, openSync, readFileSync, readdirSync, renameSync, rmSync, statSync, unlinkSync, watch, writeFileSync, writeSync } from "node:fs";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { i as PKG, r as NAME } from "./cli.mjs";
|
|
2
2
|
import { i as detectHost, n as loadConfig } from "./config-DJxMRVD8.mjs";
|
|
3
|
-
import { n as tailwind3Css, r as tailwind4Plugin, t as marverPlugin } from "./plugin-
|
|
4
|
-
import { readFileSync, readdirSync, realpathSync, statSync } from "node:fs";
|
|
3
|
+
import { n as tailwind3Css, r as tailwind4Plugin, t as marverPlugin } from "./plugin-C5u07Yhv.mjs";
|
|
4
|
+
import { existsSync, readFileSync, readdirSync, realpathSync, statSync } from "node:fs";
|
|
5
5
|
import { basename, dirname, isAbsolute, join, relative, resolve } from "node:path";
|
|
6
6
|
import { fileURLToPath } from "node:url";
|
|
7
7
|
import { createLogger, createServer, parseAst, searchForWorkspaceRoot } from "vite";
|
|
@@ -454,12 +454,12 @@ async function dev(root, portFlag) {
|
|
|
454
454
|
console.log(`\n ${NAME} · ${projectName} → http://localhost:${port}/\n`);
|
|
455
455
|
setTimeout(async () => {
|
|
456
456
|
try {
|
|
457
|
-
await (await import("./shot-
|
|
457
|
+
await (await import("./shot-BAR8hmU9.mjs")).sweepGhosts((m) => console.log(` ${m}`));
|
|
458
458
|
} catch {}
|
|
459
459
|
}, 0);
|
|
460
460
|
try {
|
|
461
461
|
const { staleManagedInstructions } = await import("./managed-HwHVNI3h.mjs");
|
|
462
|
-
const { installedVersion } = await import("./plugin-
|
|
462
|
+
const { installedVersion } = await import("./plugin-C5u07Yhv.mjs").then((n) => n.i);
|
|
463
463
|
const stale = staleManagedInstructions(root);
|
|
464
464
|
if (stale.length) {
|
|
465
465
|
const shown = stale.slice(0, 4).join(", ") + (stale.length > 4 ? `, +${stale.length - 4} more` : "");
|
|
@@ -467,6 +467,12 @@ async function dev(root, portFlag) {
|
|
|
467
467
|
console.log(` instructions predate ${v ? NAME + " " + v : "the installed version"} (${shown}) - run: npx ${NAME} init\n`);
|
|
468
468
|
}
|
|
469
469
|
} catch {}
|
|
470
|
+
try {
|
|
471
|
+
if (!existsSync(join(root, "context"))) {
|
|
472
|
+
const n = (await import("./manifest-CcdWx7ud.mjs").then((n) => n.r)).statusBoards(root).length;
|
|
473
|
+
if (n) console.log(` ${n} feature/project board${n === 1 ? "" : "s"}, no context/ - every status reads Backlog. To start it, tell your agent: "Set up our context."\n`);
|
|
474
|
+
}
|
|
475
|
+
} catch {}
|
|
470
476
|
const { loadCollab, syncOnce } = await import("./sync-BZaCWqK-.mjs").then((n) => n.o);
|
|
471
477
|
if (loadCollab(root)) console.log(` comments: syncing with the published canvas\n`);
|
|
472
478
|
let syncing = false;
|
|
@@ -497,7 +503,7 @@ async function dev(root, portFlag) {
|
|
|
497
503
|
});
|
|
498
504
|
}
|
|
499
505
|
if (config.jam) {
|
|
500
|
-
const { startJam } = await import("./daemon-
|
|
506
|
+
const { startJam } = await import("./daemon-PmNqoOAk.mjs");
|
|
501
507
|
const jam = startJam(root, config.jam, (m) => console.log(m), (board) => server.ws.send("sh:jam-comment", { board }));
|
|
502
508
|
if (jam) {
|
|
503
509
|
const close = server.close.bind(server);
|
|
@@ -2,7 +2,7 @@ import { r as NAME } from "./cli.mjs";
|
|
|
2
2
|
import { E as addFolders, J as FOLDER_MODULES, X as KIND_FOLDERS } from "./board-status-CWGHIdo_.mjs";
|
|
3
3
|
import { MANAGED_PREFIX, enumerateInstructionTemplates, hashBody, pkgDir } from "./managed-HwHVNI3h.mjs";
|
|
4
4
|
import { t as writeManaged } from "./managed-write-Bo-oPc-i.mjs";
|
|
5
|
-
import {
|
|
5
|
+
import { i as scanFrames, s as writeManifest } from "./manifest-CcdWx7ud.mjs";
|
|
6
6
|
import { a as readJson, i as detectHost, r as detectAgent, t as DEFAULTS } from "./config-DJxMRVD8.mjs";
|
|
7
7
|
import { cpSync, existsSync, mkdirSync, readFileSync, readdirSync, rmSync, writeFileSync } from "node:fs";
|
|
8
8
|
import { basename, dirname, join, relative } from "node:path";
|
|
@@ -234,10 +234,11 @@ function init(root, opts) {
|
|
|
234
234
|
console.log(`\n commit design/ - only .local/ is ignored`);
|
|
235
235
|
console.log(` uninstall = delete design/, remove the ${NAME} dependency${host.tsconfigSweepsDesign ? ", revert the \"design\" line in tsconfig exclude" : ""}`);
|
|
236
236
|
if (!noApp(host) && !existsSync(join(design, "DESIGN.md"))) console.log(`\n note: design/DESIGN.md (the brand doc) does not exist yet - have your agent create it from the app's tokens (instructions/brand.md, Path A) to reach the idle state.`);
|
|
237
|
+
if (!existsSync(join(root, "context"))) console.log(`\n note: no context/ yet - feature and project boards read Backlog until there is one, and nothing records what shipped. To start it, tell your agent: "Set up our context." (design/instructions/context.md)`);
|
|
237
238
|
if (!jamAgent) console.log(`\n note: Live Jam found no agent CLI on PATH (claude, codex, cursor, droid, opencode, grok, or pi) - install one and it arms itself on the next \`${NAME} dev\`.`);
|
|
238
239
|
else if (created.includes("design/config.ts")) console.log(`\n Live Jam is on (${jamAgent}): tag @${NAME} in a canvas comment and your agent does the work, then replies in the thread.`);
|
|
239
240
|
console.log(`\n next: npx ${NAME} dev (or: npx ${NAME} canvas - same thing; canvas on http://localhost:${DEFAULTS.port} by default)\n`);
|
|
240
|
-
if (!noApp(host)) console.log(` then, to your agent: "Read design/AGENTS.md. This is our first session - follow design/instructions/welcome.md."\n`);
|
|
241
|
+
if (!noApp(host) && created.includes("design/config.ts")) console.log(` then, to your agent: "Read design/AGENTS.md. This is our first session - follow design/instructions/welcome.md."\n`);
|
|
241
242
|
}
|
|
242
243
|
/** The host's path aliases, re-rooted one level down for design/tsconfig.json.
|
|
243
244
|
* "./src/*" becomes "../src/*" so `@/` imports resolve from inside design/. */
|
|
@@ -1,9 +1,29 @@
|
|
|
1
|
+
import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.mjs";
|
|
1
2
|
import { i as PKG, n as CONTENT_WIDTH } from "./cli.mjs";
|
|
2
3
|
import { D as boardFields, H as isBoardName, L as buildTree, N as readRegistry, O as checkBoardsDir, R as flatten, U as readDescription, W as readTitle, at as hash, j as listBoardFiles, k as checkRealDirs, t as annotateBoards, z as folderEntries } from "./board-status-CWGHIdo_.mjs";
|
|
3
4
|
import { existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, renameSync, rmSync, writeFileSync } from "node:fs";
|
|
4
5
|
import { join, relative, sep } from "node:path";
|
|
5
6
|
import { randomBytes } from "node:crypto";
|
|
6
7
|
//#region src/server/manifest.ts
|
|
8
|
+
var manifest_exports = /* @__PURE__ */ __exportAll({
|
|
9
|
+
NOTE_MAX: () => NOTE_MAX,
|
|
10
|
+
affectedFrameIds: () => affectedFrameIds,
|
|
11
|
+
codeOnly: () => codeOnly,
|
|
12
|
+
contentScan: () => contentScan,
|
|
13
|
+
contentWidthOf: () => contentWidthOf,
|
|
14
|
+
extractMeta: () => extractMeta,
|
|
15
|
+
frontMatter: () => frontMatter,
|
|
16
|
+
isNoteFile: () => isNoteFile,
|
|
17
|
+
noteFileFor: () => noteFileFor,
|
|
18
|
+
readNote: () => readNote,
|
|
19
|
+
scanFrames: () => scanFrames,
|
|
20
|
+
sceneBrief: () => sceneBrief,
|
|
21
|
+
sceneNote: () => sceneNote,
|
|
22
|
+
setSceneTitle: () => setSceneTitle,
|
|
23
|
+
statusBoards: () => statusBoards,
|
|
24
|
+
toFrameId: () => toFrameId,
|
|
25
|
+
writeManifest: () => writeManifest
|
|
26
|
+
});
|
|
7
27
|
const FRAME_EXT = /\.(tsx|jsx|html)$/;
|
|
8
28
|
const RESERVED_SCENES = /* @__PURE__ */ new Set(["components", "screens"]);
|
|
9
29
|
/** Sticky notes (spec 18): the longest note the manifest carries - a note is an aside, not a spec. */
|
|
@@ -296,6 +316,9 @@ function scanBoards(root) {
|
|
|
296
316
|
...boards.length ? { boards } : {}
|
|
297
317
|
};
|
|
298
318
|
}
|
|
319
|
+
/** The boards that wear a status (feature and project, by their resolved type) - for the dev
|
|
320
|
+
* server's word at boot when there is no context/ to read it from. */
|
|
321
|
+
const statusBoards = (root) => (scanBoards(root).boards ?? []).filter((b) => b.type === "feature" || b.type === "project").map((b) => b.name);
|
|
299
322
|
function scanFrames(root, project) {
|
|
300
323
|
const design = join(root, "design");
|
|
301
324
|
const frames = [];
|
|
@@ -452,4 +475,4 @@ function writeManifest(root, manifest) {
|
|
|
452
475
|
return true;
|
|
453
476
|
}
|
|
454
477
|
//#endregion
|
|
455
|
-
export {
|
|
478
|
+
export { setSceneTitle as a, scanFrames as i, isNoteFile as n, toFrameId as o, manifest_exports as r, writeManifest as s, affectedFrameIds as t };
|
|
@@ -2,7 +2,7 @@ import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.mjs";
|
|
|
2
2
|
import { a as ROUTE, i as PKG, r as NAME } from "./cli.mjs";
|
|
3
3
|
import { A as isRegularFile, B as folderMap, D as boardFields, F as BOARD_NAME, G as validateWire, I as FOLDERS_FILE, K as wireKids, L as buildTree, M as nodeExists, N as readRegistry, O as checkBoardsDir, P as withRegistryLock, T as AUTHOR_FIELDS, U as readDescription, W as readTitle, Y as HAS_STATUS, at as hash, et as readReason, it as settableStatuses, j as listBoardFiles, n as readContextFacts, nt as readType, rt as resolveType, t as annotateBoards, tt as readStatusWord } from "./board-status-CWGHIdo_.mjs";
|
|
4
4
|
import { n as localProfile, t as isConnected } from "./profile-BjAPAJSb.mjs";
|
|
5
|
-
import {
|
|
5
|
+
import { a as setSceneTitle, i as scanFrames, n as isNoteFile, s as writeManifest, t as affectedFrameIds } from "./manifest-CcdWx7ud.mjs";
|
|
6
6
|
import { n as loadConfig } from "./config-DJxMRVD8.mjs";
|
|
7
7
|
import { copyFileSync, existsSync, linkSync, mkdirSync, readFileSync, readdirSync, realpathSync, renameSync, rmSync, watch, writeFileSync } from "node:fs";
|
|
8
8
|
import { basename, dirname, join, resolve, sep } from "node:path";
|
|
@@ -546,7 +546,7 @@ function apiMiddleware(root, opts = {}) {
|
|
|
546
546
|
};
|
|
547
547
|
const asPng = url.searchParams.get("format") === "png";
|
|
548
548
|
const origin = opts.origin?.() ?? `http://${req.headers.host ?? "localhost"}`;
|
|
549
|
-
const { shootFrame } = await import("./shot-
|
|
549
|
+
const { shootFrame } = await import("./shot-BAR8hmU9.mjs");
|
|
550
550
|
const r = await shootFrame({
|
|
551
551
|
root,
|
|
552
552
|
viewports: opts.viewports ?? {},
|
|
@@ -596,7 +596,7 @@ function apiMiddleware(root, opts = {}) {
|
|
|
596
596
|
if (typeof theme !== "string" || !/^[a-z0-9-]+$/i.test(theme)) return json(res, 400, { error: "invalid theme" });
|
|
597
597
|
const scale = body.scale === void 0 ? void 0 : body.scale;
|
|
598
598
|
if (scale !== void 0 && !(Number.isInteger(scale) && scale >= 1 && scale <= 4)) return json(res, 400, { error: "invalid scale" });
|
|
599
|
-
const { resolveFrames, shootBatch } = await import("./shot-
|
|
599
|
+
const { resolveFrames, shootBatch } = await import("./shot-BAR8hmU9.mjs");
|
|
600
600
|
const sel = resolveFrames(root, body);
|
|
601
601
|
if (!sel.ok) return json(res, sel.status, { error: sel.error });
|
|
602
602
|
const origin = opts.origin?.() ?? `http://${req.headers.host ?? "localhost"}`;
|
|
@@ -624,7 +624,7 @@ function apiMiddleware(root, opts = {}) {
|
|
|
624
624
|
return json(res, 400, { error: "malformed JSON" });
|
|
625
625
|
}
|
|
626
626
|
if (!body || typeof body !== "object" || !Array.isArray(body.asks) || !body.asks.length || body.asks.length > 200) return json(res, 400, { error: "asks must list 1-200 frames" });
|
|
627
|
-
const { bakeBatch, ASK_MAX } = await import("./bake-
|
|
627
|
+
const { bakeBatch, ASK_MAX } = await import("./bake-CvY8QR3L.mjs");
|
|
628
628
|
let manifest = {};
|
|
629
629
|
try {
|
|
630
630
|
manifest = JSON.parse(readFileSync(join(root, "design", "manifest.json"), "utf8"));
|
|
@@ -668,8 +668,8 @@ function apiMiddleware(root, opts = {}) {
|
|
|
668
668
|
if (path === "poster" && req.method === "GET") {
|
|
669
669
|
if (!ownerGated(req)) return json(res, 403, { error: "forbidden" });
|
|
670
670
|
const src = url.searchParams.get("src") ?? "";
|
|
671
|
-
const { ensurePoster, isLocalClip } = await import("./poster-
|
|
672
|
-
const { isLocalAssetRef } = await import("./build-
|
|
671
|
+
const { ensurePoster, isLocalClip } = await import("./poster-BduzQBYz.mjs");
|
|
672
|
+
const { isLocalAssetRef } = await import("./build-B1kavcpc.mjs");
|
|
673
673
|
if (!isLocalAssetRef(src) || !isLocalClip(src)) return json(res, 400, { error: "src must be a clip under design/assets/" });
|
|
674
674
|
const r = await ensurePoster(join(root, "design", "assets"), src);
|
|
675
675
|
if (!r.ok) return json(res, r.error.includes("does not exist") ? 404 : 503, { error: r.error });
|
|
@@ -1151,7 +1151,7 @@ function marverPlugin(ctx) {
|
|
|
1151
1151
|
};
|
|
1152
1152
|
const prune = () => setTimeout(async () => {
|
|
1153
1153
|
try {
|
|
1154
|
-
(await import("./bake-
|
|
1154
|
+
(await import("./bake-CvY8QR3L.mjs")).pruneBakes(root, bakeGen);
|
|
1155
1155
|
} catch {}
|
|
1156
1156
|
}, 500);
|
|
1157
1157
|
prune();
|
|
@@ -1303,7 +1303,7 @@ function marverPlugin(ctx) {
|
|
|
1303
1303
|
});
|
|
1304
1304
|
return;
|
|
1305
1305
|
}
|
|
1306
|
-
const { shootFrame, shootBatch, resolveFrames } = await import("./shot-
|
|
1306
|
+
const { shootFrame, shootBatch, resolveFrames } = await import("./shot-BAR8hmU9.mjs");
|
|
1307
1307
|
if (ways[0] === "frame") {
|
|
1308
1308
|
if (typeof spec.frame !== "string") {
|
|
1309
1309
|
write({
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { capture, t as findChrome } from "./shot-
|
|
1
|
+
import { capture, t as findChrome } from "./shot-BAR8hmU9.mjs";
|
|
2
2
|
import { constants, copyFileSync, existsSync, mkdtempSync, realpathSync, rmSync, writeFileSync } from "node:fs";
|
|
3
3
|
import { basename, dirname, join, sep } from "node:path";
|
|
4
4
|
import { pathToFileURL } from "node:url";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { o as slideSize } from "./cli.mjs";
|
|
2
|
-
import { planShot, t as findChrome } from "./shot-
|
|
3
|
-
import { ASK_MAX, bakeBatch } from "./bake-
|
|
2
|
+
import { planShot, t as findChrome } from "./shot-BAR8hmU9.mjs";
|
|
3
|
+
import { ASK_MAX, bakeBatch } from "./bake-CvY8QR3L.mjs";
|
|
4
4
|
import { MIME } from "./serve-z5qtj_wJ.mjs";
|
|
5
5
|
import { copyFileSync, lstatSync, mkdirSync, readFileSync, realpathSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
6
6
|
import { extname, isAbsolute, join, relative, resolve } from "node:path";
|
|
@@ -337,8 +337,8 @@ async function shootFrame(opts) {
|
|
|
337
337
|
};
|
|
338
338
|
const plan = planShot(frame, viewports, size);
|
|
339
339
|
if (frame.kind !== "html") try {
|
|
340
|
-
const { scanAssetRefs } = await import("./build-
|
|
341
|
-
const { ensurePoster } = await import("./poster-
|
|
340
|
+
const { scanAssetRefs } = await import("./build-B1kavcpc.mjs");
|
|
341
|
+
const { ensurePoster } = await import("./poster-BduzQBYz.mjs");
|
|
342
342
|
const refs = scanAssetRefs(readFileSync(join(root, frame.file), "utf8"), frame.file);
|
|
343
343
|
for (const r of refs) if (r.endsWith(".poster.png")) await ensurePoster(join(root, "design", "assets"), r.slice(0, -11));
|
|
344
344
|
} catch {}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@marver-design/marver",
|
|
3
|
-
"version": "0.22.
|
|
3
|
+
"version": "0.22.1",
|
|
4
4
|
"description": "The agent-native design canvas. A design/ folder, one command, a canvas of live frames built from your repo's real components - comment @marver and your own coding agent does the work. The tool ships no AI.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"private": false,
|
|
@@ -5,6 +5,17 @@ Never drive or automate the canvas UI; read and write files only. (Starting
|
|
|
5
5
|
`npx marver dev` so the human has a live canvas - first session, or on request -
|
|
6
6
|
is the one allowed touch.)
|
|
7
7
|
|
|
8
|
+
## Before the method: a project with no `context/`
|
|
9
|
+
|
|
10
|
+
This repository has no `context/` directory? Then **every reply in which you made, specced or changed
|
|
11
|
+
a feature or project board ends with this line**, word for word, until the human answers it:
|
|
12
|
+
|
|
13
|
+
> This project has no `context/` yet, so every feature board reads Backlog and nothing records what
|
|
14
|
+
> shipped. Want me to set it up? A few questions, then a draft from the code and the deploy history.
|
|
15
|
+
|
|
16
|
+
A yes: instructions/context.md, "Setting up". A no stands for the session - stop asking. Never set
|
|
17
|
+
it up unasked.
|
|
18
|
+
|
|
8
19
|
## The method (binding)
|
|
9
20
|
|
|
10
21
|
Design work moves through phases. BEFORE working in a phase, read its instruction
|
|
@@ -5,6 +5,17 @@ Never drive or automate the canvas UI; read and write files only. (Starting
|
|
|
5
5
|
`npx marver dev` so the human has a live canvas - first session, or on request -
|
|
6
6
|
is the one allowed touch.)
|
|
7
7
|
|
|
8
|
+
## Before the method: a project with no `context/`
|
|
9
|
+
|
|
10
|
+
This repository has no `context/` directory? Then **every reply in which you made, specced or changed
|
|
11
|
+
a feature or project board ends with this line**, word for word, until the human answers it:
|
|
12
|
+
|
|
13
|
+
> This project has no `context/` yet, so every feature board reads Backlog and nothing records what
|
|
14
|
+
> shipped. Want me to set it up? A few questions, then a draft from the code and the deploy history.
|
|
15
|
+
|
|
16
|
+
A yes: instructions/context.md, "Setting up". A no stands for the session - stop asking. Never set
|
|
17
|
+
it up unasked.
|
|
18
|
+
|
|
8
19
|
## The method (binding)
|
|
9
20
|
|
|
10
21
|
Design work moves through phases. BEFORE working in a phase, read its instruction
|
|
@@ -176,7 +176,9 @@ boards fall back to the parent folder's type). Moving a board changes an inherit
|
|
|
176
176
|
capability is the board's name, or `"capability": "<slug>"`. You may decide only three things on
|
|
177
177
|
the board: `"status": "archived"`, `"paused"`, or `"blocked"` with `"reason": "<one sentence>"`.
|
|
178
178
|
**Never write `"status": "done"`** - Done comes from `context/shipped.md`, and the check fails it.
|
|
179
|
-
|
|
179
|
+
**No `context/`? Your reply ends with the context line** from design/AGENTS.md ("Before the method")
|
|
180
|
+
- every feature board reads Backlog until there is one. Only when the human declines may a board
|
|
181
|
+
say `"todo"`, `"backlog"` or `"in-progress"` by hand.
|
|
180
182
|
A person sets the same from the sidebar (right-click, Change status…) - it rewrites only `status`
|
|
181
183
|
and `reason`, so re-read a board before you edit it.
|
|
182
184
|
- In progress fills by phase: the phase scenes above, or `phase: spec | lofi | hifi` in a scene's
|
|
@@ -98,11 +98,20 @@ Context starts with people. Ask, in one message:
|
|
|
98
98
|
3. What is private, and who may see what?
|
|
99
99
|
4. How is this project named in shared spaces - keywords, tags?
|
|
100
100
|
|
|
101
|
-
Then
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
101
|
+
Then, in order - this is the whole recipe; "set up our context" asks for all of it:
|
|
102
|
+
1. `npx marver context init --kind product` - or `--kind knowledge` when the work is deliverables
|
|
103
|
+
for clients rather than a product people use. Record the answers in `context/people.md`.
|
|
104
|
+
2. Draft from evidence: the shipped record from deploy runs and the changelog (`unknown` where
|
|
105
|
+
nothing proves it), a map from the code, contracts for the capabilities that matter now.
|
|
106
|
+
3. Let the canvas read it: `npx marver init --kind <the same kind>` adds the typed folders (it never
|
|
107
|
+
moves a board); put each feature board in Features (a project in Projects), named after its
|
|
108
|
+
capability or saying `"capability": "<slug>"`; then `npx marver boards new home --type start
|
|
109
|
+
--folder start-here`.
|
|
110
|
+
4. Put the check in ci - a step running `npx marver context check` on a full-history checkout
|
|
111
|
+
(`fetch-depth: 0`) - and make it pass before you hand over.
|
|
112
|
+
|
|
113
|
+
**Context that exists but is scattered** - specs out of date, nobody sure what is live - is a job
|
|
114
|
+
for `context/playbooks/reorganize-context/PLAYBOOK.md`, not for a rewrite.
|
|
106
115
|
|
|
107
116
|
## The check
|
|
108
117
|
|