Skip to content

Commit 3cb811b

Browse files
author
Vitor Castro
committed
Drive the agent from tool contracts instead of intent crutches.
Centralize OpenAI tool descriptions and a system tool contract, drop chat-phrase enrich/nudges, treat identical edits as already applied, and lift Qwen/Hermes XML tool markup into native tool_calls so OSS models stay on the tool path.
1 parent 87fd2e1 commit 3cb811b

35 files changed

Lines changed: 3089 additions & 411 deletions
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
---
2+
description: No intent crutches — agent works from tool contract, not chat/phrase triggers
3+
alwaysApply: true
4+
---
5+
6+
# No intent crutches
7+
8+
CodeForge’s agent must work from a stable **tool + system contract**, not from hardcoded intent detection.
9+
10+
## Forbidden
11+
12+
- Rewriting the user message with “Harness note” / apply / continue enrichers based on phrase matchers
13+
- Regex (or similar) sniffers on user or assistant text to decide the model “meant apply / corrija / I’ll fix”
14+
- Soft coaching nudges injected as fake `user` turns (“you narrated without tools”, “thin final”, “stuck — try edit”)
15+
- Growing matchers for Portuguese/English synonyms instead of fixing tools or the system prompt
16+
17+
Portuguese/English regexes are allowed only as **matchers of user input** where the product must recognize locale (see `english-texts.mdc`), not to drive agent behavior.
18+
19+
## Allowed (structural)
20+
21+
- System prompt and tool schemas that state how to work (`edit` workflow, no prose-only patches)
22+
- Tool-result feedback (`Already applied`, `old_string was not found`, failed-repeat refusal)
23+
- Execution gates: `readThisTurn`, edit fingerprint block, stage/path refusals
24+
- Protocol events: length truncation, invalid tool JSON, step-budget / hard stuck wrap, oracle red
25+
26+
## When the model only describes a fix
27+
28+
Do **not** add a new trigger. Improve the contract (system/`edit` description) or the tool loop so calling tools is the natural path. Leave the failure visible rather than papering over it with matchers.

‎.cursor/rules/no-stubs.mdc‎

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
---
2+
description: Do the real work. Do not ship stubs, fake PASS results, or placeholder UI.
3+
alwaysApply: true
4+
---
5+
6+
# No stubs
7+
8+
Implement the behavior the task asks for. A compiling placeholder is not done.
9+
10+
## Forbidden
11+
12+
- Stubs, `TODO`, `FIXME`, `NotImplementedException`, "Coming soon", "would run here", or SQL / filters that contain `TBD`.
13+
- A `Pass` that only means the HTTP call returned. Validate the business rule (counts, thresholds, mismatches).
14+
- Fake data that looks like a real check. Example: every LELY-237 rule must not be `select Id from workflow_task where Status = 'Error'`.
15+
- A connector without credentials that returns a success sentence. Leave it disabled. Dependent checks stay blocked.
16+
- Admin or report pages that are only a paragraph saying the feature is pending.
17+
18+
## When the source is missing
19+
20+
Return `NotRun` (or blocked-by-connector) with the reason. Leave the task incomplete. Do not invent a result.
21+
22+
## Allowed exceptions
23+
24+
- `ManualCheck` returns `PendingManual` with the runbook steps. That waits for a person.
25+
- LLM evaluation and dashboard-snapshot evidence stay future. Do not stub them into the current path.
26+
27+
## Before you finish
28+
29+
Search the diff for `stub`, `TODO`, `TBD`, `Coming soon`, `NotImplemented`, and `placeholder`. Fix each hit or say the task is incomplete.
30+
31+
Add a test that fails if the new behavior is fake. Examples: Billing Preview must not pass without a comparison; a contracted check must call its API or end as `NotRun`.

