@blulotus/trellis 0.7.3 → 0.7.4

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.
@@ -1,19 +1,4 @@
1
1
  import { type ProjectType, type DetectedPackage } from "../utils/project-detector.js";
2
- /** How `spec/frontend/visual-design.md` is scaffolded. See config.yaml. */
3
- export type VisualDesignMode = "auto" | "always";
4
- /**
5
- * Read `spec.visual_design` from `.trellis/config.yaml`.
6
- *
7
- * `createWorkflowStructure` writes config.yaml before it writes spec, and
8
- * `writeFile` preserves an existing config, so on a re-init this reads the
9
- * user's own file. A first init has no config yet and gets `auto`.
10
- *
11
- * Hand-parsed for the same reason `loadUpdateSkipPaths` in `commands/update.ts`
12
- * is: config.yaml is read in several places without a YAML dependency.
13
- *
14
- * @internal Exported for testing only
15
- */
16
- export declare function loadVisualDesignMode(cwd: string): VisualDesignMode;
17
2
  /**
18
3
  * Options for creating workflow structure
19
4
  */
@@ -1 +1 @@
1
- {"version":3,"file":"workflow.d.ts","sourceRoot":"","sources":["../../src/configurators/workflow.ts"],"names":[],"mappings":"AAyCA,OAAO,EAEL,KAAK,WAAW,EAChB,KAAK,eAAe,EACrB,MAAM,8BAA8B,CAAC;AAOtC,2EAA2E;AAC3E,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,QAAQ,CAAC;AAEjD;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,gBAAgB,CAyClE;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,yCAAyC;IACzC,WAAW,EAAE,WAAW,CAAC;IACzB,yFAAyF;IACzF,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,kEAAkE;IAClE,QAAQ,CAAC,EAAE,eAAe,EAAE,CAAC;IAC7B,0EAA0E;IAC1E,kBAAkB,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACjC;;;;;;OAMG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,uBAAuB,CAC3C,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,eAAe,GACxB,OAAO,CAAC,IAAI,CAAC,CA0Ef"}
1
+ {"version":3,"file":"workflow.d.ts","sourceRoot":"","sources":["../../src/configurators/workflow.ts"],"names":[],"mappings":"AAwCA,OAAO,EAEL,KAAK,WAAW,EAChB,KAAK,eAAe,EACrB,MAAM,8BAA8B,CAAC;AAOtC;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,yCAAyC;IACzC,WAAW,EAAE,WAAW,CAAC;IACzB,yFAAyF;IACzF,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,kEAAkE;IAClE,QAAQ,CAAC,EAAE,eAAe,EAAE,CAAC;IAC7B,0EAA0E;IAC1E,kBAAkB,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACjC;;;;;;OAMG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,uBAAuB,CAC3C,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,eAAe,GACxB,OAAO,CAAC,IAAI,CAAC,CA+Df"}
@@ -1,4 +1,3 @@
1
- import fs from "node:fs";
2
1
  import path from "node:path";
3
2
  import { DIR_NAMES, PATHS } from "../constants/paths.js";
4
3
  import { copyTrellisDir } from "../templates/extract.js";
@@ -15,59 +14,6 @@ guidesIndexContent, guidesCrossLayerThinkingGuideContent, guidesCodeReuseThinkin
15
14
  import { writeFile, ensureDir } from "../utils/file-writer.js";
16
15
  import { replacePythonCommandLiterals } from "./shared.js";
17
16
  import { sanitizePkgName, } from "../utils/project-detector.js";
