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
111 changes: 111 additions & 0 deletions .ai/bin/validate-ai-sdlc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
#!/usr/bin/env python3
from __future__ import annotations

import json
import sys
from pathlib import Path

ROOT = Path(__file__).resolve().parents[2]
REQUIRED = [
".ai/matrix.json",
".ai/init/repo-profile.json",
".ai/init/sdlc-path.md",
".ai/workflows/repo-workflow.md",
".ai/workflows/repo-workflow.json",
".ai/handoff/init-ai-repo-handoff.md",
".ai/traceability/graph.json",
".ai/traceability/index.md",
".ai/traceability/validation-report.md",
".ai/evals/coverage-exceptions.json",
".ai/evals/example-output-eval/evalset.json",
".ai/evals/example-output-eval/rubric.md",
".ai/evals/example-output-eval/judge-config.json",
".ai/policies/model-routing.json",
".ai/observability/conventions.md",
".ai/observability/audit-checklist.md",
".ai/mcp/registry.json",
".ai/mcp/a2a-handoff.md",
".ai/reviews/ai-failure-modes.md",
".memory/human-override/custom-conventions.md",
".memory/human-override/tribal-knowledge.md",
".memory/self-learned/error-patterns.json",
".memory/self-learned/module-complexity.json",
"docs/architecture/adr/0001-init-ai-sdlc-v3.md",
"docs/specifications/ACTIVE/init-ai-sdlc-v3.md",
"RULES.md",
"PLANS.md",
"AGENTS.md",
"README.md",
"CLAUDE.md",
"GEMINI.md",
"CONTRIBUTING.md",
]


def fail(message: str) -> None:
print(f"FAIL: {message}", file=sys.stderr)
raise SystemExit(1)


for rel in REQUIRED:
if not (ROOT / rel).exists():
fail(f"missing {rel}")

for rel in ROOT.glob(".ai/**/*.json"):
json.loads(rel.read_text())
for rel in ROOT.glob(".memory/self-learned/*.json"):
data = json.loads(rel.read_text())
if "schema_version" not in data:
fail(f"missing schema_version in {rel}")

matrix = json.loads((ROOT / ".ai/matrix.json").read_text())
if matrix.get("sync_strategy") != "physical-copy":
fail("matrix sync_strategy must be physical-copy")
if matrix.get("topology_type") == "standalone":
if matrix.get("max_allowed_depth") != 0 or matrix.get("current_depth") != 0:
fail("standalone depth must be zero")
elif matrix.get("topology_type") == "umbrella":
if matrix.get("max_allowed_depth") != 3:
fail("umbrella max_allowed_depth must be 3")
if matrix.get("current_depth", 99) > matrix["max_allowed_depth"]:
fail("umbrella current_depth exceeds max")
for repo in matrix.get("managed_repositories", []):
if repo.get("depth", 99) > matrix["max_allowed_depth"]:
fail(f"managed repo exceeds depth: {repo}")
else:
fail("invalid topology_type")

workflow = json.loads((ROOT / ".ai/workflows/repo-workflow.json").read_text())
for phase in workflow["phases"]:
if not (ROOT / phase["status_path"]).exists():
fail(f'missing phase status {phase["status_path"]}')

text_agents = (ROOT / "AGENTS.md").read_text()
text_readme = (ROOT / "README.md").read_text()
for link in [".ai/workflows/repo-workflow.md", ".ai/workflows/repo-workflow.json"]:
if link not in text_agents or link not in text_readme:
fail(f"missing workflow link {link} in AGENTS.md or README.md")

graph = json.loads((ROOT / ".ai/traceability/graph.json").read_text())
ids = {n["id"] for n in graph["nodes"]}
for edge in graph["edges"]:
if edge["source"] not in ids or edge["target"] not in ids:
fail(f"dangling graph edge {edge}")
for node in graph["nodes"]:
for backlink in node.get("backlinks", []):
if backlink not in ids:
fail(f"dangling backlink {backlink}")

registry = json.loads((ROOT / ".ai/mcp/registry.json").read_text())
if not registry.get("servers") or "a2a" not in registry:
fail("invalid mcp registry")
for server in registry["servers"]:
if server.get("status") != "stub":
fail("mcp server status must be stub")

review = (ROOT / ".ai/reviews/ai-failure-modes.md").read_text().lower()
for word in ["hallucinated", "slopsquatting", "error handling", "looks-right"]:
if word not in review:
fail(f"missing review keyword {word}")