‎CodeForge.sln‎

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,26 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{75E704B8
1616
EndProject
1717
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Acme.Billing.Tests", "benchmarks\fixtures\billing\tests\Acme.Billing.Tests\Acme.Billing.Tests.csproj", "{2CBCF198-0448-A543-E33E-B0A55F3610E8}"
1818
EndProject
19+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "billing-bugs", "billing-bugs", "{8544D265-A465-0F90-01C4-AB7342F1F3E3}"
20+
EndProject
21+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{1E15E3F3-1A22-1857-467F-B585F70D613F}"
22+
EndProject
23+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Acme.Billing", "benchmarks\fixtures\billing-bugs\src\Acme.Billing\Acme.Billing.csproj", "{8B787ECE-867E-17FD-AD34-04F838CA4994}"
24+
EndProject
25+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{246F8C51-D31E-DB18-0C1D-891282FB40C3}"
26+
EndProject
27+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Acme.Billing.Tests", "benchmarks\fixtures\billing-bugs\tests\Acme.Billing.Tests\Acme.Billing.Tests.csproj", "{383AF33B-2EFC-F646-35AC-630AA4BEAEE6}"
28+
EndProject
29+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "router-cards", "router-cards", "{01A3F3FF-CA9B-1B1D-C8C2-7EB0EDFAA57D}"
30+
EndProject
31+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{6D84278A-668F-79DE-2FE2-F1ADAAA9651F}"
32+
EndProject
33+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Acme.Router", "benchmarks\fixtures\router-cards\src\Acme.Router\Acme.Router.csproj", "{5875BB8A-0415-4989-120E-20DD977490E2}"
34+
EndProject
35+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{2218CE66-902C-9745-53BA-EC7A446E523E}"
36+
EndProject
37+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Acme.Router.Tests", "benchmarks\fixtures\router-cards\tests\Acme.Router.Tests\Acme.Router.Tests.csproj", "{39486C30-994A-2938-80DF-CA761BD5E5A4}"
38+
EndProject
1939
Global
2040
GlobalSection(SolutionConfigurationPlatforms) = preSolution
2141
Debug|Any CPU = Debug|Any CPU
@@ -30,6 +50,22 @@ Global
3050
{2CBCF198-0448-A543-E33E-B0A55F3610E8}.Debug|Any CPU.Build.0 = Debug|Any CPU
3151
{2CBCF198-0448-A543-E33E-B0A55F3610E8}.Release|Any CPU.ActiveCfg = Release|Any CPU
3252
{2CBCF198-0448-A543-E33E-B0A55F3610E8}.Release|Any CPU.Build.0 = Release|Any CPU
53+
{8B787ECE-867E-17FD-AD34-04F838CA4994}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
54+
{8B787ECE-867E-17FD-AD34-04F838CA4994}.Debug|Any CPU.Build.0 = Debug|Any CPU
55+
{8B787ECE-867E-17FD-AD34-04F838CA4994}.Release|Any CPU.ActiveCfg = Release|Any CPU
56+
{8B787ECE-867E-17FD-AD34-04F838CA4994}.Release|Any CPU.Build.0 = Release|Any CPU
57+
{383AF33B-2EFC-F646-35AC-630AA4BEAEE6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
58+
{383AF33B-2EFC-F646-35AC-630AA4BEAEE6}.Debug|Any CPU.Build.0 = Debug|Any CPU
59+
{383AF33B-2EFC-F646-35AC-630AA4BEAEE6}.Release|Any CPU.ActiveCfg = Release|Any CPU
60+
{383AF33B-2EFC-F646-35AC-630AA4BEAEE6}.Release|Any CPU.Build.0 = Release|Any CPU
61+
{5875BB8A-0415-4989-120E-20DD977490E2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
62+
{5875BB8A-0415-4989-120E-20DD977490E2}.Debug|Any CPU.Build.0 = Debug|Any CPU
63+
{5875BB8A-0415-4989-120E-20DD977490E2}.Release|Any CPU.ActiveCfg = Release|Any CPU
64+
{5875BB8A-0415-4989-120E-20DD977490E2}.Release|Any CPU.Build.0 = Release|Any CPU
65+
{39486C30-994A-2938-80DF-CA761BD5E5A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
66+
{39486C30-994A-2938-80DF-CA761BD5E5A4}.Debug|Any CPU.Build.0 = Debug|Any CPU
67+
{39486C30-994A-2938-80DF-CA761BD5E5A4}.Release|Any CPU.ActiveCfg = Release|Any CPU
68+
{39486C30-994A-2938-80DF-CA761BD5E5A4}.Release|Any CPU.Build.0 = Release|Any CPU
3369
EndGlobalSection
3470
GlobalSection(SolutionProperties) = preSolution
3571
HideSolutionNode = FALSE
@@ -41,8 +77,18 @@ Global
4177
{F2A9ADC8-9C72-F8A6-E9F4-2AE26A42D867} = {87F2DFEF-6771-6C5F-308A-534D1B05A8F9}
4278
{75E704B8-F95A-BA8B-0982-342EDA781354} = {D9734131-DA50-2FA4-E292-8A411DE028FF}
4379
{2CBCF198-0448-A543-E33E-B0A55F3610E8} = {75E704B8-F95A-BA8B-0982-342EDA781354}
80+
{8544D265-A465-0F90-01C4-AB7342F1F3E3} = {AFA72641-1A30-5FD9-46FF-8D3CF9AF32B9}
81+
{1E15E3F3-1A22-1857-467F-B585F70D613F} = {8544D265-A465-0F90-01C4-AB7342F1F3E3}
82+
{8B787ECE-867E-17FD-AD34-04F838CA4994} = {1E15E3F3-1A22-1857-467F-B585F70D613F}
83+
{246F8C51-D31E-DB18-0C1D-891282FB40C3} = {8544D265-A465-0F90-01C4-AB7342F1F3E3}
84+
{383AF33B-2EFC-F646-35AC-630AA4BEAEE6} = {246F8C51-D31E-DB18-0C1D-891282FB40C3}
85+
{01A3F3FF-CA9B-1B1D-C8C2-7EB0EDFAA57D} = {AFA72641-1A30-5FD9-46FF-8D3CF9AF32B9}
86+
{6D84278A-668F-79DE-2FE2-F1ADAAA9651F} = {01A3F3FF-CA9B-1B1D-C8C2-7EB0EDFAA57D}
87+
{5875BB8A-0415-4989-120E-20DD977490E2} = {6D84278A-668F-79DE-2FE2-F1ADAAA9651F}
88+
{2218CE66-902C-9745-53BA-EC7A446E523E} = {01A3F3FF-CA9B-1B1D-C8C2-7EB0EDFAA57D}
89+
{39486C30-994A-2938-80DF-CA761BD5E5A4} = {2218CE66-902C-9745-53BA-EC7A446E523E}
4490
EndGlobalSection
4591
GlobalSection(ExtensibilityGlobals) = postSolution
46-
SolutionGuid = {DC61E0B0-E006-49BD-AAAE-6F2B47245DB7}
92+
SolutionGuid = {EFB205A7-09DC-41C0-9606-C2C8ADD38803}
4793
EndGlobalSection
4894
EndGlobal

‎extensions/codeforge/HEURISTICS.md‎

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,15 +70,30 @@ Classes:
7070
| Retrieve without rerank / mid-text context truncation | replace | done — LLM rerank + `ContextSource.items` (drop whole hits/lessons); status `noTruncate` |
7171
| Compact erases what was already read | replace | done — `FILES ALREADY READ` ledger in mid/hard compact |
7272
| Explore via many serial list/read steps | replace | done — packet retrieve + optional explore subagent (`exploreSubagent`) |
73+
| Full tool surface thrash in Agent code turns | replace | done — stage machine at **execution** (explore/act/verify); schemas stay identical for prefix cache; refuse list/search/retrieve in act/verify |
74+
| Brittle exact `edit` / truncated tool JSON | replace | done — tolerant `edit` (Unicode + LF view + strip read line nums); `apply_patch` only for gpt-* non-OSS |
75+
| Soft edit-miss nudges | remove | done — hard `readThisTurn` gate before edit/overwrite |
76+
| Identical failed `edit`/`write`/`apply_patch` retries burn step budget then prose wrap-up | replace | done — block same fingerprint after first fail (incl. duplicates in one step); clear `readThisTurn` on miss |
77+
| Model retries `edit` whose `new_string` is already on disk (fake "missing brace") | replace | done — `applyEdit` returns `alreadyApplied` success so the 35B moves on |
78+
| Intent/continue enrich, thin-final/stuck soft nudges, write-count continue | remove | done — model works from system+tool contract; harness keeps protocol (length/JSON/budget) + tool gates only |
79+
| Stuck wrap used MAX_STEPS_PROMPT (wrong situation) / PT status labels | replace | done — `STUCK_WRAP_PROMPT` vs `MAX_STEPS_PROMPT`; status/activity strings English |
80+
| Stale internal plan injection | replace | done — `internalPlans.ts` scoped to session/taskHash; archive on done/unrelated task |
81+
| Mechanical mid-compact digest | replace | done — structured LLM checkpoint (Objective / Work State / Next Move) with mechanical fallback |
82+
| Final round sends `tools: []` (breaks prefix cache) | replace | done — keep tools + `tool_choice: none` + `MAX_STEPS_PROMPT` |
83+
| Clipped tool output with no path to full body | replace | done — spill to `.CodeForge/tool-output/` with marker |
7384

7485
## Modules
7586

7687
| Module | Contents |
7788
|---|---|
7889
| `clip.ts` | data clipping with markers |
90+
| `toolOutputSpill.ts` | full clipped output under `.CodeForge/tool-output/` |
7991
| `readMemory.ts` | read cache, canonicalization, soft reads |
8092
| `nudges.ts` | claims (green / blocked) and every text the loop injects |
81-
| `editTool.ts` | `edit` with useful errors |
93+
| `editTool.ts` | tolerant `edit` with useful errors |
94+
| `applyPatch.ts` | `apply_patch` parser/applier (gpt-* only) |
95+
| `internalPlans.ts` | model-only scaffold slices under `.CodeForge/plans/` |
96+
| `structuredCompaction.ts` | Objective / Work State / Next Move checkpoint template |
8297
| `oracle.ts` | build/test detection and parsing |
8398
| `toolsets.ts` | phase labels (telemetry), `dotnet` tool, status-question tool filter |
8499
| `orchestrator.ts` / `orchestratorRun.ts` | card plan and per-item execution |

‎extensions/codeforge/package.json‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -310,15 +310,15 @@
310310
"type": "number",
311311
"default": 30,
312312
"minimum": 5,
313-
"maximum": 50,
313+
"maximum": 200,
314314
"description": "Checkpoint every N steps: evaluate agent progress and extend budget on positive reviews"
315315
},
316316
"codeforge.ai.agentHardCap": {
317317
"type": "number",
318318
"default": 100,
319319
"minimum": 20,
320-
"maximum": 200,
321-
"description": "Max steps per agent task (absolute hard cap)"
320+
"maximum": 500,
321+
"description": "Max steps per agent task (absolute hard cap; uses your settings value as-is)"
322322
},
323323
"codeforge.ai.contextBudget": {
324324
"type": "number",

0 commit comments

Comments
 (0)