18
- /**
19
- * Read `spec.visual_design` from `.trellis/config.yaml`.
20
- *
21
- * `createWorkflowStructure` writes config.yaml before it writes spec, and
22
- * `writeFile` preserves an existing config, so on a re-init this reads the
23
- * user's own file. A first init has no config yet and gets `auto`.
24
- *
25
- * Hand-parsed for the same reason `loadUpdateSkipPaths` in `commands/update.ts`
26
- * is: config.yaml is read in several places without a YAML dependency.
27
- *
28
- * @internal Exported for testing only
29
- */
30
- export function loadVisualDesignMode(cwd) {
31
- const configPath = path.join(cwd, DIR_NAMES.WORKFLOW, "config.yaml");
32
- if (!fs.existsSync(configPath))
33
- return "auto";
34
- let raw = null;
35
- try {
36
- const lines = fs.readFileSync(configPath, "utf-8").split("\n");
37
- let inSpec = false;
38
- for (const line of lines) {
39
- if (/^spec:\s*(#.*)?$/.test(line)) {
40
- inSpec = true;
41
- continue;
42
- }
43
- // A non-indented, non-comment, non-blank line closes the block.
44
- if (inSpec && /^\S/.test(line) && !line.startsWith("#")) {
45
- inSpec = false;
46
- }
47
- if (!inSpec)
48
- continue;
49
- const match = /^\s+visual_design:\s*([^#]+)/.exec(line);
50
- if (match) {
51
- raw = match[1]
52
- .trim()
53
- .replace(/^['"]|['"]$/g, "")
54
- .toLowerCase();
55
- break;
56
- }
57
- }
58
- }
59
- catch {
60
- console.warn(`Warning: failed to read ${configPath}, using spec.visual_design: auto`);
61
- return "auto";
62
- }
63
- if (raw === null || raw === "auto")
64
- return "auto";
65
- if (raw === "always")
66
- return "always";
67
- console.warn(`Warning: unknown spec.visual_design value "${raw}" in ${configPath}; ` +
68
- `expected "auto" or "always". Using "auto".`);
69
- return "auto";
70
- }
71
17
  /**
72
18
  * Create workflow structure based on project type
73
19
  *
@@ -87,10 +33,6 @@ export async function createWorkflowStructure(cwd, options) {
87
33
  const packages = options?.packages;
88
34
  const remoteSpecPackages = options?.remoteSpecPackages;
89
35
  const workflowMd = options?.workflowMdOverride ?? workflowMdTemplate;
90
- // Read before this function writes config.yaml. `--force` overwrites the
91
- // user's config with the template, so reading it later would silently reset
92
- // the choice to `auto` on exactly the run that rewrites the files.
93
- const visualDesignMode = loadVisualDesignMode(cwd);
94
36
  // Create base .trellis directory
95
37
  ensureDir(path.join(cwd, DIR_NAMES.WORKFLOW));
96
38
  // Copy scripts/ directory from templates
@@ -122,11 +64,11 @@ export async function createWorkflowStructure(cwd, options) {
122
64
  // These are NOT dogfooded - they are generic templates for new projects
123
65
  if (packages && packages.length > 0) {
124
66
  // Monorepo mode: create per-package spec directories
125
- await createSpecTemplates(cwd, projectType, visualDesignMode, packages, remoteSpecPackages);
67
+ await createSpecTemplates(cwd, projectType, packages, remoteSpecPackages);
126
68
  }
127
69
  else if (!skipSpecTemplates) {
128
70
  // Single-repo mode: create global spec (skip if using remote template)
129
- await createSpecTemplates(cwd, projectType, visualDesignMode);
71
+ await createSpecTemplates(cwd, projectType);
130
72
  }
131
73
  }
132
74
  /**
@@ -185,7 +127,7 @@ async function writeFrontendDocs(specBase) {
185
127
  /**
186
128
  * Write spec docs for a given project type into a target spec directory.
187
129
  */
188
- async function writeSpecForType(specBase, projectType, visualDesignMode) {
130
+ async function writeSpecForType(specBase, projectType) {
189
131
  if (projectType !== "frontend") {
190
132
  await writeBackendDocs(specBase);
191
133
  }
@@ -193,18 +135,16 @@ async function writeSpecForType(specBase, projectType, visualDesignMode) {
193
135
  await writeFrontendDocs(specBase);
194
136
  return;
195
137
  }
196
- if (visualDesignMode === "always") {
197
- // Backend-only layer, but the user asked for the visual craft rules
198
- // anyway backend work in this project reaches rendered surfaces. Only
199
- // this one file: every other `frontend/` doc is an unfilled stub, so
200
- // creating them would add noise the layer has no use for. The backend
201
- // index points here whenever the file exists.
202
- const frontendDir = path.join(specBase, "frontend");
203
- ensureDir(frontendDir);
204
- await writeFile(path.join(frontendDir, "visual-design.md"), frontendVisualDesignContent);
205
- }
138
+ // Backend-only layer still gets visual-design.md, and only that file: a
139
+ // backend task can span into UI work, and whether the agent is actually
140
+ // handed the rules is decided at runtime by `spec.visual_design` (read by
141
+ // inject-spec-context.py), not by what init chose to write. Every other
142
+ // `frontend/` doc is an unfilled stub a backend layer has no use for.
143
+ const frontendDir = path.join(specBase, "frontend");
144
+ ensureDir(frontendDir);
145
+ await writeFile(path.join(frontendDir, "visual-design.md"), frontendVisualDesignContent);
206
146
  }
207
- async function createSpecTemplates(cwd, projectType, visualDesignMode, packages, remoteSpecPackages) {
147
+ async function createSpecTemplates(cwd, projectType, packages, remoteSpecPackages) {
208
148
  // Ensure spec directory exists
209
149
  ensureDir(path.join(cwd, PATHS.SPEC));
210
150
  // Guides - always created regardless of mode
@@ -233,12 +173,12 @@ async function createSpecTemplates(cwd, projectType, visualDesignMode, packages,
233
173
  const pkgSpecBase = path.join(cwd, `${PATHS.SPEC}/${dirName}`);
234
174
  ensureDir(pkgSpecBase);
235
175
  const pkgType = pkg.type === "unknown" ? "fullstack" : pkg.type;
236
- await writeSpecForType(pkgSpecBase, pkgType, visualDesignMode);
176
+ await writeSpecForType(pkgSpecBase, pkgType);
237
177
  }
238
178
  }
239
179
  else {
240
180
  // Single-repo mode
241
- await writeSpecForType(path.join(cwd, PATHS.SPEC), projectType, visualDesignMode);
181
+ await writeSpecForType(path.join(cwd, PATHS.SPEC), projectType);
242
182
  }
243
183
  }
244
184
  //# sourceMappingURL=workflow.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"workflow.js","sourceRoot":"","sources":["../../src/configurators/workflow.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"workflow.js","sourceRoot":"","sources":["../../src/configurators/workflow.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ {
2
+ "version": "0.7.3",
3
+ "description": "Patch: spec index gates that skills already pointed at, a config switch for visual-design.md, and de-duplicated render-verification rules.",
4
+ "breaking": false,
5
+ "recommendMigrate": false,
6
+ "changelog": "**Bug Fixes:**\n- fix(spec): `trellis-before-dev` and `trellis-check` have long instructed the agent to \"follow the Pre-Development Checklist / Quality Check section\" of `.trellis/spec/<package>/<layer>/index.md`, but the shipped backend and frontend index templates never contained those headings — the instruction dead-ended and the gates were silently skipped. Both sections now ship, with a platform-neutral floor to extend.\n\n**Features:**\n- feat(spec): new `spec.visual_design` key in `.trellis/config.yaml` (`auto` | `always`). `auto` keeps the existing behavior — `spec/frontend/visual-design.md` lands only where a frontend layer was detected. `always` also writes it for a backend-only layer, for projects where backend work regularly reaches a rendered surface. `spec/backend/index.md` gained an existence-conditional pointer so the file is reachable from a backend layer.\n- feat(agents): the Codex `trellis-research` agent gained the source-quality discipline the Claude Code agent already had — follow every claim to the source that owns it, prefer sources openable on this machine, record the version read against.\n\n**Internal:**\n- refactor(spec): `spec/frontend/index.md`'s Quality Check restated `visual-design.md`'s render-verification rules almost verbatim. It now points at them instead, with a test asserting the duplicate cannot grow back. `visual-design.md` gained a scope-and-shelf-life note, a corrected claim about `padding` / `margin` transform equivalents, and a check date on its browser baselines.\n- refactor(skills): the `check` skill's authorization paragraph no longer restates Step 6. It keeps the commit/push boundary Step 6 does not cover, and states what a dispatched `trellis-check` sub-agent should do when there is no user turn to ask in: report upward rather than stop or widen the change.\n- test: coverage for the backend index's new sections; `platforms.integration.test.ts` given headroom over the global 10s timeout, since `spawnSync` on a cold Node start blocks a vitest worker long enough to trip it under full-suite contention.",
7
+ "migrations": [],
8
+ "notes": "No files are renamed or deleted — `--migrate` is not needed.\n\n`.trellis/spec/` is a protected path that `trellis update` never writes, so the new index sections and `visual-design.md` reach `trellis init` only. An existing project keeps its current spec tree; re-run `trellis init` in it to pick up files that are missing, or copy the two new index sections in by hand."
9
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "version": "0.7.4",
3
+ "description": "Patch: spec.visual_design becomes a runtime injection switch, and visual-design.md installs for every project type.",
4
+ "breaking": false,
5
+ "recommendMigrate": false,
6
+ "changelog": "**Behavior change:**\n- feat(spec): `spec.visual_design` in `.trellis/config.yaml` is now a **runtime** switch instead of a scaffolding one. 0.7.3 read it during `trellis init` and it only decided whether `visual-design.md` was written to disk — setting it back had no effect, and it could not be turned on for one task. It is now read by `inject-spec-context.py` on every injection event, so an edit takes effect on the next tool call with no `trellis init` and no session restart. Values: `auto` (default) follows the `paths:` globs in `visual-design.md`'s own frontmatter, so a frontend project is covered with no configuration and a backend project is left alone; `true` injects on every touched file, for a task that spans backend and UI; `false` never injects.\n- feat(spec): `spec/frontend/visual-design.md` is installed for **every** project type, backend-only included — a backend task can span into UI work. A backend-only layer gets that one file and none of the other `frontend/` to-fill stubs.\n- feat(spec): `visual-design.md` is the first shipped spec file to carry `paths:` frontmatter, making it a live example of the path-scoped injection contract. Add your own globs if the project keeps UI somewhere they miss (a Go template dir, a Rails view path, a design-token package).\n\n**Bug Fixes:**\n- fix(release): the release preflight's `npm view` timeout was 15s, but the first `npm view` of a session pays DNS plus npm startup and measures around 16s — so the first release attempt of a session failed with an `ETIMEDOUT` that read like broken release tooling. Raised to 60s.",
7
+ "migrations": [],
8
+ "notes": "No files are renamed or deleted — `--migrate` is not needed.\n\nIf you set `spec.visual_design: always` under 0.7.3, remove it: `always` is no longer a recognized value and now warns to stderr and falls back to `auto`. Its 0.7.3 purpose — getting the file into a backend-only project — is the default from this release on, so no replacement setting is needed. Use `true` only when you want the rules injected regardless of which file the agent touches.\n\n`.trellis/spec/` remains a protected path that `trellis update` never writes, so an existing project does not receive `visual-design.md` from an update. Re-run `trellis init` to have it appear."
9
+ }
@@ -26,7 +26,7 @@ This directory contains guidelines for backend development. Fill in each file wi
26
26
 
27
27
  Read before writing backend code. `trellis-before-dev` follows this section.
28
28
 
29
- 1. **Read the conventions that apply** — the files above covering the layers this change touches, plus `.trellis/spec/guides/` for the cross-cutting thinking guides. When the change reaches a rendered surface and `../frontend/visual-design.md` exists, read that too.
29
+ 1. **Read the conventions that apply** — the files above covering the layers this change touches, plus `.trellis/spec/guides/` for the cross-cutting thinking guides. When the change reaches a rendered surface, read `../frontend/visual-design.md` too — it ships in every project, backend-only included.
30
30
  2. **State the change boundary.** The smallest behavior gap between what happens now and what should happen; where that behavior actually lives (not where it is easiest to intercept); which files you expect to change and why each is necessary; what you are explicitly not doing.
31
31
  3. **Name the contract you are about to touch.** Any change to a public function signature, HTTP route, event payload, database schema, or config key has callers. Find them before editing, not after.
32
32
  4. **Decide where the test will sit** before writing code, on a boundary that survives a refactor of the implementation behind it.
@@ -45,7 +45,7 @@ Run before reporting a backend change complete. `trellis-check` follows this sec
45
45
  - [ ] Errors are propagated or handled deliberately, never swallowed. No debug logging left behind.
46
46
  - [ ] No credential, token, or personal data in logs, error messages, or committed fixtures.
47
47
  - [ ] Migrations run forward on a copy of real-shaped data, and the rollback path is known.
48
- - [ ] A change that reached a rendered surface was verified against `../frontend/visual-design.md` → **Verification**, which owns the render rules and the no-renderer fallback. Skip this line where that file does not exist in this project.
48
+ - [ ] A change that reached a rendered surface was verified against `../frontend/visual-design.md` → **Verification**, which owns the render rules and the no-renderer fallback. For a task that spans backend and UI, `spec.visual_design: true` in `.trellis/config.yaml` makes those rules arrive on every file you touch.
49
49
 
50
50
  Replace and extend these with your project's actual gates — the real verification commands, the real risky areas.
51
51
 
@@ -8,7 +8,7 @@
8
8
 
9
9
  This directory contains guidelines for frontend development. Fill in each file with your project's specific conventions.
10
10
 
11
- One file is the exception: `visual-design.md` ships filled in, because visual craft rules are general knowledge no codebase can state. Read it as-is; override a rule where your project has decided against it.
11
+ One file is the exception: `visual-design.md` ships filled in, because visual craft rules are general knowledge no codebase can state. Read it as-is; override a rule where your project has decided against it. It is also the one spec file that carries `paths:` frontmatter, so it arrives on its own when you touch a UI file — `spec.visual_design` in `.trellis/config.yaml` is the switch.
12
12
 
13
13
  ---
14
14
 
@@ -1,10 +1,30 @@
1
+ ---
2
+ name: visual-design
3
+ description: Typography, color, motion, surfaces, banned patterns, render verification
4
+ paths:
5
+ - "**/*.tsx"
6
+ - "**/*.jsx"
7
+ - "**/*.vue"
8
+ - "**/*.svelte"
9
+ - "**/*.astro"
10
+ - "**/*.css"
11
+ - "**/*.scss"
12
+ - "**/*.sass"
13
+ - "**/*.less"
14
+ - "**/*.styl"
15
+ - "**/*.html"
16
+ - "**/tailwind.config.*"
17
+ ---
18
+
1
19
  # Visual Design Rules
2
20
 
3
21
  > **This file ships filled in.** Unlike its siblings in this directory, it is not a "document your project's conventions" stub. These rules are general craft knowledge that a codebase cannot tell you — no config file states which typefaces read as unconsidered, and no linter catches a purple-to-blue gradient. Delete or override any rule your project has deliberately decided against, and record the reason where you override it.
4
22
  >
5
23
  > Project-specific token values (your palette, your type scale, your radius scale) belong in a `DESIGN.md`-style section you add at the bottom, or in `component-guidelines.md`. This file holds the rules that hold regardless of project.
6
24
  >
7
- > **Scope and shelf life.** Written for web UI: the mechanisms named are CSS, and a React Native / Flutter / desktop-toolkit surface should read the intent and ignore the syntax. Two kinds of content here decay — the browser baselines under Motion, and the typeface list under Typography — so treat both as "true when written" and re-check before leaning on them. Rules as of Trellis 0.7.3 (2026-08).
25
+ > **Scope and shelf life.** Written for web UI: the mechanisms named are CSS, and a React Native / Flutter / desktop-toolkit surface should read the intent and ignore the syntax. Two kinds of content here decay — the browser baselines under Motion, and the typeface list under Typography — so treat both as "true when written" and re-check before leaning on them. Rules as of Trellis 0.7.4 (2026-08).
26
+ >
27
+ > **When you get this file.** The `paths:` globs above are what `spec.visual_design: auto` follows — touch one of those files and these rules arrive on that tool call. Add your own globs if this project keeps UI somewhere they miss (a Go template dir, a Rails view path, a design-token package). `spec.visual_design: true` in `.trellis/config.yaml` ignores the globs and injects on every file, which is the switch for a task that spans backend and UI; `false` turns it off entirely.
8
28
 
9
29
  ---
10
30
 
@@ -332,6 +332,123 @@ def get_spec_injection_settings(
332
332
  )
333
333
 
334
334
 
335
+ VISUAL_DESIGN_BASENAME = "visual-design.md"
336
+
337
+
338
+ def get_visual_design_mode(root: Path) -> str:
339
+ """Return the `spec.visual_design` mode: "auto" | "on" | "off".
340
+
341
+ Read here rather than at `trellis init` time, so flipping it takes effect
342
+ on the next tool call — the point of the key is to be turned on for one
343
+ cross-stack task and back off afterwards, and a scaffolding-time read could
344
+ not express that.
345
+
346
+ spec:
347
+ visual_design: auto # follow the file's own `paths:` globs
348
+ # visual_design: true # inject on every touched file
349
+ # visual_design: false # never inject
350
+
351
+ Accepts the same truthy/falsy spellings as `session_auto_commit`. An
352
+ unrecognized value warns and falls back to "auto".
353
+ """
354
+ config = _read_trellis_config(root)
355
+ section = config.get("spec") if isinstance(config, dict) else None
356
+ if not isinstance(section, dict) or "visual_design" not in section:
357
+ return "auto"
358
+ raw = section["visual_design"]
359
+ if isinstance(raw, bool):
360
+ return "on" if raw else "off"
361
+ text = str(raw).strip().lower()
362
+ if text == "auto":
363
+ return "auto"
364
+ if text in ("true", "yes", "1", "on"):
365
+ return "on"
366
+ if text in ("false", "no", "0", "off"):
367
+ return "off"
368
+ _warn(
369
+ f"invalid spec.visual_design value: {raw!r}; "
370
+ f'expected auto / true / false. Using "auto"'
371
+ )
372
+ return "auto"
373
+
374
+
375
+ def apply_visual_design_mode(
376
+ root: Path,
377
+ mode: str,
378
+ matches: list,
379
+ match_files: dict[str, str],
380
+ trigger_file: str,
381
+ ) -> list:
382
+ """Apply `spec.visual_design` to a path-matched spec list.
383
+
384
+ "auto" is a no-op: the file's own `paths:` globs already decided, which is
385
+ why a frontend project needs no configuration and a backend project is left
386
+ alone. "off" drops it however it matched. "on" force-appends every
387
+ `visual-design.md` under `.trellis/spec/` that the globs did not already
388
+ pull in, so a task editing only `.go` files still gets the rules.
389
+
390
+ Appended, never prepended: `assemble_payload` spends its budget in list
391
+ order, so a forced entry must not outrank a spec the touched path actually
392
+ matched. In a monorepo with one copy per package the budget degrades the
393
+ extra copies to index lines, which is the intended cheap outcome.
394
+ """
395
+ if mode == "auto":
396
+ return matches
397
+ if mode == "off":
398
+ return [
399
+ match
400
+ for match in matches
401
+ if not match.rel_path.endswith("/" + VISUAL_DESIGN_BASENAME)
402
+ ]
403
+
404
+ try:
405
+ from common.spec_match import ( # type: ignore[import-not-found]
406
+ SpecMatch,
407
+ parse_spec_frontmatter,
408
+ )
409
+ from common.paths import ( # type: ignore[import-not-found]
410
+ DIR_SPEC,
411
+ DIR_WORKFLOW,
412
+ )
413
+ except Exception:
414
+ return matches # matcher unavailable — degrade to path-matched only
415
+
416
+ spec_dir = root / DIR_WORKFLOW / DIR_SPEC
417
+ if not spec_dir.is_dir():
418
+ return matches
419
+ try:
420
+ found = sorted(spec_dir.rglob(VISUAL_DESIGN_BASENAME))
421
+ except OSError as exc:
422
+ _warn(f"cannot scan {spec_dir} for {VISUAL_DESIGN_BASENAME}: {exc}")
423
+ return matches
424
+
425
+ for spec_file in found:
426
+ try:
427
+ rel_path = spec_file.relative_to(root).as_posix()
428
+ except ValueError:
429
+ continue
430
+ if rel_path in match_files:
431
+ continue
432
+ description = None
433
+ try:
434
+ frontmatter = parse_spec_frontmatter(
435
+ spec_file.read_text(encoding="utf-8", errors="replace")
436
+ )
437
+ if frontmatter is not None:
438
+ description = frontmatter.description
439
+ except (OSError, ValueError):
440
+ pass # description is cosmetic; a forced inject still carries the body
441
+ matches.append(
442
+ SpecMatch(
443
+ spec_path=spec_file,
444
+ rel_path=rel_path,
445
+ description=description,
446
+ )
447
+ )
448
+ match_files[rel_path] = trigger_file
449
+ return matches
450
+
451
+
335
452
  # =============================================================================
336
453
  # Identity ladder
337
454
  # =============================================================================
@@ -730,6 +847,14 @@ def main() -> int:
730
847
  continue
731
848
  matches.append(match)
732
849
  match_files[match.rel_path] = file_path
850
+
851
+ matches = apply_visual_design_mode(
852
+ root,
853
+ get_visual_design_mode(root),
854
+ matches,
855
+ match_files,
856
+ file_paths[0],
857
+ )
733
858
  if not matches:
734
859
  return 0
735
860
 
@@ -77,25 +77,28 @@ session_auto_commit: false
77
77
  # default_package: frontend
78
78
 
79
79
  #-------------------------------------------------------------------------------
80
- # Spec scaffolding
80
+ # Visual design rules
81
81
  #-------------------------------------------------------------------------------
82
82
  # `spec/frontend/visual-design.md` is the one spec file Trellis ships filled in
83
83
  # rather than as a "document your conventions" stub, because visual craft rules
84
- # are general knowledge no codebase can state. By default it lands only where a
85
- # frontend layer was detected.
86
- #
87
- # - auto (default): written for a frontend or fullstack layer, skipped for a
88
- # backend-only one.
89
- # - always: also written into `spec/frontend/` for a backend-only layer, and
90
- # nothing else from `spec/frontend/` is created. Choose this when backend work
91
- # in this project regularly reaches a rendered surface.
92
- #
93
- # To turn it off, delete the file. `.trellis/spec/` is a protected path, so
94
- # `trellis update` never writes it back.
95
- #
96
- # Read at `trellis init` time. A fresh project has no config.yaml yet, so
97
- # `always` takes effect from the second `trellis init` onward — set it, then
98
- # re-run `trellis init` to have the file appear.
84
+ # are general knowledge no codebase can state. It is installed for every project
85
+ # type, backend-only included. This key decides whether the agent is actually
86
+ # handed it, and is read at injection time — an edit takes effect on the next
87
+ # tool call, with no `trellis init` and no session restart.
88
+ #
89
+ # auto (default) Follow the `paths:` globs in visual-design.md's own
90
+ # frontmatter: the rules arrive when the agent touches a UI
91
+ # file (.tsx/.vue/.svelte/.css/...) and stay out of the way
92
+ # otherwise. A frontend project is covered without doing
93
+ # anything; a backend project essentially never sees it.
94
+ # true Inject on every touched file, ignoring those globs. Set this
95
+ # for a task that spans backend and UI, where the visible
96
+ # change is driven from files the globs do not cover.
97
+ # false Never inject, whatever the touched file is.
98
+ #
99
+ # Widening which paths count as UI is an edit to that file's `paths:` list, not
100
+ # a setting here. `spec_injection.enabled: false` further down turns off all
101
+ # path-scoped spec injection, this key included.
99
102
  #
100
103
  # spec:
101
104
  # visual_design: auto
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blulotus/trellis",
3
- "version": "0.7.3",
3
+ "version": "0.7.4",
4
4
  "description": "AI capabilities grow like ivy — Trellis provides the structure to guide them along a disciplined path",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -34,7 +34,7 @@
34
34
  "inquirer": "^9.3.7",
35
35
  "undici": "^6.21.0",
36
36
  "zod": "^4.4.2",
37
- "@blulotus/trellis-core": "0.7.3"
37
+ "@blulotus/trellis-core": "0.7.4"
38
38
  },
39
39
  "devDependencies": {
40
40
  "@eslint/js": "^9.18.0",