Skip to content

Commit 207669e

Browse files
Copilotpmcelhaney
andauthored
Rename builders to routes (plain object) and use $ as the argument convention
Agent-Logs-Url: https://github.com/counterfact/api-simulator/sessions/a80bbc52-f68f-419e-971b-d993e4e18383 Co-authored-by: pmcelhaney <51504+pmcelhaney@users.noreply.github.com>
1 parent 3391405 commit 207669e

File tree

3 files changed

+38
-44
lines changed

3 files changed

+38
-44
lines changed

.github/issue-proposals/apply-approach-1-function-injection.md

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -27,15 +27,12 @@ An apply script is a TypeScript file with a default export:
2727
// repl/sold-pets.ts
2828
import type { ApplyContext } from "counterfact";
2929

30-
export default ({ context, builders, route }: ApplyContext) => {
31-
context.petService.reset();
32-
context.petService.addPet({ id: 1, status: "sold" });
33-
context.petService.addPet({ id: 2, status: "available" });
34-
35-
builders.set(
36-
"getSoldPets",
37-
route("/pet/findByStatus").method("get").query({ status: "sold" }),
38-
);
30+
export default ($: ApplyContext) => {
31+
$.context.petService.reset();
32+
$.context.petService.addPet({ id: 1, status: "sold" });
33+
$.context.petService.addPet({ id: 2, status: "available" });
34+
35+
$.routes.getSoldPets = $.route("/pet/findByStatus").method("get").query({ status: "sold" });
3936
};
4037
```
4138

@@ -47,8 +44,8 @@ export interface ApplyContext {
4744
context: Record<string, unknown>;
4845
/** Load a context object for a specific path */
4946
loadContext: (path: string) => Record<string, unknown>;
50-
/** Named route builders injected into the REPL */
51-
builders: Map<string, RouteBuilder>;
47+
/** Named route builders available in the REPL execution context */
48+
routes: Record<string, RouteBuilder>;
5249
/** Create a new RouteBuilder for a given path */
5350
route: (path: string) => RouteBuilder;
5451
}
@@ -74,7 +71,7 @@ After execution, Counterfact compares the environment state before and after the
7471
```
7572
Applied sold-pets
7673
77-
Builders added:
74+
Routes added:
7875
getSoldPets
7976
```
8077

@@ -88,7 +85,7 @@ Context diffs are not automatically tracked in this approach — the script auth
8885
2. Resolve the file path using the ordered lookup above.
8986
3. Dynamically import the resolved module (using `tsx` or the existing transpiler if the file is TypeScript).
9087
4. Call the exported function with the live environment objects.
91-
5. Snapshot `builders` before/after and print the diff.
88+
5. Snapshot `routes` before/after and print the diff.
9289

9390
---
9491

@@ -108,8 +105,8 @@ Context diffs are not automatically tracked in this approach — the script auth
108105

109106
- [ ] `.apply <name>` resolves and executes a TypeScript file from the configured `repl/` directory
110107
- [ ] `.apply <path>` resolves and executes a TypeScript file at the given relative path
111-
- [ ] The script receives `{ context, loadContext, builders, route }` as arguments
112-
- [ ] Builders injected by the script are available in the REPL after the command runs
113-
- [ ] The REPL prints a summary of builders added and removed after each apply
108+
- [ ] The script receives `$` with `{ context, loadContext, routes, route }` as properties
109+
- [ ] Routes injected by the script are available in the REPL after the command runs
110+
- [ ] The REPL prints a summary of routes added and removed after each apply
114111
- [ ] A meaningful error is shown when the file cannot be found or the export is not a function
115112
- [ ] Existing REPL commands and behavior are unaffected

.github/issue-proposals/apply-approach-2-scenario-class-lifecycle.md

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -28,20 +28,17 @@ import type { Scenario, ApplyContext } from "counterfact";
2828
export default class SoldPetsScenario implements Scenario {
2929
static dependencies = ["base"];
3030

31-
setup({ context, builders, route }: ApplyContext): void {
32-
context.petService.addPet({ id: 1, status: "sold" });
33-
context.petService.addPet({ id: 2, status: "available" });
34-
35-
builders.set(
36-
"getSoldPets",
37-
route("/pet/findByStatus").method("get").query({ status: "sold" }),
38-
);
31+
setup($: ApplyContext): void {
32+
$.context.petService.addPet({ id: 1, status: "sold" });
33+
$.context.petService.addPet({ id: 2, status: "available" });
34+
35+
$.routes.getSoldPets = $.route("/pet/findByStatus").method("get").query({ status: "sold" });
3936
}
4037

41-
teardown({ context, builders }: ApplyContext): void {
42-
context.petService.removePet(1);
43-
context.petService.removePet(2);
44-
builders.delete("getSoldPets");
38+
teardown($: ApplyContext): void {
39+
$.context.petService.removePet(1);
40+
$.context.petService.removePet(2);
41+
delete $.routes.getSoldPets;
4542
}
4643
}
4744
```
@@ -61,6 +58,8 @@ export interface Scenario {
6158
}
6259
```
6360

61+
> `ApplyContext` provides `{ context, loadContext, routes, route }` where `routes` is a plain object in the REPL execution context.
62+
6463
### Invocation
6564

6665
```
@@ -78,7 +77,7 @@ When a scenario declares `static dependencies`, Counterfact automatically applie
7877
# Counterfact first applies "base" (dependency), then "sold-pets"
7978
Applied base → sold-pets
8079
81-
Builders added:
80+
Routes added:
8281
getSoldPets
8382
```
8483

.github/issue-proposals/apply-approach-3-proxy-based-tracking.md

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -25,29 +25,27 @@ A script is a plain TypeScript module with a default export function. The script
2525

2626
```ts
2727
// repl/sold-pets.ts
28-
export default ({ context, builders, route }) => {
29-
context.petService.reset();
28+
export default ($) => {
29+
$.context.petService.reset();
3030

31-
context.petService.addPet({ id: 1, status: "sold" });
32-
context.petService.addPet({ id: 2, status: "available" });
31+
$.context.petService.addPet({ id: 1, status: "sold" });
32+
$.context.petService.addPet({ id: 2, status: "available" });
3333

34-
builders.set(
35-
"getSoldPets",
36-
route("/pet/findByStatus").method("get").query({ status: "sold" }),
37-
);
34+
$.routes.getSoldPets = $.route("/pet/findByStatus").method("get").query({ status: "sold" });
3835
};
3936
```
4037

41-
This is identical in surface syntax to Approach 1. The difference is internal: `context` and `builders` passed to the script are **transparent reactive proxies** of the live objects.
38+
This is identical in surface syntax to Approach 1. The difference is internal: `$.context` and `$.routes` passed to the script are **transparent reactive proxies** of the live objects.
4239

4340
### Proxy-based change tracking
4441

45-
Before calling the script, Counterfact wraps each environment object in a `Proxy` that intercepts `set`, `deleteProperty`, and `Map` mutations:
42+
Before calling the script, Counterfact wraps each environment object in a `Proxy` that intercepts `set`, `deleteProperty`, and property mutations on the `routes` plain object:
4643

4744
```ts
4845
const tracked = trackChanges(liveContext);
49-
await script({ context: tracked.proxy, builders: trackBuilders(liveBuilders) });
50-
const report = tracked.changes(); // returns structured diff
46+
const trackedRoutes = trackChanges(liveRoutes);
47+
await script({ context: tracked.proxy, routes: trackedRoutes.proxy, route: createRouteFunction(...) });
48+
const report = { context: tracked.changes(), routes: trackedRoutes.changes() };
5149
```
5250

5351
The proxy forwards all reads and writes to the underlying live object, so mutations take effect immediately. It also accumulates a change log:
@@ -71,7 +69,7 @@ Applied sold-pets
7169
Context changes:
7270
petService.pets: [] → [{id:1,status:"sold"},{id:2,status:"available"}]
7371
74-
Builders added:
72+
Routes added:
7573
getSoldPets
7674
```
7775

@@ -96,7 +94,7 @@ Resolution order is the same as Approach 1:
9694

9795
1. Add `.apply` as a dot-command in `src/repl/repl.ts`.
9896
2. Resolve the file path.
99-
3. Create proxy wrappers around `context` and `builders`.
97+
3. Create proxy wrappers around `context` and `routes`.
10098
4. Dynamically import and call the script with the proxy-wrapped arguments.
10199
5. Collect the accumulated change records from the proxies.
102100
6. Print the formatted diff.
@@ -144,7 +142,7 @@ Deep (nested) change tracking can be implemented by returning a recursive proxy
144142
- [ ] `.apply <name>` resolves and executes a TypeScript file, passing proxy-wrapped environment objects
145143
- [ ] All top-level property assignments to `context` are captured in the change log
146144
- [ ] Nested property mutations (e.g. `context.petService.reset()`) are captured where feasible
147-
- [ ] `builders.set()` and `builders.delete()` calls are captured and reported
145+
- [ ] `$.routes.name = builder` assignments and `delete $.routes.name` are captured and reported
148146
- [ ] After the script runs, the REPL prints a structured diff of all recorded changes
149147
- [ ] The underlying live objects are mutated correctly (proxy is transparent for reads and writes)
150148
- [ ] Scripts that throw an error do not leave the change-tracking proxy in an inconsistent state

0 commit comments

Comments
 (0)