Skip to content
This repository was archived by the owner on May 15, 2026. It is now read-only.

Commit 379a61e

Browse files
committed
chore: add specs and generator script for active_intents.yaml
1 parent dedb07e commit 379a61e

11 files changed

Lines changed: 320 additions & 3 deletions

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ node_modules
66
package-lock.json
77
coverage/
88
mock/
9-
9+
TRP1 Challenge Week 1_ Architecting the AI-Native IDE & Intent-Code Traceability.docx
1010
.DS_Store
1111

1212
# IDEs

package.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
"knip": "knip --include files",
2727
"evals": "dotenvx run -f packages/evals/.env.development packages/evals/.env.local -- docker compose -f packages/evals/docker-compose.yml --profile server --profile runner up --build --scale runner=0",
2828
"npm:publish:types": "pnpm --filter @roo-code/types npm:publish"
29+
,
30+
"spec:generate": "node scripts/generate-specs.mjs"
2931
},
3032
"devDependencies": {
3133
"@changesets/cli": "^2.27.10",
@@ -70,5 +72,8 @@
7072
"@types/react-dom": "^18.3.5",
7173
"zod": "3.25.76"
7274
}
75+
},
76+
"dependencies": {
77+
"yaml": "^2.8.0"
7378
}
7479
}

pnpm-lock.yaml

Lines changed: 7 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

