Compare commits
No commits in common. "9cef5715d49e220103ca3bd81eff9f7684864d69" and "1463d6e9dc6057364e179e6e961938118b724ba2" have entirely different histories.
9cef5715d4
...
1463d6e9dc
77
deno.lock
generated
77
deno.lock
generated
@ -542,83 +542,6 @@
|
||||
"https://deno.land/std@0.224.0/internal/diff.ts": "6234a4b493ebe65dc67a18a0eb97ef683626a1166a1906232ce186ae9f65f4e6",
|
||||
"https://deno.land/std@0.224.0/internal/format.ts": "0a98ee226fd3d43450245b1844b47003419d34d210fa989900861c79820d21c2",
|
||||
"https://deno.land/std@0.224.0/internal/mod.ts": "534125398c8e7426183e12dc255bb635d94e06d0f93c60a297723abe69d3b22e",
|
||||
"https://deno.land/std@0.224.0/path/_common/assert_path.ts": "dbdd757a465b690b2cc72fc5fb7698c51507dec6bfafce4ca500c46b76ff7bd8",
|
||||
"https://deno.land/std@0.224.0/path/_common/basename.ts": "569744855bc8445f3a56087fd2aed56bdad39da971a8d92b138c9913aecc5fa2",
|
||||
"https://deno.land/std@0.224.0/path/_common/common.ts": "ef73c2860694775fe8ffcbcdd387f9f97c7a656febf0daa8c73b56f4d8a7bd4c",
|
||||
"https://deno.land/std@0.224.0/path/_common/constants.ts": "dc5f8057159f4b48cd304eb3027e42f1148cf4df1fb4240774d3492b5d12ac0c",
|
||||
"https://deno.land/std@0.224.0/path/_common/dirname.ts": "684df4aa71a04bbcc346c692c8485594fc8a90b9408dfbc26ff32cf3e0c98cc8",
|
||||
"https://deno.land/std@0.224.0/path/_common/format.ts": "92500e91ea5de21c97f5fe91e178bae62af524b72d5fcd246d6d60ae4bcada8b",
|
||||
"https://deno.land/std@0.224.0/path/_common/from_file_url.ts": "d672bdeebc11bf80e99bf266f886c70963107bdd31134c4e249eef51133ceccf",
|
||||
"https://deno.land/std@0.224.0/path/_common/glob_to_reg_exp.ts": "6cac16d5c2dc23af7d66348a7ce430e5de4e70b0eede074bdbcf4903f4374d8d",
|
||||
"https://deno.land/std@0.224.0/path/_common/normalize.ts": "684df4aa71a04bbcc346c692c8485594fc8a90b9408dfbc26ff32cf3e0c98cc8",
|
||||
"https://deno.land/std@0.224.0/path/_common/normalize_string.ts": "33edef773c2a8e242761f731adeb2bd6d683e9c69e4e3d0092985bede74f4ac3",
|
||||
"https://deno.land/std@0.224.0/path/_common/relative.ts": "faa2753d9b32320ed4ada0733261e3357c186e5705678d9dd08b97527deae607",
|
||||
"https://deno.land/std@0.224.0/path/_common/strip_trailing_separators.ts": "7024a93447efcdcfeaa9339a98fa63ef9d53de363f1fbe9858970f1bba02655a",
|
||||
"https://deno.land/std@0.224.0/path/_common/to_file_url.ts": "7f76adbc83ece1bba173e6e98a27c647712cab773d3f8cbe0398b74afc817883",
|
||||
"https://deno.land/std@0.224.0/path/_interface.ts": "8dfeb930ca4a772c458a8c7bbe1e33216fe91c253411338ad80c5b6fa93ddba0",
|
||||
"https://deno.land/std@0.224.0/path/_os.ts": "8fb9b90fb6b753bd8c77cfd8a33c2ff6c5f5bc185f50de8ca4ac6a05710b2c15",
|
||||
"https://deno.land/std@0.224.0/path/basename.ts": "7ee495c2d1ee516ffff48fb9a93267ba928b5a3486b550be73071bc14f8cc63e",
|
||||
"https://deno.land/std@0.224.0/path/common.ts": "03e52e22882402c986fe97ca3b5bb4263c2aa811c515ce84584b23bac4cc2643",
|
||||
"https://deno.land/std@0.224.0/path/constants.ts": "0c206169ca104938ede9da48ac952de288f23343304a1c3cb6ec7625e7325f36",
|
||||
"https://deno.land/std@0.224.0/path/dirname.ts": "85bd955bf31d62c9aafdd7ff561c4b5fb587d11a9a5a45e2b01aedffa4238a7c",
|
||||
"https://deno.land/std@0.224.0/path/extname.ts": "593303db8ae8c865cbd9ceec6e55d4b9ac5410c1e276bfd3131916591b954441",
|
||||
"https://deno.land/std@0.224.0/path/format.ts": "6ce1779b0980296cf2bc20d66436b12792102b831fd281ab9eb08fa8a3e6f6ac",
|
||||
"https://deno.land/std@0.224.0/path/from_file_url.ts": "911833ae4fd10a1c84f6271f36151ab785955849117dc48c6e43b929504ee069",
|
||||
"https://deno.land/std@0.224.0/path/glob_to_regexp.ts": "7f30f0a21439cadfdae1be1bf370880b415e676097fda584a63ce319053b5972",
|
||||
"https://deno.land/std@0.224.0/path/is_absolute.ts": "4791afc8bfd0c87f0526eaa616b0d16e7b3ab6a65b62942e50eac68de4ef67d7",
|
||||
"https://deno.land/std@0.224.0/path/is_glob.ts": "a65f6195d3058c3050ab905705891b412ff942a292bcbaa1a807a74439a14141",
|
||||
"https://deno.land/std@0.224.0/path/join.ts": "ae2ec5ca44c7e84a235fd532e4a0116bfb1f2368b394db1c4fb75e3c0f26a33a",
|
||||
"https://deno.land/std@0.224.0/path/join_globs.ts": "5b3bf248b93247194f94fa6947b612ab9d3abd571ca8386cf7789038545e54a0",
|
||||
"https://deno.land/std@0.224.0/path/mod.ts": "f6bd79cb08be0e604201bc9de41ac9248582699d1b2ee0ab6bc9190d472cf9cd",
|
||||
"https://deno.land/std@0.224.0/path/normalize.ts": "4155743ccceeed319b350c1e62e931600272fad8ad00c417b91df093867a8352",
|
||||
"https://deno.land/std@0.224.0/path/normalize_glob.ts": "cc89a77a7d3b1d01053b9dcd59462b75482b11e9068ae6c754b5cf5d794b374f",
|
||||
"https://deno.land/std@0.224.0/path/parse.ts": "77ad91dcb235a66c6f504df83087ce2a5471e67d79c402014f6e847389108d5a",
|
||||
"https://deno.land/std@0.224.0/path/posix/_util.ts": "1e3937da30f080bfc99fe45d7ed23c47dd8585c5e473b2d771380d3a6937cf9d",
|
||||
"https://deno.land/std@0.224.0/path/posix/basename.ts": "d2fa5fbbb1c5a3ab8b9326458a8d4ceac77580961b3739cd5bfd1d3541a3e5f0",
|
||||
"https://deno.land/std@0.224.0/path/posix/common.ts": "26f60ccc8b2cac3e1613000c23ac5a7d392715d479e5be413473a37903a2b5d4",
|
||||
"https://deno.land/std@0.224.0/path/posix/constants.ts": "93481efb98cdffa4c719c22a0182b994e5a6aed3047e1962f6c2c75b7592bef1",
|
||||
"https://deno.land/std@0.224.0/path/posix/dirname.ts": "76cd348ffe92345711409f88d4d8561d8645353ac215c8e9c80140069bf42f00",
|
||||
"https://deno.land/std@0.224.0/path/posix/extname.ts": "e398c1d9d1908d3756a7ed94199fcd169e79466dd88feffd2f47ce0abf9d61d2",
|
||||
"https://deno.land/std@0.224.0/path/posix/format.ts": "185e9ee2091a42dd39e2a3b8e4925370ee8407572cee1ae52838aed96310c5c1",
|
||||
"https://deno.land/std@0.224.0/path/posix/from_file_url.ts": "951aee3a2c46fd0ed488899d024c6352b59154c70552e90885ed0c2ab699bc40",
|
||||
"https://deno.land/std@0.224.0/path/posix/glob_to_regexp.ts": "76f012fcdb22c04b633f536c0b9644d100861bea36e9da56a94b9c589a742e8f",
|
||||
"https://deno.land/std@0.224.0/path/posix/is_absolute.ts": "cebe561ad0ae294f0ce0365a1879dcfca8abd872821519b4fcc8d8967f888ede",
|
||||
"https://deno.land/std@0.224.0/path/posix/is_glob.ts": "8a8b08c08bf731acf2c1232218f1f45a11131bc01de81e5f803450a5914434b9",
|
||||
"https://deno.land/std@0.224.0/path/posix/join.ts": "7fc2cb3716aa1b863e990baf30b101d768db479e70b7313b4866a088db016f63",
|
||||
"https://deno.land/std@0.224.0/path/posix/join_globs.ts": "a9475b44645feddceb484ee0498e456f4add112e181cb94042cdc6d47d1cdd25",
|
||||
"https://deno.land/std@0.224.0/path/posix/mod.ts": "2301fc1c54a28b349e20656f68a85f75befa0ee9b6cd75bfac3da5aca9c3f604",
|
||||
"https://deno.land/std@0.224.0/path/posix/normalize.ts": "baeb49816a8299f90a0237d214cef46f00ba3e95c0d2ceb74205a6a584b58a91",
|
||||
"https://deno.land/std@0.224.0/path/posix/normalize_glob.ts": "9c87a829b6c0f445d03b3ecadc14492e2864c3ebb966f4cea41e98326e4435c6",
|
||||
"https://deno.land/std@0.224.0/path/posix/parse.ts": "09dfad0cae530f93627202f28c1befa78ea6e751f92f478ca2cc3b56be2cbb6a",
|
||||
"https://deno.land/std@0.224.0/path/posix/relative.ts": "3907d6eda41f0ff723d336125a1ad4349112cd4d48f693859980314d5b9da31c",
|
||||
"https://deno.land/std@0.224.0/path/posix/resolve.ts": "08b699cfeee10cb6857ccab38fa4b2ec703b0ea33e8e69964f29d02a2d5257cf",
|
||||
"https://deno.land/std@0.224.0/path/posix/to_file_url.ts": "7aa752ba66a35049e0e4a4be5a0a31ac6b645257d2e031142abb1854de250aaf",
|
||||
"https://deno.land/std@0.224.0/path/posix/to_namespaced_path.ts": "28b216b3c76f892a4dca9734ff1cc0045d135532bfd9c435ae4858bfa5a2ebf0",
|
||||
"https://deno.land/std@0.224.0/path/relative.ts": "ab739d727180ed8727e34ed71d976912461d98e2b76de3d3de834c1066667add",
|
||||
"https://deno.land/std@0.224.0/path/resolve.ts": "a6f977bdb4272e79d8d0ed4333e3d71367cc3926acf15ac271f1d059c8494d8d",
|
||||
"https://deno.land/std@0.224.0/path/to_file_url.ts": "88f049b769bce411e2d2db5bd9e6fd9a185a5fbd6b9f5ad8f52bef517c4ece1b",
|
||||
"https://deno.land/std@0.224.0/path/to_namespaced_path.ts": "b706a4103b104cfadc09600a5f838c2ba94dbcdb642344557122dda444526e40",
|
||||
"https://deno.land/std@0.224.0/path/windows/_util.ts": "d5f47363e5293fced22c984550d5e70e98e266cc3f31769e1710511803d04808",
|
||||
"https://deno.land/std@0.224.0/path/windows/basename.ts": "6bbc57bac9df2cec43288c8c5334919418d784243a00bc10de67d392ab36d660",
|
||||
"https://deno.land/std@0.224.0/path/windows/common.ts": "26f60ccc8b2cac3e1613000c23ac5a7d392715d479e5be413473a37903a2b5d4",
|
||||
"https://deno.land/std@0.224.0/path/windows/constants.ts": "5afaac0a1f67b68b0a380a4ef391bf59feb55856aa8c60dfc01bd3b6abb813f5",
|
||||
"https://deno.land/std@0.224.0/path/windows/dirname.ts": "33e421be5a5558a1346a48e74c330b8e560be7424ed7684ea03c12c21b627bc9",
|
||||
"https://deno.land/std@0.224.0/path/windows/extname.ts": "165a61b00d781257fda1e9606a48c78b06815385e7d703232548dbfc95346bef",
|
||||
"https://deno.land/std@0.224.0/path/windows/format.ts": "bbb5ecf379305b472b1082cd2fdc010e44a0020030414974d6029be9ad52aeb6",
|
||||
"https://deno.land/std@0.224.0/path/windows/from_file_url.ts": "ced2d587b6dff18f963f269d745c4a599cf82b0c4007356bd957cb4cb52efc01",
|
||||
"https://deno.land/std@0.224.0/path/windows/glob_to_regexp.ts": "e45f1f89bf3fc36f94ab7b3b9d0026729829fabc486c77f414caebef3b7304f8",
|
||||
"https://deno.land/std@0.224.0/path/windows/is_absolute.ts": "4a8f6853f8598cf91a835f41abed42112cebab09478b072e4beb00ec81f8ca8a",
|
||||
"https://deno.land/std@0.224.0/path/windows/is_glob.ts": "8a8b08c08bf731acf2c1232218f1f45a11131bc01de81e5f803450a5914434b9",
|
||||
"https://deno.land/std@0.224.0/path/windows/join.ts": "8d03530ab89195185103b7da9dfc6327af13eabdcd44c7c63e42e27808f50ecf",
|
||||
"https://deno.land/std@0.224.0/path/windows/join_globs.ts": "a9475b44645feddceb484ee0498e456f4add112e181cb94042cdc6d47d1cdd25",
|
||||
"https://deno.land/std@0.224.0/path/windows/mod.ts": "2301fc1c54a28b349e20656f68a85f75befa0ee9b6cd75bfac3da5aca9c3f604",
|
||||
"https://deno.land/std@0.224.0/path/windows/normalize.ts": "78126170ab917f0ca355a9af9e65ad6bfa5be14d574c5fb09bb1920f52577780",
|
||||
"https://deno.land/std@0.224.0/path/windows/normalize_glob.ts": "9c87a829b6c0f445d03b3ecadc14492e2864c3ebb966f4cea41e98326e4435c6",
|
||||
"https://deno.land/std@0.224.0/path/windows/parse.ts": "08804327b0484d18ab4d6781742bf374976de662f8642e62a67e93346e759707",
|
||||
"https://deno.land/std@0.224.0/path/windows/relative.ts": "3e1abc7977ee6cc0db2730d1f9cb38be87b0ce4806759d271a70e4997fc638d7",
|
||||
"https://deno.land/std@0.224.0/path/windows/resolve.ts": "8dae1dadfed9d46ff46cc337c9525c0c7d959fb400a6308f34595c45bdca1972",
|
||||
"https://deno.land/std@0.224.0/path/windows/to_file_url.ts": "40e560ee4854fe5a3d4d12976cef2f4e8914125c81b11f1108e127934ced502e",
|
||||
"https://deno.land/std@0.224.0/path/windows/to_namespaced_path.ts": "4ffa4fb6fae321448d5fe810b3ca741d84df4d7897e61ee29be961a6aac89a4c",
|
||||
"https://deno.land/std@0.224.0/testing/asserts.ts": "d0cdbabadc49cc4247a50732ee0df1403fdcd0f95360294ad448ae8c240f3f5c",
|
||||
"https://deno.land/std@0.224.0/yaml/_dumper/dumper.ts": "08b595b40841a2e1c75303f5096392323b6baf8e9662430a91e3b36fbe175fe9",
|
||||
"https://deno.land/std@0.224.0/yaml/_dumper/dumper_state.ts": "9e29f700ea876ed230b43f11fa006fcb1a62eedc1e27d32baaeaf3210f19f1e7",
|
||||
|
||||
@ -1,74 +0,0 @@
|
||||
# Agent Forum v4 - Fundamental Data Structures Reference
|
||||
|
||||
This document serves as the comprehensive list and reference for all data structures, data sources, and embedded storage mechanisms outlined in the `agent-forum-v4` blueprint. The goal is to provide a unified overview of the machine-readable structures that agents will interact with, entirely eliminating the need for external cloud SaaS databases.
|
||||
|
||||
## 1. Storage Layers (Git-Native Storage)
|
||||
|
||||
### 1.1 Git Notes (`refs/notes/commits`)
|
||||
- **Purpose**: Attaches arbitrary metadata directly to Git commits without altering the commit hash or polluting the working directory.
|
||||
- **Content**: Primarily JSON payloads containing:
|
||||
- Agent "meta-thoughts" and reasoning.
|
||||
- Risk assessments (e.g., generated by the Adversary).
|
||||
- Telemetry summaries related to a specific commit.
|
||||
- **Example Fetch**: `git log --show-notes="forum/reasoning"`
|
||||
|
||||
### 1.2 Orphan Branches (Meta-State Branch)
|
||||
- **Purpose**: An isolated Git branch (e.g., `forum/meta-state`) that tracks ongoing project state separately from the main source code. It shares no commit history with the main branch.
|
||||
- **Content**:
|
||||
- CI/CD telemetry JSONs.
|
||||
- Requirements Traceability Matrices (RTM).
|
||||
- The Project Task DAG files.
|
||||
- Periodic serialized graphs (e.g., SQLite dumps or graph snapshots).
|
||||
|
||||
### 1.3 Embedded Vector Databases (`sqlite-vec`)
|
||||
- **Purpose**: Provides fuzzy, associative memory retrieval without a dedicated network vector database. Compresses large documents via Locality-Sensitive Hashing (LSH) and HNSW.
|
||||
- **Content**: Highly compressed, quantized embeddings of concepts (PRDs, ADRs, documentation).
|
||||
- **Structure**: Isolated SQLite files (e.g., `docs_graph.sqlite`, `telemetry_graph.sqlite`) to prevent cross-contamination of semantic data.
|
||||
|
||||
## 2. Process & Governance Structures
|
||||
|
||||
### 2.1 The Project DAG (YAML)
|
||||
- **Purpose**: Replaces traditional flat project management tools (like Jira or Markdown task lists). Dictates execution order mathematically.
|
||||
- **Content**: YAML files representing a Directed Acyclic Graph.
|
||||
- **Key Fields**:
|
||||
- `id`: A UUIDv7 acting as the unique identifier.
|
||||
- `blocked_by`: Array of UUIDs this task depends on.
|
||||
- `legacy_slug` (Optional): The visual human-readable string (e.g., `YYYY-MMDD.[sequence]...`).
|
||||
- `status`: e.g., `pending`, `in_progress`, `completed`.
|
||||
- `description`: The actual prompt/goal.
|
||||
|
||||
### 2.2 Bounded Model Checking (Transitions Matrix)
|
||||
- **Purpose**: Defines strict state machine rules for the agent pipeline to guarantee proper governance.
|
||||
- **Format**: `transitions.json`
|
||||
- **Content**: A JSON mapping that states which roles can execute under which conditions (e.g., `"Coder": { "requires": ["Gatekeeper_Approval"] }`).
|
||||
|
||||
### 2.3 The Constitution (`AGENTS.md`)
|
||||
- **Purpose**: The supreme machine-readable ruleset that all agents must ingest to understand the target application stack, constraints, and operational boundaries.
|
||||
|
||||
## 3. Code Intelligence Structures
|
||||
|
||||
### 3.1 SCIP Indexes (Semantic Code Intelligence Protocol)
|
||||
- **Purpose**: Replaces unreliable regex-based searching with a statically guaranteed mapping of code symbols.
|
||||
- **Content**: A lightweight database mapping definitions, references, and relationships across the codebase. Extracted typically via Tree-sitter.
|
||||
|
||||
### 3.2 Abstract Syntax Trees (ASTs) & Control Flow Graphs (CFGs)
|
||||
- **Purpose**: Structured representations of code syntax and execution paths.
|
||||
- **Content**: JSON/XML mapping of every possible path a variable can take, used by the Adversary agent to deterministically prove security flaws (e.g., unsanitized inputs reaching SQL statements).
|
||||
|
||||
### 3.3 Mutation Testing Scores
|
||||
- **Purpose**: Represents the "blast radius" and effectiveness of test suites.
|
||||
- **Content**: Structured outputs from tools like Stryker or Mutmut that indicate how many injected bugs were successfully caught by the test physics.
|
||||
|
||||
## 4. Semantic & Telemetry Structures
|
||||
|
||||
### 4.1 Ontologies (JSON-LD)
|
||||
- **Purpose**: Replaces legacy requirements management (like DOORS). Achieves deep traceability by linking code/tasks to business requirements.
|
||||
- **Content**: Linked Data JSON blocks embedded in documentation (`@type: "Requirement"`). These compile into a single mathematical `ontology.graph` file.
|
||||
|
||||
### 4.2 OpenTelemetry Traces (`.trace.json`)
|
||||
- **Purpose**: Captures millisecond-level execution latencies during testing.
|
||||
- **Content**: Standardized OTel trace JSON payloads ingested by the Adversary to find physical execution bottlenecks in the code.
|
||||
|
||||
### 4.3 Team Friction Telemetry
|
||||
- **Purpose**: Used by the Analyst agent to measure the efficiency of human-to-agent collaboration.
|
||||
- **Content**: JSON payloads stored in the meta-state branch recording metrics like Mean Time to Resolution (MTTR), PR comment-to-code ratios, and idle handoff durations.
|
||||
@ -28,8 +28,7 @@ To ensure this new protocol does not interfere with the primary intent of Auth-Y
|
||||
|
||||
You mentioned appreciating the file naming conventions (visual history), risk assessments, and meta-thoughts of the old system. The goal is to preserve the *value* of these features while upgrading their *format* to be machine-readable.
|
||||
|
||||
- **UUIDv7 & Legacy Identifiers:** To align with the strict blueprint, **UUIDv7** will be the primary and required identifier (Artifact-ID/Key) for all items in YAML DAGs. The old file naming convention (`YYYY-MMDD.[sequence]...[short-description]`) will be stored strictly as an optional `legacy_slug` metadata field inside the YAML structure. This preserves visual history and backwards compatibility for human readers while completely detaching it from filenames and the core machine-communication ID system, avoiding string-parsing errors or pollution of the core concept.
|
||||
- **Visual History:** To preserve the human visual experience, a simple Deno script (e.g., `deno task forum:view`) can parse the DAG and the optional `legacy_slug` metadata from the orphan branch history to output an interactive terminal UI or a generated HTML report showing the exact progression of work.
|
||||
- **Visual History & Filenames:** We can retain the descriptive nomenclature (`YYYY-MMDD.[sequence]...[short-description]`) but use it as the **UUID/Key** inside the YAML DAGs rather than just a filename. To preserve the human visual experience, we can write a simple Deno script (`deno task forum:view`) that parses the DAG and orphan branch history to output a beautiful, interactive terminal UI (via Cliffy) or a generated HTML report showing the exact progression of work.
|
||||
- **Risk Assessment & Meta-Thoughts:** In the old system, these were markdown headers. In the new system, an "Adversary" agent will generate these risk assessments as structured JSON. We will store this JSON in **Git Notes** attached to the relevant commits. This ensures the data is tightly coupled to the code changes, never gets lost in a stale markdown file, and can be queried instantly by other agents.
|
||||
- **Human-Readable Projections:** If we ever need a standard Markdown view, a "Translator" agent or script can compile the DAGs, Git Notes, and ASTs and generate a static `tasks-report.md` on demand.
|
||||
|
||||
|
||||
@ -1,78 +0,0 @@
|
||||
import { join, dirname, fromFileUrl } from "https://deno.land/std@0.224.0/path/mod.ts";
|
||||
import { blue, green, red, yellow, bold } from "https://deno.land/std@0.224.0/fmt/colors.ts";
|
||||
|
||||
// Define the experiments to run
|
||||
const EXPERIMENTS = [
|
||||
{ name: "Git Storage PoC", file: "git_storage_poc.ts", description: "Verifies ability to read/write Git Notes and manipulate orphan branches." },
|
||||
{ name: "DAG Engine PoC", file: "dag_engine_poc.ts", description: "Verifies mathematical dependency resolution of YAML task graphs." },
|
||||
{ name: "Code Intelligence PoC", file: "code_intelligence_poc.ts", description: "Verifies structural code parsing (AST/Exports) instead of raw text reading." },
|
||||
{ name: "State Machine PoC", file: "state_machine_poc.ts", description: "Verifies Bounded Model Checking for pipeline governance." },
|
||||
{ name: "Ontology Traceability PoC", file: "ontology_poc.ts", description: "Verifies linking business requirements to code using JSON-LD graphs." }
|
||||
];
|
||||
|
||||
async function runExperiment(file: string): Promise<{ success: boolean; output: string }> {
|
||||
const currentDir = dirname(fromFileUrl(import.meta.url));
|
||||
const filePath = join(currentDir, file);
|
||||
|
||||
try {
|
||||
const command = new Deno.Command("deno", {
|
||||
args: ["run", "-A", filePath], // Allow all permissions for experiments for now, restrict later if needed
|
||||
stdout: "piped",
|
||||
stderr: "piped",
|
||||
});
|
||||
|
||||
const { code, stdout, stderr } = await command.output();
|
||||
const decoder = new TextDecoder();
|
||||
|
||||
const outputString = decoder.decode(stdout) + decoder.decode(stderr);
|
||||
|
||||
return {
|
||||
success: code === 0,
|
||||
output: outputString.trim()
|
||||
};
|
||||
} catch (error) {
|
||||
return {
|
||||
success: false,
|
||||
output: `Failed to execute ${file}: ${error}`
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
async function runLab() {
|
||||
console.log(bold(blue("=== Agent Forum v4 - Experimental Laboratory ===")));
|
||||
console.log("Running fundamental foundational proofs of concept...\n");
|
||||
|
||||
let passed = 0;
|
||||
let failed = 0;
|
||||
|
||||
for (const exp of EXPERIMENTS) {
|
||||
console.log(bold(`[Running] ${exp.name}`));
|
||||
console.log(`> ${exp.description}`);
|
||||
|
||||
const { success, output } = await runExperiment(exp.file);
|
||||
|
||||
if (success) {
|
||||
console.log(green("✅ PASS\n"));
|
||||
console.log(output);
|
||||
passed++;
|
||||
} else {
|
||||
console.log(red("❌ FAIL\n"));
|
||||
console.log(output);
|
||||
failed++;
|
||||
}
|
||||
console.log(yellow("--------------------------------------------------\n"));
|
||||
}
|
||||
|
||||
console.log(bold(blue("=== Laboratory Results ===")));
|
||||
console.log(`Total Experiments: ${EXPERIMENTS.length}`);
|
||||
console.log(green(`Passed: ${passed}`));
|
||||
console.log(red(`Failed: ${failed}`));
|
||||
|
||||
if (failed > 0) {
|
||||
Deno.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (import.meta.main) {
|
||||
runLab().catch(console.error);
|
||||
}
|
||||
@ -1,119 +0,0 @@
|
||||
import { assert } from "https://deno.land/std@0.224.0/assert/mod.ts";
|
||||
|
||||
// Define the Linked Data structures
|
||||
interface JsonLdNode {
|
||||
"@context"?: string;
|
||||
"@type": string;
|
||||
"@id": string;
|
||||
name: string;
|
||||
description?: string;
|
||||
satisfies?: string[]; // IDs of other nodes this node fulfills/relates to
|
||||
}
|
||||
|
||||
// Mock embedded JSON-LD blocks (normally these would be extracted from the frontmatter of Markdown files)
|
||||
const mockReq1: JsonLdNode = {
|
||||
"@context": "https://schema.org",
|
||||
"@type": "BusinessRequirement",
|
||||
"@id": "REQ-001",
|
||||
name: "User Authentication",
|
||||
description: "The system must authenticate users securely."
|
||||
};
|
||||
|
||||
const mockTask1: JsonLdNode = {
|
||||
"@context": "https://schema.org",
|
||||
"@type": "EngineeringTask",
|
||||
"@id": "urn:uuid:018f6c3a-1234-7890-abcd-ef0123456789",
|
||||
name: "Implement Login Endpoint",
|
||||
satisfies: ["REQ-001"] // This links the technical task to the business requirement
|
||||
};
|
||||
|
||||
const mockTest1: JsonLdNode = {
|
||||
"@context": "https://schema.org",
|
||||
"@type": "TestCase",
|
||||
"@id": "TEST-AUTH-01",
|
||||
name: "Test invalid passwords return 401",
|
||||
satisfies: ["urn:uuid:018f6c3a-1234-7890-abcd-ef0123456789"] // This links the test to the task
|
||||
};
|
||||
|
||||
/**
|
||||
* Builds a simple adjacency list representing the ontology graph.
|
||||
*/
|
||||
function buildOntologyGraph(nodes: JsonLdNode[]): Map<string, string[]> {
|
||||
const graph = new Map<string, string[]>();
|
||||
|
||||
// Initialize all nodes
|
||||
for (const node of nodes) {
|
||||
if (!graph.has(node["@id"])) {
|
||||
graph.set(node["@id"], []);
|
||||
}
|
||||
}
|
||||
|
||||
// Map edges (satisfies) -> Note: doing a reverse mapping here (A satisfies B means B is dependent on A)
|
||||
// For traceability, we want to look at a Requirement and ask "What implements this?"
|
||||
for (const node of nodes) {
|
||||
if (node.satisfies) {
|
||||
for (const targetId of node.satisfies) {
|
||||
if (!graph.has(targetId)) {
|
||||
graph.set(targetId, []); // Create the node if it doesn't exist
|
||||
}
|
||||
// Link the target ID to the node that satisfies it
|
||||
graph.get(targetId)!.push(node["@id"]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return graph;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively find all technical artifacts that trace back to a specific requirement.
|
||||
*/
|
||||
function traceRequirement(graph: Map<string, string[]>, startId: string): string[] {
|
||||
const visited = new Set<string>();
|
||||
const stack = [startId];
|
||||
|
||||
while (stack.length > 0) {
|
||||
const current = stack.pop()!;
|
||||
if (!visited.has(current)) {
|
||||
visited.add(current);
|
||||
const edges = graph.get(current) || [];
|
||||
for (const edge of edges) {
|
||||
stack.push(edge);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Array.from(visited);
|
||||
}
|
||||
|
||||
async function runOntologyPoC() {
|
||||
console.log("--- Agent Forum: Ontology & Traceability PoC ---");
|
||||
|
||||
const allNodes = [mockReq1, mockTask1, mockTest1];
|
||||
console.log(`Parsed ${allNodes.length} JSON-LD blocks from mock repository.`);
|
||||
|
||||
// Build the graph
|
||||
const graph = buildOntologyGraph(allNodes);
|
||||
console.log("\nGenerated Ontology Graph (Adjacency List):");
|
||||
for (const [id, edges] of graph.entries()) {
|
||||
console.log(` ${id} is satisfied by: [${edges.join(", ")}]`);
|
||||
}
|
||||
|
||||
// Trace the requirement
|
||||
console.log(`\nTracing impact for Business Requirement: ${mockReq1["@id"]}...`);
|
||||
const traceResults = traceRequirement(graph, mockReq1["@id"]);
|
||||
|
||||
console.log(`Artifacts tracing back to ${mockReq1["@id"]}:`, traceResults);
|
||||
|
||||
assert(traceResults.includes(mockTask1["@id"]), "Graph failed to link Task to Requirement");
|
||||
assert(traceResults.includes(mockTest1["@id"]), "Graph failed to link Test to Task and up to Requirement");
|
||||
|
||||
console.log("\nPoC Successful: Deep traceability achieved via mathematical graph traversal.");
|
||||
}
|
||||
|
||||
if (import.meta.main) {
|
||||
runOntologyPoC().catch(err => {
|
||||
console.error("PoC Failed:", err);
|
||||
Deno.exit(1);
|
||||
});
|
||||
}
|
||||
@ -1,81 +0,0 @@
|
||||
import { assert } from "https://deno.land/std@0.224.0/assert/mod.ts";
|
||||
|
||||
// Define the structure of the transitions.json configuration
|
||||
interface TransitionRule {
|
||||
requires: string[];
|
||||
}
|
||||
|
||||
type TransitionsConfig = Record<string, TransitionRule>;
|
||||
|
||||
// Mock transitions.json content (in a real scenario, this is read from .forum/transitions.json)
|
||||
const MOCK_TRANSITIONS_JSON = `
|
||||
{
|
||||
"Coder": {
|
||||
"requires": ["Gatekeeper_Approval"]
|
||||
},
|
||||
"Gatekeeper": {
|
||||
"requires": []
|
||||
},
|
||||
"Evaluator": {
|
||||
"requires": ["Coder_Completion"]
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
// Simulated state of the repository/pipeline
|
||||
const currentSystemState = {
|
||||
activeFlags: new Set<string>(), // e.g., 'Gatekeeper_Approval', 'Coder_Completion'
|
||||
};
|
||||
|
||||
/**
|
||||
* The Evaluator script that mathematically enforces pipeline progression.
|
||||
* It checks the transitions matrix to see if a specific Agent Role is allowed to execute based on the current flags.
|
||||
*/
|
||||
function canAgentExecute(roleName: string, config: TransitionsConfig, currentState: Set<string>): boolean {
|
||||
const rule = config[roleName];
|
||||
if (!rule) {
|
||||
throw new Error(`Role ${roleName} is not defined in the transitions matrix. Execution denied.`);
|
||||
}
|
||||
|
||||
// Bounded Model Checking: All required flags must be present in the current state.
|
||||
return rule.requires.every(req => currentState.has(req));
|
||||
}
|
||||
|
||||
async function runStateMachinePoC() {
|
||||
console.log("--- Agent Forum: State Machine & Governance PoC ---");
|
||||
|
||||
// 1. Parse the machine-readable matrix
|
||||
const matrix: TransitionsConfig = JSON.parse(MOCK_TRANSITIONS_JSON);
|
||||
console.log("Loaded Transitions Matrix:", Object.keys(matrix));
|
||||
|
||||
// 2. Attempt to run Coder BEFORE Gatekeeper has approved
|
||||
console.log("\nScenario 1: Attempting to run 'Coder' with empty system state...");
|
||||
const canCoderRunInitial = canAgentExecute("Coder", matrix, currentSystemState.activeFlags);
|
||||
console.log(`Result: Coder execution allowed? ${canCoderRunInitial}`);
|
||||
assert(canCoderRunInitial === false, "Coder should NOT be able to run without Gatekeeper_Approval");
|
||||
|
||||
// 3. Gatekeeper runs (it has no requirements)
|
||||
console.log("\nScenario 2: Running 'Gatekeeper'...");
|
||||
const canGatekeeperRun = canAgentExecute("Gatekeeper", matrix, currentSystemState.activeFlags);
|
||||
console.log(`Result: Gatekeeper execution allowed? ${canGatekeeperRun}`);
|
||||
assert(canGatekeeperRun === true, "Gatekeeper should be able to run");
|
||||
|
||||
// Simulate Gatekeeper finishing its job and setting the flag in the meta-state
|
||||
console.log("Gatekeeper finished. Setting 'Gatekeeper_Approval' flag...");
|
||||
currentSystemState.activeFlags.add("Gatekeeper_Approval");
|
||||
|
||||
// 4. Attempt to run Coder AFTER Gatekeeper has approved
|
||||
console.log("\nScenario 3: Attempting to run 'Coder' with updated system state...");
|
||||
const canCoderRunNow = canAgentExecute("Coder", matrix, currentSystemState.activeFlags);
|
||||
console.log(`Result: Coder execution allowed? ${canCoderRunNow}`);
|
||||
assert(canCoderRunNow === true, "Coder SHOULD be able to run now that Gatekeeper_Approval is present");
|
||||
|
||||
console.log("\nPoC Successful: Bounded Model Checking mathematically prevents out-of-order execution.");
|
||||
}
|
||||
|
||||
if (import.meta.main) {
|
||||
runStateMachinePoC().catch(err => {
|
||||
console.error("PoC Failed:", err);
|
||||
Deno.exit(1);
|
||||
});
|
||||
}
|
||||
41
scratch/agent-forum-experiments/ASSESSMENT.md
Normal file
41
scratch/agent-forum-experiments/ASSESSMENT.md
Normal file
@ -0,0 +1,41 @@
|
||||
# Agent Forum v4 Assessment & Research Report
|
||||
|
||||
## 1. Overview & Usefulness
|
||||
|
||||
The `agent-forum-v4` blueprint outlines a "Git-Native Agent Collaboration Ecosystem." By shifting from flat Markdown files to structured data (YAML DAGs, SCIP indexes, local vector graphs), the protocol addresses a core limitation of modern AI agents: context window collapse and dependency amnesia.
|
||||
|
||||
**Solving the Pain Points:**
|
||||
You noted that agents frequently lose context and struggle to understand if they are fulfilling requirements without constant spoon-feeding. The proposed shift to a **Semantic Project Management** system directly solves this:
|
||||
- **Dependencies:** Instead of relying on an agent to read a folder and "figure out" what to do, the system uses strict YAML Directed Acyclic Graphs (DAGs). An Evaluator script mathematically determines the critical path. An agent is only ever handed an explicitly unblocked task.
|
||||
- **Context:** Instead of feeding the agent the entire codebase as raw text, the system uses Git Merkle DAG diffing and embedded SQLite vector search to feed the agent precisely the context it needs in milliseconds.
|
||||
|
||||
## 2. Compatibility with the Repository
|
||||
|
||||
The Auth-Yes repository is characterized by a strict, zero-dependency, hermetic environment prioritizing Deno, minimal external SaaS dependencies, and self-contained runtime operations.
|
||||
|
||||
- **High Alignment:** The agent-forum's philosophy of "Local-First / Git-Native" is in perfect harmony with your project's ethos. Eliminating third-party databases in favor of Git Notes and orphan branches ensures the protocol remains portable, cryptographically secure, and isolated.
|
||||
- **Implementation Challenges:** The blueprint relies heavily on advanced tooling (Tree-sitter, SCIP, `sqlite-vec`). Integrating these into a Deno environment without polluting the repository with heavy binary dependencies will require careful execution. We should lean towards WebAssembly (WASM) ports of these tools (e.g., `tree-sitter.wasm`, or Deno's native FFI for SQLite) to keep the repository lightweight.
|
||||
|
||||
## 3. Isolation Strategy (Preventing Bleed)
|
||||
|
||||
To ensure this new protocol does not interfere with the primary intent of Auth-Yes or other target projects, we must implement strict physical and logical boundaries:
|
||||
|
||||
1. **The `.forum/` (or `.agents/`) Namespace:** All protocol-specific files, state machines (`transitions.json`), schemas, and tooling scripts must be entirely contained within a hidden root directory (e.g., `.forum/`). The target repository should have zero awareness of these files.
|
||||
2. **Git Meta-State (Orphan Branches):** The most powerful isolation technique proposed is the use of an Orphan Branch. Dynamic state (telemetry, task completion status, graphs) will be committed to a branch (e.g., `forum/meta-state`) that shares no history with `main`. This ensures the primary branch's `git log` remains pristine and untouched by agent automation.
|
||||
3. **Git Notes for Meta-Thoughts:** By using custom Git Note refs (e.g., `refs/notes/forum/reasoning`), agents can attach vast amounts of JSON metadata, risk assessments, and historical context to a commit without altering the commit hash or the working directory tree.
|
||||
|
||||
## 4. Adapting the Legacy `/tasks` Workflow
|
||||
|
||||
You mentioned appreciating the file naming conventions (visual history), risk assessments, and meta-thoughts of the old system. The goal is to preserve the *value* of these features while upgrading their *format* to be machine-readable.
|
||||
|
||||
- **Visual History & Filenames:** We can retain the descriptive nomenclature (`YYYY-MMDD.[sequence]...[short-description]`) but use it as the **UUID/Key** inside the YAML DAGs rather than just a filename. To preserve the human visual experience, we can write a simple Deno script (`deno task forum:view`) that parses the DAG and orphan branch history to output a beautiful, interactive terminal UI (via Cliffy) or a generated HTML report showing the exact progression of work.
|
||||
- **Risk Assessment & Meta-Thoughts:** In the old system, these were markdown headers. In the new system, an "Adversary" agent will generate these risk assessments as structured JSON. We will store this JSON in **Git Notes** attached to the relevant commits. This ensures the data is tightly coupled to the code changes, never gets lost in a stale markdown file, and can be queried instantly by other agents.
|
||||
- **Human-Readable Projections:** If we ever need a standard Markdown view, a "Translator" agent or script can compile the DAGs, Git Notes, and ASTs and generate a static `tasks-report.md` on demand.
|
||||
|
||||
## 5. Proposed Experimental Path (Proof of Concept)
|
||||
|
||||
We will not build the fully automated loop yet. Instead, we will build foundational experiments in `scratch/agent-forum-experiments/` to verify the hard concepts:
|
||||
|
||||
1. **Git Storage PoC (`git_storage_poc.ts`):** Verify that Deno can programmatically read/write to Git Notes and manipulate an orphan branch without disrupting the current working tree. This proves we can store agent state invisibly.
|
||||
2. **DAG Engine PoC (`dag_engine_poc.ts`):** Create a minimal script that parses a YAML task graph, resolves dependencies (`blocked_by`), and mathematically outputs the exact next task an agent should work on.
|
||||
3. **Local Intelligence PoC (`code_intelligence_poc.ts`):** Experiment with lightweight semantic parsing (e.g., extracting exports or AST structure from a file) to prove we can feed agents structured code intelligence rather than raw strings.
|
||||
104
scratch/agent-forum-experiments/code_intelligence_poc.ts
Normal file
104
scratch/agent-forum-experiments/code_intelligence_poc.ts
Normal file
@ -0,0 +1,104 @@
|
||||
import { assertEquals } from "https://deno.land/std@0.224.0/testing/asserts.ts";
|
||||
|
||||
/**
|
||||
* Proof of Concept: Local Code Intelligence (AST Parsing)
|
||||
*
|
||||
* In the full implementation, this would use Tree-sitter WASM or SCIP.
|
||||
* For this Deno PoC, we will simulate the extraction of structured data
|
||||
* from raw code by building a lightweight regex-based scanner that
|
||||
* extracts exported function signatures. This proves the concept of
|
||||
* transforming "raw text" into "structured JSON context" for an agent.
|
||||
*/
|
||||
|
||||
export interface ExportSymbol {
|
||||
name: string;
|
||||
type: "function" | "class" | "const";
|
||||
signature: string;
|
||||
}
|
||||
|
||||
export function extractExports(sourceCode: string): ExportSymbol[] {
|
||||
const exports: ExportSymbol[] = [];
|
||||
|
||||
// A naive regex for PoC purposes to find exported functions
|
||||
// Matches: export function foo(bar: string): void {
|
||||
const functionRegex = /export\s+(?:async\s+)?function\s+([a-zA-Z0-9_]+)\s*\(([^)]*)\)(?:\s*:\s*([^ {]+))?/g;
|
||||
|
||||
let match;
|
||||
while ((match = functionRegex.exec(sourceCode)) !== null) {
|
||||
const name = match[1];
|
||||
const args = match[2].trim();
|
||||
const returnType = match[3] ? match[3].trim() : "any";
|
||||
|
||||
exports.push({
|
||||
name,
|
||||
type: "function",
|
||||
signature: `(${args}) => ${returnType}`,
|
||||
});
|
||||
}
|
||||
|
||||
// Matches: export const foo = ...
|
||||
const constRegex = /export\s+const\s+([a-zA-Z0-9_]+)\s*=/g;
|
||||
while ((match = constRegex.exec(sourceCode)) !== null) {
|
||||
exports.push({
|
||||
name: match[1],
|
||||
type: "const",
|
||||
signature: "const",
|
||||
});
|
||||
}
|
||||
|
||||
return exports;
|
||||
}
|
||||
|
||||
// In a real scenario, tests would be separated. For this PoC, we will run the tests here.
|
||||
if (import.meta.main) {
|
||||
console.log("Running Local Code Intelligence PoC tests...");
|
||||
|
||||
const mockSourceCode = `
|
||||
import { stuff } from "somewhere";
|
||||
|
||||
/**
|
||||
* Calculates a complex value.
|
||||
*/
|
||||
export async function calculateValue(input: number, mode: string): Promise<number> {
|
||||
return input * 2;
|
||||
}
|
||||
|
||||
// An internal helper
|
||||
function internalHelper() {
|
||||
return true;
|
||||
}
|
||||
|
||||
export const MAX_RETRIES = 5;
|
||||
|
||||
export function doSomethingElse(): void {
|
||||
console.log(MAX_RETRIES);
|
||||
}
|
||||
`;
|
||||
|
||||
try {
|
||||
const extracted = extractExports(mockSourceCode);
|
||||
|
||||
assertEquals(extracted.length, 3);
|
||||
|
||||
const calcFunc = extracted.find(e => e.name === "calculateValue");
|
||||
assertEquals(calcFunc?.type, "function");
|
||||
assertEquals(calcFunc?.signature, "(input: number, mode: string) => Promise<number>");
|
||||
|
||||
const maxRetries = extracted.find(e => e.name === "MAX_RETRIES");
|
||||
assertEquals(maxRetries?.type, "const");
|
||||
|
||||
const doSomething = extracted.find(e => e.name === "doSomethingElse");
|
||||
assertEquals(doSomething?.type, "function");
|
||||
assertEquals(doSomething?.signature, "() => void");
|
||||
|
||||
console.log("✅ Local Code Intelligence PoC successful: Extracted structured context from raw source.");
|
||||
|
||||
// Simulate what the agent would actually see:
|
||||
console.log("\n--- Agent Context Payload ---");
|
||||
console.log(JSON.stringify(extracted, null, 2));
|
||||
console.log("-----------------------------\n");
|
||||
|
||||
} catch (err) {
|
||||
console.error("❌ Local Code Intelligence PoC failed:", err);
|
||||
}
|
||||
}
|
||||
105
scratch/agent-forum-experiments/dag_engine_poc.ts
Normal file
105
scratch/agent-forum-experiments/dag_engine_poc.ts
Normal file
@ -0,0 +1,105 @@
|
||||
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";
|
||||
|
||||
/**
|
||||
* Proof of Concept: Semantic Task DAG Engine
|
||||
*
|
||||
* This module demonstrates how we can parse a strict YAML Directed Acyclic Graph (DAG)
|
||||
* of tasks to calculate the critical path and ensure agents are only ever handed
|
||||
* explicitly unblocked tasks.
|
||||
*/
|
||||
|
||||
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";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// In a real scenario, tests would be separated. For this PoC, we will run the tests here.
|
||||
if (import.meta.main) {
|
||||
console.log("Running DAG Engine PoC tests...");
|
||||
|
||||
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 {
|
||||
const dag = new TaskDAG(yamlInput);
|
||||
|
||||
// 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("✅ DAG Engine PoC successful: Correctly calculated unblocked tasks.");
|
||||
} catch (err) {
|
||||
console.error("❌ DAG Engine PoC failed:", err);
|
||||
}
|
||||
}
|
||||
71
scratch/agent-forum-experiments/git_storage_poc.ts
Normal file
71
scratch/agent-forum-experiments/git_storage_poc.ts
Normal file
@ -0,0 +1,71 @@
|
||||
import { assert, assertEquals } from "https://deno.land/std@0.224.0/testing/asserts.ts";
|
||||
|
||||
/**
|
||||
* Proof of Concept: Git Storage (Notes & Orphan Branches)
|
||||
*
|
||||
* This module demonstrates how we can use Deno's `Deno.Command` API to interact
|
||||
* with Git Notes and Orphan Branches to store agent state and metadata without
|
||||
* polluting the main working tree.
|
||||
*/
|
||||
|
||||
async function runGitCmd(args: string[]): Promise<string> {
|
||||
const cmd = new Deno.Command("git", {
|
||||
args,
|
||||
stdout: "piped",
|
||||
stderr: "piped",
|
||||
});
|
||||
const output = await cmd.output();
|
||||
const stdout = new TextDecoder().decode(output.stdout).trim();
|
||||
const stderr = new TextDecoder().decode(output.stderr).trim();
|
||||
|
||||
if (!output.success) {
|
||||
throw new Error(`Git command failed: git ${args.join(" ")}\n${stderr}`);
|
||||
}
|
||||
return stdout;
|
||||
}
|
||||
|
||||
export async function addGitNote(ref: string, message: string, targetRef: string = "HEAD") {
|
||||
// First, check if a note already exists to avoid overwriting blindly
|
||||
// For this PoC, we will append or overwrite
|
||||
await runGitCmd(["notes", "--ref", ref, "add", "-f", "-m", message, targetRef]);
|
||||
}
|
||||
|
||||
export async function readGitNote(ref: string, targetRef: string = "HEAD"): Promise<string> {
|
||||
try {
|
||||
return await runGitCmd(["notes", "--ref", ref, "show", targetRef]);
|
||||
} catch (error: any) {
|
||||
if (error.message.includes("No note found")) {
|
||||
return "";
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
// In a real scenario, tests would be separated. For this PoC, we will run the tests here.
|
||||
if (import.meta.main) {
|
||||
console.log("Running Git Storage PoC tests...");
|
||||
|
||||
// 1. Test Git Notes
|
||||
const customRef = "forum/test-reasoning";
|
||||
const testMessage = JSON.stringify({
|
||||
agent: "poc-agent",
|
||||
risk: "low",
|
||||
thought: "This is a hidden thought stored in a git note."
|
||||
});
|
||||
|
||||
try {
|
||||
console.log(`Adding note to current HEAD under ref ${customRef}...`);
|
||||
await addGitNote(customRef, testMessage);
|
||||
|
||||
console.log(`Reading note back...`);
|
||||
const readMessage = await readGitNote(customRef);
|
||||
|
||||
assertEquals(readMessage, testMessage);
|
||||
console.log("✅ Git Notes PoC successful: Read/Write worked as expected.");
|
||||
|
||||
// Clean up
|
||||
await runGitCmd(["notes", "--ref", customRef, "remove", "HEAD"]);
|
||||
} catch (err) {
|
||||
console.error("❌ Git Notes PoC failed:", err);
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user