@xn-intenton-z2a/agentic-lib 7.1.65 → 7.1.67
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/package.json +1 -1
- package/src/actions/agentic-step/index.js +1 -0
- package/src/actions/agentic-step/logging.js +6 -0
- package/src/actions/agentic-step/tasks/fix-code.js +4 -2
- package/src/actions/agentic-step/tasks/resolve-issue.js +1 -0
- package/src/actions/agentic-step/tasks/transform.js +1 -0
- package/src/seeds/missions/c64-emulator.md +103 -49
- package/src/seeds/zero-package.json +1 -1
package/package.json
CHANGED
|
@@ -34,6 +34,7 @@ import * as core from "@actions/core";
|
|
|
34
34
|
* @param {Array} [options.promptBudget] - Prompt budget entries { section, size, files, notes }
|
|
35
35
|
* @param {string} [options.closingNotes] - Auto-generated limit concern notes
|
|
36
36
|
* @param {number} [options.transformationCost] - Transformation cost for this entry (0 or 1)
|
|
37
|
+
* @param {string} [options.narrative] - LLM-generated narrative description of the change
|
|
37
38
|
*/
|
|
38
39
|
export function logActivity({
|
|
39
40
|
filepath,
|
|
@@ -57,6 +58,7 @@ export function logActivity({
|
|
|
57
58
|
promptBudget,
|
|
58
59
|
closingNotes,
|
|
59
60
|
transformationCost,
|
|
61
|
+
narrative,
|
|
60
62
|
}) {
|
|
61
63
|
const dir = dirname(filepath);
|
|
62
64
|
if (!existsSync(dir)) {
|
|
@@ -110,6 +112,10 @@ export function logActivity({
|
|
|
110
112
|
parts.push("", "### Closing Notes");
|
|
111
113
|
parts.push(closingNotes);
|
|
112
114
|
}
|
|
115
|
+
if (narrative) {
|
|
116
|
+
parts.push("", "### Narrative");
|
|
117
|
+
parts.push(narrative);
|
|
118
|
+
}
|
|
113
119
|
if (details) {
|
|
114
120
|
parts.push("");
|
|
115
121
|
parts.push(details);
|
|
@@ -98,7 +98,7 @@ async function resolveConflicts({ config, pr, prNumber, instructions, model, wri
|
|
|
98
98
|
].join("\n");
|
|
99
99
|
|
|
100
100
|
const t = config.tuning || {};
|
|
101
|
-
const { tokensUsed, inputTokens, outputTokens, cost } = await runCopilotTask({
|
|
101
|
+
const { tokensUsed, inputTokens, outputTokens, cost, content: resultContent } = await runCopilotTask({
|
|
102
102
|
model,
|
|
103
103
|
systemMessage: `You are resolving git merge conflicts on PR #${prNumber}. Write resolved versions of each conflicted file, removing all conflict markers. Preserve the PR's feature intent while incorporating main's updates.`,
|
|
104
104
|
prompt,
|
|
@@ -116,6 +116,7 @@ async function resolveConflicts({ config, pr, prNumber, instructions, model, wri
|
|
|
116
116
|
cost,
|
|
117
117
|
model,
|
|
118
118
|
details: `Resolved ${conflicts.length} conflicted file(s) on PR #${prNumber}`,
|
|
119
|
+
narrative: (resultContent || "").substring(0, 2000),
|
|
119
120
|
};
|
|
120
121
|
}
|
|
121
122
|
|
|
@@ -186,7 +187,7 @@ export async function fixCode(context) {
|
|
|
186
187
|
].join("\n");
|
|
187
188
|
|
|
188
189
|
const t = config.tuning || {};
|
|
189
|
-
const { tokensUsed, inputTokens, outputTokens, cost } = await runCopilotTask({
|
|
190
|
+
const { tokensUsed, inputTokens, outputTokens, cost, content: resultContent } = await runCopilotTask({
|
|
190
191
|
model,
|
|
191
192
|
systemMessage: `You are an autonomous coding agent fixing failing tests on PR #${prNumber}. Make minimal, targeted changes to fix the test failures.`,
|
|
192
193
|
prompt,
|
|
@@ -204,5 +205,6 @@ export async function fixCode(context) {
|
|
|
204
205
|
cost,
|
|
205
206
|
model,
|
|
206
207
|
details: `Applied fix for ${failedChecks.length} failing check(s) on PR #${prNumber}`,
|
|
208
|
+
narrative: (resultContent || "").substring(0, 2000),
|
|
207
209
|
};
|
|
208
210
|
}
|
|
@@ -183,6 +183,7 @@ export async function transform(context) {
|
|
|
183
183
|
cost,
|
|
184
184
|
model,
|
|
185
185
|
details: resultContent.substring(0, 500),
|
|
186
|
+
narrative: (resultContent || "").substring(0, 2000),
|
|
186
187
|
promptBudget,
|
|
187
188
|
contextNotes: `Transformed with ${sourceFiles.length} source files (mtime-sorted, cleaned), ${features.length} features, ${openIssues.length} issues (${rawIssues.length - openIssues.length} stale filtered).`,
|
|
188
189
|
};
|
|
@@ -1,110 +1,164 @@
|
|
|
1
1
|
# Mission
|
|
2
2
|
|
|
3
|
-
A JavaScript Commodore 64 emulator capable of
|
|
3
|
+
A JavaScript Commodore 64 emulator that runs in the browser, capable of playing the classic game "The Lords of Midnight" (1984, Mike Singleton).
|
|
4
|
+
|
|
5
|
+
## Browser Presentation
|
|
6
|
+
|
|
7
|
+
The emulator runs entirely in the browser as a single-page application:
|
|
8
|
+
|
|
9
|
+
- **Canvas rendering** — VIC-II output drawn to an HTML `<canvas>` element at native 320x200, scaled with CSS `image-rendering: pixelated`.
|
|
10
|
+
- **Web Audio API** — SID output fed to an `AudioWorklet` (or `ScriptProcessorNode` fallback) for real-time sound.
|
|
11
|
+
- **Keyboard input** — browser `keydown`/`keyup` events mapped to the C64 keyboard matrix.
|
|
12
|
+
- **ROM loading** — user provides KERNAL, BASIC, and character ROM files via file input or drag-and-drop. ROMs are NOT bundled (they are copyrighted).
|
|
13
|
+
- **PRG loading** — user loads `.prg` game files via file input or drag-and-drop.
|
|
14
|
+
- **Responsive layout** — centred emulator screen with C64-style colour scheme, status bar showing cycle count and FPS.
|
|
15
|
+
|
|
16
|
+
Website files under `public/`:
|
|
17
|
+
|
|
18
|
+
| File | Purpose |
|
|
19
|
+
|------|---------|
|
|
20
|
+
| `public/index.html` | Main page — canvas, file inputs, controls |
|
|
21
|
+
| `public/style.css` | C64-themed styling (dark blue background, light blue text) |
|
|
22
|
+
| `public/emulator.js` | Browser entry point — imports core lib, wires up canvas/audio/input |
|
|
4
23
|
|
|
5
24
|
## Architecture
|
|
6
25
|
|
|
7
|
-
The emulator is structured as
|
|
26
|
+
The core emulator is structured as independently testable modules under `src/lib/`:
|
|
27
|
+
|
|
28
|
+
| File | Module | Purpose |
|
|
29
|
+
|------|--------|---------|
|
|
30
|
+
| `src/lib/main.js` | Entry point | Re-exports all public API functions from submodules |
|
|
31
|
+
| `src/lib/cpu.js` | MOS 6510 CPU | 6502 variant with I/O port at $00/$01 |
|
|
32
|
+
| `src/lib/opcodes.js` | Opcode table | Data-driven array of 256 entries (mnemonic, addressing mode, cycles, handler) |
|
|
33
|
+
| `src/lib/memory.js` | Memory subsystem | 64KB RAM, ROM banking, I/O area routing |
|
|
34
|
+
| `src/lib/vic.js` | VIC-II video | Text/bitmap modes, sprites, raster interrupts, framebuffer |
|
|
35
|
+
| `src/lib/sid.js` | SID sound | 3-voice synthesiser, ADSR envelopes, PCM output |
|
|
36
|
+
| `src/lib/cia.js` | CIA timers | Timer interrupts, keyboard matrix scanning, joystick |
|
|
37
|
+
| `src/lib/input.js` | Input mapping | Browser key event codes to C64 8x8 keyboard matrix |
|
|
38
|
+
| `src/lib/loader.js` | PRG loader | Parse `.prg` header and load data into memory |
|
|
39
|
+
| `src/lib/c64.js` | Machine | Wires all subsystems together, provides `createC64()` and `runFrame()` |
|
|
40
|
+
|
|
41
|
+
This multi-file structure allows the agent to iterate on each subsystem independently without hitting context limits. Each module has a corresponding test file under `tests/`.
|
|
8
42
|
|
|
9
|
-
|
|
10
|
-
2. **Memory subsystem** — 64KB RAM, ROM banking (BASIC, KERNAL, character ROM), I/O area ($D000–$DFFF)
|
|
11
|
-
3. **VIC-II video** — text mode (40x25), bitmap mode, sprites, raster interrupt timing
|
|
12
|
-
4. **SID sound** — 3-voice synthesiser with ADSR envelopes (basic waveform generation)
|
|
13
|
-
5. **CIA timers** — two CIA chips for keyboard scanning, timer interrupts, and joystick input
|
|
14
|
-
6. **Input** — keyboard matrix and joystick mapped to browser events
|
|
15
|
-
7. **PRG/TAP loader** — load `.prg` files (and optionally `.tap` tape images) into memory
|
|
43
|
+
## Research Phase
|
|
16
44
|
|
|
17
|
-
|
|
45
|
+
During web-search and document-gathering workflow phases, the agent should look up:
|
|
18
46
|
|
|
19
|
-
|
|
47
|
+
- **6502/6510 opcode reference** — complete instruction set with addressing modes, cycle counts, and flag effects. Key resource: "6502 Instruction Set" tables listing all 151 official opcode variants.
|
|
48
|
+
- **VIC-II register map** — all registers at $D000–$D03F, their bit layouts, and behaviour (C64 Programmer's Reference Guide).
|
|
49
|
+
- **SID register map** — registers at $D400–$D41C, waveform generation, ADSR timing.
|
|
50
|
+
- **CIA register map** — CIA1 ($DC00–$DC0F) and CIA2 ($DD00–$DD0F), keyboard matrix wiring, timer modes.
|
|
51
|
+
- **C64 keyboard matrix** — the 8x8 matrix mapping (which row/column pair for each physical key).
|
|
52
|
+
- **C64 colour palette** — the 16 VIC-II colours as RGB values.
|
|
53
|
+
- **Lords of Midnight technical details** — memory layout, which C64 features the game uses, loading address.
|
|
54
|
+
- **Existing open-source C64 emulators in JavaScript** — study approaches (e.g. virtual6502, SAE, c64js) for implementation patterns and known pitfalls.
|
|
20
55
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
56
|
+
The opcode table in particular should be assembled from reference data during the research phase and stored as `src/lib/opcodes.js` — a data-driven 256-entry array — rather than hand-coded instruction by instruction. This avoids the agent losing track of which opcodes are implemented and reduces the chance of transcription errors.
|
|
57
|
+
|
|
58
|
+
## Core API
|
|
59
|
+
|
|
60
|
+
Export from `src/lib/main.js` (re-exporting from submodules):
|
|
61
|
+
|
|
62
|
+
- `createC64(opts?)` — create an emulator instance with 64KB RAM and subsystem objects (`cpu`, `memory`, `vic`, `sid`, `cia1`, `cia2`).
|
|
63
|
+
- `loadROMs(c64, { kernal, basic, chargen })` — load ROM images (Uint8Arrays). Must be called before running.
|
|
64
|
+
- `loadPRG(c64, data)` — load a `.prg` file (Uint8Array) into memory at the address from its two-byte header.
|
|
65
|
+
- `step(c64)` — execute one CPU instruction, advance cycle count, update timers. Returns the updated state.
|
|
66
|
+
- `runFrame(c64)` — execute one PAL video frame (~19656 cycles). Fire raster interrupts. Returns the RGBA framebuffer.
|
|
67
|
+
- `getFramebuffer(c64)` — return the current screen as a Uint8Array RGBA pixel buffer (320x200).
|
|
26
68
|
- `pressKey(c64, key)` / `releaseKey(c64, key)` — simulate keyboard input via CIA1 keyboard matrix.
|
|
27
69
|
- `joystickInput(c64, port, directions)` — set joystick state (up/down/left/right/fire) on port 1 or 2.
|
|
28
|
-
- `reset(c64)` —
|
|
70
|
+
- `reset(c64)` — hardware reset (CPU to reset vector, clear subsystem state).
|
|
29
71
|
|
|
30
|
-
## CPU
|
|
72
|
+
## CPU (src/lib/cpu.js, src/lib/opcodes.js)
|
|
31
73
|
|
|
32
74
|
- All official 6502 opcodes (56 instructions, 151 opcode variants) with correct cycle counts.
|
|
33
|
-
- Decimal mode (BCD arithmetic)
|
|
75
|
+
- Decimal mode (BCD arithmetic).
|
|
34
76
|
- IRQ and NMI interrupt handling with correct stack behaviour.
|
|
35
|
-
-
|
|
36
|
-
- Undocumented/illegal opcodes
|
|
77
|
+
- 6510 I/O port at $00/$01 for ROM/RAM bank switching.
|
|
78
|
+
- Undocumented/illegal opcodes: implement as NOP (not required for Lords of Midnight).
|
|
79
|
+
- The opcode table (`opcodes.js`) is a data-driven array of 256 entries to keep the code manageable and verifiable against reference data gathered during the research phase.
|
|
37
80
|
|
|
38
|
-
## Memory
|
|
81
|
+
## Memory (src/lib/memory.js)
|
|
39
82
|
|
|
40
83
|
- $0000–$00FF: Zero page
|
|
41
84
|
- $0100–$01FF: Stack
|
|
42
85
|
- $0200–$9FFF: Free RAM (programs load here)
|
|
43
86
|
- $A000–$BFFF: BASIC ROM (banked, RAM underneath)
|
|
44
87
|
- $C000–$CFFF: Free RAM
|
|
45
|
-
- $D000–$D3FF: VIC-II registers
|
|
46
|
-
- $D400–$D7FF: SID registers
|
|
88
|
+
- $D000–$D3FF: VIC-II registers (routed to VIC-II module)
|
|
89
|
+
- $D400–$D7FF: SID registers (routed to SID module)
|
|
47
90
|
- $D800–$DBFF: Colour RAM (nibbles)
|
|
48
|
-
- $DC00–$DCFF: CIA1 (
|
|
49
|
-
- $DD00–$DDFF: CIA2 (
|
|
91
|
+
- $DC00–$DCFF: CIA1 registers (routed to CIA module)
|
|
92
|
+
- $DD00–$DDFF: CIA2 registers (routed to CIA module)
|
|
50
93
|
- $E000–$FFFF: KERNAL ROM (banked, RAM underneath)
|
|
51
94
|
|
|
52
|
-
## Video
|
|
95
|
+
## Video — VIC-II (src/lib/vic.js)
|
|
53
96
|
|
|
54
|
-
- Standard text mode (
|
|
97
|
+
- Standard text mode (40x25 characters, 16 colours, character ROM).
|
|
55
98
|
- Multicolour text mode.
|
|
56
99
|
- Standard bitmap mode (320x200) and multicolour bitmap mode (160x200).
|
|
57
100
|
- Hardware sprites (8 sprites, 24x21 pixels, multicolour optional).
|
|
58
101
|
- Raster interrupt — trigger IRQ at a programmable scanline.
|
|
59
|
-
- Border
|
|
60
|
-
- Correct raster timing
|
|
102
|
+
- Border and background colour registers.
|
|
103
|
+
- Correct raster timing — Lords of Midnight uses raster effects.
|
|
61
104
|
|
|
62
|
-
## Sound
|
|
105
|
+
## Sound — SID (src/lib/sid.js)
|
|
63
106
|
|
|
64
|
-
- 3 oscillator voices
|
|
107
|
+
- 3 oscillator voices: triangle, sawtooth, pulse, noise waveforms.
|
|
65
108
|
- ADSR envelope per voice.
|
|
66
109
|
- Frequency and pulse-width registers.
|
|
67
|
-
- Audio output as PCM sample buffer
|
|
110
|
+
- Audio output as PCM sample buffer (44100 Hz, mono) for Web Audio API.
|
|
68
111
|
- Full filter emulation is NOT required (passthrough acceptable).
|
|
69
112
|
|
|
70
|
-
## Input
|
|
113
|
+
## Input (src/lib/input.js, src/lib/cia.js)
|
|
71
114
|
|
|
72
|
-
- CIA1 keyboard matrix
|
|
73
|
-
- Joystick via CIA1
|
|
115
|
+
- CIA1 keyboard matrix — map browser `KeyboardEvent.code` values to the C64 8x8 keyboard matrix.
|
|
116
|
+
- Joystick via CIA1 port registers — Lords of Midnight uses keyboard, but joystick support enables other games.
|
|
74
117
|
|
|
75
118
|
## Lords of Midnight Compatibility
|
|
76
119
|
|
|
77
|
-
The target game exercises
|
|
120
|
+
The target game exercises:
|
|
78
121
|
- Custom character sets (redefined at $3000 or similar)
|
|
79
122
|
- Full keyboard input (directional + action keys)
|
|
80
123
|
- Raster interrupts for split-screen effects
|
|
81
124
|
- IRQ-driven game loop timing via CIA timer
|
|
82
125
|
- PRG loading at the correct start address
|
|
83
126
|
|
|
127
|
+
## Test Strategy
|
|
128
|
+
|
|
129
|
+
Testing a full emulator requires care to avoid the verification gap (passing unit tests but failing on real software):
|
|
130
|
+
|
|
131
|
+
- **CPU tests**: verify each addressing mode and instruction against known-good results. Use the research-phase opcode reference to generate expected values. Test interrupt handling (IRQ vector jump, flag push, RTI return).
|
|
132
|
+
- **Memory tests**: test bank switching ($01 register), I/O area routing, ROM overlay behaviour.
|
|
133
|
+
- **VIC-II tests**: set known register states, render one frame, verify specific pixels in the framebuffer.
|
|
134
|
+
- **Input tests**: simulate key press sequences, verify CIA1 port reads return correct matrix values.
|
|
135
|
+
- **Stub ROMs**: tests use minimal ROMs — just enough to set the reset vector ($FFFC/$FFFD) and RTI from the IRQ vector. The agent should create these as hex-encoded Uint8Arrays in the test fixtures.
|
|
136
|
+
- **Integration test**: a small test PRG (hex-encoded in the test file) that writes "HELLO" to screen RAM ($0400) and halts. Run it, verify the framebuffer contains the correct character glyphs.
|
|
137
|
+
- **Smoke test for the browser UI**: verify `public/index.html` loads without errors and the canvas element is present (can use a headless browser or DOM parser).
|
|
138
|
+
|
|
84
139
|
## Requirements
|
|
85
140
|
|
|
86
|
-
- No external dependencies
|
|
87
|
-
-
|
|
88
|
-
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
- VIC-II: test mode switching, framebuffer output for known register states.
|
|
92
|
-
- Input: test keyboard matrix encoding/decoding.
|
|
93
|
-
- Integration test: load a small test PRG that writes to screen memory and verify framebuffer output.
|
|
94
|
-
- README with architecture overview, usage example, and instructions for obtaining legal ROM dumps.
|
|
141
|
+
- No external runtime dependencies — pure JavaScript using only browser-provided APIs (Canvas, Web Audio, File API).
|
|
142
|
+
- ROMs must NOT be bundled. The `loadROMs()` function and browser drag-and-drop accept user-supplied ROM files.
|
|
143
|
+
- Multi-file structure as specified in the Architecture section.
|
|
144
|
+
- The `public/` website is self-contained and can be served with any static file server.
|
|
145
|
+
- README with architecture overview, browser usage instructions, and guidance on obtaining legal ROM dumps.
|
|
95
146
|
|
|
96
147
|
## Acceptance Criteria
|
|
97
148
|
|
|
98
149
|
- [ ] CPU executes all 151 official opcodes with correct results and cycle counts
|
|
99
150
|
- [ ] CPU handles IRQ and NMI interrupts correctly (push PC+flags, jump to vector)
|
|
100
151
|
- [ ] Memory bank switching works ($01 register controls ROM/RAM visibility)
|
|
101
|
-
- [ ] VIC-II text mode renders 40x25 character display to framebuffer
|
|
152
|
+
- [ ] VIC-II text mode renders 40x25 character display to RGBA framebuffer
|
|
102
153
|
- [ ] VIC-II raster interrupt fires at the programmed scanline
|
|
103
154
|
- [ ] SID produces audible waveform output for at least triangle and pulse waves
|
|
104
155
|
- [ ] CIA1 keyboard matrix correctly maps key presses to the scanned row/column
|
|
105
156
|
- [ ] `loadPRG()` places data at the correct address from the PRG header
|
|
106
|
-
- [ ] `runFrame()` executes
|
|
157
|
+
- [ ] `runFrame()` executes the correct number of cycles per PAL frame (~19656)
|
|
107
158
|
- [ ] A test PRG that writes "HELLO" to screen RAM ($0400) produces correct framebuffer output
|
|
108
159
|
- [ ] `reset()` returns the emulator to a known initial state
|
|
160
|
+
- [ ] Browser UI renders emulator output to canvas at 50 FPS (PAL rate)
|
|
161
|
+
- [ ] Browser UI plays SID audio via Web Audio API
|
|
162
|
+
- [ ] Browser UI accepts ROM and PRG files via drag-and-drop or file input
|
|
109
163
|
- [ ] All unit tests pass
|
|
110
|
-
- [ ] README documents architecture and ROM
|
|
164
|
+
- [ ] README documents architecture, browser usage, and how to obtain legal ROM dumps
|