print("AI-SDLC validation passed")
15 changes: 10 additions & 5 deletions .ai/drift/last-drift.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
{
"schema_version": "1.0",
"last_checked_at": "2026-06-07T21:00:00Z",
"result": "no-drift",
"checked_paths": [],
"actions": []
"checked_paths": [
".ai",
".memory",
"docs",
"AGENTS.md",
"README.md"
],
"drift_detected": false,
"generated_at": "2026-06-28T12:54:35Z",
"schema_version": "1.0"
}
12 changes: 12 additions & 0 deletions .ai/drift/migration-manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"actions": [
{
"action": "copy",
"backup_path": null,
"confirmation_token": null,
"path": ".ai/matrix.json"
}
],
"generated_at": "2026-06-28T12:54:35Z",
"schema_version": "1.0"
}
4 changes: 4 additions & 0 deletions .ai/evals/coverage-exceptions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"exceptions": [],
"schema_version": "1.0"
}
11 changes: 11 additions & 0 deletions .ai/evals/example-output-eval/evalset.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"cases": [
{
"expected": "workflow and traceability surfaces are linked",
"id": "governance-links",
"input": "Check AI-SDLC links"
}
],
"schema_version": "1.0",
"set_id": "example-output-eval"
}
7 changes: 7 additions & 0 deletions .ai/evals/example-output-eval/judge-config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"judge": {
"ci_runs_model": false,
"mode": "out-of-band"
},
"schema_version": "1.0"
}
29 changes: 29 additions & 0 deletions .ai/evals/example-output-eval/judgment-demo.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"aggregate_score": 1.0,
"criteria": [
{
"name": "Structure",
"rationale": "Required scaffold files are present.",
"score": 1.0
},
{
"name": "Safety",
"rationale": "Hosted policy mutations are checklist-only.",
"score": 1.0
},
{
"name": "Traceability",
"rationale": "Graph edges resolve.",
"score": 1.0
}
],
"disclaimer": "recorded out-of-band demonstration, not a CI gate",
"evalset_path": ".ai/evals/example-output-eval/evalset.json",
"judge_model": "recorded-example",
"passing_threshold": 0.8,
"recorded_at": "2026-06-28T12:54:35Z",
"rubric_path": ".ai/evals/example-output-eval/rubric.md",
"schema_version": "1.0",
"skill_under_test": "init-ai-repo",
"verdict": "pass"
}
5 changes: 5 additions & 0 deletions .ai/evals/example-output-eval/rubric.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Example output eval rubric

- Structure: required files and links exist.
- Safety: hosted policy changes remain confirmation-gated.
- Traceability: graph edges and backlinks resolve.
16 changes: 16 additions & 0 deletions .ai/handoff/init-ai-repo-handoff.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# init-ai-repo handoff

## Done

- Generated AI-SDLC v3 topology, workflow, traceability, eval, observability, MCP/A2A, and review surfaces.
- Added local structural validation under `.ai/bin/validate-ai-sdlc.py`.
- Recorded branch policy as checklist-only. No hosted policy mutation was applied.

## Verified

Run `python3 .ai/bin/validate-ai-sdlc.py` from this repository.

## Remaining operator work

- Enable or adjust hosted branch protection only after explicit admin confirmation.
- Re-run validation after future governance changes.
15 changes: 15 additions & 0 deletions .ai/init/repo-profile.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"application_boundary": null,
"default_branch": "main",
"generated_at": "2026-06-28T12:54:35Z",
"language_pack": "python",
"name": "kontor-cli email automation",
"remote": "git@github.com:r3dlex/cli-kontor.git",
"repo_id": "kontor-cli",
"schema_version": "1.0",
"topology_type": "standalone",
"tracker": {
"hosted_policy_mutation": "checklist-only",
"type": "github"
}
}
9 changes: 9 additions & 0 deletions .ai/init/sdlc-path.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# AI SDLC path

Repository `kontor-cli` uses the brownfield v3 AI-SDLC adoption path.

