mirror of
https://github.com/garrytan/gstack.git
synced 2026-05-02 03:35:09 +02:00
feat: add JSON Schema definitions + COMPATIBILITY.md for cross-runtime contracts
Four schemas for the OpenClaw dispatch protocol: - dispatch.schema.json (task dispatch with target_agent, source_signature) - completion.schema.json (session completion report with retry_count) - handoff.schema.json (cross-runtime context transfer with resume_prompt) - activity-entry.schema.json (weekly activity index entries) COMPATIBILITY.md defines breaking vs non-breaking changes so future contributors don't guess under pressure. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
# Schema Compatibility
|
||||
|
||||
gstack uses JSON Schema definitions in `schemas/` for cross-runtime file formats
|
||||
(dispatch, completion, handoff, activity). Both the gstack dispatch daemon and
|
||||
OpenClaw bridge skill validate against these schemas.
|
||||
|
||||
## Version policy
|
||||
|
||||
Schema version is tied to gstack's `VERSION` file.
|
||||
|
||||
### Breaking change (major version bump required)
|
||||
|
||||
A change is **breaking** if it:
|
||||
- Removes a required field
|
||||
- Changes a field's type (e.g., string to integer)
|
||||
- Changes the semantics of an existing field (e.g., `duration` from milliseconds to seconds)
|
||||
- Narrows an enum (removes a valid value)
|
||||
|
||||
### Non-breaking change (minor version bump)
|
||||
|
||||
A change is **non-breaking** if it:
|
||||
- Adds a new optional field
|
||||
- Widens an enum (adds a new valid value)
|
||||
- Relaxes a constraint (e.g., increases maxLength)
|
||||
- Adds a new schema file
|
||||
|
||||
### Rules
|
||||
|
||||
1. **Additive by default.** New fields are always optional. Existing readers ignore unknown fields.
|
||||
2. **Breaking changes require a major version bump** and must be called out in CHANGELOG.
|
||||
3. **Both sides validate.** The gstack daemon validates incoming dispatch files. The OpenClaw bridge validates completion reports. If validation fails, the file is rejected with an error status, not silently ignored.
|
||||
4. **Schema version in file.** Future versions may add a `schema_version` field to each file for explicit version negotiation. For now, schema version is implied by gstack VERSION.
|
||||
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "https://github.com/garrytan/gstack/schemas/activity-entry.schema.json",
|
||||
"title": "gstack Activity Entry",
|
||||
"description": "Single entry in the weekly activity index (activity-YYYY-WNN.jsonl)",
|
||||
"type": "object",
|
||||
"required": ["ts", "project", "skill", "duration"],
|
||||
"properties": {
|
||||
"ts": { "type": "string", "format": "date-time" },
|
||||
"project": { "type": "string" },
|
||||
"skill": { "type": "string" },
|
||||
"artifacts": { "type": "array", "items": { "type": "string" }, "description": "References to produced artifacts (e.g., pr:47, review-log.jsonl, learnings:3)" },
|
||||
"duration": { "type": "integer", "description": "Session duration in seconds" },
|
||||
"dispatch": { "type": "string", "description": "Orchestrator identity if this was a dispatched session" }
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "https://github.com/garrytan/gstack/schemas/completion.schema.json",
|
||||
"title": "gstack Dispatch Completion",
|
||||
"description": "Completion report from a gstack coding session back to the orchestrator",
|
||||
"type": "object",
|
||||
"required": ["dispatch_id", "status", "duration"],
|
||||
"properties": {
|
||||
"dispatch_id": { "type": "string", "pattern": "^dispatch-" },
|
||||
"status": { "enum": ["completed", "failed", "cancelled", "timeout"] },
|
||||
"duration": { "type": "integer", "description": "Session duration in seconds" },
|
||||
"commits": { "type": "integer", "minimum": 0 },
|
||||
"pr": { "type": "string", "description": "PR reference in owner/repo#number format" },
|
||||
"error": { "type": "string", "description": "Error description, present only on failure/timeout" },
|
||||
"retry_count": { "type": "integer", "minimum": 0, "description": "Number of retries attempted" },
|
||||
"target_agent": { "enum": ["claude", "codex", "cursor", "gemini"] }
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "https://github.com/garrytan/gstack/schemas/dispatch.schema.json",
|
||||
"title": "gstack Dispatch",
|
||||
"description": "Task dispatch from an orchestrator (e.g., OpenClaw/Wintermute) to gstack coding agent",
|
||||
"type": "object",
|
||||
"required": ["id", "dispatched_by", "task", "project", "project_dir"],
|
||||
"properties": {
|
||||
"id": { "type": "string", "pattern": "^dispatch-" },
|
||||
"dispatched_by": { "type": "string" },
|
||||
"task": { "type": "string", "minLength": 1 },
|
||||
"project": { "type": "string" },
|
||||
"project_dir": { "type": "string" },
|
||||
"target_agent": { "enum": ["claude", "codex", "cursor", "gemini"], "default": "claude" },
|
||||
"learnings": { "type": "array", "items": { "type": "string" } },
|
||||
"constraints": { "type": "array", "items": { "type": "string" } },
|
||||
"callback_url": { "type": "string", "format": "uri" },
|
||||
"clawvisor_task_id": { "type": "string" },
|
||||
"source_signature": { "type": "string", "description": "HMAC-SHA256 of task field with local secret" },
|
||||
"ttl_seconds": { "type": "integer", "minimum": 60, "maximum": 86400 }
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "https://github.com/garrytan/gstack/schemas/handoff.schema.json",
|
||||
"title": "gstack Session Handoff",
|
||||
"description": "Cross-runtime context transfer between gstack and an orchestrator (e.g., OpenClaw)",
|
||||
"type": "object",
|
||||
"required": ["from", "to", "project", "timestamp"],
|
||||
"properties": {
|
||||
"from": { "enum": ["gstack", "wintermute", "openclaw"] },
|
||||
"to": { "enum": ["gstack", "wintermute", "openclaw"] },
|
||||
"project": { "type": "string" },
|
||||
"branch": { "type": "string" },
|
||||
"timestamp": { "type": "string", "format": "date-time" },
|
||||
"resume_prompt": { "type": "string", "maxLength": 4096, "description": "Exact prompt to resume session in the target runtime" }
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
Reference in New Issue
Block a user