Reasoning loop implemntation or handshake done and teste as well

This commit is contained in:
Bethel Yohannes 2026-02-21 13:01:30 +03:00
parent 085f30872a
commit 5f225d946f
7 changed files with 90 additions and 8 deletions

View file

@ -1,3 +1,3 @@
{"id":"df1a0b04-1993-45f4-b3cb-c0b4fcb2dba2","timestamp":"2026-02-21T08:37:15.794Z","vcs":{"revision_id":"abc123"},"files":[{"relative_path":"src/api/weather.ts","conversations":[{"url":"session-1","contributor":{"entity_type":"AI","model_identifier":"test-model"},"ranges":[{"start_line":1,"end_line":2,"content_hash":"sha256:2e4ec5cf14cfeb55ef32cb663ffd2c4fe6ab22bb2d2fe77ee8e284fe62866cac"}],"related":[{"type":"specification","value":"INT-001"}]}]}]}
{"id":"7f9541c8-7fd4-4cef-ae44-c51f191b942a","timestamp":"2026-02-21T08:37:15.797Z","files":[{"relative_path":"src/api/forecast.ts","conversations":[{"contributor":{"entity_type":"AI","model_identifier":"unknown"},"ranges":[{"start_line":1,"end_line":1,"content_hash":"sha256:c47272be41ffa9d8a897b81b3f9f6d5e13fbb5d6dd4609a7b20c282950f11842"}],"related":[{"type":"specification","value":"INT-001"}]}]}]}
{"id":"da60914f-8e16-4c59-8c5d-2c673793287d","timestamp":"2026-02-21T08:37:15.803Z","vcs":{"revision_id":"rev-1"},"files":[{"relative_path":"src/api/demo.ts","conversations":[{"url":"log-1","contributor":{"entity_type":"AI","model_identifier":"model-1"},"ranges":[{"start_line":1,"end_line":1,"content_hash":"sha256:bd994c26b795571c7c1e0357cba348f1d0238b648b748b9ec7a4d0de264d212f"}],"related":[{"type":"specification","value":"INT-001"}]}]}]}
{"id":"02a7c124-4730-4e49-8783-08f861f640ba","timestamp":"2026-02-21T09:48:48.707Z","vcs":{"revision_id":"abc123"},"files":[{"relative_path":"src/api/weather.ts","conversations":[{"url":"session-1","contributor":{"entity_type":"AI","model_identifier":"test-model"},"ranges":[{"start_line":1,"end_line":2,"content_hash":"sha256:2e4ec5cf14cfeb55ef32cb663ffd2c4fe6ab22bb2d2fe77ee8e284fe62866cac"}],"related":[{"type":"specification","value":"INT-001"}]}]}]}
{"id":"e55e9867-663a-412e-b341-af61f85dbedd","timestamp":"2026-02-21T09:48:48.716Z","files":[{"relative_path":"src/api/forecast.ts","conversations":[{"contributor":{"entity_type":"AI","model_identifier":"unknown"},"ranges":[{"start_line":1,"end_line":1,"content_hash":"sha256:c47272be41ffa9d8a897b81b3f9f6d5e13fbb5d6dd4609a7b20c282950f11842"}],"related":[{"type":"specification","value":"INT-001"}]}]}]}
{"id":"3609a24b-418e-4e1a-a554-2e3cf9db1be9","timestamp":"2026-02-21T09:48:48.737Z","vcs":{"revision_id":"rev-1"},"files":[{"relative_path":"src/api/demo.ts","conversations":[{"url":"log-1","contributor":{"entity_type":"AI","model_identifier":"model-1"},"ranges":[{"start_line":1,"end_line":1,"content_hash":"sha256:bd994c26b795571c7c1e0357cba348f1d0238b648b748b9ec7a4d0de264d212f"}],"related":[{"type":"specification","value":"INT-001"}]}]}]}

47
scripts/test_phase1.js Normal file
View file

@ -0,0 +1,47 @@
const fs = require("fs")
const path = require("path")
// Load active intents
const intentsPath = path.join(__dirname, "..", ".orchestration", "active_intents.yaml")
const yaml = require("js-yaml")
const intents = yaml.load(fs.readFileSync(intentsPath, "utf8")).active_intents
// Simple PreHook simulation
function preHook(intentId, targetFile) {
const intent = intents.find((i) => i.id === intentId)
if (!intent) {
throw new Error("You must select a valid active Intent ID before writing code.")
}
const allowed = intent.owned_scope.some((scope) => targetFile.startsWith(scope.replace("**", "")))
if (!allowed) {
throw new Error(`Scope Violation: ${intentId} is not authorized to edit ${targetFile}`)
}
console.log(`PreHook Passed: ${targetFile} is within scope for ${intentId}`)
}
// Simulate AI writing a file
function writeFile(intentId, filePath, content) {
preHook(intentId, filePath)
fs.writeFileSync(filePath, content)
console.log(`File written successfully: ${filePath}`)
}
// === TEST CASES ===
try {
// Valid case
writeFile("INT-001", "src/api/weather.ts", "// Weather API code here")
// Invalid scope
writeFile("INT-001", "src/db/db.ts", "// DB code here")
} catch (err) {
console.error("Error:", err.message)
}
try {
// Invalid intent
writeFile("INT-999", "src/api/weather.ts", "// Should fail")
} catch (err) {
console.error("Error:", err.message)
}

