Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions packages/agents-audit/src/package-metadata.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ describe('package metadata', () => {
it('keeps the spec package mature and discoverable', () => {
const pkg = readPackageJson('packages/spec/package.json');
expect(pkg.name).toBe('@workspacejson/spec');
expect(pkg.version).toBe('0.2.0');
expect((pkg.repository as { directory?: string } | undefined)?.directory).toBe('packages/spec');
expect(pkg.version).toBe('0.3.0');
expect((pkg.repository as { directory?: string } | undefined)?.directory).toBeUndefined();
Comment thread
qmarcelle marked this conversation as resolved.
expect((pkg.publishConfig as { access?: string } | undefined)?.access).toBe('public');
const keywords = pkg.keywords as string[];
expect(keywords.includes('workspace.json')).toBe(true);
Expand All @@ -32,7 +32,7 @@ describe('package metadata', () => {
it('keeps the rules package mature and discoverable', () => {
const pkg = readPackageJson('packages/rules/package.json');
expect(pkg.name).toBe('@workspacejson/rules');
expect(pkg.version).toBe('0.2.0');
expect(pkg.version).toBe('0.2.1');
expect((pkg.repository as { directory?: string } | undefined)?.directory).toBe('packages/rules');
expect((pkg.publishConfig as { access?: string } | undefined)?.access).toBe('public');
const keywords = pkg.keywords as string[];
Expand All @@ -51,7 +51,7 @@ describe('package metadata', () => {
it('keeps the CLI package mature and executable', () => {
const pkg = readPackageJson('packages/agents-audit/package.json');
expect(pkg.name).toBe('agents-audit');
expect(pkg.version).toBe('0.2.0');
expect(pkg.version).toBe('0.2.1');
expect((pkg.bin as { [key: string]: string } | undefined)?.['agents-audit']).toBe('./dist/cli.js');
expect((pkg.publishConfig as { access?: string } | undefined)?.access).toBe('public');
const keywords = pkg.keywords as string[];
Expand Down
19 changes: 19 additions & 0 deletions packages/spec/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,25 @@ All notable changes to `@workspacejson/spec` are documented here.

## Unreleased

## [0.3.0] - 2026-05-22

### Breaking changes
- Schema shape changed to four-property structure: `manual`, `generated`, `agents`, `health`.
- Canonical write path corrected to `.agents/agents.workspace.json` (v0.2.0 incorrectly stated repo root).
- Top-level `version` field removed; schema version now lives at `generated.specVersion = "0.3"`.
- Per-file fragility data lives at `generated.fileIndex.{path}` (not `files.{path}`).
- Framework detection lives at `generated.frameworkManifest`.

### Ecosystem alignment
- Field names match `jnuyens/gsd-plugin v2.42.3` SessionStart read paths (first shipped consumer of `.agents/agents.workspace.json`).

### Added
- `examples/` directory with minimal, populated, and with-manual-block example files.
- `validate()` and `validateLegacy()` exports in `src/index.ts`.
Comment thread
qmarcelle marked this conversation as resolved.

### Migration
Check `generated.specVersion === "0.3"` to detect v0.3 documents. Fall back to v0.1 shape if `specVersion` is absent.

## 0.2.0 - 2026-05-08

### Added
Expand Down
17 changes: 17 additions & 0 deletions packages/spec/examples/minimal-v0.3.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"manual": {},
"generated": {
"specVersion": "0.3",
"generatedAt": "2026-05-22T00:00:00Z",
"by": { "name": "example-producer", "version": "0.1.0" },
"frameworkManifest": [],
"fileIndex": {},
"warnings": []
},
"agents": {},
"health": {
"intelligenceState": "INSUFFICIENT_DATA",
"observationCount": 0,
"confidence": 0
}
}
28 changes: 28 additions & 0 deletions packages/spec/examples/populated-v0.3.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"manual": {},
"generated": {
"specVersion": "0.3",
"generatedAt": "2026-05-22T00:00:00Z",
"by": { "name": "vreko-daemon", "version": "0.3.0" },
"frameworkManifest": [
{ "name": "next.js", "version": "15.0.0", "confidence": 0.95 }
],
"fileIndex": {
"apps/api/src/auth.ts": {
"fragility": 0.82,
"aiModificationCount": 7,
"humanModificationCount": 3
}
},
"topology": { "packageCount": 38 },
"warnings": []
},
"agents": {},
"health": {
"intelligenceState": "CONFIDENT",
"observationCount": 1247,
"confidence": 0.87,
"averageFragility": 0.34,
"fragileFileCount": 12
}
}
27 changes: 27 additions & 0 deletions packages/spec/examples/with-manual-block-v0.3.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"manual": {
"fragileFiles": [
{ "path": "apps/api/src/auth.ts", "reason": "high rollback rate, auth logic" }
],
"coChangePatterns": [
{
"files": ["apps/cli/src/commands/check.ts", "apps/cli/src/commands/interactive.ts"],
"note": "always change together"
}
]
},
"generated": {
"specVersion": "0.3",
"generatedAt": "2026-05-22T00:00:00Z",
"by": { "name": "vreko-daemon", "version": "0.3.0" },
"frameworkManifest": [],
"fileIndex": {},
"warnings": []
},
"agents": {},
"health": {
"intelligenceState": "OBSERVING",
"observationCount": 42,
"confidence": 0.45
}
}
2 changes: 1 addition & 1 deletion packages/spec/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@workspacejson/spec",
"version": "0.2.0",
"version": "0.3.0",
"description": "JSON Schema and TypeScript types for agents.workspace.json",
"license": "Apache-2.0",
"author": "workspace-json contributors",
Expand Down
160 changes: 82 additions & 78 deletions packages/spec/schema/v1.json
Original file line number Diff line number Diff line change
@@ -1,99 +1,103 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://workspacejson.dev/schemas/agents.workspace.v1.json",
"$id": "https://www.workspacejson.dev/schema/v1.json",
"title": "agents.workspace.json",
"type": "object",
"required": ["version"],
"required": ["manual", "generated", "agents", "health"],
"additionalProperties": false,
"properties": {
"version": {
"type": "string"
},
"generatedAt": {
"type": "string",
"format": "date-time"
},
"repository": {
"type": "string"
},
"topology": {
"type": "string",
"enum": ["single-package", "monorepo", "polyglot-monorepo"]
},
"ciProvider": {
"type": "string",
"enum": ["github-actions", "gitlab-ci", "circleci", "jenkins", "none", "unknown"]
},
"agentFiles": {
"manual": {
"type": "object",
"description": "Human-authored content preserved across regenerations.",
"properties": {
"agentsMd": { "type": "string" },
"workspaceJson": { "type": "string" }
},
"additionalProperties": false
},
"frameworks": {
"type": "array",
"items": { "type": "string" }
},
"conventions": {
"type": "array",
"items": {
"type": "object",
"required": ["raw", "type", "canonical"],
"properties": {
"raw": { "type": "string" },
"type": {
"type": "string",
"enum": ["filename-case", "directory-layout", "naming", "structural", "other"]
},
"canonical": { "type": "string" }
},
"additionalProperties": false
}
},
"packages": {
"type": "array",
"items": {
"type": "object",
"required": ["path"],
"properties": {
"name": { "type": "string" },
"path": { "type": "string" },
"agentsMd": { "type": "string" },
"dependencies": {
"type": "array",
"items": { "type": "string" }
"fragileFiles": {
"type": "array",
"description": "Human-annotated fragile files. Read by gsd-plugin v2.42.3.",
"items": {
"type": "object",
"properties": {
"path": { "type": "string" },
"reason": { "type": "string" }
}
}
},
"additionalProperties": true
}
},
"gitSummary": {
"type": "object",
"properties": {
"nonAgentsCommitCount30Days": { "type": "integer", "minimum": 0 },
"filesChangedLast30Days": {
"coChangePatterns": {
"type": "array",
"items": { "type": "string" }
"description": "Human-annotated co-change observations. Read by gsd-plugin v2.42.3.",
"items": { "type": "object" }
}
},
"additionalProperties": false
"additionalProperties": true
},
"hygiene": {
"generated": {
"type": "object",
"required": ["specVersion", "generatedAt", "by"],
"properties": {
"score": { "type": "number", "minimum": 0, "maximum": 100 },
"grade": { "type": "string", "enum": ["A", "B", "C", "D", "F"] },
"failCount": { "type": "integer", "minimum": 0 },
"warnCount": { "type": "integer", "minimum": 0 },
"scannedAt": { "type": "string", "format": "date-time" }
"specVersion": { "const": "0.3" },
"generatedAt": { "type": "string", "format": "date-time" },
"by": {
"type": "object",
"required": ["name", "version"],
"properties": {
"name": { "type": "string" },
"version": { "type": "string" }
}
},
"frameworkManifest": {
"type": "array",
"description": "Detected frameworks (confidence >= 0.7). Read by gsd-plugin v2.42.3.",
"items": {
"type": "object",
"properties": {
"name": { "type": "string" },
"version": { "type": "string" },
"confidence": { "type": "number", "minimum": 0, "maximum": 1 }
}
}
},
"fileIndex": {
"type": "object",
"description": "Per-file behavioral intelligence keyed by relative path. Read by gsd-plugin v2.42.3.",
"additionalProperties": {
"type": "object",
"properties": {
"fragility": { "type": "number", "minimum": 0, "maximum": 1 },
"aiModificationCount": { "type": "integer", "minimum": 0 },
"humanModificationCount": { "type": "integer", "minimum": 0 }
}
}
},
"topology": { "type": "object" },
"conventions": { "type": "array" },
"gitSummary": { "type": "object" },
"hygiene": { "type": "object" },
"warnings": { "type": "array", "items": { "type": "string" } }
},
"additionalProperties": false
"additionalProperties": true
},
"agents": {
"type": "object",
"description": "Cross-tool agent configuration surface."
},
"metadata": {
"health": {
"type": "object",
"description": "Summary metrics and intelligence state. Per-file detail belongs under generated.fileIndex.",
"properties": {
"intelligenceState": {
"type": "string",
"enum": ["INSUFFICIENT_DATA", "OBSERVING", "CONFIDENT"]
},
"observationCount": { "type": "integer", "minimum": 0 },
"confidence": { "type": "number", "minimum": 0, "maximum": 1 },
"boundRate": { "type": "number" },
"averageFragility": { "type": "number" },
"fragileFileCount": { "type": "integer", "minimum": 0 },
"aiAttributionRate": { "type": "number" },
"rollbackRate": { "type": "number" },
"trend": { "type": "string" },
"lastUpdated": { "type": "string", "format": "date-time" }
},
"additionalProperties": true
}
},
"additionalProperties": true
}
}
Loading
Loading