agent-enderun 0.4.6 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.enderun/ENDERUN.md +24 -24
- package/ENDERUN.md +12 -12
- package/README.md +7 -7
- package/bin/cli.js +2 -10
- package/claude.md +5 -2
- package/codex.md +5 -2
- package/cursor.md +5 -2
- package/gemini-extension.json +1 -1
- package/gemini.md +5 -2
- package/package.json +10 -8
- package/packages/framework-mcp/dist/index.js +2 -1
- package/packages/framework-mcp/dist/tools/memory.js +3 -1
- package/packages/framework-mcp/dist/tools/messages.js +1 -1
- package/packages/framework-mcp/dist/tools/repository.js +6 -2
- package/packages/framework-mcp/dist/utils.js +3 -3
- package/packages/framework-mcp/package.json +1 -1
- package/packages/framework-mcp/src/index.ts +2 -1
- package/packages/framework-mcp/src/tools/academy.ts +17 -11
- package/packages/framework-mcp/src/tools/codebase.ts +5 -5
- package/packages/framework-mcp/src/tools/contract.ts +3 -3
- package/packages/framework-mcp/src/tools/database.ts +1 -1
- package/packages/framework-mcp/src/tools/framework.ts +5 -5
- package/packages/framework-mcp/src/tools/git.ts +1 -1
- package/packages/framework-mcp/src/tools/index.ts +1 -1
- package/packages/framework-mcp/src/tools/knowledge.ts +2 -2
- package/packages/framework-mcp/src/tools/memory.ts +5 -3
- package/packages/framework-mcp/src/tools/messages.ts +15 -7
- package/packages/framework-mcp/src/tools/repository.ts +8 -3
- package/packages/framework-mcp/src/tools/security.ts +2 -2
- package/packages/framework-mcp/src/utils.ts +3 -3
- package/packages/shared-types/package.json +1 -1
package/.enderun/ENDERUN.md
CHANGED
|
@@ -1,63 +1,63 @@
|
|
|
1
|
-
# Agent Enderun (v0.
|
|
1
|
+
# Agent Enderun (v0.5.0)
|
|
2
2
|
# Place in project root. This file is the single source of truth for Base Project AI Extensions.
|
|
3
3
|
|
|
4
4
|
## 🎖️ AGENT CHECKLIST (MANDATORY BEFORE RESPONSE)
|
|
5
5
|
> Check this list at the end of every response:
|
|
6
6
|
> - [ ] **Zero Mock:** Did you use fake data or placeholders? (Strictly Forbidden)
|
|
7
7
|
> - [ ] **Contract First:** Are `shared-types` and `contract.version.json` up to date?
|
|
8
|
-
> - [ ] **Audit Log:** Did you log this action in
|
|
9
|
-
> - [ ] **CLI Orchestration:** Does the action comply with `
|
|
8
|
+
> - [ ] **Audit Log:** Did you log this action in `{{FRAMEWORK_DIR}}/logs/[agent].json`?
|
|
9
|
+
> - [ ] **CLI Orchestration:** Does the action comply with `{{ADAPTER}} cli` rules?
|
|
10
10
|
> - [ ] **No "..." allowed:** Did you write the code completely without omitting parts?
|
|
11
11
|
|
|
12
12
|
---
|
|
13
13
|
|
|
14
14
|
## Constitution Status
|
|
15
|
-
This file (`./
|
|
15
|
+
This file (`./{{ADAPTER}}.md`) and the `{{FRAMEWORK_DIR}}/docs/` folder represent the "Supreme Law" of the project. All agents must read this file first in every session and strictly comply with its rules 100%. All framework-specific documentation is stored within `{{FRAMEWORK_DIR}}/docs/`.
|
|
16
16
|
|
|
17
17
|
---
|
|
18
18
|
|
|
19
19
|
## STEP 0 — STARTUP (EVERY SESSION, NON-NEGOTIABLE)
|
|
20
20
|
|
|
21
|
-
1. **Read ./
|
|
22
|
-
2. **Check
|
|
23
|
-
3. **Absorb Context:** Read
|
|
24
|
-
4. **Demand Context:** If the
|
|
25
|
-
5.
|
|
21
|
+
1. **Read ./{{ADAPTER}}.md First:** Read and fully understand this file before taking any action.
|
|
22
|
+
2. **Check `{{FRAMEWORK_DIR}}/docs/` Folder:** Verify the existence of the `{{FRAMEWORK_DIR}}/docs/` folder (located within the framework directory).
|
|
23
|
+
3. **Absorb Context:** Read `{{FRAMEWORK_DIR}}/docs/tech-stack.md`. If it is empty, ask the user to fill it before proceeding.
|
|
24
|
+
4. **Demand Context:** If the `{{FRAMEWORK_DIR}}/docs/` folder does not exist, ask the user for project context and target audience information before writing any code.
|
|
25
|
+
5. **Mandatory @manager Activation:** You MUST act as `@manager` for the initial response to any new user request.
|
|
26
26
|
|
|
27
|
-
**NEVER SKIP THIS STEP.** Do not assume context; read first, then act.
|
|
27
|
+
**NEVER SKIP THIS STEP.** Do not assume context; read first, then act as @manager.
|
|
28
28
|
|
|
29
29
|
---
|
|
30
30
|
|
|
31
31
|
## CORE PRINCIPLES
|
|
32
32
|
|
|
33
|
-
- **
|
|
33
|
+
- **Team-Lead MANDATORY Orchestration:** Every user request MUST first be handled by the `@manager` (Team-Lead) agent. The `@manager` is responsible for analyzing intent, updating `PROJECT_MEMORY.md`, and delegating tasks to specialists. Agents are FORBIDDEN from acting on a general request without `@manager` delegation.
|
|
34
34
|
- **Zero-Request Logging Policy:** Agents MUST log every action and update `PROJECT_MEMORY.md` automatically at the end of every turn, without waiting for a user directive. This is the "Operating Mode" of the framework.
|
|
35
35
|
- **Immediate Memory Sync:** Every state change, decision, or improved capability must be reflected in the memory files immediately.
|
|
36
36
|
- **Contract-First Agent Evolution:** Tools and SOPs used by agents must be defined via schemas and contracts first.
|
|
37
37
|
- **Zero Mock Policy:** The use of fake (mock) data or placeholders is strictly forbidden. Every line of code must connect to a real endpoint or a typed contract. (Exception: Controlled mock usage is allowed for external 3rd party services like Stripe, Twilio).
|
|
38
38
|
- **Branded Types Law:** All IDs (UserID, ProjectID, etc.) must be in the "Branded Types" format defined under `packages/shared-types`. Using plain strings or numbers is forbidden.
|
|
39
39
|
- **CLI-First Policy:** Due to the AI CLI Assistant focus, all outputs must be user-friendly (using Chalk, Clack, etc.) and stream-based. All commands must support the `--output json` flag and produce machine-readable output.
|
|
40
|
-
- **Audit Logging Necessity:** Every critical action must be logged traceably under the
|
|
40
|
+
- **Audit Logging Necessity:** Every critical action must be logged traceably under the `{{FRAMEWORK_DIR}}/logs/` folder.
|
|
41
41
|
- **Design Continuity & Response Policy:** All UI changes MUST be responsive (Mobile-First + Fluid) and surgical. Unnecessary overhauls of existing layouts are strictly forbidden.
|
|
42
42
|
- **Shared Component First Policy:** Defining common UI elements (Button, Input, Card, etc.) inside page files is FORBIDDEN. All atomic UI components must be created in a shared directory (e.g., `apps/web/src/components/ui/`) and reused across the project.
|
|
43
43
|
- **File Ownership Rule:** Each file is the responsibility of a single agent.
|
|
44
|
-
- **CLI Command Mapping:** All CLI commands in the project must be defined in the
|
|
44
|
+
- **CLI Command Mapping:** All CLI commands in the project must be defined in the `{{FRAMEWORK_DIR}}/cli-commands.json` file and assigned to the relevant agent.
|
|
45
45
|
- **Exit Code Standard:** Standard exit codes (e.g., 64: User Error, 70: Internal Error) must be used in error situations.
|
|
46
46
|
- **Phase-Based Execution:** The development process must progress through defined Phases. You cannot move to the next phase until the current one is completed.
|
|
47
|
-
- **CLI-Driven Orchestration:** All agent interactions and task delegations must be traceable via `
|
|
47
|
+
- **CLI-Driven Orchestration:** All agent interactions and task delegations must be traceable via `{{ADAPTER}} cli`.
|
|
48
48
|
- **Monorepo Discipline:** Commands must always be run from the monorepo root directory using npm workspaces (e.g., `npm run dev --workspace=web`).
|
|
49
49
|
|
|
50
50
|
---
|
|
51
51
|
|
|
52
52
|
## STEP 1 — VALIDATE BEFORE ACTING
|
|
53
53
|
|
|
54
|
-
Before writing any code or design, check
|
|
54
|
+
Before writing any code or design, check `{{FRAMEWORK_DIR}}/docs/tech-stack.md`:
|
|
55
55
|
|
|
56
56
|
| Unknown | Action |
|
|
57
57
|
|---|---|
|
|
58
58
|
| Target Audience | Ask — do not proceed |
|
|
59
59
|
| Platform (web / mobile / desktop / backend) | Ask — do not proceed |
|
|
60
|
-
| **Technology Stack** | **Check
|
|
60
|
+
| **Technology Stack** | **Check `{{FRAMEWORK_DIR}}/docs/tech-stack.md` → If missing → ASK** |
|
|
61
61
|
| **Execution Profile (Full / Lightweight)** | **Ask — do not proceed** |
|
|
62
62
|
| Database (MariaDB / SQLite / PostgreSQL) | Ask — do not proceed |
|
|
63
63
|
| Environment (prototype / production) | Ask — do not proceed |
|
|
@@ -148,7 +148,7 @@ This file is the single source of truth for API stability. `@backend-architect`
|
|
|
148
148
|
|
|
149
149
|
The development process follows a strict State Machine. Transition to the next phase is prohibited until the "Success Criteria" of the current phase is met.
|
|
150
150
|
|
|
151
|
-
- **[STATE: PHASE_0] Discovery & Setup:** Profile selection (Lightweight/Full), requirement analysis, and validating
|
|
151
|
+
- **[STATE: PHASE_0] Discovery & Setup:** Profile selection (Lightweight/Full), requirement analysis, and validating `{{FRAMEWORK_DIR}}/docs/tech-stack.md`.
|
|
152
152
|
- **[STATE: PHASE_1] Architecture & Contracts:** Setup of data models, API schemas, and `packages/shared-types`. Cannot proceed until Frontend and Backend approve these schemas.
|
|
153
153
|
- **[STATE: PHASE_2] Core Development:** Active agents build core features in parallel based on the selected profile. (Under the apps/ folder)
|
|
154
154
|
- **[STATE: PHASE_3] Integration & Testing:** System integration.
|
|
@@ -166,13 +166,13 @@ Every agent must produce a response for their assigned task within a maximum of
|
|
|
166
166
|
|
|
167
167
|
## CLI STANDARDS & CONFIGURATION
|
|
168
168
|
|
|
169
|
-
### 1. CLI Command Map (
|
|
169
|
+
### 1. CLI Command Map (`{{FRAMEWORK_DIR}}/cli-commands.json`)
|
|
170
170
|
All CLI commands are centrally managed in this file. Each command must have a designated owner agent.
|
|
171
171
|
|
|
172
|
-
### 2. Configuration (
|
|
172
|
+
### 2. Configuration (`{{FRAMEWORK_DIR}}/config.json`)
|
|
173
173
|
CLI behaviors (logLevel, outputFormat, defaultProfile) are managed through this file.
|
|
174
174
|
|
|
175
|
-
**Priority Rule:** CLI Flags >
|
|
175
|
+
**Priority Rule:** CLI Flags > `{{FRAMEWORK_DIR}}/config.json` > `.env` > Default Values.
|
|
176
176
|
|
|
177
177
|
### 3. Exit Codes
|
|
178
178
|
- `0`: Success
|
|
@@ -191,12 +191,12 @@ All APIs are versioned via the URL path (`/api/v1/...`). The `packages/shared-ty
|
|
|
191
191
|
## PARALLEL EXECUTION & COORDINATION RULES
|
|
192
192
|
|
|
193
193
|
1. **Shared-Types as Source of Truth:** All agents reference `packages/shared-types` and the `contract.version.json` file.
|
|
194
|
-
2. **Commit-Level Logging:** Every agent must log every atomic change to the
|
|
194
|
+
2. **Commit-Level Logging:** Every agent must log every atomic change to the `{{FRAMEWORK_DIR}}/logs/[agent-name].json` file.
|
|
195
195
|
3. **Implicit Dependency Lock:** If an agent's required output is not ready, it switches to `WAITING` state.
|
|
196
196
|
4. **Ownership Enforcement:** Changes to files outside an agent's scope cannot be made without `@team-lead` approval.
|
|
197
|
-
5. **No Blind Coding:** Agents must periodically read
|
|
198
|
-
6. **Agent Directives (Message Queue):**
|
|
199
|
-
- **Message Queue Lock Protocol:** Before writing to a file, check for
|
|
197
|
+
5. **No Blind Coding:** Agents must periodically read `{{FRAMEWORK_DIR}}/logs/` and `{{FRAMEWORK_DIR}}/STATUS.md`.
|
|
198
|
+
6. **Agent Directives (Message Queue):** `{{FRAMEWORK_DIR}}/messages/` is used for inter-agent communication.
|
|
199
|
+
- **Message Queue Lock Protocol:** Before writing to a file, check for `{{FRAMEWORK_DIR}}/messages/.lock`.
|
|
200
200
|
- If it exists, wait 500ms and retry (max 3 retries).
|
|
201
201
|
- If lock persists after 3 retries, the agent MUST assume a **stale lock**, delete it, and notify `@team-lead` in their log.
|
|
202
202
|
- Delete `.lock` and the message file immediately after processing.
|
package/ENDERUN.md
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
# Agent Enderun (v0.
|
|
1
|
+
# Agent Enderun (v0.5.0)
|
|
2
2
|
# Place in project root. This file is the single source of truth for Base Project AI Extensions.
|
|
3
3
|
|
|
4
4
|
## 🎖️ AGENT CHECKLIST (MANDATORY BEFORE RESPONSE)
|
|
5
5
|
> Check this list at the end of every response:
|
|
6
6
|
> - [ ] **Zero Mock:** Did you use fake data or placeholders? (Strictly Forbidden)
|
|
7
7
|
> - [ ] **Contract First:** Are `shared-types` and `contract.version.json` up to date?
|
|
8
|
-
> - [ ] **Audit Log:** Did you log this action in
|
|
9
|
-
> - [ ] **CLI Orchestration:** Does the action comply with `
|
|
8
|
+
> - [ ] **Audit Log:** Did you log this action in `{{FRAMEWORK_DIR}}/logs/[agent].json`?
|
|
9
|
+
> - [ ] **CLI Orchestration:** Does the action comply with `{{ADAPTER}} cli` rules?
|
|
10
10
|
> - [ ] **No "..." allowed:** Did you write the code completely without omitting parts?
|
|
11
11
|
|
|
12
12
|
---
|
|
@@ -22,22 +22,22 @@ This file (`./{{ADAPTER}}.md`) and the `{{FRAMEWORK_DIR}}/docs/` folder represen
|
|
|
22
22
|
2. **Check `{{FRAMEWORK_DIR}}/docs/` Folder:** Verify the existence of the `{{FRAMEWORK_DIR}}/docs/` folder (located within the framework directory).
|
|
23
23
|
3. **Absorb Context:** Read `{{FRAMEWORK_DIR}}/docs/tech-stack.md`. If it is empty, ask the user to fill it before proceeding.
|
|
24
24
|
4. **Demand Context:** If the `{{FRAMEWORK_DIR}}/docs/` folder does not exist, ask the user for project context and target audience information before writing any code.
|
|
25
|
-
5.
|
|
25
|
+
5. **Mandatory @manager Activation:** You MUST act as `@manager` for the initial response to any new user request.
|
|
26
26
|
|
|
27
|
-
**NEVER SKIP THIS STEP.** Do not assume context; read first, then act.
|
|
27
|
+
**NEVER SKIP THIS STEP.** Do not assume context; read first, then act as @manager.
|
|
28
28
|
|
|
29
29
|
---
|
|
30
30
|
|
|
31
31
|
## CORE PRINCIPLES
|
|
32
32
|
|
|
33
|
-
- **Team-Lead
|
|
33
|
+
- **Team-Lead MANDATORY Orchestration:** Every user request MUST first be handled by the `@manager` (Team-Lead) agent. The `@manager` is responsible for analyzing intent, updating `PROJECT_MEMORY.md`, and delegating tasks to specialists. Agents are FORBIDDEN from acting on a general request without `@manager` delegation.
|
|
34
34
|
- **Contract-First Approach:** Communication between Backend and Frontend must always be defined via schemas first. The `packages/shared-types/contract.version.json` file must be kept in MAJOR.MINOR format and updated with every change. The `@backend-architect` is responsible for updating this file.
|
|
35
35
|
- **Zero Mock Policy:** The use of fake (mock) data or placeholders is strictly forbidden. Every line of code must connect to a real endpoint or a typed contract. (Exception: Controlled mock usage is allowed for external 3rd party services like Stripe, Twilio).
|
|
36
36
|
- **Branded Types Law:** All IDs (UserID, ProjectID, etc.) must be in the "Branded Types" format defined under `packages/shared-types`. Using plain strings or numbers is forbidden.
|
|
37
37
|
- **CLI-First Policy:** Due to the AI CLI Assistant focus, all outputs must be user-friendly (using Chalk, Clack, etc.) and stream-based. All commands must support the `--output json` flag and produce machine-readable output.
|
|
38
38
|
- **Audit Logging Necessity:** Every critical action must be logged traceably under the `{{FRAMEWORK_DIR}}/logs/` folder.
|
|
39
39
|
- **File Ownership Rule:** Each file is the responsibility of a single agent.
|
|
40
|
-
- **CLI Command Mapping:** All CLI commands in the project must be defined in the
|
|
40
|
+
- **CLI Command Mapping:** All CLI commands in the project must be defined in the `{{FRAMEWORK_DIR}}/cli-commands.json` file and assigned to the relevant agent.
|
|
41
41
|
- **Exit Code Standard:** Standard exit codes (e.g., 64: User Error, 70: Internal Error) must be used in error situations.
|
|
42
42
|
- **Phase-Based Execution:** The development process must progress through defined Phases. You cannot move to the next phase until the current one is completed.
|
|
43
43
|
- **CLI-Driven Orchestration:** All agent interactions and task delegations must be traceable via `{{ADAPTER}} cli`.
|
|
@@ -47,7 +47,7 @@ This file (`./{{ADAPTER}}.md`) and the `{{FRAMEWORK_DIR}}/docs/` folder represen
|
|
|
47
47
|
|
|
48
48
|
## STEP 1 — VALIDATE BEFORE ACTING
|
|
49
49
|
|
|
50
|
-
Before writing any code or design, check
|
|
50
|
+
Before writing any code or design, check `{{FRAMEWORK_DIR}}/docs/tech-stack.md`:
|
|
51
51
|
|
|
52
52
|
| Unknown | Action |
|
|
53
53
|
|---|---|
|
|
@@ -144,7 +144,7 @@ This file is the single source of truth for API stability. `@backend-architect`
|
|
|
144
144
|
|
|
145
145
|
The development process follows a strict State Machine. Transition to the next phase is prohibited until the "Success Criteria" of the current phase is met.
|
|
146
146
|
|
|
147
|
-
- **[STATE: PHASE_0] Discovery & Setup:** Profile selection (Lightweight/Full), requirement analysis, and validating
|
|
147
|
+
- **[STATE: PHASE_0] Discovery & Setup:** Profile selection (Lightweight/Full), requirement analysis, and validating `{{FRAMEWORK_DIR}}/docs/tech-stack.md`.
|
|
148
148
|
- **[STATE: PHASE_1] Architecture & Contracts:** Setup of data models, API schemas, and `packages/shared-types`. Cannot proceed until Frontend and Backend approve these schemas.
|
|
149
149
|
- **[STATE: PHASE_2] Core Development:** Active agents build core features in parallel based on the selected profile. (Under the apps/ folder)
|
|
150
150
|
- **[STATE: PHASE_3] Integration & Testing:** System integration.
|
|
@@ -162,13 +162,13 @@ Every agent must produce a response for their assigned task within a maximum of
|
|
|
162
162
|
|
|
163
163
|
## CLI STANDARDS & CONFIGURATION
|
|
164
164
|
|
|
165
|
-
### 1. CLI Command Map (
|
|
165
|
+
### 1. CLI Command Map (`{{FRAMEWORK_DIR}}/cli-commands.json`)
|
|
166
166
|
All CLI commands are centrally managed in this file. Each command must have a designated owner agent.
|
|
167
167
|
|
|
168
|
-
### 2. Configuration (
|
|
168
|
+
### 2. Configuration (`{{FRAMEWORK_DIR}}/config.json`)
|
|
169
169
|
CLI behaviors (logLevel, outputFormat, defaultProfile) are managed through this file.
|
|
170
170
|
|
|
171
|
-
**Priority Rule:** CLI Flags >
|
|
171
|
+
**Priority Rule:** CLI Flags > `{{FRAMEWORK_DIR}}/config.json` > `.env` > Default Values.
|
|
172
172
|
|
|
173
173
|
### 3. Exit Codes
|
|
174
174
|
- `0`: Success
|
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# 🏛️ Agent Enderun — v0.
|
|
1
|
+
# 🏛️ Agent Enderun — v0.5.0
|
|
2
2
|
|
|
3
3
|
**The Supreme AI Governance & Orchestration Framework for Enterprise Development**
|
|
4
4
|
|
|
@@ -110,7 +110,7 @@ agent-enderun verify-contract
|
|
|
110
110
|
|
|
111
111
|
Agent Enderun consists of **4 integrated layers**:
|
|
112
112
|
|
|
113
|
-
### Layer 1: Governance (
|
|
113
|
+
### Layer 1: Governance ({{FRAMEWORK_DIR}}/)
|
|
114
114
|
```
|
|
115
115
|
.enderun/
|
|
116
116
|
├── ENDERUN.md ← The "Supreme Law" (read this first!)
|
|
@@ -349,7 +349,7 @@ agent-enderun/
|
|
|
349
349
|
### Q: Do agents actually understand all this?
|
|
350
350
|
**A:** Yes. Before every action, agents read:
|
|
351
351
|
1. `ENDERUN.md` (the constitution)
|
|
352
|
-
2.
|
|
352
|
+
2. `{{FRAMEWORK_DIR}}/PROJECT_MEMORY.md` (project state)
|
|
353
353
|
3. `docs/` files (your requirements)
|
|
354
354
|
4. `.enderun/knowledge/` (technical guidelines)
|
|
355
355
|
|
|
@@ -373,7 +373,7 @@ agent-enderun/
|
|
|
373
373
|
|
|
374
374
|
## 🔗 Key Files to Read First
|
|
375
375
|
|
|
376
|
-
1.
|
|
376
|
+
1. **`{{FRAMEWORK_DIR}}/ENDERUN.md`** — The constitution (rules all agents must follow)
|
|
377
377
|
2. **`.enderun/PROJECT_MEMORY.md`** — Current project state and history
|
|
378
378
|
3. **`docs/tech-stack.md`** — Technology decisions
|
|
379
379
|
4. **`packages/shared-types/src/index.ts`** — The contract (types)
|
|
@@ -492,7 +492,7 @@ agent-enderun verify-contract
|
|
|
492
492
|
|
|
493
493
|
Agent Enderun **4 entegre katmandan** oluşur:
|
|
494
494
|
|
|
495
|
-
### Katman 1: Yönetişim (
|
|
495
|
+
### Katman 1: Yönetişim ({{FRAMEWORK_DIR}}/)
|
|
496
496
|
- `ENDERUN.md` — Anayasa (bunu ilk oku!)
|
|
497
497
|
- `PROJECT_MEMORY.md` — Proje durumu
|
|
498
498
|
- `agents/` — 8 ajan rolü tanımları
|
|
@@ -597,7 +597,7 @@ agent-enderun/
|
|
|
597
597
|
### S: Ajanlar bütün bunları anlıyor mu?
|
|
598
598
|
**C:** Evet. Her işlem öncesi şunları okurlar:
|
|
599
599
|
1. `ENDERUN.md` (anayasa)
|
|
600
|
-
2.
|
|
600
|
+
2. `{{FRAMEWORK_DIR}}/PROJECT_MEMORY.md` (proje durumu)
|
|
601
601
|
3. `docs/` dosyaları (gereksinimler)
|
|
602
602
|
4. `.enderun/knowledge/` (teknik rehberler)
|
|
603
603
|
|
|
@@ -617,7 +617,7 @@ agent-enderun/
|
|
|
617
617
|
|
|
618
618
|
## 🔗 Önce Okumanız Gereken Dosyalar
|
|
619
619
|
|
|
620
|
-
1.
|
|
620
|
+
1. **`{{FRAMEWORK_DIR}}/ENDERUN.md`** — Anayasa
|
|
621
621
|
2. **`.enderun/PROJECT_MEMORY.md`** — Proje durumu
|
|
622
622
|
3. **`docs/tech-stack.md`** — Teknoloji kararları
|
|
623
623
|
4. **`packages/shared-types/src/index.ts`** — Sözleşme (türler)
|
package/bin/cli.js
CHANGED
|
@@ -197,16 +197,8 @@ function mergePackageJson(targetPath, sourcePath) {
|
|
|
197
197
|
function updateGitIgnore(targetPath, frameworkDir = ".enderun") {
|
|
198
198
|
const IGNORE_LINES = [
|
|
199
199
|
"# AI-Enderun",
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
".cursor/logs/*.json",
|
|
203
|
-
".codex/logs/*.json",
|
|
204
|
-
".enderun/logs/*.json",
|
|
205
|
-
".enderun/*.lock",
|
|
206
|
-
".claude/*.lock",
|
|
207
|
-
".cursor/*.lock",
|
|
208
|
-
".codex/*.lock",
|
|
209
|
-
".enderun/*.lock",
|
|
200
|
+
`${frameworkDir}/logs/*.json`,
|
|
201
|
+
`${frameworkDir}/*.lock`,
|
|
210
202
|
".env",
|
|
211
203
|
".DS_Store"
|
|
212
204
|
];
|
package/claude.md
CHANGED
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
This file is the entry point for Claude. The project's "Supreme Law" and all instructions are located in the following file:
|
|
4
4
|
|
|
5
|
-
👉 **[
|
|
5
|
+
👉 **[{{FRAMEWORK_DIR}}/ENDERUN.md]({{FRAMEWORK_DIR}}/ENDERUN.md)**
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
### 🤖 AGENT DIRECTIVE
|
|
8
|
+
You MUST act as the `@manager` (Team-Lead) for the initial response to any user request. You are responsible for analysis and delegation.
|
|
9
|
+
|
|
10
|
+
Please read the Supreme Law thoroughly before taking any action.
|
package/codex.md
CHANGED
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
This file is the entry point for Codex. The project's "Supreme Law" and all instructions are located in the following file:
|
|
4
4
|
|
|
5
|
-
👉 **[
|
|
5
|
+
👉 **[{{FRAMEWORK_DIR}}/ENDERUN.md]({{FRAMEWORK_DIR}}/ENDERUN.md)**
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
### 🤖 AGENT DIRECTIVE
|
|
8
|
+
You MUST act as the `@manager` (Team-Lead) for the initial response to any user request. You are responsible for analysis and delegation.
|
|
9
|
+
|
|
10
|
+
Please read the Supreme Law thoroughly before taking any action.
|
package/cursor.md
CHANGED
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
This file is the entry point for Cursor. The project's "Supreme Law" and all instructions are located in the following file:
|
|
4
4
|
|
|
5
|
-
👉 **[
|
|
5
|
+
👉 **[{{FRAMEWORK_DIR}}/ENDERUN.md]({{FRAMEWORK_DIR}}/ENDERUN.md)**
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
### 🤖 AGENT DIRECTIVE
|
|
8
|
+
You MUST act as the `@manager` (Team-Lead) for the initial response to any user request. You are responsible for analysis and delegation.
|
|
9
|
+
|
|
10
|
+
Please read the Supreme Law thoroughly before taking any action.
|
package/gemini-extension.json
CHANGED
package/gemini.md
CHANGED
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
This file is the entry point for Gemini. The project's "Supreme Law" and all instructions are located in the following file:
|
|
4
4
|
|
|
5
|
-
👉 **[
|
|
5
|
+
👉 **[{{FRAMEWORK_DIR}}/ENDERUN.md]({{FRAMEWORK_DIR}}/ENDERUN.md)**
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
### 🤖 AGENT DIRECTIVE
|
|
8
|
+
You MUST act as the `@manager` (Team-Lead) for the initial response to any user request. You are responsible for analysis and delegation.
|
|
9
|
+
|
|
10
|
+
Please read the Supreme Law thoroughly before taking any action.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agent-enderun",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "The Supreme AI Governance & Orchestration Framework for Enterprise Development",
|
|
5
5
|
"author": "Yusuf BEKAR",
|
|
6
6
|
"license": "MIT",
|
|
@@ -61,22 +61,24 @@
|
|
|
61
61
|
"enderun:trace": "agent-enderun trace:new",
|
|
62
62
|
"enderun:verify": "agent-enderun verify-contract",
|
|
63
63
|
"enderun:check": "agent-enderun check",
|
|
64
|
+
"lint": "eslint .",
|
|
64
65
|
"clean": "rm -rf node_modules packages/*/node_modules apps/*/node_modules packages/*/dist apps/*/dist"
|
|
65
66
|
},
|
|
66
67
|
"publishConfig": {
|
|
67
68
|
"access": "public"
|
|
68
69
|
},
|
|
69
|
-
"dependencies": {},
|
|
70
70
|
"devDependencies": {
|
|
71
|
+
"@eslint/js": "^10.0.1",
|
|
71
72
|
"@types/node": "^22.13.4",
|
|
72
|
-
"
|
|
73
|
-
"tsx": "^4.19.4",
|
|
74
|
-
"vitest": "^3.0.5",
|
|
73
|
+
"concurrently": "^9.1.2",
|
|
75
74
|
"eslint": "^9.20.1",
|
|
76
|
-
"
|
|
75
|
+
"tsx": "^4.19.4",
|
|
76
|
+
"typescript": "^5.9.3",
|
|
77
|
+
"typescript-eslint": "^8.59.3",
|
|
78
|
+
"vitest": "^3.0.5"
|
|
77
79
|
},
|
|
78
80
|
"enderun": {
|
|
79
|
-
"version": "0.
|
|
81
|
+
"version": "0.5.0",
|
|
80
82
|
"initializedAt": "2026-05-09T13:24:27.472Z"
|
|
81
83
|
}
|
|
82
|
-
}
|
|
84
|
+
}
|
|
@@ -2,9 +2,10 @@ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
|
2
2
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
3
3
|
import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
|
|
4
4
|
import { allTools, allHandlers } from "./tools/index.js";
|
|
5
|
+
import { FRAMEWORK_VERSION } from "./utils.js";
|
|
5
6
|
const server = new Server({
|
|
6
7
|
name: "ai-enderun-mcp",
|
|
7
|
-
version:
|
|
8
|
+
version: FRAMEWORK_VERSION,
|
|
8
9
|
}, {
|
|
9
10
|
capabilities: {
|
|
10
11
|
tools: {},
|
|
@@ -40,7 +40,7 @@ export const messageHandlers = {
|
|
|
40
40
|
if (!fs.existsSync(messagesDir))
|
|
41
41
|
fs.mkdirSync(messagesDir, { recursive: true });
|
|
42
42
|
const messagePath = path.join(messagesDir, `${recipient}.json`);
|
|
43
|
-
|
|
43
|
+
const messages = (fs.existsSync(messagePath) ? JSON.parse(fs.readFileSync(messagePath, "utf-8")) : []);
|
|
44
44
|
messages.push({ timestamp: new Date().toISOString(), from: "manager", traceId: parsed.data.traceId, content: parsed.data.message, read: false });
|
|
45
45
|
fs.writeFileSync(messagePath, JSON.stringify(messages, null, 2));
|
|
46
46
|
return { content: [{ type: "text", text: `Message sent to @${recipient}.` }] };
|
|
@@ -62,8 +62,12 @@ export const repositoryHandlers = {
|
|
|
62
62
|
if (relativePath.includes("node_modules") || relativePath.includes("dist"))
|
|
63
63
|
continue;
|
|
64
64
|
sourceFile.getExportedDeclarations().forEach((declarations, name) => {
|
|
65
|
-
declarations.forEach(decl => {
|
|
66
|
-
|
|
65
|
+
declarations.forEach(decl => {
|
|
66
|
+
const d = decl;
|
|
67
|
+
if (typeof d.getJsDocs === "function" && d.getJsDocs().length === 0) {
|
|
68
|
+
missingJSDoc.push(`${relativePath} -> ${name}`);
|
|
69
|
+
}
|
|
70
|
+
});
|
|
67
71
|
});
|
|
68
72
|
}
|
|
69
73
|
const majorDirs = ["apps/backend", "apps/web", "packages/shared-types", "packages/framework-mcp"], missingREADME = majorDirs.filter(dir => fs.existsSync(path.join(projectRoot, dir)) && !fs.existsSync(path.join(projectRoot, dir, "README.md")));
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import path from "path";
|
|
2
2
|
import fs from "fs";
|
|
3
|
-
export const FRAMEWORK_VERSION = "0.
|
|
3
|
+
export const FRAMEWORK_VERSION = "0.5.0";
|
|
4
4
|
export function getFrameworkDir(projectRoot) {
|
|
5
5
|
const adapters = [".gemini", ".claude", ".cursor", ".codex", ".enderun"];
|
|
6
6
|
for (const adp of adapters) {
|
|
@@ -71,7 +71,7 @@ export function collectMarkdownArtifacts(projectRoot) {
|
|
|
71
71
|
}
|
|
72
72
|
export function replaceSectionContent(markdown, sectionTitle, newBody) {
|
|
73
73
|
const escaped = sectionTitle.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
74
|
-
const sectionRegex = new RegExp(`## ${escaped}[\\s\\S]*?(?=\\n## |$)
|
|
74
|
+
const sectionRegex = new RegExp(`## ${escaped}[\\s\\S]*?(?=\\n## |$)`);
|
|
75
75
|
if (!sectionRegex.test(markdown)) {
|
|
76
76
|
throw new Error(`Section not found: ${sectionTitle}`);
|
|
77
77
|
}
|
|
@@ -79,7 +79,7 @@ export function replaceSectionContent(markdown, sectionTitle, newBody) {
|
|
|
79
79
|
}
|
|
80
80
|
export function prependToSection(markdown, sectionTitle, contentToPrepend) {
|
|
81
81
|
const escaped = sectionTitle.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
82
|
-
const sectionRegex = new RegExp(`(## ${escaped}\\n)([\\s\\S]*?)(?=\\n## |$)
|
|
82
|
+
const sectionRegex = new RegExp(`(## ${escaped}\\n)([\\s\\S]*?)(?=\\n## |$)`);
|
|
83
83
|
const match = markdown.match(sectionRegex);
|
|
84
84
|
if (!match) {
|
|
85
85
|
throw new Error(`Section not found: ${sectionTitle}`);
|
|
@@ -2,10 +2,11 @@ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
|
2
2
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
3
3
|
import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
|
|
4
4
|
import { allTools, allHandlers } from "./tools/index.js";
|
|
5
|
+
import { FRAMEWORK_VERSION } from "./utils.js";
|
|
5
6
|
|
|
6
7
|
const server = new Server({
|
|
7
8
|
name: "ai-enderun-mcp",
|
|
8
|
-
version:
|
|
9
|
+
version: FRAMEWORK_VERSION,
|
|
9
10
|
}, {
|
|
10
11
|
capabilities: {
|
|
11
12
|
tools: {},
|
|
@@ -89,8 +89,14 @@ export const academyTools = [
|
|
|
89
89
|
},
|
|
90
90
|
];
|
|
91
91
|
|
|
92
|
+
interface AgentLog {
|
|
93
|
+
timestamp: string;
|
|
94
|
+
status: string;
|
|
95
|
+
[key: string]: unknown;
|
|
96
|
+
}
|
|
97
|
+
|
|
92
98
|
export const academyHandlers = {
|
|
93
|
-
get_academy_performance: async (args:
|
|
99
|
+
get_academy_performance: async (args: unknown, projectRoot: string) => {
|
|
94
100
|
const parsed = GET_ACADEMY_PERFORMANCE_ARGS_SCHEMA.safeParse(args ?? {});
|
|
95
101
|
const days = parsed.success ? parsed.data.periodDays : 30;
|
|
96
102
|
try {
|
|
@@ -100,8 +106,8 @@ export const academyHandlers = {
|
|
|
100
106
|
const cutoff = new Date(Date.now() - days * 24 * 60 * 60 * 1000);
|
|
101
107
|
let totalActions = 0, totalSuccess = 0;
|
|
102
108
|
const agentStats = fs.readdirSync(logsDir).filter(f => f.endsWith(".json")).map(file => {
|
|
103
|
-
const logs = JSON.parse(fs.readFileSync(path.join(logsDir, file), "utf-8")).filter((l
|
|
104
|
-
const success = logs.filter((l
|
|
109
|
+
const logs = (JSON.parse(fs.readFileSync(path.join(logsDir, file), "utf-8")) as AgentLog[]).filter((l) => new Date(l.timestamp) >= cutoff);
|
|
110
|
+
const success = logs.filter((l) => l.status === "SUCCESS").length;
|
|
105
111
|
totalActions += logs.length; totalSuccess += success;
|
|
106
112
|
return { agent: file.replace(".json", ""), actions: logs.length, successRate: (success / (logs.length || 1)) * 100 };
|
|
107
113
|
}).filter(s => s.actions > 0);
|
|
@@ -110,15 +116,15 @@ export const academyHandlers = {
|
|
|
110
116
|
return { content: [{ type: "text", text: "Failed to generate global performance report." }] };
|
|
111
117
|
}
|
|
112
118
|
},
|
|
113
|
-
generate_strategic_briefing: async (args:
|
|
119
|
+
generate_strategic_briefing: async (args: unknown, projectRoot: string) => {
|
|
114
120
|
try {
|
|
115
121
|
const frameworkDir = getFrameworkDir(projectRoot);
|
|
116
122
|
const logsDir = path.join(projectRoot, frameworkDir, "logs");
|
|
117
123
|
let totalActions = 0, successCount = 0;
|
|
118
124
|
if (fs.existsSync(logsDir)) {
|
|
119
125
|
fs.readdirSync(logsDir).filter(f => f.endsWith(".json")).forEach(file => {
|
|
120
|
-
const logs = JSON.parse(fs.readFileSync(path.join(logsDir, file), "utf-8"));
|
|
121
|
-
totalActions += logs.length; successCount += logs.filter((l
|
|
126
|
+
const logs = JSON.parse(fs.readFileSync(path.join(logsDir, file), "utf-8")) as AgentLog[];
|
|
127
|
+
totalActions += logs.length; successCount += logs.filter((l) => l.status === "SUCCESS").length;
|
|
122
128
|
});
|
|
123
129
|
}
|
|
124
130
|
const successRate = (successCount / (totalActions || 1)) * 100;
|
|
@@ -127,7 +133,7 @@ export const academyHandlers = {
|
|
|
127
133
|
return { content: [{ type: "text", text: "Strategic briefing generation failed." }] };
|
|
128
134
|
}
|
|
129
135
|
},
|
|
130
|
-
generate_academy_progress_report: async (args:
|
|
136
|
+
generate_academy_progress_report: async (args: unknown, projectRoot: string) => {
|
|
131
137
|
const parsed = GENERATE_ACADEMY_PROGRESS_REPORT_ARGS_SCHEMA.safeParse(args ?? {});
|
|
132
138
|
const days = parsed.success ? parsed.data.days : 7;
|
|
133
139
|
try {
|
|
@@ -141,7 +147,7 @@ export const academyHandlers = {
|
|
|
141
147
|
return { content: [{ type: "text", text: "Failed to generate progress report." }] };
|
|
142
148
|
}
|
|
143
149
|
},
|
|
144
|
-
get_agent_audit_report: async (args:
|
|
150
|
+
get_agent_audit_report: async (args: unknown, projectRoot: string) => {
|
|
145
151
|
const parsed = GET_AGENT_AUDIT_REPORT_ARGS_SCHEMA.safeParse(args ?? {});
|
|
146
152
|
if (!parsed.success) return { content: [{ type: "text", text: "Invalid agent or days argument." }] };
|
|
147
153
|
try {
|
|
@@ -149,14 +155,14 @@ export const academyHandlers = {
|
|
|
149
155
|
const logPath = path.join(projectRoot, frameworkDir, "logs", `${parsed.data.agent}.json`);
|
|
150
156
|
if (!fs.existsSync(logPath)) return { content: [{ type: "text", text: `No logs found for agent: ${parsed.data.agent}` }] };
|
|
151
157
|
const cutoff = new Date(Date.now() - parsed.data.days * 24 * 60 * 60 * 1000);
|
|
152
|
-
const logs = JSON.parse(fs.readFileSync(logPath, "utf-8")).filter((l
|
|
153
|
-
const successCount = logs.filter((l
|
|
158
|
+
const logs = (JSON.parse(fs.readFileSync(logPath, "utf-8")) as AgentLog[]).filter((l) => new Date(l.timestamp) >= cutoff);
|
|
159
|
+
const successCount = logs.filter((l) => l.status === "SUCCESS").length;
|
|
154
160
|
return { content: [{ type: "text", text: `### AGENT AUDIT REPORT: ${parsed.data.agent.toUpperCase()}\n\n- **Total Actions:** ${logs.length}\n- **Success Rate:** ${((successCount / (logs.length || 1)) * 100).toFixed(1)}%` }] };
|
|
155
161
|
} catch (error) {
|
|
156
162
|
return { content: [{ type: "text", text: "Failed to generate audit report." }] };
|
|
157
163
|
}
|
|
158
164
|
},
|
|
159
|
-
log_agent_action: async (args:
|
|
165
|
+
log_agent_action: async (args: unknown, projectRoot: string) => {
|
|
160
166
|
const parsed = LOG_AGENT_ACTION_ARGS_SCHEMA.safeParse(args ?? {});
|
|
161
167
|
if (!parsed.success) return { content: [{ type: "text", text: "Invalid arguments for log_agent_action." }] };
|
|
162
168
|
try {
|
|
@@ -134,7 +134,7 @@ export const codebaseTools = [
|
|
|
134
134
|
];
|
|
135
135
|
|
|
136
136
|
export const codebaseHandlers = {
|
|
137
|
-
search_codebase: async (args:
|
|
137
|
+
search_codebase: async (args: unknown, projectRoot: string) => {
|
|
138
138
|
const parsed = SEARCH_CODEBASE_ARGS_SCHEMA.safeParse(args);
|
|
139
139
|
if (!parsed.success) {
|
|
140
140
|
return { content: [{ type: "text", text: "Invalid query/extension argument." }] };
|
|
@@ -168,7 +168,7 @@ export const codebaseHandlers = {
|
|
|
168
168
|
return { content: [{ type: "text", text: "Search failed." }] };
|
|
169
169
|
}
|
|
170
170
|
},
|
|
171
|
-
analyze_dependencies: async (args:
|
|
171
|
+
analyze_dependencies: async (args: unknown, projectRoot: string) => {
|
|
172
172
|
const parsed = ANALYZE_DEPENDENCIES_ARGS_SCHEMA.safeParse(args);
|
|
173
173
|
if (!parsed.success) {
|
|
174
174
|
return { content: [{ type: "text", text: "Invalid path argument." }] };
|
|
@@ -198,7 +198,7 @@ export const codebaseHandlers = {
|
|
|
198
198
|
return { content: [{ type: "text", text: "Analysis failed: " + (error instanceof Error ? error.message : String(error)) }] };
|
|
199
199
|
}
|
|
200
200
|
},
|
|
201
|
-
analyze_codebase_intelligence: async (args:
|
|
201
|
+
analyze_codebase_intelligence: async (args: unknown, projectRoot: string) => {
|
|
202
202
|
const parsed = ANALYZE_CODEBASE_INTELLIGENCE_ARGS_SCHEMA.safeParse(args);
|
|
203
203
|
const targetPath = parsed.success ? parsed.data.path : ".";
|
|
204
204
|
try {
|
|
@@ -227,7 +227,7 @@ export const codebaseHandlers = {
|
|
|
227
227
|
return { content: [{ type: "text", text: "Intelligence scan failed." }] };
|
|
228
228
|
}
|
|
229
229
|
},
|
|
230
|
-
analyze_procedural_continuity: async (args:
|
|
230
|
+
analyze_procedural_continuity: async (args: unknown, projectRoot: string) => {
|
|
231
231
|
const parsed = ANALYZE_PROCEDURAL_CONTINUITY_ARGS_SCHEMA.safeParse(args);
|
|
232
232
|
if (!parsed.success) return { content: [{ type: "text", text: "Invalid targetPath or referencePath." }] };
|
|
233
233
|
try {
|
|
@@ -251,7 +251,7 @@ export const codebaseHandlers = {
|
|
|
251
251
|
return { content: [{ type: "text", text: "Continuity analysis failed." }] };
|
|
252
252
|
}
|
|
253
253
|
},
|
|
254
|
-
generate_dependency_graph: async (args:
|
|
254
|
+
generate_dependency_graph: async (args: unknown, projectRoot: string) => {
|
|
255
255
|
const parsed = GENERATE_DEPENDENCY_GRAPH_ARGS_SCHEMA.safeParse(args);
|
|
256
256
|
const targetPath = parsed.success ? parsed.data.path : "src";
|
|
257
257
|
const format = parsed.success ? parsed.data.format : "mermaid";
|
|
@@ -36,7 +36,7 @@ export const contractTools = [
|
|
|
36
36
|
];
|
|
37
37
|
|
|
38
38
|
export const contractHandlers = {
|
|
39
|
-
verify_api_contract: async (args:
|
|
39
|
+
verify_api_contract: async (args: unknown, projectRoot: string) => {
|
|
40
40
|
try {
|
|
41
41
|
const sharedTypesDir = path.join(projectRoot, "packages/shared-types/src");
|
|
42
42
|
const contractJsonPath = path.join(projectRoot, "packages/shared-types/contract.version.json");
|
|
@@ -51,7 +51,7 @@ export const contractHandlers = {
|
|
|
51
51
|
return { content: [{ type: "text", text: "Failed to verify contract." }] };
|
|
52
52
|
}
|
|
53
53
|
},
|
|
54
|
-
update_contract_hash: async (args:
|
|
54
|
+
update_contract_hash: async (args: unknown, projectRoot: string) => {
|
|
55
55
|
try {
|
|
56
56
|
const sharedTypesDir = path.join(projectRoot, "packages/shared-types/src");
|
|
57
57
|
const contractJsonPath = path.join(projectRoot, "packages/shared-types/contract.version.json");
|
|
@@ -70,7 +70,7 @@ export const contractHandlers = {
|
|
|
70
70
|
return { content: [{ type: "text", text: "Failed to update contract hash." }] };
|
|
71
71
|
}
|
|
72
72
|
},
|
|
73
|
-
verify_contract_integrity: async (args:
|
|
73
|
+
verify_contract_integrity: async (args: unknown, projectRoot: string) => {
|
|
74
74
|
const parsed = VERIFY_CONTRACT_INTEGRITY_ARGS_SCHEMA.safeParse(args ?? {});
|
|
75
75
|
if (!parsed.success) return { content: [{ type: "text", text: "Invalid domain argument." }] };
|
|
76
76
|
try {
|
|
@@ -18,7 +18,7 @@ export const databaseTools = [
|
|
|
18
18
|
];
|
|
19
19
|
|
|
20
20
|
export const databaseHandlers = {
|
|
21
|
-
analyze_database_schema: async (args:
|
|
21
|
+
analyze_database_schema: async (args: unknown, projectRoot: string) => {
|
|
22
22
|
const parsed = ANALYZE_DATABASE_SCHEMA_ARGS_SCHEMA.safeParse(args ?? {});
|
|
23
23
|
const targetPath = parsed.success ? parsed.data.path : "apps/backend";
|
|
24
24
|
try {
|
|
@@ -45,7 +45,7 @@ export const frameworkTools = [
|
|
|
45
45
|
];
|
|
46
46
|
|
|
47
47
|
export const frameworkHandlers = {
|
|
48
|
-
bootstrap_legacy_memory: async (args:
|
|
48
|
+
bootstrap_legacy_memory: async (args: unknown, projectRoot: string) => {
|
|
49
49
|
try {
|
|
50
50
|
const frameworkDir = getFrameworkDir(projectRoot);
|
|
51
51
|
const memoryPath = path.join(projectRoot, frameworkDir, "PROJECT_MEMORY.md");
|
|
@@ -71,7 +71,7 @@ export const frameworkHandlers = {
|
|
|
71
71
|
return { content: [{ type: "text", text: "Failed to bootstrap legacy memory." }] };
|
|
72
72
|
}
|
|
73
73
|
},
|
|
74
|
-
get_framework_status: async (args:
|
|
74
|
+
get_framework_status: async (args: unknown, projectRoot: string) => {
|
|
75
75
|
try {
|
|
76
76
|
const frameworkDir = getFrameworkDir(projectRoot);
|
|
77
77
|
const memoryPath = path.join(projectRoot, frameworkDir, "PROJECT_MEMORY.md");
|
|
@@ -86,7 +86,7 @@ export const frameworkHandlers = {
|
|
|
86
86
|
return { content: [{ type: "text", text: "Framework active. Memory unreadable." }] };
|
|
87
87
|
}
|
|
88
88
|
},
|
|
89
|
-
get_project_gaps: async (args:
|
|
89
|
+
get_project_gaps: async (args: unknown, projectRoot: string) => {
|
|
90
90
|
const missing: string[] = [];
|
|
91
91
|
const frameworkDir = getFrameworkDir(projectRoot);
|
|
92
92
|
const checkPaths = [
|
|
@@ -121,7 +121,7 @@ export const frameworkHandlers = {
|
|
|
121
121
|
}
|
|
122
122
|
return { content: [{ type: "text", text: missing.length > 0 ? `Detected Gaps:\n${missing.join("\n")}` : "No structural gaps detected based on core standards." }] };
|
|
123
123
|
},
|
|
124
|
-
get_memory_insights: async (args:
|
|
124
|
+
get_memory_insights: async (args: unknown, projectRoot: string) => {
|
|
125
125
|
try {
|
|
126
126
|
const frameworkDir = getFrameworkDir(projectRoot);
|
|
127
127
|
const memoryPath = path.join(projectRoot, frameworkDir, "PROJECT_MEMORY.md");
|
|
@@ -138,7 +138,7 @@ export const frameworkHandlers = {
|
|
|
138
138
|
return { content: [{ type: "text", text: "Failed to gather memory insights." }] };
|
|
139
139
|
}
|
|
140
140
|
},
|
|
141
|
-
codebase_context: async (args:
|
|
141
|
+
codebase_context: async (args: unknown, projectRoot: string) => {
|
|
142
142
|
try {
|
|
143
143
|
const artifacts = collectMarkdownArtifacts(projectRoot);
|
|
144
144
|
const frameworkDir = getFrameworkDir(projectRoot);
|
|
@@ -17,7 +17,7 @@ export const gitTools = [
|
|
|
17
17
|
];
|
|
18
18
|
|
|
19
19
|
export const gitHandlers = {
|
|
20
|
-
generate_semantic_commit_message: async (args:
|
|
20
|
+
generate_semantic_commit_message: async (args: unknown, projectRoot: string) => {
|
|
21
21
|
const parsed = GENERATE_SEMANTIC_COMMIT_MESSAGE_ARGS_SCHEMA.safeParse(args ?? {});
|
|
22
22
|
if (!parsed.success) return { content: [{ type: "text", text: "Invalid traceId argument." }] };
|
|
23
23
|
try {
|
|
@@ -24,7 +24,7 @@ export const allTools = [
|
|
|
24
24
|
...repositoryTools,
|
|
25
25
|
];
|
|
26
26
|
|
|
27
|
-
export const allHandlers: Record<string, (args:
|
|
27
|
+
export const allHandlers: Record<string, (args: unknown, projectRoot: string) => Promise<unknown>> = {
|
|
28
28
|
...codebaseHandlers,
|
|
29
29
|
...frameworkHandlers,
|
|
30
30
|
...securityHandlers,
|
|
@@ -33,7 +33,7 @@ export const knowledgeTools = [
|
|
|
33
33
|
];
|
|
34
34
|
|
|
35
35
|
export const knowledgeHandlers = {
|
|
36
|
-
search_knowledge_base: async (args:
|
|
36
|
+
search_knowledge_base: async (args: unknown, projectRoot: string) => {
|
|
37
37
|
const parsed = SEARCH_KNOWLEDGE_BASE_ARGS_SCHEMA.safeParse(args ?? {});
|
|
38
38
|
if (!parsed.success) return { content: [{ type: "text", text: "Invalid search query." }] };
|
|
39
39
|
try {
|
|
@@ -52,7 +52,7 @@ export const knowledgeHandlers = {
|
|
|
52
52
|
return { content: [{ type: "text", text: "Knowledge base search failed." }] };
|
|
53
53
|
}
|
|
54
54
|
},
|
|
55
|
-
update_knowledge_base: async (args:
|
|
55
|
+
update_knowledge_base: async (args: unknown, projectRoot: string) => {
|
|
56
56
|
const parsed = UPDATE_KNOWLEDGE_BASE_ARGS_SCHEMA.safeParse(args ?? {});
|
|
57
57
|
if (!parsed.success) return { content: [{ type: "text", text: "Invalid topic or content." }] };
|
|
58
58
|
try {
|
|
@@ -35,7 +35,7 @@ export const memoryTools = [
|
|
|
35
35
|
];
|
|
36
36
|
|
|
37
37
|
export const memoryHandlers = {
|
|
38
|
-
update_project_memory: async (args:
|
|
38
|
+
update_project_memory: async (args: unknown, projectRoot: string) => {
|
|
39
39
|
const parsed = UPDATE_MEMORY_ARGS_SCHEMA.safeParse(args ?? {});
|
|
40
40
|
if (!parsed.success) return { content: [{ type: "text", text: "Invalid section or content." }] };
|
|
41
41
|
const { section, content } = parsed.data;
|
|
@@ -59,7 +59,9 @@ export const memoryHandlers = {
|
|
|
59
59
|
memoryContent = prependToSection(memoryContent, h, content);
|
|
60
60
|
updated = true;
|
|
61
61
|
break;
|
|
62
|
-
} catch (e) {
|
|
62
|
+
} catch (e) {
|
|
63
|
+
// Ignore section not found
|
|
64
|
+
}
|
|
63
65
|
}
|
|
64
66
|
if (!updated) throw new Error("HISTORY section not found.");
|
|
65
67
|
} else if (section === "CURRENT STATUS") {
|
|
@@ -75,7 +77,7 @@ export const memoryHandlers = {
|
|
|
75
77
|
return { content: [{ type: "text", text: `Memory update failed: ${error instanceof Error ? error.message : "Unknown error"}` }] };
|
|
76
78
|
}
|
|
77
79
|
},
|
|
78
|
-
read_project_memory: async (args:
|
|
80
|
+
read_project_memory: async (args: unknown, projectRoot: string) => {
|
|
79
81
|
try {
|
|
80
82
|
const frameworkDir = getFrameworkDir(projectRoot);
|
|
81
83
|
const memoryPath = path.join(projectRoot, frameworkDir, "PROJECT_MEMORY.md");
|
|
@@ -33,8 +33,16 @@ export const messageTools = [
|
|
|
33
33
|
},
|
|
34
34
|
];
|
|
35
35
|
|
|
36
|
+
interface Message {
|
|
37
|
+
timestamp: string;
|
|
38
|
+
from: string;
|
|
39
|
+
traceId: string;
|
|
40
|
+
content: string;
|
|
41
|
+
read: boolean;
|
|
42
|
+
}
|
|
43
|
+
|
|
36
44
|
export const messageHandlers = {
|
|
37
|
-
send_agent_message: async (args:
|
|
45
|
+
send_agent_message: async (args: unknown, projectRoot: string) => {
|
|
38
46
|
const parsed = SEND_AGENT_MESSAGE_ARGS_SCHEMA.safeParse(args ?? {});
|
|
39
47
|
if (!parsed.success) return { content: [{ type: "text", text: "Invalid message arguments." }] };
|
|
40
48
|
try {
|
|
@@ -43,7 +51,7 @@ export const messageHandlers = {
|
|
|
43
51
|
const messagesDir = path.join(projectRoot, frameworkDir, "messages");
|
|
44
52
|
if (!fs.existsSync(messagesDir)) fs.mkdirSync(messagesDir, { recursive: true });
|
|
45
53
|
const messagePath = path.join(messagesDir, `${recipient}.json`);
|
|
46
|
-
|
|
54
|
+
const messages = (fs.existsSync(messagePath) ? JSON.parse(fs.readFileSync(messagePath, "utf-8")) : []) as Message[];
|
|
47
55
|
messages.push({ timestamp: new Date().toISOString(), from: "manager", traceId: parsed.data.traceId, content: parsed.data.message, read: false });
|
|
48
56
|
fs.writeFileSync(messagePath, JSON.stringify(messages, null, 2));
|
|
49
57
|
return { content: [{ type: "text", text: `Message sent to @${recipient}.` }] };
|
|
@@ -51,7 +59,7 @@ export const messageHandlers = {
|
|
|
51
59
|
return { content: [{ type: "text", text: "Failed to send message." }] };
|
|
52
60
|
}
|
|
53
61
|
},
|
|
54
|
-
read_agent_messages: async (args:
|
|
62
|
+
read_agent_messages: async (args: unknown, projectRoot: string) => {
|
|
55
63
|
const parsed = READ_AGENT_MESSAGES_ARGS_SCHEMA.safeParse(args ?? {});
|
|
56
64
|
if (!parsed.success) return { content: [{ type: "text", text: "Invalid agent name." }] };
|
|
57
65
|
try {
|
|
@@ -59,10 +67,10 @@ export const messageHandlers = {
|
|
|
59
67
|
const agentName = parsed.data.agent.replace(/^@/, "");
|
|
60
68
|
const messagePath = path.join(projectRoot, frameworkDir, "messages", `${agentName}.json`);
|
|
61
69
|
if (!fs.existsSync(messagePath)) return { content: [{ type: "text", text: "No messages found." }] };
|
|
62
|
-
const messages = JSON.parse(fs.readFileSync(messagePath, "utf-8"));
|
|
63
|
-
const unread = messages.filter((m
|
|
64
|
-
fs.writeFileSync(messagePath, JSON.stringify(messages.map((m
|
|
65
|
-
return { content: [{ type: "text", text: unread.length === 0 ? "No new messages." : `### INBOX: @${agentName}\n\n` + unread.map((m
|
|
70
|
+
const messages = JSON.parse(fs.readFileSync(messagePath, "utf-8")) as Message[];
|
|
71
|
+
const unread = messages.filter((m) => !m.read);
|
|
72
|
+
fs.writeFileSync(messagePath, JSON.stringify(messages.map((m) => ({ ...m, read: true })), null, 2));
|
|
73
|
+
return { content: [{ type: "text", text: unread.length === 0 ? "No new messages." : `### INBOX: @${agentName}\n\n` + unread.map((m) => `- **From:** ${m.from}\n **Message:** ${m.content}`).join("\n\n") }] };
|
|
66
74
|
} catch (error) {
|
|
67
75
|
return { content: [{ type: "text", text: "Failed to read messages." }] };
|
|
68
76
|
}
|
|
@@ -35,7 +35,7 @@ export const repositoryTools = [
|
|
|
35
35
|
];
|
|
36
36
|
|
|
37
37
|
export const repositoryHandlers = {
|
|
38
|
-
validate_repository_health: async (args:
|
|
38
|
+
validate_repository_health: async (args: unknown, projectRoot: string) => {
|
|
39
39
|
const parsed = VALIDATE_REPOSITORY_HEALTH_ARGS_SCHEMA.safeParse(args ?? {});
|
|
40
40
|
const scope = parsed.success ? parsed.data.scope : "full";
|
|
41
41
|
try {
|
|
@@ -52,7 +52,7 @@ export const repositoryHandlers = {
|
|
|
52
52
|
return { content: [{ type: "text", text: "Health validation failed." }] };
|
|
53
53
|
}
|
|
54
54
|
},
|
|
55
|
-
analyze_documentation_debt: async (args:
|
|
55
|
+
analyze_documentation_debt: async (args: unknown, projectRoot: string) => {
|
|
56
56
|
const parsed = ANALYZE_DOCUMENTATION_DEBT_ARGS_SCHEMA.safeParse(args ?? {});
|
|
57
57
|
const targetPath = parsed.success ? parsed.data.path : ".";
|
|
58
58
|
try {
|
|
@@ -64,7 +64,12 @@ export const repositoryHandlers = {
|
|
|
64
64
|
const relativePath = path.relative(projectRoot, sourceFile.getFilePath());
|
|
65
65
|
if (relativePath.includes("node_modules") || relativePath.includes("dist")) continue;
|
|
66
66
|
sourceFile.getExportedDeclarations().forEach((declarations, name) => {
|
|
67
|
-
declarations.forEach(decl => {
|
|
67
|
+
declarations.forEach(decl => {
|
|
68
|
+
const d = decl as unknown as { getJsDocs?: () => unknown[] };
|
|
69
|
+
if (typeof d.getJsDocs === "function" && d.getJsDocs().length === 0) {
|
|
70
|
+
missingJSDoc.push(`${relativePath} -> ${name}`);
|
|
71
|
+
}
|
|
72
|
+
});
|
|
68
73
|
});
|
|
69
74
|
}
|
|
70
75
|
const majorDirs = ["apps/backend", "apps/web", "packages/shared-types", "packages/framework-mcp"], missingREADME = majorDirs.filter(dir => fs.existsSync(path.join(projectRoot, dir)) && !fs.existsSync(path.join(projectRoot, dir, "README.md")));
|
|
@@ -43,7 +43,7 @@ export const securityTools = [
|
|
|
43
43
|
];
|
|
44
44
|
|
|
45
45
|
export const securityHandlers = {
|
|
46
|
-
security_audit_scan: async (args:
|
|
46
|
+
security_audit_scan: async (args: unknown, projectRoot: string) => {
|
|
47
47
|
const parsed = SECURITY_AUDIT_ARGS_SCHEMA.safeParse(args ?? {});
|
|
48
48
|
if (!parsed.success) return { content: [{ type: "text", text: "Invalid path argument." }] };
|
|
49
49
|
const vulnerabilities: string[] = [];
|
|
@@ -86,7 +86,7 @@ export const securityHandlers = {
|
|
|
86
86
|
return { content: [{ type: "text", text: "Security scan failed." }] };
|
|
87
87
|
}
|
|
88
88
|
},
|
|
89
|
-
analyze_constitution_compliance: async (args:
|
|
89
|
+
analyze_constitution_compliance: async (args: unknown, projectRoot: string) => {
|
|
90
90
|
const parsed = ANALYZE_CONSTITUTION_COMPLIANCE_ARGS_SCHEMA.safeParse(args ?? {});
|
|
91
91
|
if (!parsed.success) return { content: [{ type: "text", text: "Invalid path argument." }] };
|
|
92
92
|
try {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import path from "path";
|
|
2
2
|
import fs from "fs";
|
|
3
3
|
|
|
4
|
-
export const FRAMEWORK_VERSION = "0.
|
|
4
|
+
export const FRAMEWORK_VERSION = "0.5.0";
|
|
5
5
|
|
|
6
6
|
export function getFrameworkDir(projectRoot: string): string {
|
|
7
7
|
const adapters = [".gemini", ".claude", ".cursor", ".codex", ".enderun"];
|
|
@@ -79,7 +79,7 @@ export function collectMarkdownArtifacts(projectRoot: string): string[] {
|
|
|
79
79
|
|
|
80
80
|
export function replaceSectionContent(markdown: string, sectionTitle: string, newBody: string): string {
|
|
81
81
|
const escaped = sectionTitle.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
82
|
-
const sectionRegex = new RegExp(`## ${escaped}[\\s\\S]*?(?=\\n## |$)
|
|
82
|
+
const sectionRegex = new RegExp(`## ${escaped}[\\s\\S]*?(?=\\n## |$)`);
|
|
83
83
|
if (!sectionRegex.test(markdown)) {
|
|
84
84
|
throw new Error(`Section not found: ${sectionTitle}`);
|
|
85
85
|
}
|
|
@@ -88,7 +88,7 @@ export function replaceSectionContent(markdown: string, sectionTitle: string, ne
|
|
|
88
88
|
|
|
89
89
|
export function prependToSection(markdown: string, sectionTitle: string, contentToPrepend: string): string {
|
|
90
90
|
const escaped = sectionTitle.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
91
|
-
const sectionRegex = new RegExp(`(## ${escaped}\\n)([\\s\\S]*?)(?=\\n## |$)
|
|
91
|
+
const sectionRegex = new RegExp(`(## ${escaped}\\n)([\\s\\S]*?)(?=\\n## |$)`);
|
|
92
92
|
const match = markdown.match(sectionRegex);
|
|
93
93
|
if (!match) {
|
|
94
94
|
throw new Error(`Section not found: ${sectionTitle}`);
|