1
src/api/weather.ts Normal file
View file

@ -0,0 +1 @@
// Weather API code here

View file

@ -10,6 +10,7 @@ import { isEmpty } from "../../utils/object"
import { McpHub } from "../../services/mcp/McpHub"
import { CodeIndexManager } from "../../services/code-index/manager"
import { SkillsManager } from "../../services/skills/SkillsManager"
import { INTENT_DRIVEN_PROMPT_SNIPPET } from "../../hooks/intent-prompt-snippet"
import type { SystemPromptSettings } from "./types"
import {
@ -84,6 +85,8 @@ async function generatePrompt(
const basePrompt = `${roleDefinition}
${INTENT_DRIVEN_PROMPT_SNIPPET}
${markdownFormattingSection()}
${getSharedToolUseSection()}${toolsCatalog}

View file

@ -1,4 +1,5 @@
import type OpenAI from "openai"
import { selectActiveIntentToolDefinition } from "../../../../hooks/select-active-intent-tool"
import accessMcpResource from "./access_mcp_resource"
import { apply_diff } from "./apply_diff"
import applyPatch from "./apply_patch"
@ -47,6 +48,7 @@ export function getNativeTools(options: NativeToolsOptions = {}): OpenAI.Chat.Ch
}
return [
selectActiveIntentToolDefinition,
accessMcpResource,
apply_diff,
applyPatch,

View file

@ -34,8 +34,9 @@ export async function loadIntentContext(cwd: string, intentId: string): Promise<
/**
* Build an XML block to inject as the tool result for select_active_intent.
* Optionally include related agent trace entries for consolidated context.
*/
export function buildIntentContextXml(context: IntentContext): string {
export function buildIntentContextXml(context: IntentContext, relatedTracePaths: string[] = []): string {
const constraintsXml =
context.constraints.length > 0
? context.constraints.map((c) => ` <constraint>${escapeXml(c)}</constraint>`).join("\n")
@ -48,6 +49,10 @@ export function buildIntentContextXml(context: IntentContext): string {
(context.acceptance_criteria?.length ?? 0) > 0
? context.acceptance_criteria!.map((a) => ` <criterion>${escapeXml(a)}</criterion>`).join("\n")
: " <criterion>None specified</criterion>"
const traceXml =
relatedTracePaths.length > 0
? relatedTracePaths.map((p) => ` <file>${escapeXml(p)}</file>`).join("\n")
: " <file>None yet</file>"
return `<intent_context>
<id>${escapeXml(context.id)}</id>
@ -62,9 +67,34 @@ ${scopeXml}
<acceptance_criteria>
${criteriaXml}
</acceptance_criteria>
<related_agent_trace>
${traceXml}
</related_agent_trace>
</intent_context>`
}
/**
* Load intent from active_intents.yaml, gather related agent_trace entries for that intent,
* and return a consolidated XML context block (for Pre-Hook injection).
*/
export async function buildConsolidatedIntentContextXml(cwd: string, intentId: string): Promise<string | null> {
const context = await loadIntentContext(cwd, intentId)
if (!context) return null
const traceLines = await readRecentTraceForIntent(cwd, intentId, 20)
const paths = new Set<string>()
for (const line of traceLines) {
try {
const entry = JSON.parse(line) as { files?: Array<{ relative_path?: string }> }
for (const f of entry.files ?? []) {
if (f.relative_path) paths.add(f.relative_path)
}
} catch {
// skip malformed lines
}
}
return buildIntentContextXml(context, [...paths])
}
function escapeXml(s: string): string {
return s
.replace(/&/g, "&amp;")

View file

@ -2,7 +2,7 @@ import path from "path"
import type { HookResult } from "./types"
import { DESTRUCTIVE_TOOLS } from "./types"
import { loadIntentContext, buildIntentContextXml } from "./context-loader"
import { loadIntentContext, buildConsolidatedIntentContextXml } from "./context-loader"
import { pathInScope } from "./scope"
/** Block paths that escape workspace (.. or absolute outside cwd). */
@ -41,15 +41,14 @@ export class PreHook {
if (!intentId) {
return { blocked: true, error: "You must provide a valid intent_id when calling select_active_intent." }
}
const context = await loadIntentContext(cwd, intentId)
if (!context) {
const xml = await buildConsolidatedIntentContextXml(cwd, intentId)
if (!xml) {
return {
blocked: true,
error: `You must cite a valid active Intent ID. Intent "${intentId}" was not found in .orchestration/active_intents.yaml.`,
}
}
setActiveIntentId(intentId)
const xml = buildIntentContextXml(context)
return { blocked: false, injectResult: xml }
}