vinta-ai-workflows 0.1.7
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 +830 -0
- package/LICENSE +21 -0
- package/README.md +547 -0
- package/package.json +27 -0
- package/schemas/README.md +84 -0
- package/schemas/mcp-preflight-cache.v1.schema.json +50 -0
- package/schemas/prs-context-comments.v1.schema.json +51 -0
- package/schemas/prs-context-frontmatter.v1.schema.json +77 -0
- package/schemas/sub-agent.v1.schema.json +105 -0
- package/schemas/vinta-ai-workflows-config.v1.schema.json +283 -0
- package/skills/vinta-analyze-codebase/SKILL.md +325 -0
- package/skills/vinta-bootstrap-ai-tools/SKILL.md +375 -0
- package/skills/vinta-bootstrap-ai-tools/resources/stacks/README.md +50 -0
- package/skills/vinta-bootstrap-ai-tools/resources/stacks/django/notes.md +52 -0
- package/skills/vinta-bootstrap-ai-tools/resources/stacks/medplum/notes.md +45 -0
- package/skills/vinta-bootstrap-ai-tools/resources/stacks/nextjs-app-router/notes.md +35 -0
- package/skills/vinta-bootstrap-ai-tools/resources/stacks/python-package/notes.md +31 -0
- package/skills/vinta-bootstrap-ai-tools/resources/stacks/typescript-monorepo/notes.md +32 -0
- package/skills/vinta-derive-skills/SKILL.md +200 -0
- package/skills/vinta-derive-skills/resources/amend-plan-template.md +355 -0
- package/skills/vinta-derive-skills/resources/foundation-skills/add-one-off-script/SKILL.md +292 -0
- package/skills/vinta-derive-skills/resources/foundation-skills/add-one-off-script/resources/one_off_script_base.py +602 -0
- package/skills/vinta-derive-skills/resources/foundation-skills/add-one-off-script/resources/one_off_script_base.ts +624 -0
- package/skills/vinta-derive-skills/resources/foundation-skills/create-qa-use-cases/SKILL.md +232 -0
- package/skills/vinta-derive-skills/resources/foundation-skills/create-spec/SKILL.md +235 -0
- package/skills/vinta-derive-skills/resources/foundation-skills/open-pr-from-context/SKILL.md +78 -0
- package/skills/vinta-derive-skills/resources/foundation-skills/open-pr-from-context/scripts/open-pr.sh +357 -0
- package/skills/vinta-derive-skills/resources/foundation-skills/plan-feature/SKILL.md +418 -0
- package/skills/vinta-derive-skills/resources/implement-plan-template.md +375 -0
- package/skills/vinta-derive-skills/resources/prs-context-template.md +91 -0
- package/skills/vinta-derive-skills/resources/systematic-debugging-mcp-tools.md +125 -0
- package/skills/vinta-derive-skills/resources/systematic-debugging-template.md +167 -0
- package/skills/vinta-derive-subagents/SKILL.md +192 -0
- package/skills/vinta-install-ai-tools-setup/SKILL.md +138 -0
- package/skills/vinta-install-ai-tools-setup/resources/setup-ai-tools.mjs +392 -0
- package/skills/vinta-migrate-plans-specs/SKILL.md +229 -0
- package/skills/vinta-sync-ai-tools/SKILL.md +184 -0
- package/skills/vinta-update-project-skills/SKILL.md +178 -0
- package/skills/vinta-write-agents-md/SKILL.md +192 -0
- package/vinta-ai-workflows.mjs +316 -0
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# Schemas
|
|
2
|
+
|
|
3
|
+
JSON Schema (Draft 2020-12) contracts for every YAML file the vinta-ai-workflows toolchain produces or consumes. Every YAML file carries a `schema_version` integer at its top level; that integer matches the suffix on the schema filename.
|
|
4
|
+
|
|
5
|
+
## Inventory
|
|
6
|
+
|
|
7
|
+
| Artifact | YAML location in target project | Schema file | Authored by | Read by |
|
|
8
|
+
|---|---|---|---|---|
|
|
9
|
+
| Project config | `.vinta-ai-workflows.yaml` (repo root) | [`vinta-ai-workflows-config.v1.schema.json`](vinta-ai-workflows-config.v1.schema.json) | `vinta-bootstrap-ai-tools` (initial) → `vinta-sync-ai-tools` (updates) | every builder skill, every template render, every meta-skill |
|
|
10
|
+
| Sub-agent definition | `ai-tools/agents/<name>.yaml` | [`sub-agent.v1.schema.json`](sub-agent.v1.schema.json) | `vinta-derive-subagents` | `setup-ai-tools.mjs` (emits per-vendor copies) |
|
|
11
|
+
| PR-context frontmatter | top-of-file YAML in `.vinta-ai-workflows/prs-context/{feature-kebab}/phase-{phase.id}.md` | [`prs-context-frontmatter.v1.schema.json`](prs-context-frontmatter.v1.schema.json) | `implement-plan` / `amend-plan` | `open-pr.sh` |
|
|
12
|
+
| PR-context inline comments | YAML inside the ` ```yaml ... ``` ` fence under `# Comments` of the same file | [`prs-context-comments.v1.schema.json`](prs-context-comments.v1.schema.json) | `implement-plan` / `amend-plan` | `open-pr.sh` |
|
|
13
|
+
| MCP preflight cache | `.vinta-ai-workflows/cache.yaml` (gitignored — per-developer-machine state) | [`mcp-preflight-cache.v1.schema.json`](mcp-preflight-cache.v1.schema.json) | rendered `systematic-debugging` SKILL.md (writes during Phase 0) | rendered `systematic-debugging` SKILL.md (reads at Phase 0 start) |
|
|
14
|
+
|
|
15
|
+
## Versioning rules
|
|
16
|
+
|
|
17
|
+
Each schema file carries its own major version. The major appears in the filename (`*.vN.schema.json`) and in the YAML payload's `schema_version` field.
|
|
18
|
+
|
|
19
|
+
- **Adding an optional field** → no version bump. Update the schema in place.
|
|
20
|
+
- **Adding a required field** → only allowed at vN+1 (breaking). Bump major, ship `vN+1.schema.json` alongside `vN.schema.json`. Both files stay in the repo so old projects can validate; `vinta-sync-ai-tools` migrates payloads forward.
|
|
21
|
+
- **Removing or renaming a field** → bump major. Same as above.
|
|
22
|
+
- **Tightening an enum** (removing a permitted value) → bump major. New enum lands in vN+1.
|
|
23
|
+
- **Loosening an enum / pattern** (allowing more values) → no bump.
|
|
24
|
+
- **Changing the meaning of a field without changing its shape** → bump major even when the shape is identical. The schema is a contract; semantics is part of it.
|
|
25
|
+
|
|
26
|
+
When you bump the major:
|
|
27
|
+
|
|
28
|
+
1. Copy `<artifact>.vN.schema.json` to `<artifact>.v(N+1).schema.json`.
|
|
29
|
+
2. Modify the new file. Set `schema_version.const` to `N+1`.
|
|
30
|
+
3. Add a migration step in `vinta-sync-ai-tools` covering the diff between vN and vN+1.
|
|
31
|
+
4. Document the breaking change in [CHANGELOG.md](../CHANGELOG.md).
|
|
32
|
+
|
|
33
|
+
## IDE wiring
|
|
34
|
+
|
|
35
|
+
Add the schema directive to the top of any YAML file you author by hand. Editors with the Red Hat YAML extension (VS Code, Cursor) auto-validate against the URL.
|
|
36
|
+
|
|
37
|
+
```yaml
|
|
38
|
+
# yaml-language-server: $schema=https://github.com/vintasoftware/vinta-ai-workflows/schemas/vinta-ai-workflows-config.v1.schema.json
|
|
39
|
+
schema_version: 1
|
|
40
|
+
vinta_ai_workflows_version: 0.1.2
|
|
41
|
+
# ...
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
For PR-context files (markdown with YAML frontmatter), the directive goes inside the frontmatter block:
|
|
45
|
+
|
|
46
|
+
```markdown
|
|
47
|
+
---
|
|
48
|
+
# yaml-language-server: $schema=https://github.com/vintasoftware/vinta-ai-workflows/schemas/prs-context-frontmatter.v1.schema.json
|
|
49
|
+
schema_version: 1
|
|
50
|
+
plan_id: checkout-flow
|
|
51
|
+
# ...
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
# Title
|
|
55
|
+
...
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Local-path schemas work too if the project has the `vinta-ai-workflows` clone vendored:
|
|
59
|
+
|
|
60
|
+
```yaml
|
|
61
|
+
# yaml-language-server: $schema=./node_modules/vinta-ai-workflows/schemas/vinta-ai-workflows-config.v1.schema.json
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Authoring tools (`vinta-bootstrap-ai-tools`, `vinta-derive-subagents`, `implement-plan`, `amend-plan`) embed the directive when they emit a fresh file.
|
|
65
|
+
|
|
66
|
+
## Validation in CI
|
|
67
|
+
|
|
68
|
+
Optional but recommended. Any of the standard tools work:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
# Check the project config (uses ajv-cli + js-yaml)
|
|
72
|
+
npx -y ajv-cli validate \
|
|
73
|
+
-s schemas/vinta-ai-workflows-config.v1.schema.json \
|
|
74
|
+
-d .vinta-ai-workflows.yaml
|
|
75
|
+
|
|
76
|
+
# Check every sub-agent
|
|
77
|
+
for f in ai-tools/agents/*.yaml; do
|
|
78
|
+
npx -y ajv-cli validate \
|
|
79
|
+
-s schemas/sub-agent.v1.schema.json \
|
|
80
|
+
-d "$f"
|
|
81
|
+
done
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
For PR-context frontmatter, extract the YAML block first (`yq` does this cleanly), then validate.
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://github.com/vintasoftware/vinta-ai-workflows/schemas/mcp-preflight-cache.v1.schema.json",
|
|
4
|
+
"title": "MCP preflight cache",
|
|
5
|
+
"description": "Per-server preflight state for the `systematic-debugging` foundation skill. Lives at `.vinta-ai-workflows/cache.yaml` in the target project (gitignored — never committed; entries reflect the current developer machine, not project-wide truth). Read + written by the rendered `systematic-debugging` SKILL.md and the `refresh-mcp-cache` CLI command. No TTL — entries stay valid until something fails. A failed MCP call mid-debug-session marks the offending server `dirty`, forcing the next debug run to re-preflight that server (and only that server).",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": ["schema_version", "mcp_preflight"],
|
|
8
|
+
"additionalProperties": false,
|
|
9
|
+
"properties": {
|
|
10
|
+
"schema_version": {
|
|
11
|
+
"description": "Schema major version. Bumped only on breaking changes.",
|
|
12
|
+
"type": "integer",
|
|
13
|
+
"const": 1
|
|
14
|
+
},
|
|
15
|
+
"mcp_preflight": {
|
|
16
|
+
"description": "Map of MCP server identifier (matching an entry in `skills.systematic-debugging.observability_mcp_servers` of `.vinta-ai-workflows.yaml`) to its last-known preflight state.",
|
|
17
|
+
"type": "object",
|
|
18
|
+
"additionalProperties": {
|
|
19
|
+
"type": "object",
|
|
20
|
+
"required": ["status", "verified_at"],
|
|
21
|
+
"additionalProperties": false,
|
|
22
|
+
"properties": {
|
|
23
|
+
"status": {
|
|
24
|
+
"description": "`ok` skips preflight on subsequent runs. Any other value forces a fresh preflight on the next debug run AND surfaces the entry to the user as needing attention.",
|
|
25
|
+
"type": "string",
|
|
26
|
+
"enum": ["ok", "dirty", "missing", "auth-error", "unreachable"]
|
|
27
|
+
},
|
|
28
|
+
"verified_at": {
|
|
29
|
+
"description": "ISO 8601 timestamp the entry was last written. For `ok` entries, the time the server was last reachable + invocable. For non-ok entries, the time the failure was observed.",
|
|
30
|
+
"type": "string",
|
|
31
|
+
"format": "date-time"
|
|
32
|
+
},
|
|
33
|
+
"tools_count": {
|
|
34
|
+
"description": "Number of tools the server exposed when last preflighted with `status: ok`. Sanity signal — a sudden drop to zero on a previously-ok server is suspicious.",
|
|
35
|
+
"type": "integer",
|
|
36
|
+
"minimum": 0
|
|
37
|
+
},
|
|
38
|
+
"error_message": {
|
|
39
|
+
"description": "Verbatim error message captured when `status` is non-ok. Quoted to the user on the next debug run so they can see what failed without re-triggering the call.",
|
|
40
|
+
"type": "string"
|
|
41
|
+
},
|
|
42
|
+
"marked_dirty_during": {
|
|
43
|
+
"description": "Optional pointer to the debug session that flipped this entry to `dirty` (free-form — phase id, plan id, timestamp, whatever the caller passed). Helps trace which run discovered the failure.",
|
|
44
|
+
"type": "string"
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://github.com/vintasoftware/vinta-ai-workflows/schemas/prs-context-comments.v1.schema.json",
|
|
4
|
+
"title": "PR-context inline comments list",
|
|
5
|
+
"description": "YAML list embedded inside the ` ```yaml ... ``` ` fence under the `# Comments` section of a `.vinta-ai-workflows/prs-context/{feature-kebab}/phase-{phase.id}.md` file. Authored by `implement-plan` (or `amend-plan`); read by `open-pr.sh` to post each entry as an inline review comment via `gh` / `glab`. Empty list is valid (clean phase, nothing non-obvious).",
|
|
6
|
+
"type": "array",
|
|
7
|
+
"items": {
|
|
8
|
+
"type": "object",
|
|
9
|
+
"required": ["file", "start_line", "body"],
|
|
10
|
+
"additionalProperties": false,
|
|
11
|
+
"properties": {
|
|
12
|
+
"file": {
|
|
13
|
+
"description": "Path relative to the repo root.",
|
|
14
|
+
"type": "string",
|
|
15
|
+
"minLength": 1
|
|
16
|
+
},
|
|
17
|
+
"start_line": {
|
|
18
|
+
"description": "First line of the commented region on the new side of the diff (1-based).",
|
|
19
|
+
"type": "integer",
|
|
20
|
+
"minimum": 1
|
|
21
|
+
},
|
|
22
|
+
"end_line": {
|
|
23
|
+
"description": "Optional last line of a multi-line comment (1-based, inclusive). Omit for single-line comments.",
|
|
24
|
+
"type": "integer",
|
|
25
|
+
"minimum": 1
|
|
26
|
+
},
|
|
27
|
+
"side": {
|
|
28
|
+
"description": "Which side of the diff the comment attaches to. `RIGHT` = post-change (default). `LEFT` = pre-change (rare; for comments on removed code).",
|
|
29
|
+
"type": "string",
|
|
30
|
+
"enum": ["LEFT", "RIGHT"],
|
|
31
|
+
"default": "RIGHT"
|
|
32
|
+
},
|
|
33
|
+
"body": {
|
|
34
|
+
"description": "Markdown comment body. 1–3 lines explaining non-obvious context. Reference the plan's `Goals + Non-goals` / `Guiding Decisions` entries by name when the decision lives there — never use `§N` shorthand. Don't restate code.",
|
|
35
|
+
"type": "string",
|
|
36
|
+
"minLength": 1
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
"allOf": [
|
|
40
|
+
{
|
|
41
|
+
"description": "If end_line is provided, it must be >= start_line.",
|
|
42
|
+
"if": { "required": ["end_line"] },
|
|
43
|
+
"then": {
|
|
44
|
+
"properties": {
|
|
45
|
+
"end_line": { "type": "integer" }
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
]
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://github.com/vintasoftware/vinta-ai-workflows/schemas/prs-context-frontmatter.v1.schema.json",
|
|
4
|
+
"title": "PR-context file frontmatter (`.vinta-ai-workflows/prs-context/<feature>/<phase>.md`)",
|
|
5
|
+
"description": "YAML frontmatter at the top of every `.vinta-ai-workflows/prs-context/{feature-kebab}/phase-{phase.id}.md` file. Authored by `implement-plan` (and rewritten by `amend-plan`); read + updated by the bundled `open-pr.sh` script. The `# Title`, `# Description`, `# Comments` body sections that follow the frontmatter are markdown / fenced YAML and not covered by this schema; the `# Comments` YAML list has its own schema (`prs-context-comments.v1.schema.json`).",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": [
|
|
8
|
+
"schema_version",
|
|
9
|
+
"plan_id",
|
|
10
|
+
"feature_name",
|
|
11
|
+
"phase_id",
|
|
12
|
+
"phase_title",
|
|
13
|
+
"branch",
|
|
14
|
+
"base",
|
|
15
|
+
"created_at",
|
|
16
|
+
"status"
|
|
17
|
+
],
|
|
18
|
+
"additionalProperties": false,
|
|
19
|
+
"properties": {
|
|
20
|
+
"schema_version": {
|
|
21
|
+
"description": "Schema major version. Bumped only on breaking changes.",
|
|
22
|
+
"type": "integer",
|
|
23
|
+
"const": 1
|
|
24
|
+
},
|
|
25
|
+
"plan_id": {
|
|
26
|
+
"description": "Kebab-case identifier of the plan. Filename feature portion (strip `YYYY-MM-DD-` prefix and `_PLAN.md` suffix, lowercase).",
|
|
27
|
+
"type": "string",
|
|
28
|
+
"pattern": "^[a-z0-9][a-z0-9-]*$",
|
|
29
|
+
"minLength": 1
|
|
30
|
+
},
|
|
31
|
+
"feature_name": {
|
|
32
|
+
"description": "`UPPERCASE_WITH_UNDERSCORES` feature name. Matches the plan + spec filename feature portion.",
|
|
33
|
+
"type": "string",
|
|
34
|
+
"pattern": "^[A-Z][A-Z0-9_]*$",
|
|
35
|
+
"minLength": 1
|
|
36
|
+
},
|
|
37
|
+
"phase_id": {
|
|
38
|
+
"description": "Phase id verbatim from the plan's `Phased Rollout` section (e.g. `1`, `4a`, `2.5`).",
|
|
39
|
+
"type": "string",
|
|
40
|
+
"pattern": "^[0-9]+(\\.[0-9]+)?[a-z]?$",
|
|
41
|
+
"minLength": 1
|
|
42
|
+
},
|
|
43
|
+
"phase_title": {
|
|
44
|
+
"description": "Phase title verbatim from the plan's `Phased Rollout` section.",
|
|
45
|
+
"type": "string",
|
|
46
|
+
"minLength": 1
|
|
47
|
+
},
|
|
48
|
+
"branch": {
|
|
49
|
+
"description": "Source branch the PR opens from. Default convention `plan/<plan-id-kebab>/phase-<phase.id>`.",
|
|
50
|
+
"type": "string",
|
|
51
|
+
"minLength": 1
|
|
52
|
+
},
|
|
53
|
+
"base": {
|
|
54
|
+
"description": "Target branch. Either the project's default branch (`main`) or the previous phase's stacked branch.",
|
|
55
|
+
"type": "string",
|
|
56
|
+
"minLength": 1
|
|
57
|
+
},
|
|
58
|
+
"created_at": {
|
|
59
|
+
"description": "ISO 8601 timestamp when the PR-context file was first written.",
|
|
60
|
+
"type": "string",
|
|
61
|
+
"format": "date-time"
|
|
62
|
+
},
|
|
63
|
+
"status": {
|
|
64
|
+
"description": "Lifecycle. `pending` until `open-pr.sh` publishes; then `published`.",
|
|
65
|
+
"type": "string",
|
|
66
|
+
"enum": ["pending", "published"]
|
|
67
|
+
},
|
|
68
|
+
"pr_url": {
|
|
69
|
+
"description": "URL of the published PR / MR. Populated by `open-pr.sh` on success. Empty string while `status: pending`.",
|
|
70
|
+
"type": "string",
|
|
71
|
+
"anyOf": [
|
|
72
|
+
{ "format": "uri" },
|
|
73
|
+
{ "const": "" }
|
|
74
|
+
]
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://github.com/vintasoftware/vinta-ai-workflows/schemas/sub-agent.v1.schema.json",
|
|
4
|
+
"title": "vinta-ai-workflows sub-agent definition",
|
|
5
|
+
"description": "Vendor-agnostic sub-agent definition. Lives at `ai-tools/agents/<name>.yaml` in a target project. Read by `setup-ai-tools.mjs` which emits per-vendor copies (Claude markdown, Cursor markdown, Copilot `.agent.md`, Codex TOML). One file per agent. See schemas/README.md for versioning rules.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": ["schema_version", "name", "description", "access", "body"],
|
|
8
|
+
"additionalProperties": false,
|
|
9
|
+
"properties": {
|
|
10
|
+
"schema_version": {
|
|
11
|
+
"description": "Schema major version. Bumped only on breaking changes.",
|
|
12
|
+
"type": "integer",
|
|
13
|
+
"const": 1
|
|
14
|
+
},
|
|
15
|
+
"name": {
|
|
16
|
+
"description": "Agent identifier. Lowercase kebab-case. Used as filename stem and as the agent's slash-command name.",
|
|
17
|
+
"type": "string",
|
|
18
|
+
"pattern": "^[a-z][a-z0-9-]*$",
|
|
19
|
+
"minLength": 1
|
|
20
|
+
},
|
|
21
|
+
"description": {
|
|
22
|
+
"description": "One-line role + when-to-use summary. Used in vendor frontmatter for delegation hints.",
|
|
23
|
+
"type": "string",
|
|
24
|
+
"minLength": 1
|
|
25
|
+
},
|
|
26
|
+
"access": {
|
|
27
|
+
"description": "Read/write capability profile. Drives vendor-specific defaults (Claude `tools:`, Cursor `readonly:`, Codex `sandbox_mode`, Copilot `tools[]`).",
|
|
28
|
+
"type": "string",
|
|
29
|
+
"enum": ["read-only", "read-write"]
|
|
30
|
+
},
|
|
31
|
+
"body": {
|
|
32
|
+
"description": "Markdown body of the agent prompt. Multi-line literal block. Becomes the body of every per-vendor file emitted by `setup-ai-tools.mjs`.",
|
|
33
|
+
"type": "string",
|
|
34
|
+
"minLength": 1
|
|
35
|
+
},
|
|
36
|
+
"claude-tools": {
|
|
37
|
+
"description": "Optional shorthand: top-level Claude Code `tools:` value. When set, overrides the default derived from `access`. Equivalent to `overrides.claude.tools`.",
|
|
38
|
+
"type": "string"
|
|
39
|
+
},
|
|
40
|
+
"model": {
|
|
41
|
+
"description": "Optional default model preference (per-vendor when present at top level). Vendor-specific overrides win.",
|
|
42
|
+
"type": "string"
|
|
43
|
+
},
|
|
44
|
+
"is_background": {
|
|
45
|
+
"description": "Cursor-only top-level flag — agent runs as a background task.",
|
|
46
|
+
"type": "boolean"
|
|
47
|
+
},
|
|
48
|
+
"overrides": {
|
|
49
|
+
"description": "Vendor-specific overrides. Each vendor's keys mirror what the vendor's frontmatter accepts.",
|
|
50
|
+
"type": "object",
|
|
51
|
+
"additionalProperties": false,
|
|
52
|
+
"properties": {
|
|
53
|
+
"claude": {
|
|
54
|
+
"type": "object",
|
|
55
|
+
"additionalProperties": true,
|
|
56
|
+
"properties": {
|
|
57
|
+
"tools": {
|
|
58
|
+
"description": "Comma-separated tool names (Claude format).",
|
|
59
|
+
"type": "string"
|
|
60
|
+
},
|
|
61
|
+
"model": { "type": "string" }
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
"cursor": {
|
|
65
|
+
"type": "object",
|
|
66
|
+
"additionalProperties": true,
|
|
67
|
+
"properties": {
|
|
68
|
+
"model": { "type": "string" },
|
|
69
|
+
"readonly": { "type": "boolean" },
|
|
70
|
+
"is_background": { "type": "boolean" }
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
"copilot": {
|
|
74
|
+
"type": "object",
|
|
75
|
+
"additionalProperties": true,
|
|
76
|
+
"properties": {
|
|
77
|
+
"tools": {
|
|
78
|
+
"description": "List of Copilot tool ids (e.g. `codebase`, `editFiles`, `runCommands`).",
|
|
79
|
+
"type": "array",
|
|
80
|
+
"items": { "type": "string" }
|
|
81
|
+
},
|
|
82
|
+
"model": { "type": "string" },
|
|
83
|
+
"user-invocable": { "type": "boolean" },
|
|
84
|
+
"disable-model-invocation": { "type": "boolean" }
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
"codex": {
|
|
88
|
+
"type": "object",
|
|
89
|
+
"additionalProperties": true,
|
|
90
|
+
"properties": {
|
|
91
|
+
"sandbox_mode": {
|
|
92
|
+
"type": "string",
|
|
93
|
+
"enum": ["read-only", "workspace-write", "workspace-network"]
|
|
94
|
+
},
|
|
95
|
+
"model": { "type": "string" },
|
|
96
|
+
"model_reasoning_effort": {
|
|
97
|
+
"type": "string",
|
|
98
|
+
"enum": ["low", "medium", "high"]
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://github.com/vintasoftware/vinta-ai-workflows/schemas/vinta-ai-workflows-config.v1.schema.json",
|
|
4
|
+
"title": "vinta-ai-workflows project config",
|
|
5
|
+
"description": "Single source of truth for vinta-ai-workflows configuration in a target project. Lives at `.vinta-ai-workflows.yaml` at the repo root. Authored by `vinta-bootstrap-ai-tools`; updated in place by `vinta-sync-ai-tools`. Read by every builder skill, foundation skill template, and meta-skill. See schemas/README.md for versioning rules.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": [
|
|
8
|
+
"schema_version",
|
|
9
|
+
"vinta_ai_workflows_version",
|
|
10
|
+
"project",
|
|
11
|
+
"commands",
|
|
12
|
+
"policies",
|
|
13
|
+
"vendors",
|
|
14
|
+
"foundation_skills",
|
|
15
|
+
"foundation_agents"
|
|
16
|
+
],
|
|
17
|
+
"additionalProperties": false,
|
|
18
|
+
"properties": {
|
|
19
|
+
"schema_version": {
|
|
20
|
+
"description": "Schema major version. Bumped only on breaking changes.",
|
|
21
|
+
"type": "integer",
|
|
22
|
+
"const": 1
|
|
23
|
+
},
|
|
24
|
+
"vinta_ai_workflows_version": {
|
|
25
|
+
"description": "Last `vinta-ai-workflows` package version this project synced from. Compared against the cloned package version by `vinta-sync-ai-tools` to enumerate releases since.",
|
|
26
|
+
"type": "string",
|
|
27
|
+
"pattern": "^\\d+\\.\\d+\\.\\d+(-[A-Za-z0-9.-]+)?$"
|
|
28
|
+
},
|
|
29
|
+
"last_synced_at": {
|
|
30
|
+
"description": "ISO 8601 timestamp of the last successful bootstrap or sync run.",
|
|
31
|
+
"type": "string",
|
|
32
|
+
"format": "date-time"
|
|
33
|
+
},
|
|
34
|
+
"project": {
|
|
35
|
+
"type": "object",
|
|
36
|
+
"required": ["name", "default_branch", "code_host", "stack_summary", "ai_plans_dir"],
|
|
37
|
+
"additionalProperties": false,
|
|
38
|
+
"properties": {
|
|
39
|
+
"name": { "type": "string", "minLength": 1 },
|
|
40
|
+
"default_branch": { "type": "string", "minLength": 1, "examples": ["main", "master"] },
|
|
41
|
+
"code_host": {
|
|
42
|
+
"type": "string",
|
|
43
|
+
"enum": ["github", "gitlab", "bitbucket", "self-hosted", "other"]
|
|
44
|
+
},
|
|
45
|
+
"stack_summary": {
|
|
46
|
+
"description": "Human-readable one-liner of the stack (lang + framework + key deps). Pulled from `vinta-analyze-codebase` inventory.",
|
|
47
|
+
"type": "string"
|
|
48
|
+
},
|
|
49
|
+
"ai_plans_dir": {
|
|
50
|
+
"description": "Directory holding `YYYY-MM-DD-FEATURE_NAME_{SPEC,PLAN}.md` files. Default `ai-plans`. Monorepos often nest it under a service dir (e.g. `apps/<service>/ai-plans`).",
|
|
51
|
+
"type": "string",
|
|
52
|
+
"minLength": 1,
|
|
53
|
+
"default": "ai-plans"
|
|
54
|
+
},
|
|
55
|
+
"pr_template_paths": {
|
|
56
|
+
"description": "Paths (relative to repo root) of the project's existing PR / MR templates. Detected at bootstrap by scanning for `.github/pull_request_template.md`, `.github/PULL_REQUEST_TEMPLATE.md`, `.github/PULL_REQUEST_TEMPLATE/*.md`, `pull_request_template.md`, `docs/pull_request_template.md` (GitHub case-insensitive) and `.gitlab/merge_request_templates/*.md` (GitLab). When non-empty, `implement-plan` / `amend-plan` use the template as the scaffold for the prs-context file's `# Description` section. Empty array → free-form description. Multiple entries (template dir) → orchestrator asks the user which to use, or picks `default.md` if present.",
|
|
57
|
+
"type": "array",
|
|
58
|
+
"items": { "type": "string", "minLength": 1 },
|
|
59
|
+
"uniqueItems": true,
|
|
60
|
+
"default": []
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
"commands": {
|
|
65
|
+
"description": "Commands consumed by `implement-plan` / `amend-plan` / project foundation skills at runtime.",
|
|
66
|
+
"type": "object",
|
|
67
|
+
"required": ["lint", "build", "test_unit"],
|
|
68
|
+
"additionalProperties": true,
|
|
69
|
+
"properties": {
|
|
70
|
+
"lint": { "type": "string" },
|
|
71
|
+
"format": { "type": "string" },
|
|
72
|
+
"build": {
|
|
73
|
+
"description": "Type-check / build gate. Often the same as the test command on Python projects.",
|
|
74
|
+
"type": "string"
|
|
75
|
+
},
|
|
76
|
+
"test_unit": { "type": "string" },
|
|
77
|
+
"test_unit_scoped": {
|
|
78
|
+
"description": "Per-package or per-app scoped suite (e.g. `pnpm test:patient`).",
|
|
79
|
+
"type": "string"
|
|
80
|
+
},
|
|
81
|
+
"test_unit_new_pattern": {
|
|
82
|
+
"description": "Pattern for running a single new test file in isolation. Use placeholders like `<pkg>` / `<new-test-path>`.",
|
|
83
|
+
"type": "string"
|
|
84
|
+
},
|
|
85
|
+
"e2e": { "type": "string" }
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
"policies": {
|
|
89
|
+
"description": "Step-0 interview answers driving template rendering + agent prompts.",
|
|
90
|
+
"type": "object",
|
|
91
|
+
"required": ["pr_creation", "ai_coauthor", "commit_style", "stage_pattern"],
|
|
92
|
+
"additionalProperties": false,
|
|
93
|
+
"properties": {
|
|
94
|
+
"pr_creation": {
|
|
95
|
+
"description": "Whether agents open PRs or only push branches. Drives the `implement-plan` skill's `Open PR via context file` step matrix.",
|
|
96
|
+
"type": "string",
|
|
97
|
+
"enum": ["agents-create", "branches-only"]
|
|
98
|
+
},
|
|
99
|
+
"ai_coauthor": {
|
|
100
|
+
"description": "Whether commits may carry AI co-author trailers (`Co-Authored-By: Claude ...`).",
|
|
101
|
+
"type": "string",
|
|
102
|
+
"enum": ["allowed", "forbidden"]
|
|
103
|
+
},
|
|
104
|
+
"commit_style": {
|
|
105
|
+
"type": "string",
|
|
106
|
+
"enum": ["conventional", "imperative", "other"]
|
|
107
|
+
},
|
|
108
|
+
"stage_pattern": {
|
|
109
|
+
"description": "Default `git add` pattern shown to subagents (no `git add -A`).",
|
|
110
|
+
"type": "string"
|
|
111
|
+
},
|
|
112
|
+
"anti_git_add_all_reason": {
|
|
113
|
+
"description": "One-line reason `git add -A` is forbidden in this repo (e.g. secrets, build artifacts in tree).",
|
|
114
|
+
"type": "string"
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
},
|
|
118
|
+
"vendors": {
|
|
119
|
+
"description": "Vendor coverage selected at bootstrap. Consumed by `setup-ai-tools.mjs` `--only` flag.",
|
|
120
|
+
"type": "array",
|
|
121
|
+
"items": { "type": "string", "enum": ["claude", "cursor", "copilot", "codex"] },
|
|
122
|
+
"uniqueItems": true,
|
|
123
|
+
"minItems": 1
|
|
124
|
+
},
|
|
125
|
+
"foundation_skills": {
|
|
126
|
+
"description": "Per-foundation-skill opt-in. Use `enabled` / `disabled`. `disabled` is a sticky opt-out — `vinta-sync-ai-tools` does not re-propose disabled skills.",
|
|
127
|
+
"type": "object",
|
|
128
|
+
"additionalProperties": { "type": "string", "enum": ["enabled", "disabled"] },
|
|
129
|
+
"properties": {
|
|
130
|
+
"plan-feature": { "type": "string", "enum": ["enabled", "disabled"] },
|
|
131
|
+
"create-spec": { "type": "string", "enum": ["enabled", "disabled"] },
|
|
132
|
+
"create-qa-use-cases": { "type": "string", "enum": ["enabled", "disabled"] },
|
|
133
|
+
"implement-plan": { "type": "string", "enum": ["enabled", "disabled"] },
|
|
134
|
+
"amend-plan": { "type": "string", "enum": ["enabled", "disabled"] },
|
|
135
|
+
"open-pr-from-context": { "type": "string", "enum": ["enabled", "disabled"] },
|
|
136
|
+
"add-e2e-test": { "type": "string", "enum": ["enabled", "disabled"] },
|
|
137
|
+
"add-env-var": { "type": "string", "enum": ["enabled", "disabled"] },
|
|
138
|
+
"add-one-off-script": {
|
|
139
|
+
"description": "Author safe operational one-off scripts (backfills, cleanups, ad-hoc data fixes) following a strict contract: dry-run by default, idempotent on re-run, batched DB operations, streamed reads, segmented CSV backups before destructive writes (max 1M cells/file, never nested across tables), interruption-safe signal handlers, and console + filesystem + S3 logging. Bundles a `BaseOneOffScript` class template under [resources/foundation-skills/add-one-off-script/resources/](resources/foundation-skills/add-one-off-script/resources/). When `enabled`, project-level configuration lives under `skills.add-one-off-script` (scripts dir, S3 bucket/prefix, default batch size).",
|
|
140
|
+
"type": "string",
|
|
141
|
+
"enum": ["enabled", "disabled"]
|
|
142
|
+
},
|
|
143
|
+
"systematic-debugging": {
|
|
144
|
+
"description": "Root-cause-first debugging skill rendered from `vinta-derive-skills/resources/systematic-debugging-template.md`. When `enabled`, the per-project MCP tool selection lives in `skills.systematic-debugging.observability_mcp_tools`.",
|
|
145
|
+
"type": "string",
|
|
146
|
+
"enum": ["enabled", "disabled"]
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
},
|
|
150
|
+
"foundation_agents": {
|
|
151
|
+
"description": "Per-foundation-agent opt-in. Foundation trio (`implementer` / `reviewer` / `fixer`) are usually `enabled`.",
|
|
152
|
+
"type": "object",
|
|
153
|
+
"additionalProperties": { "type": "string", "enum": ["enabled", "disabled"] },
|
|
154
|
+
"properties": {
|
|
155
|
+
"implementer": { "type": "string", "enum": ["enabled", "disabled"] },
|
|
156
|
+
"reviewer": { "type": "string", "enum": ["enabled", "disabled"] },
|
|
157
|
+
"fixer": { "type": "string", "enum": ["enabled", "disabled"] }
|
|
158
|
+
}
|
|
159
|
+
},
|
|
160
|
+
"stacks": {
|
|
161
|
+
"description": "Stack templates applied at bootstrap (e.g. `medplum`, `django`, `nextjs-app-router`).",
|
|
162
|
+
"type": "array",
|
|
163
|
+
"items": { "type": "string", "minLength": 1 },
|
|
164
|
+
"uniqueItems": true,
|
|
165
|
+
"default": []
|
|
166
|
+
},
|
|
167
|
+
"stack_specialist_agents": {
|
|
168
|
+
"description": "Stack-specific sub-agents shipped (e.g. `migration-author` for Django, `deploy-author` for Medplum).",
|
|
169
|
+
"type": "array",
|
|
170
|
+
"items": { "type": "string", "minLength": 1 },
|
|
171
|
+
"uniqueItems": true,
|
|
172
|
+
"default": []
|
|
173
|
+
},
|
|
174
|
+
"run_options": {
|
|
175
|
+
"description": "Per-skill run-option defaults. Skills override via per-invocation prompts; values here are the defaults shown.",
|
|
176
|
+
"type": "object",
|
|
177
|
+
"additionalProperties": true,
|
|
178
|
+
"properties": {
|
|
179
|
+
"implement-plan": {
|
|
180
|
+
"type": "object",
|
|
181
|
+
"additionalProperties": false,
|
|
182
|
+
"properties": {
|
|
183
|
+
"pause_between_phases": { "type": "boolean", "default": false },
|
|
184
|
+
"generate_inline_comments": { "type": "boolean", "default": false }
|
|
185
|
+
}
|
|
186
|
+
},
|
|
187
|
+
"amend-plan": {
|
|
188
|
+
"type": "object",
|
|
189
|
+
"additionalProperties": false,
|
|
190
|
+
"properties": {
|
|
191
|
+
"blast_radius_signal_threshold": {
|
|
192
|
+
"description": "How many tripping signals before suggesting restart-from-scratch. 2 = `high-blast-radius`, 3 = `restart-recommended`.",
|
|
193
|
+
"type": "integer",
|
|
194
|
+
"minimum": 1,
|
|
195
|
+
"maximum": 7,
|
|
196
|
+
"default": 2
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
},
|
|
200
|
+
"systematic-debugging": {
|
|
201
|
+
"type": "object",
|
|
202
|
+
"additionalProperties": false,
|
|
203
|
+
"properties": {
|
|
204
|
+
"allow_local_only_debug": {
|
|
205
|
+
"description": "Whether the user is permitted to opt out of the MCP preflight + categories block on a per-run basis (e.g. `/systematic-debugging local-only — flaky test`). Defaults to `true`. Set to `false` for projects where production-only bugs must always go through the observability sweep — the skill will then refuse the `local-only` keyword and require the user to wire up an MCP server (or remove `systematic-debugging` from the project) instead.",
|
|
206
|
+
"type": "boolean",
|
|
207
|
+
"default": true
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
},
|
|
213
|
+
"skills": {
|
|
214
|
+
"description": "Per-skill custom config. Open schema — each skill defines its own keys.",
|
|
215
|
+
"type": "object",
|
|
216
|
+
"additionalProperties": { "type": "object" },
|
|
217
|
+
"properties": {
|
|
218
|
+
"systematic-debugging": {
|
|
219
|
+
"description": "Configuration for the `systematic-debugging` foundation skill. Required when `foundation_skills.systematic-debugging` is `enabled`; ignored otherwise.",
|
|
220
|
+
"type": "object",
|
|
221
|
+
"required": ["observability_mcp_servers"],
|
|
222
|
+
"additionalProperties": false,
|
|
223
|
+
"properties": {
|
|
224
|
+
"observability_mcp_servers": {
|
|
225
|
+
"description": "Free-form list of MCP server identifiers the agent should introspect during Phase 0 (evidence sweep) before any hypothesis. Identifiers use whatever shorthand the team recognises (e.g. `sentry`, `datadog`, `our-internal-traces`, `grafana-prod`). No enum is enforced — the systematic-debugging agent discovers specific tool names + capabilities at runtime by listing the tools each server exposes and matching them against the evidence categories baked into the rendered SKILL.md (see `vinta-derive-skills/resources/systematic-debugging-mcp-tools.md`). Empty array is allowed but degrades the skill — the rendered Phase 0 collapses to 'local logs only'. Order is preserved in the rendered list; not significant otherwise.",
|
|
226
|
+
"type": "array",
|
|
227
|
+
"items": { "type": "string", "minLength": 1 },
|
|
228
|
+
"uniqueItems": true,
|
|
229
|
+
"default": []
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
},
|
|
233
|
+
"add-one-off-script": {
|
|
234
|
+
"description": "Configuration for the `add-one-off-script` foundation skill. Optional when `foundation_skills.add-one-off-script` is `enabled` — sensible defaults apply when omitted.",
|
|
235
|
+
"type": "object",
|
|
236
|
+
"additionalProperties": false,
|
|
237
|
+
"properties": {
|
|
238
|
+
"scripts_dir": {
|
|
239
|
+
"description": "Where one-off scripts live in the repo. Default `scripts/one_off`. Override for monorepos that nest scripts under a service / package dir.",
|
|
240
|
+
"type": "string",
|
|
241
|
+
"minLength": 1,
|
|
242
|
+
"default": "scripts/one_off"
|
|
243
|
+
},
|
|
244
|
+
"language": {
|
|
245
|
+
"description": "Primary language for scripts; selects which `BaseOneOffScript` template to stage. Default inferred from project stack at bootstrap.",
|
|
246
|
+
"type": "string",
|
|
247
|
+
"enum": ["python", "typescript"]
|
|
248
|
+
},
|
|
249
|
+
"log_dir": {
|
|
250
|
+
"description": "Where logs, PID files, processed-items logs, and CSV backups land. Default `.vinta-ai-workflows/one-off-runs` (gitignored).",
|
|
251
|
+
"type": "string",
|
|
252
|
+
"minLength": 1,
|
|
253
|
+
"default": ".vinta-ai-workflows/one-off-runs"
|
|
254
|
+
},
|
|
255
|
+
"default_batch_size": {
|
|
256
|
+
"description": "Default batch size injected into the `BaseOneOffScript` config when scripts don't override. Smaller for wide rows / contended tables.",
|
|
257
|
+
"type": "integer",
|
|
258
|
+
"minimum": 1,
|
|
259
|
+
"maximum": 100000,
|
|
260
|
+
"default": 500
|
|
261
|
+
},
|
|
262
|
+
"csv_max_cells": {
|
|
263
|
+
"description": "Per-CSV-chunk cell cap (rows × columns) before the writer rolls over to the next file. The contract requires segmented CSVs so a single backup chunk stays loadable without OOM.",
|
|
264
|
+
"type": "integer",
|
|
265
|
+
"minimum": 1000,
|
|
266
|
+
"maximum": 10000000,
|
|
267
|
+
"default": 1000000
|
|
268
|
+
},
|
|
269
|
+
"s3_bucket": {
|
|
270
|
+
"description": "S3 bucket for log + CSV-backup uploads. Falls back to the `ONE_OFF_S3_BUCKET` env var at runtime when unset. Empty string disables S3 upload (filesystem copy remains authoritative).",
|
|
271
|
+
"type": "string"
|
|
272
|
+
},
|
|
273
|
+
"s3_prefix": {
|
|
274
|
+
"description": "S3 key prefix for uploads. Falls back to `ONE_OFF_S3_PREFIX` env, default `one-off-runs/`. Trailing slash recommended.",
|
|
275
|
+
"type": "string",
|
|
276
|
+
"default": "one-off-runs/"
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|