@osovv/vv-opencode 1.3.6-rc.6 → 1.3.6-rc.8
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 +17 -0
- package/README.md +32 -2
- package/dist/cli.js +5 -3
- package/dist/cli.js.map +1 -1
- package/dist/commands/lint.d.ts +74 -0
- package/dist/commands/lint.js +269 -0
- package/dist/commands/lint.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +6 -5
- package/dist/index.js.map +1 -1
- package/dist/lib/opencode.js +3 -2
- package/dist/lib/opencode.js.map +1 -1
- package/dist/lib/plugin-toggle-config.d.ts +13 -1
- package/dist/lib/plugin-toggle-config.js +38 -4
- package/dist/lib/plugin-toggle-config.js.map +1 -1
- package/dist/lib/spec-lint-cache.d.ts +34 -0
- package/dist/lib/spec-lint-cache.js +140 -0
- package/dist/lib/spec-lint-cache.js.map +1 -0
- package/dist/lib/spec-lint.d.ts +57 -0
- package/dist/lib/spec-lint.js +963 -0
- package/dist/lib/spec-lint.js.map +1 -0
- package/dist/lib/vvoc-config.d.ts +25 -0
- package/dist/lib/vvoc-config.js +9 -0
- package/dist/lib/vvoc-config.js.map +1 -1
- package/dist/lib/vvoc-paths.d.ts +1 -0
- package/dist/lib/vvoc-paths.js +15 -5
- package/dist/lib/vvoc-paths.js.map +1 -1
- package/dist/plugins/spec-guard/index.d.ts +39 -0
- package/dist/plugins/spec-guard/index.js +253 -0
- package/dist/plugins/spec-guard/index.js.map +1 -0
- package/package.json +6 -2
- package/schemas/vvoc/v3.json +23 -6
- package/templates/skills/vv-execute/SKILL.md +8 -3
- package/templates/skills/vv-plan/SKILL.md +7 -7
- package/templates/skills/vv-plan/references/plan-template.xml +11 -6
- package/templates/skills/vv-spec/SKILL.md +5 -3
- package/templates/skills/vv-spec/references/design-context-template.xml +2 -2
- package/templates/skills/vv-spec/references/spec-template.xml +17 -9
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,20 @@
|
|
|
1
|
+
## <small>1.3.6-rc.8 (2026-08-29)</small>
|
|
2
|
+
|
|
3
|
+
### Summary
|
|
4
|
+
|
|
5
|
+
This release fixes a reliability issue in the spec-guard plugin and corrects the documented GRACE CLI workflow. Read-path validation previously linted the tool's rendered output, which hosts may decorate with envelope tags and line-number prefixes, causing false well-formedness errors on valid spec files; read verdicts are now derived from the actual artifact file on disk, so validation results are accurate and independent of host rendering. In addition, the agent documentation now directs users to invoke the installed stable `grace` binary directly rather than the stale `rc` dist-tag, ensuring linting and status checks run against the correct validator version.
|
|
6
|
+
|
|
7
|
+
* docs(agents): invoke the installed grace binary instead of the stale rc tag ([8e59a00](https://github.com/osovv/vv-opencode/commit/8e59a00))
|
|
8
|
+
* fix(spec-guard): derive read verdicts from the artifact file, not the tool rendering ([ea8bd52](https://github.com/osovv/vv-opencode/commit/ea8bd52))
|
|
9
|
+
|
|
10
|
+
## <small>1.3.6-rc.7 (2026-08-29)</small>
|
|
11
|
+
|
|
12
|
+
### Summary
|
|
13
|
+
|
|
14
|
+
This release introduces deterministic, host-side verification for spec-package artifacts with a new COMPONENT identity format: spec, plan, and design-context components now share element-name identities across documents, fields are unified to snake_case, and the plan-subset-of-spec traceability rule is enforced mechanically rather than left to convention. A new strict lint engine checks well-formedness, template contracts, identity uniqueness, references, and lifecycle-aware severity, with results cached content-addressed under the XDG cache home. Users get a new `vvoc lint` command that targets files, packages, or whole specs trees with stable exit codes plus strict, JSON, no-cache, and archive flags (archived packages are skipped by default), and a new SpecGuardPlugin that appends lint verdicts to reads of active artifacts and validates writes through the same cache, defaulting to warn mode while enforce only refuses ERROR-severity writes so in-progress draft composition is never blocked and internal failures degrade fail-open. Schema v3, plugin toggles, exports, templates, skills, and README stay synchronized with the new format and command.
|
|
15
|
+
|
|
16
|
+
* feat(spec-lint): add COMPONENT identity format, vvoc lint, and spec-guard ([a28cde6](https://github.com/osovv/vv-opencode/commit/a28cde6))
|
|
17
|
+
|
|
1
18
|
## <small>1.3.6-rc.6 (2026-08-27)</small>
|
|
2
19
|
|
|
3
20
|
### Summary
|
package/README.md
CHANGED
|
@@ -146,12 +146,13 @@ All artifacts for one feature live together:
|
|
|
146
146
|
|
|
147
147
|
Package ids are date-prefixed (`YYYY-MM-DD-<slug>`, for example `2026-06-24-cache-store`) so active packages sort by creation date; the prefix is date-only, never a full timestamp. Spec and plan lifecycle runs through a top-level status: `draft` while being written, `approved` after explicit user approval, `applied` after successful execution. `vv-execute` archives applied packages by moving the whole directory to `.vvoc/specs/archive/YYYY-MM-DD-<slug>-<timestamp>/`.
|
|
148
148
|
|
|
149
|
-
Specs and plans are XML, so requirements, tasks, acceptance criteria, and dependencies stay grep-able.
|
|
149
|
+
Specs and plans are XML, so requirements, tasks, acceptance criteria, and dependencies stay grep-able. Identity lives in unique element names — tasks and waves as `<TASK-T-001>…</TASK-T-001>` and `<WAVE-1>…</WAVE-1>`, spec and plan components as `<COMPONENT-CACHE-STORE>…</COMPONENT-CACHE-STORE>` — so grep/sed extraction stays exact without a separate query language. Field names use snake_case; component references are bare slugs; plan architecture components always reuse the exact identities declared in spec.xml, so a plan component without a spec component is a lint error, not a convention breach:
|
|
150
150
|
|
|
151
151
|
```bash
|
|
152
152
|
grep '<TASK-T-' .vvoc/specs/*/plan.xml # task ids
|
|
153
153
|
grep '<criterion>' .vvoc/specs/*/plan.xml # acceptance criteria
|
|
154
154
|
grep '<task_id>' .vvoc/specs/*/plan.xml # dependency graph
|
|
155
|
+
grep '<COMPONENT-' .vvoc/specs/*/*.xml # component map across spec and plan
|
|
155
156
|
```
|
|
156
157
|
|
|
157
158
|
`vv-controller` explicitly routes `vv-spec`, `vv-plan`, and `vv-review`; `vv-execute`, `vv-reflect`, and `vv-handoff` are available as managed skills for plan execution, durable repository memory, and end-of-session handoff notes.
|
|
@@ -160,7 +161,7 @@ grep '<task_id>' .vvoc/specs/*/plan.xml # dependency graph
|
|
|
160
161
|
|
|
161
162
|
## What's inside
|
|
162
163
|
|
|
163
|
-
### The
|
|
164
|
+
### The twelve plugins
|
|
164
165
|
|
|
165
166
|
| Plugin | What it does |
|
|
166
167
|
|---|---|
|
|
@@ -174,6 +175,7 @@ grep '<task_id>' .vvoc/specs/*/plan.xml # dependency graph
|
|
|
174
175
|
| **ToolHistoryCompactionPlugin** | Shrinks the context replayed to the model by compacting old tool outputs non-destructively, without touching on-disk history. |
|
|
175
176
|
| **AnalyticsPlugin** | Local-only token and cache telemetry per model step, a live `cache NN%` indicator in the TUI, and `vvoc analytics cache-hit-rate` for retrospective comparison. |
|
|
176
177
|
| **PeakHoursPlugin** | Warns or blocks models whose provider is in peak-priced hours right now, suggests connected off-peak providers, and shows a persistent orange banner in the TUI. |
|
|
178
|
+
| **SpecGuardPlugin** | Deterministic host-side verification of spec-package artifacts: annotates reads with lint verdicts and validates writes; in enforce mode refuses writes that would break the format. |
|
|
177
179
|
| **ContextTuiPlugin** | The `/context` inspector: an honest, scrollable TUI dialog showing context-window usage by category, tool, and MCP server. |
|
|
178
180
|
|
|
179
181
|
### Managed agents
|
|
@@ -541,6 +543,34 @@ Config lives in `vvoc.json` under `plugins["peak-hours"]` and is conservatively
|
|
|
541
543
|
|
|
542
544
|
Windows use `HH:MM` in an explicit timezone (default UTC), may cross midnight (`"start": "22:00", "end": "02:00"`), and accept an optional `days` restriction (0=Sunday … 6=Saturday, default all days). A provider entry may override the global mode with `"mode": "hard"`. Set the top-level `"mode": "hard"` to enforce blocking everywhere, or `"enabled": false` to disable the plugin entirely. Changes require an OpenCode restart, like other runtime plugin settings.
|
|
543
545
|
|
|
546
|
+
### Spec lint and spec-guard
|
|
547
|
+
|
|
548
|
+
The spec-package format is verified by deterministic host-side tooling, not by model discipline: models keep grep/sed as their query layer, and `vvoc lint` plus `SpecGuardPlugin` enforce the invariants in code.
|
|
549
|
+
|
|
550
|
+
```bash
|
|
551
|
+
vvoc lint # lint .vvoc/specs (active packages only)
|
|
552
|
+
vvoc lint .vvoc/specs/2026-08-24-cache/ # one package directory
|
|
553
|
+
vvoc lint .vvoc/specs/2026-08-24-cache/plan.xml # one file (its sibling spec joins for cross-file rules)
|
|
554
|
+
vvoc lint --archive # include archived packages for migration audits
|
|
555
|
+
vvoc lint --strict # exit 1 on warnings, not only errors
|
|
556
|
+
vvoc lint --format json --no-cache # one JSON verdict object; bypass the cache
|
|
557
|
+
```
|
|
558
|
+
|
|
559
|
+
The engine checks well-formedness, the attribute ban, the template contract per artifact type, `COMPONENT-UPPER-SLUG` / `TASK-T-NNN` / `WAVE-N` identity patterns and uniqueness, reference integrity (component slugs, task ids), the **plan-components-subset-of-spec-components** rule, lifecycle vocabulary, and package layout. Severity is lifecycle-aware: a `draft` document may have empty sections mid-interview and is never an error; `approved`/`applied` documents must be complete. Exit codes are stable for scripts: `0` without errors, `1` with errors, `--strict` escalates warnings. Results are cached content-addressed under `$XDG_CACHE_HOME/vvoc/lint/` — a verdict is recomputed whenever any input byte or the lint rule version changes.
|
|
560
|
+
|
|
561
|
+
`SpecGuardPlugin` brings the same verdicts into the session:
|
|
562
|
+
|
|
563
|
+
- **reads**: reading an active `spec.xml` / `plan.xml` / `design-context.xml` appends a bounded `[spec-guard]` verdict to the tool result, so agents see drift before trusting the file; archived files are never annotated;
|
|
564
|
+
- **writes**: `warn` (default) appends the verdict after a write; `enforce` additionally refuses writes whose result would contain ERROR-severity findings — incremental draft editing is never blocked, because draft incompleteness is never an error.
|
|
565
|
+
|
|
566
|
+
```json
|
|
567
|
+
"plugins": {
|
|
568
|
+
"spec-guard": { "enabled": true, "mode": "warn" }
|
|
569
|
+
}
|
|
570
|
+
```
|
|
571
|
+
|
|
572
|
+
Conservatively materialized by `vvoc sync`/`init`; `enforce` blocks only ERROR states; internal failures degrade to a warning log and never break a tool call. Changes require an OpenCode restart, like other runtime plugin settings.
|
|
573
|
+
|
|
544
574
|
### Web tools
|
|
545
575
|
|
|
546
576
|
`WebToolsPlugin` exposes exactly two canonical model-facing tools:
|
package/dist/cli.js
CHANGED
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
// VERSION: 0.2.10
|
|
4
4
|
// START_MODULE_CONTRACT
|
|
5
5
|
// PURPOSE: Assemble and run the vvoc CLI entrypoint.
|
|
6
|
-
// SCOPE: Package version lookup, top-level command registration, and main command execution.
|
|
7
|
-
// DEPENDS: [citty, src/commands/analytics.ts, src/commands/completion.ts, src/commands/config.ts, src/commands/doctor.ts, src/commands/guardian.ts, src/commands/init.ts, src/commands/install.ts, src/commands/launch.ts, src/commands/orchestration.ts, src/commands/patch-provider.ts, src/commands/preset.ts, src/commands/plugin.ts, src/commands/role.ts, src/commands/status.ts, src/commands/sync.ts, src/commands/upgrade.ts, src/commands/version.ts, src/lib/package.ts]
|
|
6
|
+
// SCOPE: Package version lookup, top-level command registration including the lint command, and main command execution.
|
|
7
|
+
// DEPENDS: [citty, src/commands/analytics.ts, src/commands/completion.ts, src/commands/config.ts, src/commands/doctor.ts, src/commands/guardian.ts, src/commands/init.ts, src/commands/install.ts, src/commands/launch.ts, src/commands/orchestration.ts, src/commands/lint.ts, src/commands/patch-provider.ts, src/commands/preset.ts, src/commands/plugin.ts, src/commands/role.ts, src/commands/status.ts, src/commands/sync.ts, src/commands/upgrade.ts, src/commands/version.ts, src/lib/package.ts]
|
|
8
8
|
// LINKS: [M-CLI-COMMANDS]
|
|
9
9
|
// ROLE: SCRIPT
|
|
10
10
|
// MAP_MODE: LOCALS
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
// END_MODULE_MAP
|
|
17
17
|
//
|
|
18
18
|
// START_CHANGE_SUMMARY
|
|
19
|
-
// LAST_CHANGE: [
|
|
19
|
+
// LAST_CHANGE: [C-SPEC-IDENTITY-LINT - Registered the lint command in the CLI tree.]
|
|
20
20
|
// END_CHANGE_SUMMARY
|
|
21
21
|
import { defineCommand, runMain } from "citty";
|
|
22
22
|
import analytics from "./commands/analytics.js";
|
|
@@ -27,6 +27,7 @@ import guardian from "./commands/guardian.js";
|
|
|
27
27
|
import init from "./commands/init.js";
|
|
28
28
|
import install from "./commands/install.js";
|
|
29
29
|
import launch from "./commands/launch.js";
|
|
30
|
+
import lint from "./commands/lint.js";
|
|
30
31
|
import orchestration from "./commands/orchestration.js";
|
|
31
32
|
import patchProvider from "./commands/patch-provider.js";
|
|
32
33
|
import preset from "./commands/preset.js";
|
|
@@ -54,6 +55,7 @@ const main = defineCommand({
|
|
|
54
55
|
init,
|
|
55
56
|
install,
|
|
56
57
|
launch,
|
|
58
|
+
lint,
|
|
57
59
|
orchestration,
|
|
58
60
|
"patch-provider": patchProvider,
|
|
59
61
|
preset,
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA,mBAAmB;AACnB,kBAAkB;AAClB,wBAAwB;AACxB,uDAAuD;AACvD
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA,mBAAmB;AACnB,kBAAkB;AAClB,wBAAwB;AACxB,uDAAuD;AACvD,0HAA0H;AAC1H,4eAA4e;AAC5e,4BAA4B;AAC5B,iBAAiB;AACjB,qBAAqB;AACrB,sBAAsB;AACtB,EAAE;AACF,mBAAmB;AACnB,oEAAoE;AACpE,wCAAwC;AACxC,iBAAiB;AACjB,EAAE;AACF,uBAAuB;AACvB,uFAAuF;AACvF,qBAAqB;AAErB,OAAO,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAC/C,OAAO,SAAS,MAAM,yBAAyB,CAAC;AAChD,OAAO,UAAU,MAAM,0BAA0B,CAAC;AAClD,OAAO,MAAM,MAAM,sBAAsB,CAAC;AAC1C,OAAO,MAAM,MAAM,sBAAsB,CAAC;AAC1C,OAAO,QAAQ,MAAM,wBAAwB,CAAC;AAC9C,OAAO,IAAI,MAAM,oBAAoB,CAAC;AACtC,OAAO,OAAO,MAAM,uBAAuB,CAAC;AAC5C,OAAO,MAAM,MAAM,sBAAsB,CAAC;AAC1C,OAAO,IAAI,MAAM,oBAAoB,CAAC;AACtC,OAAO,aAAa,MAAM,6BAA6B,CAAC;AACxD,OAAO,aAAa,MAAM,8BAA8B,CAAC;AACzD,OAAO,MAAM,MAAM,sBAAsB,CAAC;AAC1C,OAAO,MAAM,MAAM,sBAAsB,CAAC;AAC1C,OAAO,IAAI,MAAM,oBAAoB,CAAC;AACtC,OAAO,MAAM,MAAM,sBAAsB,CAAC;AAC1C,OAAO,IAAI,MAAM,oBAAoB,CAAC;AACtC,OAAO,OAAO,MAAM,uBAAuB,CAAC;AAC5C,OAAO,OAAO,MAAM,uBAAuB,CAAC;AAC5C,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAErD,iCAAiC;AACjC,MAAM,cAAc,GAAG,MAAM,iBAAiB,EAAE,CAAC;AAEjD,MAAM,IAAI,GAAG,aAAa,CAAC;IACzB,IAAI,EAAE;QACJ,IAAI,EAAE,MAAM;QACZ,OAAO,EAAE,cAAc;QACvB,WAAW,EACT,+HAA+H;KAClI;IACD,WAAW,EAAE;QACX,SAAS;QACT,UAAU;QACV,MAAM;QACN,MAAM;QACN,QAAQ;QACR,IAAI;QACJ,OAAO;QACP,MAAM;QACN,IAAI;QACJ,aAAa;QACb,gBAAgB,EAAE,aAAa;QAC/B,MAAM;QACN,MAAM;QACN,IAAI;QACJ,MAAM;QACN,IAAI;QACJ,OAAO;QACP,OAAO;KACR;CACF,CAAC,CAAC;AACH,+BAA+B;AAE/B,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { type SpecLintVerdict } from "../lib/spec-lint.js";
|
|
2
|
+
export declare const ARTIFACT_FILE_NAMES: readonly ["spec.xml", "plan.xml", "design-context.xml"];
|
|
3
|
+
export interface LintCommandOptions {
|
|
4
|
+
/** File, package directory, or specs tree to lint. Defaults to .vvoc/specs. */
|
|
5
|
+
target: string;
|
|
6
|
+
/** Include archived packages instead of skipping them. */
|
|
7
|
+
includeArchive: boolean;
|
|
8
|
+
/** Escalate warnings to exit failure. */
|
|
9
|
+
strict: boolean;
|
|
10
|
+
/** Bypass the lint cache entirely. */
|
|
11
|
+
noCache: boolean;
|
|
12
|
+
}
|
|
13
|
+
export interface LintArtifactResult {
|
|
14
|
+
verdict: SpecLintVerdict;
|
|
15
|
+
cached: boolean;
|
|
16
|
+
}
|
|
17
|
+
export interface LintRunResult {
|
|
18
|
+
lintVersion: number;
|
|
19
|
+
target: string;
|
|
20
|
+
skippedArchived: number;
|
|
21
|
+
packages: Array<{
|
|
22
|
+
dir: string;
|
|
23
|
+
artifacts: LintArtifactResult[];
|
|
24
|
+
}>;
|
|
25
|
+
}
|
|
26
|
+
export declare const DEFAULT_LINT_TARGET = ".vvoc/specs";
|
|
27
|
+
/**
|
|
28
|
+
* Resolve a lint target into package groups. A file target becomes its own
|
|
29
|
+
* group (plus the sibling spec as a cross-file input for plan targets) with
|
|
30
|
+
* the requested file marked as the reporting primary; a directory target
|
|
31
|
+
* walks recursively and groups artifacts by containing directory. Archived
|
|
32
|
+
* files are counted and skipped unless included explicitly.
|
|
33
|
+
*/
|
|
34
|
+
export declare function collectLintTargets(target: string, includeArchive: boolean): Promise<{
|
|
35
|
+
groups: Array<{
|
|
36
|
+
dir: string;
|
|
37
|
+
files: string[];
|
|
38
|
+
primary?: string;
|
|
39
|
+
}>;
|
|
40
|
+
skippedArchived: number;
|
|
41
|
+
}>;
|
|
42
|
+
/** Execute one lint run over resolved targets through the content-addressed cache. */
|
|
43
|
+
export declare function runLint(options: LintCommandOptions, cacheRoot?: string): Promise<LintRunResult>;
|
|
44
|
+
export declare function renderLintReport(result: LintRunResult, strict: boolean): string;
|
|
45
|
+
export declare function computeLintExitCode(result: LintRunResult, strict: boolean): 0 | 1;
|
|
46
|
+
declare const _default: import("citty").CommandDef<{
|
|
47
|
+
readonly path: {
|
|
48
|
+
readonly type: "positional";
|
|
49
|
+
readonly description: "File, package directory, or specs tree to lint (default: .vvoc/specs)";
|
|
50
|
+
readonly fallback: ".vvoc/specs";
|
|
51
|
+
};
|
|
52
|
+
readonly strict: {
|
|
53
|
+
readonly type: "boolean";
|
|
54
|
+
readonly default: false;
|
|
55
|
+
readonly description: "Fail on warnings, not only errors.";
|
|
56
|
+
};
|
|
57
|
+
readonly format: {
|
|
58
|
+
readonly type: "enum";
|
|
59
|
+
readonly options: ["text", "json"];
|
|
60
|
+
readonly default: "text";
|
|
61
|
+
readonly description: "Output format.";
|
|
62
|
+
};
|
|
63
|
+
readonly "no-cache": {
|
|
64
|
+
readonly type: "boolean";
|
|
65
|
+
readonly default: false;
|
|
66
|
+
readonly description: "Bypass the content-addressed lint cache.";
|
|
67
|
+
};
|
|
68
|
+
readonly archive: {
|
|
69
|
+
readonly type: "boolean";
|
|
70
|
+
readonly default: false;
|
|
71
|
+
readonly description: "Include archived packages instead of skipping them.";
|
|
72
|
+
};
|
|
73
|
+
}>;
|
|
74
|
+
export default _default;
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
// FILE: src/commands/lint.ts
|
|
2
|
+
// VERSION: 1.0.0
|
|
3
|
+
// START_MODULE_CONTRACT
|
|
4
|
+
// PURPOSE: Lint .vvoc spec-package XML artifacts (spec.xml, plan.xml, design-context.xml) with lifecycle-aware severity and stable exit codes.
|
|
5
|
+
// SCOPE: Target resolution for a file, package directory, or specs tree; package grouping with cross-file sibling spec inputs; archive skipping with a visible count unless --archive; cache-backed lint runs; text and JSON output; exit code 0 without errors, 1 with errors, --strict escalating warnings.
|
|
6
|
+
// DEPENDS: [citty, node:fs/promises, node:path, src/lib/spec-lint.ts, src/lib/spec-lint-cache.ts]
|
|
7
|
+
// LINKS: [M-CLI-COMMANDS, M-SPEC-LINT]
|
|
8
|
+
// ROLE: RUNTIME
|
|
9
|
+
// MAP_MODE: EXPORTS
|
|
10
|
+
// END_MODULE_CONTRACT
|
|
11
|
+
//
|
|
12
|
+
// START_MODULE_MAP
|
|
13
|
+
// LintCommandOptions - Core lint-run options shared by the CLI and tests.
|
|
14
|
+
// LintArtifactResult - One artifact's verdict plus its cache-hit flag.
|
|
15
|
+
// LintRunResult - Structured result of one lint run over resolved targets.
|
|
16
|
+
// ARTIFACT_FILE_NAMES - Recognized spec-package artifact file names.
|
|
17
|
+
// DEFAULT_LINT_TARGET - Default lint target path (.vvoc/specs).
|
|
18
|
+
// collectLintTargets - Resolve a path into package groups plus an archive skip count.
|
|
19
|
+
// runLint - Execute the lint run over resolved targets through the cache.
|
|
20
|
+
// renderLintReport - Render the text report for a lint run result.
|
|
21
|
+
// computeLintExitCode - Map a run result to the stable exit-code contract.
|
|
22
|
+
// default - vvoc lint command definition.
|
|
23
|
+
// END_MODULE_MAP
|
|
24
|
+
//
|
|
25
|
+
// START_CHANGE_SUMMARY
|
|
26
|
+
// LAST_CHANGE: [C-SPEC-IDENTITY-LINT - Initial command: file/package/tree targets, lifecycle-aware severity, archive skip, cache integration, strict/json flags.]
|
|
27
|
+
// END_CHANGE_SUMMARY
|
|
28
|
+
import { defineCommand } from "citty";
|
|
29
|
+
import { readdir, readFile, stat } from "node:fs/promises";
|
|
30
|
+
import { dirname, join, relative, resolve } from "node:path";
|
|
31
|
+
import { isSpecArchivePath, LINT_VERSION, } from "../lib/spec-lint.js";
|
|
32
|
+
import { createSpecLintCache } from "../lib/spec-lint-cache.js";
|
|
33
|
+
// START_BLOCK_TYPES
|
|
34
|
+
export const ARTIFACT_FILE_NAMES = ["spec.xml", "plan.xml", "design-context.xml"];
|
|
35
|
+
export const DEFAULT_LINT_TARGET = ".vvoc/specs";
|
|
36
|
+
// END_BLOCK_TYPES
|
|
37
|
+
// START_BLOCK_TARGET_RESOLUTION
|
|
38
|
+
async function walkXmlArtifacts(root, base, found) {
|
|
39
|
+
let entries;
|
|
40
|
+
try {
|
|
41
|
+
entries = await readdir(root, { withFileTypes: true });
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
for (const entry of entries) {
|
|
47
|
+
const full = join(root, entry.name);
|
|
48
|
+
if (entry.isDirectory()) {
|
|
49
|
+
await walkXmlArtifacts(full, base, found);
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
if (!entry.isFile())
|
|
53
|
+
continue;
|
|
54
|
+
if (!ARTIFACT_FILE_NAMES.includes(entry.name))
|
|
55
|
+
continue;
|
|
56
|
+
const relativePath = relative(base, full).replace(/\\/g, "/");
|
|
57
|
+
found.push({ path: full, archived: isSpecArchivePath(relativePath) });
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Resolve a lint target into package groups. A file target becomes its own
|
|
62
|
+
* group (plus the sibling spec as a cross-file input for plan targets) with
|
|
63
|
+
* the requested file marked as the reporting primary; a directory target
|
|
64
|
+
* walks recursively and groups artifacts by containing directory. Archived
|
|
65
|
+
* files are counted and skipped unless included explicitly.
|
|
66
|
+
*/
|
|
67
|
+
export async function collectLintTargets(target, includeArchive) {
|
|
68
|
+
const absolute = resolve(target);
|
|
69
|
+
let targetStat;
|
|
70
|
+
try {
|
|
71
|
+
targetStat = await stat(absolute);
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
throw new Error(`lint target not found: ${target}`);
|
|
75
|
+
}
|
|
76
|
+
if (targetStat.isFile()) {
|
|
77
|
+
const fileName = absolute.split(/[/\\]/).pop() ?? "";
|
|
78
|
+
if (!ARTIFACT_FILE_NAMES.includes(fileName)) {
|
|
79
|
+
throw new Error(`not a spec-package artifact: ${fileName} (expected ${ARTIFACT_FILE_NAMES.join(", ")})`);
|
|
80
|
+
}
|
|
81
|
+
const files = [absolute];
|
|
82
|
+
if (fileName === "plan.xml") {
|
|
83
|
+
const sibling = join(dirname(absolute), "spec.xml");
|
|
84
|
+
try {
|
|
85
|
+
await stat(sibling);
|
|
86
|
+
files.push(sibling);
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
// Missing sibling degrades to the engine's spec-missing warning.
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return {
|
|
93
|
+
groups: [{ dir: dirname(absolute), files, primary: absolute.replace(/\\/g, "/") }],
|
|
94
|
+
skippedArchived: 0,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
const found = [];
|
|
98
|
+
await walkXmlArtifacts(absolute, absolute, found);
|
|
99
|
+
const groups = new Map();
|
|
100
|
+
let skippedArchived = 0;
|
|
101
|
+
for (const item of found) {
|
|
102
|
+
if (item.archived && !includeArchive) {
|
|
103
|
+
skippedArchived++;
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
const dir = dirname(item.path);
|
|
107
|
+
const bucket = groups.get(dir) ?? [];
|
|
108
|
+
bucket.push(item.path);
|
|
109
|
+
groups.set(dir, bucket);
|
|
110
|
+
}
|
|
111
|
+
return {
|
|
112
|
+
groups: [...groups.entries()]
|
|
113
|
+
.sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))
|
|
114
|
+
.map(([dir, files]) => ({ dir, files })),
|
|
115
|
+
skippedArchived,
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
// END_BLOCK_TARGET_RESOLUTION
|
|
119
|
+
// START_BLOCK_RUN
|
|
120
|
+
async function readArtifactInputs(files) {
|
|
121
|
+
const inputs = [];
|
|
122
|
+
for (const file of files.sort()) {
|
|
123
|
+
try {
|
|
124
|
+
const content = await readFile(file, "utf8");
|
|
125
|
+
inputs.push({ file: file.replace(/\\/g, "/"), content });
|
|
126
|
+
}
|
|
127
|
+
catch {
|
|
128
|
+
// Unreadable files degrade to an explicit finding through the engine's unknown path.
|
|
129
|
+
inputs.push({ file: file.replace(/\\/g, "/"), content: "" });
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return inputs;
|
|
133
|
+
}
|
|
134
|
+
/** Execute one lint run over resolved targets through the content-addressed cache. */
|
|
135
|
+
export async function runLint(options, cacheRoot) {
|
|
136
|
+
const cache = await createSpecLintCache({ cacheRoot, bypass: options.noCache });
|
|
137
|
+
const { groups, skippedArchived } = await collectLintTargets(options.target, options.includeArchive);
|
|
138
|
+
const packages = [];
|
|
139
|
+
for (const group of groups) {
|
|
140
|
+
const inputs = await readArtifactInputs(group.files);
|
|
141
|
+
const result = await cache.lint(inputs);
|
|
142
|
+
const byFile = new Map(result.verdicts.map((v) => [v.file, v]));
|
|
143
|
+
const reportFiles = group.primary
|
|
144
|
+
? group.files.filter((file) => file.replace(/\\/g, "/") === group.primary)
|
|
145
|
+
: group.files;
|
|
146
|
+
const artifacts = reportFiles
|
|
147
|
+
.map((file) => file.replace(/\\/g, "/"))
|
|
148
|
+
.filter((file) => byFile.has(file))
|
|
149
|
+
.map((file) => ({ verdict: byFile.get(file), cached: result.hit }));
|
|
150
|
+
packages.push({ dir: group.dir.replace(/\\/g, "/"), artifacts });
|
|
151
|
+
}
|
|
152
|
+
return { lintVersion: LINT_VERSION, target: options.target, skippedArchived, packages };
|
|
153
|
+
}
|
|
154
|
+
// END_BLOCK_RUN
|
|
155
|
+
// START_BLOCK_REPORT
|
|
156
|
+
export function renderLintReport(result, strict) {
|
|
157
|
+
const lines = [];
|
|
158
|
+
let artifacts = 0;
|
|
159
|
+
let errors = 0;
|
|
160
|
+
let warnings = 0;
|
|
161
|
+
for (const pkg of result.packages) {
|
|
162
|
+
const pkgErrors = pkg.artifacts.reduce((sum, a) => sum + a.verdict.findings.filter((f) => f.severity === "error").length, 0);
|
|
163
|
+
const pkgWarnings = pkg.artifacts.reduce((sum, a) => sum + a.verdict.findings.filter((f) => f.severity === "warning").length, 0);
|
|
164
|
+
artifacts += pkg.artifacts.length;
|
|
165
|
+
errors += pkgErrors;
|
|
166
|
+
warnings += pkgWarnings;
|
|
167
|
+
lines.push(`${pkg.dir}: ${pkg.artifacts.length} artifact(s), ${pkgErrors} error(s), ${pkgWarnings} warning(s)`);
|
|
168
|
+
for (const artifact of pkg.artifacts) {
|
|
169
|
+
const name = artifact.verdict.file.split("/").pop() ?? artifact.verdict.file;
|
|
170
|
+
if (artifact.verdict.findings.length === 0) {
|
|
171
|
+
lines.push(` ${name}: OK${artifact.cached ? " (cached)" : ""}`);
|
|
172
|
+
continue;
|
|
173
|
+
}
|
|
174
|
+
lines.push(` ${name}:${artifact.cached ? " (cached)" : ""}`);
|
|
175
|
+
for (const finding of artifact.verdict.findings) {
|
|
176
|
+
lines.push(` ${artifact.verdict.file}:${finding.line} ${finding.severity} [${finding.rule}]: ${finding.message}`);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
if (result.skippedArchived > 0) {
|
|
181
|
+
lines.push(`Skipped ${result.skippedArchived} archived artifact(s); use --archive to include them.`);
|
|
182
|
+
}
|
|
183
|
+
const fail = errors > 0 || (strict && warnings > 0);
|
|
184
|
+
lines.push(`${artifacts} artifact(s) checked: ${errors} error(s), ${warnings} warning(s) — ${fail ? "FAIL" : "OK"}${strict ? " (strict)" : ""}`);
|
|
185
|
+
return lines.join("\n");
|
|
186
|
+
}
|
|
187
|
+
export function computeLintExitCode(result, strict) {
|
|
188
|
+
const hasErrors = result.packages.some((pkg) => pkg.artifacts.some((a) => a.verdict.findings.some((f) => f.severity === "error")));
|
|
189
|
+
if (hasErrors)
|
|
190
|
+
return 1;
|
|
191
|
+
if (strict) {
|
|
192
|
+
const hasWarnings = result.packages.some((pkg) => pkg.artifacts.some((a) => a.verdict.findings.some((f) => f.severity === "warning")));
|
|
193
|
+
if (hasWarnings)
|
|
194
|
+
return 1;
|
|
195
|
+
}
|
|
196
|
+
return 0;
|
|
197
|
+
}
|
|
198
|
+
// END_BLOCK_REPORT
|
|
199
|
+
// defineCommand wrapper: the run body is the RUN_LINT_COMMAND block below
|
|
200
|
+
export default defineCommand({
|
|
201
|
+
meta: {
|
|
202
|
+
name: "lint",
|
|
203
|
+
description: "Lint .vvoc spec-package artifacts (spec.xml, plan.xml, design-context.xml).",
|
|
204
|
+
},
|
|
205
|
+
args: {
|
|
206
|
+
path: {
|
|
207
|
+
type: "positional",
|
|
208
|
+
description: `File, package directory, or specs tree to lint (default: ${DEFAULT_LINT_TARGET})`,
|
|
209
|
+
fallback: DEFAULT_LINT_TARGET,
|
|
210
|
+
},
|
|
211
|
+
strict: {
|
|
212
|
+
type: "boolean",
|
|
213
|
+
default: false,
|
|
214
|
+
description: "Fail on warnings, not only errors.",
|
|
215
|
+
},
|
|
216
|
+
format: {
|
|
217
|
+
type: "enum",
|
|
218
|
+
options: ["text", "json"],
|
|
219
|
+
default: "text",
|
|
220
|
+
description: "Output format.",
|
|
221
|
+
},
|
|
222
|
+
"no-cache": {
|
|
223
|
+
type: "boolean",
|
|
224
|
+
default: false,
|
|
225
|
+
description: "Bypass the content-addressed lint cache.",
|
|
226
|
+
},
|
|
227
|
+
archive: {
|
|
228
|
+
type: "boolean",
|
|
229
|
+
default: false,
|
|
230
|
+
description: "Include archived packages instead of skipping them.",
|
|
231
|
+
},
|
|
232
|
+
},
|
|
233
|
+
async run({ args }) {
|
|
234
|
+
// START_BLOCK_RUN_LINT_COMMAND
|
|
235
|
+
const options = {
|
|
236
|
+
target: typeof args.path === "string" && args.path ? args.path : DEFAULT_LINT_TARGET,
|
|
237
|
+
includeArchive: args.archive === true,
|
|
238
|
+
strict: args.strict === true,
|
|
239
|
+
noCache: args["no-cache"] === true,
|
|
240
|
+
};
|
|
241
|
+
const result = await runLint(options);
|
|
242
|
+
const strict = options.strict;
|
|
243
|
+
if (args.format === "json") {
|
|
244
|
+
console.log(JSON.stringify({
|
|
245
|
+
lintVersion: result.lintVersion,
|
|
246
|
+
target: result.target,
|
|
247
|
+
ok: computeLintExitCode(result, strict) === 0,
|
|
248
|
+
strict,
|
|
249
|
+
skippedArchived: result.skippedArchived,
|
|
250
|
+
packages: result.packages.map((pkg) => ({
|
|
251
|
+
dir: pkg.dir,
|
|
252
|
+
artifacts: pkg.artifacts.map((a) => ({
|
|
253
|
+
file: a.verdict.file,
|
|
254
|
+
kind: a.verdict.kind,
|
|
255
|
+
ok: a.verdict.ok,
|
|
256
|
+
cached: a.cached,
|
|
257
|
+
findings: a.verdict.findings,
|
|
258
|
+
})),
|
|
259
|
+
})),
|
|
260
|
+
}, null, 2));
|
|
261
|
+
}
|
|
262
|
+
else {
|
|
263
|
+
console.log(renderLintReport(result, strict));
|
|
264
|
+
}
|
|
265
|
+
process.exitCode = computeLintExitCode(result, strict);
|
|
266
|
+
// END_BLOCK_RUN_LINT_COMMAND
|
|
267
|
+
},
|
|
268
|
+
});
|
|
269
|
+
//# sourceMappingURL=lint.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lint.js","sourceRoot":"","sources":["../../src/commands/lint.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -8,3 +8,4 @@ export { WebToolsPlugin } from "./plugins/web-tools/index.js";
|
|
|
8
8
|
export { ToolHistoryCompactionPlugin } from "./plugins/tool-history-compaction/index.js";
|
|
9
9
|
export { AnalyticsPlugin } from "./plugins/analytics/index.js";
|
|
10
10
|
export { PeakHoursPlugin } from "./plugins/peak-hours/index.js";
|
|
11
|
+
export { SpecGuardPlugin } from "./plugins/spec-guard/index.js";
|
package/dist/index.js
CHANGED
|
@@ -2,19 +2,19 @@
|
|
|
2
2
|
// VERSION: 1.0.0
|
|
3
3
|
// START_MODULE_CONTRACT
|
|
4
4
|
// PURPOSE: Re-export the public vv-opencode plugin entrypoints from the package root.
|
|
5
|
-
// SCOPE: Package-root exports for GuardianPlugin, HashlineEditPlugin, ModelRolesPlugin, SystemContextInjectionPlugin, WorkflowPlugin, SecretsRedactionPlugin, WebToolsPlugin, ToolHistoryCompactionPlugin, AnalyticsPlugin, and
|
|
6
|
-
// DEPENDS: [src/plugins/guardian/index.ts, src/plugins/hashline-edit/index.ts, src/plugins/model-roles/index.ts, src/plugins/system-context-injection/index.ts, src/plugins/workflow/index.ts, src/plugins/secrets-redaction.ts, src/plugins/web-tools/index.ts, src/plugins/tool-history-compaction/index.ts, src/plugins/analytics/index.ts, src/plugins/peak-hours/index.ts]
|
|
7
|
-
// LINKS: [M-PLUGIN-GUARDIAN, M-PLUGIN-HASHLINE-EDIT, M-PLUGIN-MODEL-ROLES, M-PLUGIN-SYSTEM-CONTEXT-INJECTION, M-PLUGIN-WORKFLOW, M-PLUGIN-SECRETS-REDACTION, M-PLUGIN-WEB-TOOLS, M-PLUGIN-TOOL-HISTORY-COMPACTION, M-PLUGIN-ANALYTICS, M-PLUGIN-PEAK-HOURS]
|
|
5
|
+
// SCOPE: Package-root exports for GuardianPlugin, HashlineEditPlugin, ModelRolesPlugin, SystemContextInjectionPlugin, WorkflowPlugin, SecretsRedactionPlugin, WebToolsPlugin, ToolHistoryCompactionPlugin, AnalyticsPlugin, PeakHoursPlugin, and SpecGuardPlugin.
|
|
6
|
+
// DEPENDS: [src/plugins/guardian/index.ts, src/plugins/hashline-edit/index.ts, src/plugins/model-roles/index.ts, src/plugins/system-context-injection/index.ts, src/plugins/workflow/index.ts, src/plugins/secrets-redaction.ts, src/plugins/web-tools/index.ts, src/plugins/tool-history-compaction/index.ts, src/plugins/analytics/index.ts, src/plugins/peak-hours/index.ts, src/plugins/spec-guard/index.ts]
|
|
7
|
+
// LINKS: [M-PLUGIN-GUARDIAN, M-PLUGIN-HASHLINE-EDIT, M-PLUGIN-MODEL-ROLES, M-PLUGIN-SYSTEM-CONTEXT-INJECTION, M-PLUGIN-WORKFLOW, M-PLUGIN-SECRETS-REDACTION, M-PLUGIN-WEB-TOOLS, M-PLUGIN-TOOL-HISTORY-COMPACTION, M-PLUGIN-ANALYTICS, M-PLUGIN-PEAK-HOURS, M-PLUGIN-SPEC-GUARD]
|
|
8
8
|
// ROLE: BARREL
|
|
9
9
|
// MAP_MODE: SUMMARY
|
|
10
10
|
// END_MODULE_CONTRACT
|
|
11
11
|
//
|
|
12
12
|
// START_MODULE_MAP
|
|
13
|
-
// GuardianPlugin, HashlineEditPlugin, ModelRolesPlugin, SystemContextInjectionPlugin, WorkflowPlugin, SecretsRedactionPlugin, WebToolsPlugin, ToolHistoryCompactionPlugin, AnalyticsPlugin, PeakHoursPlugin - Public plugin exports available from @osovv/vv-opencode.
|
|
13
|
+
// GuardianPlugin, HashlineEditPlugin, ModelRolesPlugin, SystemContextInjectionPlugin, WorkflowPlugin, SecretsRedactionPlugin, WebToolsPlugin, ToolHistoryCompactionPlugin, AnalyticsPlugin, PeakHoursPlugin, SpecGuardPlugin - Public plugin exports available from @osovv/vv-opencode.
|
|
14
14
|
// END_MODULE_MAP
|
|
15
15
|
//
|
|
16
16
|
// START_CHANGE_SUMMARY
|
|
17
|
-
// LAST_CHANGE: [C-
|
|
17
|
+
// LAST_CHANGE: [C-SPEC-IDENTITY-LINT - Added SpecGuardPlugin to the package-root exports.]
|
|
18
18
|
// END_CHANGE_SUMMARY
|
|
19
19
|
export { GuardianPlugin } from "./plugins/guardian/index.js";
|
|
20
20
|
export { HashlineEditPlugin } from "./plugins/hashline-edit/index.js";
|
|
@@ -26,4 +26,5 @@ export { WebToolsPlugin } from "./plugins/web-tools/index.js";
|
|
|
26
26
|
export { ToolHistoryCompactionPlugin } from "./plugins/tool-history-compaction/index.js";
|
|
27
27
|
export { AnalyticsPlugin } from "./plugins/analytics/index.js";
|
|
28
28
|
export { PeakHoursPlugin } from "./plugins/peak-hours/index.js";
|
|
29
|
+
export { SpecGuardPlugin } from "./plugins/spec-guard/index.js";
|
|
29
30
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,qBAAqB;AACrB,iBAAiB;AACjB,wBAAwB;AACxB,wFAAwF;AACxF,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,qBAAqB;AACrB,iBAAiB;AACjB,wBAAwB;AACxB,wFAAwF;AACxF,oQAAoQ;AACpQ,mZAAmZ;AACnZ,mRAAmR;AACnR,iBAAiB;AACjB,sBAAsB;AACtB,sBAAsB;AACtB,EAAE;AACF,mBAAmB;AACnB,0RAA0R;AAC1R,iBAAiB;AACjB,EAAE;AACF,uBAAuB;AACvB,6FAA6F;AAC7F,qBAAqB;AAErB,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AACtE,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAClE,OAAO,EAAE,4BAA4B,EAAE,MAAM,6CAA6C,CAAC;AAC3F,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAC;AACxE,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAC9D,OAAO,EAAE,2BAA2B,EAAE,MAAM,4CAA4C,CAAC;AACzF,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC"}
|
package/dist/lib/opencode.js
CHANGED
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
// END_MODULE_MAP
|
|
66
66
|
//
|
|
67
67
|
// START_CHANGE_SUMMARY
|
|
68
|
-
// LAST_CHANGE: [C-
|
|
68
|
+
// LAST_CHANGE: [C-SPEC-IDENTITY-LINT - Materialized the conservative spec-guard plugin entry during install, init, and sync writes.]
|
|
69
69
|
// END_CHANGE_SUMMARY
|
|
70
70
|
import { applyEdits, format, modify, parse } from "jsonc-parser";
|
|
71
71
|
import { lstat, mkdir, readFile, readlink, symlink, unlink, writeFile } from "node:fs/promises";
|
|
@@ -77,7 +77,7 @@ import { resolveOrchestrationPolicy } from "./orchestration.js";
|
|
|
77
77
|
import { createDefaultVvocConfig, createGuardianConfig, parseVvocConfigText, parseVersionedVvocConfigText, renderVvocConfig, } from "./vvoc-config.js";
|
|
78
78
|
import { getPinnedPackageSpecifier, PACKAGE_NAME, PACKAGE_VERSION } from "./package.js";
|
|
79
79
|
import { resolveConfigWriteTargets, resolveOpenCodeConfigSource, resolveOpenCodeTuiConfigSource, resolveVvocConfigSource, } from "./config-layers.js";
|
|
80
|
-
import { materializeHashlineEditEntry, materializeToolHistoryCompactionEntry, materializePeakHoursEntry, } from "./plugin-toggle-config.js";
|
|
80
|
+
import { materializeHashlineEditEntry, materializeToolHistoryCompactionEntry, materializePeakHoursEntry, materializeSpecGuardEntry, } from "./plugin-toggle-config.js";
|
|
81
81
|
import { getConfigHome, getGlobalOpencodeSkillsDir, getGlobalVvocDir, getVvocAgentsDir, getVvocSkillsDir, } from "./vvoc-paths.js";
|
|
82
82
|
export const CLI_NAME = "vvoc";
|
|
83
83
|
export { PACKAGE_NAME };
|
|
@@ -616,6 +616,7 @@ export async function syncVvocConfig(paths) {
|
|
|
616
616
|
nextConfig.plugins["hashline-edit"] = materializeHashlineEditEntry(nextConfig.plugins["hashline-edit"]);
|
|
617
617
|
nextConfig.plugins["tool-history-compaction"] = materializeToolHistoryCompactionEntry(nextConfig.plugins["tool-history-compaction"]);
|
|
618
618
|
nextConfig.plugins["peak-hours"] = materializePeakHoursEntry(nextConfig.plugins["peak-hours"]);
|
|
619
|
+
nextConfig.plugins["spec-guard"] = materializeSpecGuardEntry(nextConfig.plugins["spec-guard"]);
|
|
619
620
|
return writeResolvedVvocConfig(paths.vvocConfigPath, currentText, nextConfig);
|
|
620
621
|
}
|
|
621
622
|
export async function writeGuardianConfig(paths, overrides, options = {}) {
|