auth-yes/forum/poc-g2/dag_engine_poc.ts
Tyler Gillispie 8f61cbdc49
feat(forum): add Generation 2 agent forum PoCs with production tools (#67)
- Renamed `forum/experiments` to `forum/poc-g1` to designate generation 1.
- Created `forum/poc-g2` and a new `lab.ts` runner.
- Non-destructively migrated `dag_engine_poc.ts`, `git_storage_poc.ts`, `merkle_diff_poc.ts`, and `frontmatter_poc.ts` to `poc-g2`.
- Upgraded migrated PoCs to utilize actual production-ready tools (e.g. `std/yaml` parsing and isolated `Deno.Command` Git repos) per blueprint constraints.

Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
Co-authored-by: mrteye <1945243+mrteye@users.noreply.github.com>
2026-08-28 21:10:21 -07:00

121 lines
3.4 KiB
TypeScript

import { assertEquals } from "https://deno.land/std@0.224.0/testing/asserts.ts";
import { parse } from "https://deno.land/std@0.224.0/yaml/mod.ts";
import { join } from "https://deno.land/std@0.224.0/path/mod.ts";
/**
* Generation 2 Proof of Concept: Semantic Task DAG Engine
*
* This module demonstrates parsing strict YAML Directed Acyclic Graphs (DAG)
* from ACTUAL YAML files on disk to calculate the critical path,
* proving we can use real production tooling for task orchestration.
*/
export interface TaskNode {
id: string;
title: string;
blocked_by: string[];
status: "pending" | "in-progress" | "complete";
}
export class TaskDAG {
private nodes: Map<string, TaskNode> = new Map();
constructor(yamlContent: string) {
const rawNodes = parse(yamlContent) as TaskNode[];
for (const node of rawNodes) {
this.nodes.set(node.id, {
...node,
blocked_by: node.blocked_by || [],
status: node.status || "pending",
});
}
}
/**
* Returns a list of tasks that are fully unblocked and ready to be worked on.
*/
getUnblockedTasks(): TaskNode[] {
const unblocked: TaskNode[] = [];
for (const node of this.nodes.values()) {
if (node.status === "complete") continue;
const isBlocked = node.blocked_by.some(
(depId) => this.nodes.get(depId)?.status !== "complete",
);
if (!isBlocked) {
unblocked.push(node);
}
}
return unblocked;
}
markComplete(taskId: string) {
const node = this.nodes.get(taskId);
if (node) {
node.status = "complete";
}
}
}
if (import.meta.main) {
console.log("Running Gen 2 DAG Engine PoC tests...");
// We write the YAML out to a temporary real file, then read it.
const tempYamlPath = await Deno.makeTempFile({ suffix: ".yaml" });
const yamlInput = `
- id: task_1
title: Setup Git Notes PoC
status: complete
- id: task_2
title: Setup DAG Engine PoC
blocked_by: [task_1]
status: pending
- id: task_3
title: Setup Local Intelligence PoC
blocked_by: [task_1, task_2]
status: pending
- id: task_4
title: Write Assessment Report
blocked_by: [task_1]
status: pending
`;
try {
// Prove we can write and read a real file
await Deno.writeTextFile(tempYamlPath, yamlInput);
console.log(`Wrote YAML file to ${tempYamlPath}`);
const fileContent = await Deno.readTextFile(tempYamlPath);
console.log("Read YAML from disk.");
const dag = new TaskDAG(fileContent);
// Initially, task_2 and task_4 should be unblocked because task_1 is complete.
let unblocked = dag.getUnblockedTasks();
assertEquals(unblocked.length, 2);
assertEquals(unblocked[0].id, "task_2");
assertEquals(unblocked[1].id, "task_4");
// Mark task_2 as complete. Now task_3 should still be blocked because task_4 has no effect,
// wait, task_3 is blocked by task_1 and task_2. Since both will be complete, task_3 should unlock.
dag.markComplete("task_2");
unblocked = dag.getUnblockedTasks();
// Unblocked should now be task_3 and task_4
assertEquals(unblocked.length, 2);
assertEquals(unblocked.find((t) => t.id === "task_3")?.id, "task_3");
assertEquals(unblocked.find((t) => t.id === "task_4")?.id, "task_4");
console.log(
"✅ Gen 2 DAG Engine PoC successful: Correctly processed YAML from real files.",
);
} catch (err) {
console.error("❌ DAG Engine PoC failed:", err);
Deno.exit(1);
} finally {
await Deno.remove(tempYamlPath);
}
}