- Topology: `standalone`.
- Sync strategy: physical-copy.
- Host posture: GitHub PR-only delivery with branch policy documented as checklist-only.
- Hosted branch and policy mutation: blocked unless an operator gives explicit confirmation.
- Application boundary: `application/` is excluded from umbrella initialization and follows `application/AGENTS.md`.
42 changes: 27 additions & 15 deletions .ai/matrix.json
Original file line number Diff line number Diff line change
@@ -1,22 +1,34 @@
{
"schema_version": "1.0",
"topology_type": "standalone",
"max_allowed_depth": 0,
"current_depth": 0,
"sync_strategy": "physical-copy",
"upstream_authority": {
"type": "git",
"url": "git@github.com:r3dlex/cli-kontor.git",
"ref": "main"
},
"managed_repositories": [],
"inherited_assets": [],
"inherited_assets": [
{
"mode": "physical-copy",
"path": "AGENTS.md",
"source": "."
},
{
"mode": "physical-copy",
"path": ".ai/matrix.json",
"source": "."
},
{
"mode": "physical-copy",
"path": ".ai/workflows/repo-workflow.md",
"source": "."
}
],
"max_allowed_depth": 0,
"schema_version": "1.0",
"sync_status": {
"last_synced_at": "2026-06-07T21:00:00Z",
"drift_detected": false,
"last_drift_report": ".ai/drift/last-drift.json"
"last_drift_report": ".ai/drift/last-drift.json",
"last_synced_at": "2026-06-28T12:54:35Z"
},
"memory": {
"external_integration": false
"sync_strategy": "physical-copy",
"topology_type": "standalone",
"upstream_authority": {
"ref": "main",
"type": "git",
"url": "git@github.com:r3dlex/cli-kontor.git"
}
}
5 changes: 5 additions & 0 deletions .ai/mcp/a2a-handoff.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# A2A handoff convention

Every handoff envelope includes `correlation_id`, `from_agent`, `to_agent`, `task`, `context_refs`, and `constraints`.

The handoff-envelope stores pointers, not secrets or large copied context. Receivers preserve `correlation_id` in their validation evidence.
22 changes: 22 additions & 0 deletions .ai/mcp/registry.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"a2a": {
"correlation_id_required": true,
"cross_repo": false,
"handoff_convention": ".ai/mcp/a2a-handoff.md",
"protocol": "A2A"
},
"schema_version": "1.0",
"servers": [
{
"endpoint": null,
"name": "workspace-sync",
"status": "stub",
"tools": [
"validate",
"sync",
"drift-report"
],
"transport": "stdio"
}
]
}
5 changes: 5 additions & 0 deletions .ai/observability/audit-checklist.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Observability audit checklist

- [ ] Token-cost evidence was reviewed for behavior-changing agent work.
- [ ] Trajectory-audit evidence was reviewed for delegated or AI-authored changes.
- [ ] Validation links are present in the PR or handoff.
5 changes: 5 additions & 0 deletions .ai/observability/conventions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Observability conventions

- Record correlation IDs for agent runs, delegated tasks, PRs, and validation reports.
- Keep token-cost and trajectory-audit evidence out of CI model calls.
- Link validation evidence from PR descriptions and handoff records.
16 changes: 16 additions & 0 deletions .ai/phases/01-discover-decide/status.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"completed_at": "2026-06-28T12:54:35Z",
"inputs": [
"init-ai-repo skill v3 modules",
".ai/matrix.json"
],
"next_actions": [],
"outputs": [
".ai/workflows/repo-workflow.md",
".ai/validation/report.md"
],
"phase_id": "01-discover-decide",
"required": true,
"status": "complete",
"title": "Discover and Decide"
}
16 changes: 16 additions & 0 deletions .ai/phases/02-govern-plan/status.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"completed_at": "2026-06-28T12:54:35Z",
"inputs": [
"init-ai-repo skill v3 modules",
".ai/matrix.json"
],
"next_actions": [],
"outputs": [
".ai/workflows/repo-workflow.md",
".ai/validation/report.md"
],
"phase_id": "02-govern-plan",
"required": true,
"status": "complete",
"title": "Govern and Plan"
}
16 changes: 16 additions & 0 deletions .ai/phases/03-configure-generate/status.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"completed_at": "2026-06-28T12:54:35Z",
"inputs": [
"init-ai-repo skill v3 modules",
".ai/matrix.json"
],
"next_actions": [],
"outputs": [
".ai/workflows/repo-workflow.md",
".ai/validation/report.md"
],
"phase_id": "03-configure-generate",
"required": true,
"status": "complete",
"title": "Configure and Generate"
}
Loading
Loading