scripts/generate-specs.mjs

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
import fs from "node:fs/promises"
2+
import path from "node:path"
3+
import crypto from "node:crypto"
4+
import * as yaml from "yaml"
5+
6+
function sha256(text) {
7+
return crypto.createHash("sha256").update(text).digest("hex")
8+
}
9+
10+
function parseSpecMarkdown(md) {
11+
// Extremely small “SpecKit-like” parser: extracts the 4 sections we need.
12+
// Sections are identified by headings:
13+
// - "## Intent"
14+
// - "## Scope (owned_scope)"
15+
// - "## Constraints"
16+
// - "## Acceptance Criteria"
17+
const getSection = (title) => {
18+
const re = new RegExp(`^##\\s+${title}\\s*$`, "m")
19+
const m = md.match(re)
20+
if (!m) return ""
21+
const start = m.index + m[0].length
22+
const rest = md.slice(start)
23+
const next = rest.search(/^##\s+/m)
24+
return (next === -1 ? rest : rest.slice(0, next)).trim()
25+
}
26+
27+
const intent = getSection("Intent").trim()
28+
const scope = getSection("Scope \\(owned_scope\\)")
29+
.split("\n")
30+
.map((l) => l.trim())
31+
.filter((l) => l.startsWith("- "))
32+
.map((l) => l.slice(2).trim().replace(/^`|`$/g, ""))
33+
34+
const constraints = getSection("Constraints")
35+
.split("\n")
36+
.map((l) => l.trim())
37+
.filter((l) => l.startsWith("- "))
38+
.map((l) => l.slice(2).trim())
39+
40+
const acceptance = getSection("Acceptance Criteria")
41+
.split("\n")
42+
.map((l) => l.trim())
43+
.filter((l) => l.startsWith("- "))
44+
.map((l) => l.slice(2).trim())
45+
46+
return { intent, scope, constraints, acceptance }
47+
}
48+
49+
async function main() {
50+
const repoRoot = process.cwd()
51+
const specsDir = path.join(repoRoot, "specs")
52+
const orchestrationDir = path.join(repoRoot, ".orchestration")
53+
54+
await fs.mkdir(specsDir, { recursive: true })
55+
await fs.mkdir(orchestrationDir, { recursive: true })
56+
57+
const specFiles = (await fs.readdir(specsDir)).filter((f) => f.endsWith(".md"))
58+
if (specFiles.length === 0) {
59+
console.log("No spec files found in ./specs. Add at least one *.md spec and rerun.")
60+
process.exit(1)
61+
}
62+
63+
const activeIntentsPath = path.join(orchestrationDir, "active_intents.yaml")
64+
const existingYaml = await fs.readFile(activeIntentsPath, "utf-8").catch(() => "active_intents: []\n")
65+
const existing = (yaml.parse(existingYaml) ?? {}) || {}
66+
const active_intents = Array.isArray(existing.active_intents) ? existing.active_intents : []
67+
68+
for (const file of specFiles) {
69+
const full = path.join(specsDir, file)
70+
const md = await fs.readFile(full, "utf-8")
71+
72+
const idMatch = file.match(/^(INT-\d+)/i)
73+
const id = idMatch ? idMatch[1].toUpperCase() : `INT-${sha256(file).slice(0, 3).toUpperCase()}`
74+
const name = md.split("\n").find((l) => l.startsWith("# "))?.replace(/^#\s+/, "").trim() || file
75+
76+
const parsed = parseSpecMarkdown(md)
77+
78+
const intentEntry = {
79+
id,
80+
name,
81+
status: "IN_PROGRESS",
82+
owned_scope: parsed.scope,
83+
constraints: parsed.constraints,
84+
acceptance_criteria: parsed.acceptance,
85+
created_at: new Date().toISOString(),
86+
updated_at: new Date().toISOString(),
87+
spec_hash: `sha256:${sha256(md)}`,
88+
spec_file: `specs/${file}`,
89+
}
90+
91+
const i = active_intents.findIndex((x) => x?.id === id)
92+
if (i >= 0) active_intents[i] = intentEntry
93+
else active_intents.push(intentEntry)
94+
}
95+
96+
await fs.writeFile(activeIntentsPath, yaml.stringify({ active_intents }), "utf-8")
97+
console.log(`Updated .orchestration/active_intents.yaml with ${active_intents.length} intent(s).`)
98+
}
99+
100+
main().catch((err) => {
101+
console.error(err)
102+
process.exit(1)
103+
})
104+
105+
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# INT-001 — Intent-Code Traceability (Spec)
2+
3+
## Intent
4+
Build an Intent-Code Traceability system for Roo Code that enforces a two-stage reasoning loop and produces durable, auditable traces linking intents to code changes.
5+
6+
## Scope (owned_scope)
7+
- `src/core/assistant-message/**`
8+
- `src/core/tools/**`
9+
- `src/core/hooks/**`
10+
- `src/core/orchestration/**`
11+
- `src/core/prompts/**`
12+
- `.orchestration/**`
13+
14+
## Constraints
15+
- Must enforce **intent selection before any destructive tool** (`write_to_file`, `edit_file`, `apply_diff`, etc.).
16+
- Must keep **privilege separation**: UI emits events; extension host executes privileged actions; hooks are middleware.
17+
- Must log **spatially independent** traces via content hashing.
18+
19+
## Acceptance Criteria
20+
- Agent cannot write code before calling `select_active_intent(intent_id)`.
21+
- When a file is written, a JSONL entry is appended to `.orchestration/agent_trace.jsonl` that includes:
22+
- intent id
23+
- file path
24+
- line range (best-effort)
25+
- `sha256:` content hash of the modified block
26+
- `.orchestration/active_intents.yaml` exists and contains this intent.
27+
28+
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# INT-002 — Hook System Implementation
2+
3+
## Intent
4+
Implement a hook system that intercepts tool execution in Roo Code to enforce intent selection and validate AI-generated code before execution.
5+
6+
## Scope (owned_scope)
7+
- `src/core/hooks/**`
8+
- `src/core/assistant-message/presentAssistantMessage.ts`
9+
- `src/core/tools/**`
10+
- `.orchestration/**`
11+
12+
## Constraints
13+
- Must integrate with existing `presentAssistantMessage()` function without breaking current tool execution flow.
14+
- Pre-hooks must run **before** `tool.handle()` is called.
15+
- Post-hooks must run **after** `tool.execute()` completes but before result is returned.
16+
- Hook system must be non-blocking for non-destructive tools (read-only operations).
17+
- Must maintain backward compatibility with existing tools.
18+
19+
## Acceptance Criteria
20+
- `HookEngine` class exists in `src/core/hooks/HookEngine.ts`.
21+
- Pre-hook validates intent selection for destructive tools (`write_to_file`, `edit_file`, `execute_command`, etc.).
22+
- Pre-hook enforces scope validation (file path must be within intent's `owned_scope`).
23+
- Post-hook logs trace entries to `.orchestration/agent_trace.jsonl` for mutating actions.
24+
- `presentAssistantMessage()` integrates `HookEngine` with Pre-Hook and Post-Hook calls.
25+
- All existing tests pass after hook integration.
26+

specs/INT-003-reasoning-loop.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# INT-003 — Two-Stage Reasoning Loop
2+
3+
## Intent
4+
Implement a two-stage state machine that enforces intent selection before code generation and validates AI output against intent constraints.
5+
6+
## Scope (owned_scope)
7+
- `src/core/hooks/HookEngine.ts`
8+
- `src/core/prompts/sections/tool-use-guidelines.ts`
9+
- `src/core/tools/SelectActiveIntentTool.ts`
10+
- `src/core/task/Task.ts`
11+
12+
## Constraints
13+
- **Stage 1 (Reasoning Intercept):** Agent MUST call `select_active_intent(intent_id)` before any destructive tool.
14+
- **Stage 2 (Contextualized Action):** Agent receives intent context and must include it when making code changes.
15+
- System prompt must enforce this protocol in tool-use guidelines.
16+
- Intent context must be injected into the agent's context before code generation.
17+
18+
## Acceptance Criteria
19+
- System prompt includes instructions requiring `select_active_intent` before code changes.
20+
- `SelectActiveIntentTool` returns XML `<intent_context>` block with scope, constraints, and acceptance criteria.
21+
- Pre-hook blocks destructive tools if no active intent is selected.
22+
- Agent receives intent context in subsequent tool calls.
23+
- Intent context is logged in `agent_trace.jsonl` entries.
24+
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# INT-004 — Orchestration Directory Management
2+
3+
## Intent
4+
Implement a robust data model for managing `.orchestration/` directory files with proper initialization, validation, and atomic updates.
5+
6+
## Scope (owned_scope)
7+
- `src/core/orchestration/OrchestrationDataModel.ts`
8+
- `.orchestration/active_intents.yaml`
9+
- `.orchestration/agent_trace.jsonl`
10+
- `.orchestration/intent_map.md`
11+
- `.orchestration/AGENT.md`
12+
13+
## Constraints
14+
- `.orchestration/` directory must be machine-managed (not user-edited directly).
15+
- `active_intents.yaml` must be valid YAML and follow the schema defined in `document.md`.
16+
- `agent_trace.jsonl` must be append-only (no modifications, only appends).
17+
- All file operations must be atomic (write to temp file, then rename).
18+
- Directory and files must be initialized on first use.
19+
20+
## Acceptance Criteria
21+
- `OrchestrationDataModel` class provides methods:
22+
- `initialize()`: Creates directory and initializes files if missing.
23+
- `readActiveIntents()`: Parses and returns active intents.
24+
- `appendAgentTrace()`: Appends trace entry to JSONL file.
25+
- `updateIntentMap()`: Updates intent-to-file mapping.
26+
- `appendAgentKnowledge()`: Appends to AGENT.md.
27+
- All methods handle errors gracefully and log failures.
28+
- Files are created with proper templates if missing.
29+
- YAML parsing validates schema and reports errors clearly.
30+
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# INT-005 — Logging & Traceability
2+
3+
## Intent
4+
Implement comprehensive trace logging that links intents to code changes via content hashing, enabling spatial independence and auditability.
5+
6+
## Scope (owned_scope)
7+
- `src/core/hooks/HookEngine.ts` (Post-Hook implementation)
8+
- `src/core/orchestration/OrchestrationDataModel.ts`
9+
- `.orchestration/agent_trace.jsonl`
10+
- `src/utils/git.ts` (for VCS revision tracking)
11+
12+
## Constraints
13+
- Trace entries must include `sha256:` content hash of modified code blocks.
14+
- Line ranges must be best-effort (may be approximate for complex edits).
15+
- Each trace entry must link to:
16+
- Intent ID
17+
- File path (relative to workspace root)
18+
- VCS revision (Git SHA)
19+
- Timestamp
20+
- Model identifier
21+
- Content hashing must be spatially independent (same code block = same hash regardless of file location).
22+
23+
## Acceptance Criteria
24+
- Post-hook computes SHA-256 hash of modified content for file tools.
25+
- Trace entry includes all required fields per `document.md` schema:
26+
- `id` (UUID)
27+
- `timestamp` (ISO 8601)
28+
- `vcs.revision_id` (Git SHA)
29+
- `files[]` with `relative_path`, `conversations[]`, `ranges[]`, `content_hash`
30+
- Trace entries are appended atomically to `agent_trace.jsonl`.
31+
- Content hash format: `sha256:<hex>`.
32+
- Git SHA is retrieved from workspace root (handles non-Git repos gracefully).
33+
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# INT-006 — Testing & Validation
2+
3+
## Intent
4+
Create comprehensive test coverage for the Intent-Code Traceability system, including unit tests, integration tests, and end-to-end validation scenarios.
5+
6+
## Scope (owned_scope)
7+
- `src/core/hooks/**/*.test.ts`
8+
- `src/core/orchestration/**/*.test.ts`
9+
- `src/core/tools/SelectActiveIntentTool.test.ts`
10+
- `tests/integration/hook-system.test.ts`
11+
- `tests/e2e/intent-traceability.test.ts`
12+
13+
## Constraints
14+
- Tests must not modify production `.orchestration/` files (use temp directories).
15+
- Tests must be deterministic and isolated (no shared state).
16+
- Integration tests must verify hook system works with real tool execution.
17+
- E2E tests must simulate full agent workflow (intent selection → code change → trace logging).
18+
19+
## Acceptance Criteria
20+
- Unit tests for `HookEngine.preHook()` and `HookEngine.postHook()`.
21+
- Unit tests for `OrchestrationDataModel` file operations.
22+
- Unit tests for `SelectActiveIntentTool` intent loading and context generation.
23+
- Integration test: Verify Pre-Hook blocks destructive tool without intent.
24+
- Integration test: Verify Post-Hook logs trace entry after file write.
25+
- E2E test: Full workflow from intent selection to trace logging.
26+
- All tests pass in CI/CD pipeline.
27+
- Test coverage > 80% for hook and orchestration modules.
28+

0 commit comments

Comments
 (0)