mirror of
https://github.com/BillyOutlast/Pax-Automata.git
synced 2026-11-07 08:15:59 -10:00
Working manual login flow
This commit is contained in:
1 parent
fdc487bed4
commit
eec0219641
8 files changed
+550
-43
No files matched your search
@@ -5,6 +5,10 @@
|
||||
*.pem
|
||||
secrets/
|
||||
|
||||
# Auth state (captured from manual login — never commit)
|
||||
auth/
|
||||
auth_profile/
|
||||
|
||||
# Dependencies
|
||||
node_modules/
|
||||
|
||||
|
||||
@@ -18,7 +18,9 @@ This file defines the **permanent operating rules** for Claude Code in this repo
|
||||
|-------------|---------------------|--------|
|
||||
| Browser automation | **Playwright** | Intercept `/api/simple-chat`, drive UI (action box, advisor box). |
|
||||
| Runtime | **Node.js + TypeScript** | Preferred for Playwright and tooling; use Python only if explicitly required. |
|
||||
| LLM | TBD (API or local) | Used for reasoning and batch-of-actions generation. |
|
||||
| LLM | **Anthropic Claude API** (via SDK) | Reasoning and batch-of-actions generation. |
|
||||
| Validation | **Zod** | Schema validation at all JSON boundaries. |
|
||||
| TS execution | **tsx** | Fast TypeScript execution (replaces ts-node). |
|
||||
| War Room storage | JSON + Markdown + TXT in `war-room/` | See folder layout below. |
|
||||
|
||||
---
|
||||
@@ -40,7 +42,11 @@ This file defines the **permanent operating rules** for Claude Code in this repo
|
||||
│ ├── crisis_handbook.txt # Tactical playbook.
|
||||
│ ├── strategic_ledger.json # Active plans / long-term memory.
|
||||
│ └── current_state.json # Latest game state (written by Spy).
|
||||
├── src/ # Application code (structure TBD: e.g. spy/, brain/, hand/).
|
||||
├── src/ # Application code.
|
||||
│ ├── spy/ # Perception layer (Playwright intercept, state parsing).
|
||||
│ ├── brain/ # Reasoning layer (context assembly, LLM calls, action generation).
|
||||
│ ├── hand/ # Execution layer (Playwright UI automation).
|
||||
│ └── shared/ # Types, Zod schemas, utilities shared across modules.
|
||||
└── scripts/ # One-off or scaffold scripts (e.g. scaffold.sh).
|
||||
```
|
||||
|
||||
@@ -56,7 +62,49 @@ This file defines the **permanent operating rules** for Claude Code in this repo
|
||||
|
||||
---
|
||||
|
||||
## 5. Workflow + Git Rules
|
||||
## 5. Pre-flight Rule
|
||||
|
||||
**Before creating any new file or module**, check this file (`CLAUDE.md`) to confirm the correct path, naming convention, and module boundary. If the file doesn't fit the canonical structure, stop and discuss.
|
||||
|
||||
---
|
||||
|
||||
## 6. Coding Standards
|
||||
|
||||
- **Functional-first:** No classes unless there's a clear reason (e.g. Playwright Page wrapper). Prefer plain functions and modules.
|
||||
- **Zod at boundaries:** Every JSON file read/write and every external API response gets a Zod schema. Validate, don't assume.
|
||||
- **Explicit return types** on all exported functions.
|
||||
- **Barrel exports:** Each module directory (`spy/`, `brain/`, `hand/`, `shared/`) has an `index.ts` re-exporting its public API.
|
||||
- **No `any`:** Use `unknown` + Zod parsing instead. TypeScript strict mode.
|
||||
- **Imports:** Prefer relative imports within a module; use `../shared/` for cross-module shared code.
|
||||
|
||||
---
|
||||
|
||||
## 7. Architecture — Data-Flow Contracts
|
||||
|
||||
The cognitive loop passes data through well-defined boundaries:
|
||||
|
||||
```
|
||||
Spy (Playwright intercept)
|
||||
→ writes current_state.json (Zod-validated GameState)
|
||||
→ emits "new-turn" event
|
||||
|
||||
Brain (context assembly)
|
||||
← reads current_state.json, constitution.md, crisis_handbook.txt, strategic_ledger.json
|
||||
→ calls Anthropic Claude API with assembled prompt
|
||||
→ receives ActionBatch (Zod-validated)
|
||||
→ updates strategic_ledger.json
|
||||
|
||||
Hand (Playwright UI driver)
|
||||
← receives ActionBatch from Brain
|
||||
→ types each action into the action box, submits
|
||||
→ optionally queries advisor, returns advice to Brain
|
||||
```
|
||||
|
||||
Each boundary has a Zod schema. Modules communicate through files (War Room) and function calls — no shared mutable state.
|
||||
|
||||
---
|
||||
|
||||
## 8. Workflow + Git Rules
|
||||
|
||||
- **Branch first:** Always do work on a feature branch, never directly on `main`. Use branch names like `feature/...`, `fix/...`, `chore/...`.
|
||||
- **Commits:** You may create local commits as checkpoints. Keep them meaningful and scoped. **Never push** to the remote—pushing is always a human action.
|
||||
@@ -67,7 +115,7 @@ This file defines the **permanent operating rules** for Claude Code in this repo
|
||||
|
||||
---
|
||||
|
||||
## 6. Memory Rules (Dual-Document System)
|
||||
## 9. Memory Rules (Dual-Document System)
|
||||
|
||||
| File / Location | Type | Purpose |
|
||||
|----------------------|------------|---------|
|
||||
@@ -79,7 +127,7 @@ Do **not** use `CLAUDE.md` for task lists or progress. Update `docs/project-trac
|
||||
|
||||
---
|
||||
|
||||
## 7. Session Hygiene
|
||||
## 10. Session Hygiene
|
||||
|
||||
- Use **`/clear`** when switching to a new, unrelated task (e.g. finishing UI work and starting database work).
|
||||
- Use **`/compact`** during long debugging/refactor sessions to reduce context bloat; preserve key state, discard raw logs.
|
||||
@@ -87,7 +135,7 @@ Do **not** use `CLAUDE.md` for task lists or progress. Update `docs/project-trac
|
||||
|
||||
---
|
||||
|
||||
## 8. Editing + Safety
|
||||
## 11. Editing + Safety
|
||||
|
||||
- Prefer **Plan Mode** for complex or multi-file changes. Always propose a plan before large refactors.
|
||||
- Do not modify unrelated files. Avoid repo-wide formatting or drive-by edits.
|
||||
@@ -95,20 +143,20 @@ Do **not** use `CLAUDE.md` for task lists or progress. Update `docs/project-trac
|
||||
|
||||
---
|
||||
|
||||
## 9. Quality Gates
|
||||
## 12. Quality Gates
|
||||
|
||||
- Keep `main` in a working, deployable state.
|
||||
- Before merging work into `main`, ensure: tests pass; typecheck/lint passes (if applicable); diff is reviewed and scoped.
|
||||
|
||||
---
|
||||
|
||||
## 10. Parallel Work (Advanced)
|
||||
## 13. Parallel Work (Advanced)
|
||||
|
||||
- If running multiple Claude sessions, isolate work using Git worktrees: one branch + one worktree per task; avoid overlapping edits on the same files.
|
||||
|
||||
---
|
||||
|
||||
## 11. Behavioral Guardrails (#)
|
||||
## 14. Behavioral Guardrails (#)
|
||||
|
||||
These rules are permanent. Follow them unless the user explicitly overrides in the current conversation.
|
||||
|
||||
@@ -124,13 +172,13 @@ These rules are permanent. Follow them unless the user explicitly overrides in t
|
||||
|
||||
---
|
||||
|
||||
## 12. Default Operating Principle
|
||||
## 15. Default Operating Principle
|
||||
|
||||
Claude should behave like a careful engineering teammate: small, reversible steps; explicit plans for complex work; branch isolation; human-controlled pushes; repo stays clean and readable.
|
||||
|
||||
---
|
||||
|
||||
## 13. Day-One Checklist (Human)
|
||||
## 16. Day-One Checklist (Human)
|
||||
|
||||
When opening this repo for a new work session:
|
||||
|
||||
|
||||
@@ -1,13 +1,98 @@
|
||||
# Pax-Automata
|
||||
|
||||
Autonomous agent for **Pax Historia** (browser grand-strategy). Perceives game state, reasons via a local “War Room,” and executes actions through Playwright.
|
||||
An autonomous AI agent that plays [Pax Historia](https://www.paxhistoria.co) — a browser-based, AI-powered grand strategy game where you lead a nation through alternate history.
|
||||
|
||||
**Before making changes:**
|
||||
## What is Pax Historia?
|
||||
|
||||
1. Read **`CLAUDE.md`** (constitution: tech stack, paths, git workflow, behavioral rules).
|
||||
2. Check **`docs/project-tracker.md`** for current status.
|
||||
3. Create a `feature/` or `fix/` branch; do not commit directly to `main`.
|
||||
Pax Historia is a grand strategy sandbox where players pick a nation and a moment in history, then reshape the world through free-text actions, AI-driven diplomacy, and time-jumps. Every decision is processed by generative AI that simulates realistic geopolitical consequences. Think Civilization meets a creative writing partner.
|
||||
|
||||
**Design:** `docs/PRD.md` · **Flow:** `docs/diagrams/war-room-flow.mmd` (and `.png`).
|
||||
## How It Works
|
||||
|
||||
**Scaffold:** `./scripts/scaffold.sh` — creates `war-room/` and `src/spy|brain|hand/`.
|
||||
Pax-Automata runs a **cognitive loop** that mimics how a human player thinks:
|
||||
|
||||
1. **Spy (Perception)** — Intercepts the game's network traffic to read the current world state: borders, battalions, events, diplomacy.
|
||||
2. **War Room (Memory)** — Consults local files that define the agent's long-term goals, tactical playbook, and memory of ongoing operations.
|
||||
3. **Brain (Reasoning)** — Sends all context to an LLM (Claude) which updates its strategic plans and generates a batch of actions.
|
||||
4. **Hand (Execution)** — Types each action into the game's UI via browser automation, then triggers a time-jump to advance the world.
|
||||
|
||||
This loop repeats every turn, building on previous plans and adapting to new events.
|
||||
|
||||
## Architecture
|
||||
|
||||
See `docs/diagrams/war-room-flow.mmd` for the full sequence diagram, or the rendered version at `docs/diagrams/war-room-flow.png`.
|
||||
|
||||
```
|
||||
Browser (Pax Historia)
|
||||
↕ network intercept
|
||||
Spy → current_state.json → Brain → ActionBatch → Hand → Browser
|
||||
↑ ↑
|
||||
constitution.md Claude API
|
||||
crisis_handbook.txt
|
||||
strategic_ledger.json
|
||||
```
|
||||
|
||||
## Getting Started
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- Node.js 18+
|
||||
- npm
|
||||
|
||||
### Install
|
||||
|
||||
```bash
|
||||
git clone https://github.com/phillipyan300/Pax-Automata.git
|
||||
cd Pax-Automata
|
||||
npm install
|
||||
```
|
||||
|
||||
### Build
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
### Run
|
||||
|
||||
```bash
|
||||
npm start
|
||||
```
|
||||
|
||||
> The agent is under active development. Currently only the project scaffold is in place — no phases are implemented yet. See [Project Status](#project-status) below.
|
||||
|
||||
## Project Status
|
||||
|
||||
Tracked in [`docs/project-tracker.md`](docs/project-tracker.md).
|
||||
|
||||
| Phase | Status |
|
||||
|-------|--------|
|
||||
| Phase 0: Project Init | Done |
|
||||
| Phase 1: Perception (Spy) | In Progress |
|
||||
| Phase 2: War Room | Pending |
|
||||
| Phase 2.5: Advisor Query | Pending |
|
||||
| Phase 3: Brain (LLM) | Pending |
|
||||
| Phase 4: Hand (Execution) | Pending |
|
||||
|
||||
## Tech Stack
|
||||
|
||||
| Layer | Choice |
|
||||
|-------|--------|
|
||||
| Browser automation | Playwright |
|
||||
| Runtime | Node.js + TypeScript |
|
||||
| LLM | Anthropic Claude API |
|
||||
| Validation | Zod |
|
||||
| TS execution | tsx |
|
||||
| Agent memory | JSON + Markdown files in `war-room/` |
|
||||
|
||||
## Design Docs
|
||||
|
||||
- **Product spec:** [`docs/PRD.md`](docs/PRD.md)
|
||||
- **Sequence diagram:** [`docs/diagrams/war-room-flow.mmd`](docs/diagrams/war-room-flow.mmd)
|
||||
- **Game research:** [`docs/pax-historia-research.md`](docs/pax-historia-research.md)
|
||||
|
||||
## Contributing
|
||||
|
||||
1. Read [`CLAUDE.md`](CLAUDE.md) — the project constitution (tech stack, paths, coding standards, git workflow).
|
||||
2. Check [`docs/project-tracker.md`](docs/project-tracker.md) for current status.
|
||||
3. Create a `feature/`, `fix/`, or `chore/` branch. Never commit directly to `main`.
|
||||
4. The maintainer squash-merges into `main` after review.
|
||||
@@ -0,0 +1,159 @@
|
||||
# Auth setup (Google login for Pax Historia)
|
||||
|
||||
The game at [paxhistoria.co](https://www.paxhistoria.co) uses Google login. Automating the login form with Playwright usually triggers Google’s bot detection (“This browser or app may not be secure”). So we **don’t automate login**; we **log in once manually** and reuse the saved auth state.
|
||||
|
||||
---
|
||||
|
||||
## Demo: “login” with saved state (no password)
|
||||
|
||||
To see that the saved state works, run:
|
||||
|
||||
```bash
|
||||
npm run demo-auth
|
||||
```
|
||||
|
||||
That script **does not type a password or touch Google’s login form**. It:
|
||||
|
||||
1. Reads **`auth/auth_state.json`** (cookies + localStorage).
|
||||
2. Starts a new Playwright browser and **injects** that state into it.
|
||||
3. Opens **paxhistoria.co**. The site sees the same cookies/localStorage as when you logged in, so it treats the browser as already logged in.
|
||||
4. You should see the game or your dashboard instead of a login page. The script prints the page URL and title, then closes after a few seconds.
|
||||
|
||||
So “logging in with the cookies” = **loading that JSON file into the browser before navigating**. No credentials are stored in code; they live only in `auth/auth_state.json` (and in the browser profile, see below).
|
||||
|
||||
---
|
||||
|
||||
## What is `auth/profile/`? What must **not** be pushed to GitHub?
|
||||
|
||||
| Item | What it is | Push to GitHub? |
|
||||
|------|------------|-----------------|
|
||||
| **`auth/auth_state.json`** | Snapshot of cookies + localStorage from one browser session. Used by the **game runner** and **demo** so they open already “logged in”. | **No.** Contains session tokens and identifiers. |
|
||||
| **`auth/profile/`** | A **persistent browser profile** (like Chrome’s “user data” folder). Used **only by the capture script**. When you run `npm run capture-auth`, it opens this profile so you may already be logged in from last time; you only re-save when you want to refresh `auth_state.json`. | **No.** Contains cookies, cache, and other browser data. |
|
||||
| **`auth_profile/`** (root) | Old location for the same kind of profile; ignored for new runs. | **No.** |
|
||||
|
||||
The repo’s **`.gitignore`** already has:
|
||||
|
||||
- **`auth/`** — ignores the whole directory (so `auth_state.json` and `profile/` never get committed).
|
||||
- **`auth_profile/`** — ignores the legacy profile folder if it still exists.
|
||||
|
||||
So **none of these should be pushed to GitHub**. If you ever commit them by mistake, treat the session as compromised: log out everywhere, re-capture auth state, and remove the secrets from git history (e.g. with `git filter-branch` or BFG).
|
||||
|
||||
---
|
||||
|
||||
## What’s in `auth/auth_state.json`?
|
||||
|
||||
Playwright’s **storage state** saves everything needed to restore a logged-in session:
|
||||
|
||||
| Part | What it is |
|
||||
|------|------------|
|
||||
| **`cookies`** | Array of all cookies. Each has `name`, `value`, `domain`, `path`, **`expires`**, `httpOnly`, `secure`, `sameSite`. |
|
||||
| **`origins`** | Per-origin **localStorage** (and sessionStorage if present). Sites like Pax Historia store tokens and app state here too. |
|
||||
|
||||
So you get **cookies + localStorage** in one file. No need to copy anything by hand.
|
||||
|
||||
### Where are the cookies?
|
||||
|
||||
At the **top level** of the JSON:
|
||||
|
||||
```json
|
||||
{
|
||||
"cookies": [
|
||||
{ "name": "SID", "value": "...", "domain": ".google.com", "path": "/", "expires": 1805061408.701884, ... },
|
||||
...
|
||||
],
|
||||
"origins": [
|
||||
{ "origin": "https://www.paxhistoria.co", "localStorage": [ ... ] },
|
||||
...
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### What does `expires` mean?
|
||||
|
||||
**`expires`** is a **Unix timestamp in seconds** (decimal allowed). When that time passes, the cookie is no longer sent by the browser.
|
||||
|
||||
- **Example:** `1805061408` → **2027-03-13** (Google “Stay signed in”–style cookies often last ~1 year).
|
||||
- **Session cookies:** Sometimes stored as `-1` or a past date; they last until the browser/tab is closed.
|
||||
- **To check a value:** In JS: `new Date(1805061408 * 1000)` or in the shell: `date -r 1805061408` (macOS).
|
||||
|
||||
So yes: auth state saves **everything** (cookies + localStorage), the **cookies** are in the `cookies` array, and **expiration** is the `expires` number on each cookie.
|
||||
|
||||
---
|
||||
|
||||
## Recommended: Auth state (log in once, reuse)
|
||||
|
||||
### 1. Capture state (one-time or when it expires)
|
||||
|
||||
```bash
|
||||
npx tsx scripts/capture-auth-state.ts
|
||||
```
|
||||
|
||||
- A **real browser window** opens (persistent profile, not headless).
|
||||
- Go to the game and log in with Google (including the popup).
|
||||
- When you’re fully in the game, switch back to the terminal and **press Enter**.
|
||||
- The script saves cookies + localStorage to **`auth/auth_state.json`** (directory `auth/` is gitignored).
|
||||
|
||||
### 2. Use it in your Playwright game runner
|
||||
|
||||
When starting the browser for the agent, load that file so the session is already logged in:
|
||||
|
||||
```ts
|
||||
import { chromium } from "playwright";
|
||||
|
||||
const browser = await chromium.launch();
|
||||
const context = await browser.newContext({
|
||||
storageState: "auth/auth_state.json",
|
||||
});
|
||||
const page = await context.newPage();
|
||||
await page.goto("https://www.paxhistoria.co/game/...");
|
||||
// You should already be logged in.
|
||||
```
|
||||
|
||||
No need to look at the Network tab or copy cookies by hand; `storageState` captures everything Playwright needs.
|
||||
|
||||
---
|
||||
|
||||
## How long does it last?
|
||||
|
||||
- **Session cookies:** Until the browser session that created them would have closed (often hours).
|
||||
- **Persistent cookies (e.g. “Stay signed in”):** Often weeks to months; Google and the game set their own expiry.
|
||||
- **In practice:** Re-run the capture script whenever you get logged out or hit a login page again. The script uses a persistent profile (`auth/profile/`) so you can reopen and re-capture anytime.
|
||||
|
||||
---
|
||||
|
||||
## Optional: Match your real Chrome (if you copy from Chrome)
|
||||
|
||||
If you ever export cookies from **regular Chrome** and inject them into Playwright, the site may see a different **User-Agent** and treat the session as suspicious. To reduce that:
|
||||
|
||||
1. In Chrome DevTools → **Console** run: `navigator.userAgent` and copy the string.
|
||||
2. When creating the Playwright context, set the same string:
|
||||
|
||||
```ts
|
||||
const context = await browser.newContext({
|
||||
storageState: "auth/auth_state.json",
|
||||
userAgent: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) ...", // paste from Chrome
|
||||
});
|
||||
```
|
||||
|
||||
With the **capture script** (Playwright-only), the saved state already comes from a Playwright Chromium profile, so User-Agent usually matches and you don’t need this unless you hit issues.
|
||||
|
||||
---
|
||||
|
||||
## Finding cookies manually (only if you need to debug)
|
||||
|
||||
You don’t need this for the recommended flow. If you ever do:
|
||||
|
||||
- **User-Agent:** DevTools → **Console** → `navigator.userAgent`
|
||||
- **Cookies:** DevTools → **Application** → **Storage** → **Cookies** → select `https://www.paxhistoria.co` (and `accounts.google.com` if needed). Each row is one cookie; a single request sends all of them in one `Cookie:` header, semicolon-separated. Prefer using `storageState` instead of copying these by hand.
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
| Approach | Use when |
|
||||
|-----------------------|-----------------------------------|
|
||||
| **Capture script** | Normal setup: one-time manual login, then reuse `auth/auth_state.json`. |
|
||||
| **Persistent profile**| Same script uses `auth/profile/` so you can reopen and re-capture anytime. |
|
||||
| **Manual cookie copy**| Only for debugging or when you can’t run the capture script. |
|
||||
|
||||
Run `npm run capture-auth`, log in once, press Enter. State is saved under `auth/`. Use `storageState: 'auth/auth_state.json'` in your game runner.
|
||||
+119
-24
@@ -4,41 +4,136 @@
|
||||
|
||||
---
|
||||
|
||||
## Current status (high level)
|
||||
## Current Status (High Level)
|
||||
|
||||
| Area | Status | Notes |
|
||||
|-------------------|----------|--------|
|
||||
| Repo / docs setup | Done | PRD in docs, diagrams in docs/diagrams, CLAUDE.md and this tracker in place. |
|
||||
| War Room scaffold | Done | `war-room/` and placeholder files in place. |
|
||||
| Phase 1: Perception | Pending | Playwright Spy + `/api/simple-chat` → `current_state.json`. |
|
||||
| Phase 2: War Room | Pending | constitution.md, crisis_handbook.txt, strategic_ledger.json. |
|
||||
| Phase 2.5: Advisor | Pending | Query advisor chat, scrape response into context. |
|
||||
| Phase 3: Brain | Pending | Assemble context, update ledger, filter by constitution, output batch of actions. |
|
||||
| Phase 4: Hand | Pending | Batch execution via Playwright (action box submit). |
|
||||
| Phase | Status | Description |
|
||||
|-------|--------|-------------|
|
||||
| Phase 0: Project Init | **Done** | Repo scaffold, Node+TS, Playwright, docs, CLAUDE.md |
|
||||
| Phase 1: Perception | **In Progress** | Playwright Spy + `/api/simple-chat` → `current_state.json` |
|
||||
| Phase 2: War Room | Pending | Populate constitution, handbook, ledger schema |
|
||||
| Phase 2.5: Advisor | Pending | Query advisor chat, scrape response into context |
|
||||
| Phase 3: Brain | Pending | Context assembly, LLM reasoning, action batch generation |
|
||||
| Phase 4: Hand | Pending | Batch execution via Playwright (action box submit) |
|
||||
|
||||
---
|
||||
|
||||
## Done
|
||||
## Phase 0: Project Init — Done
|
||||
|
||||
- [x] Reorganize repo: PRD → `docs/PRD.md`, diagrams → `docs/diagrams/war-room-flow.{mmd,png}`.
|
||||
- [x] Add `CLAUDE.md` (constitution), `docs/project-tracker.md`, `docs/logs/`.
|
||||
- [x] Add scaffold script (see `scripts/scaffold.sh`).
|
||||
- [x] Initialize Node.js + TypeScript project (Playwright, ts-node, tsconfig, entry point).
|
||||
- [x] Reorganize repo: PRD → `docs/PRD.md`, diagrams → `docs/diagrams/`
|
||||
- [x] Add `CLAUDE.md` (constitution), `docs/project-tracker.md`, `docs/logs/`
|
||||
- [x] Add scaffold script (`scripts/scaffold.sh`)
|
||||
- [x] Initialize Node.js + TypeScript project (Playwright, tsx, Zod, tsconfig)
|
||||
- [x] Create `war-room/` placeholders (constitution.md, crisis_handbook.txt, strategic_ledger.json, current_state.json)
|
||||
- [x] Create `src/` skeleton (spy/, brain/, hand/, index.ts)
|
||||
- [x] Consolidate game research into `docs/pax-historia-research.md`
|
||||
- [x] Lock CLAUDE.md: tech stack, coding standards, folder structure, data-flow contracts
|
||||
|
||||
---
|
||||
|
||||
## Pending
|
||||
## Phase 1: Perception — In Progress
|
||||
|
||||
- [x] Run `./scripts/scaffold.sh` to create `war-room/` and placeholders.
|
||||
- [x] Choose runtime (Node/TS recommended) and add package manager + base deps.
|
||||
- [ ] Phase 1: Implement Perception layer (Spy + current_state.json).
|
||||
- [ ] Phase 2: Populate War Room templates (constitution, handbook, ledger schema).
|
||||
- [ ] Phase 2.5: Implement advisor query + response scrape.
|
||||
- [ ] Phase 3: Implement Brain (context assembly, ledger update, action batch).
|
||||
- [ ] Phase 4: Implement Hand (batch execution in browser).
|
||||
**Goal:** Intercept `/api/simple-chat` responses and write parsed game state to `current_state.json`.
|
||||
|
||||
**Files to create/modify:**
|
||||
- `src/shared/schemas.ts` — Zod schema for GameState
|
||||
- `src/shared/index.ts` — barrel export
|
||||
- `src/spy/interceptor.ts` — Playwright route handler for `/api/simple-chat`
|
||||
- `src/spy/state-parser.ts` — parse raw API response → validated GameState
|
||||
- `src/spy/state-writer.ts` — write GameState to `war-room/current_state.json`
|
||||
- `src/spy/index.ts` — barrel export
|
||||
|
||||
**Sub-tasks:**
|
||||
- [ ] Capture a real `/api/simple-chat` response (need DevTools network tab — human task)
|
||||
- [ ] Define Zod GameState schema from captured payload
|
||||
- [ ] Implement route interceptor (Playwright `page.route()`)
|
||||
- [ ] Implement state parser (raw JSON → Zod-validated GameState)
|
||||
- [ ] Implement state writer (GameState → `war-room/current_state.json`)
|
||||
- [ ] Wire into `src/index.ts` entry point
|
||||
- [ ] Smoke test: launch browser, trigger a game event, verify `current_state.json` is written
|
||||
|
||||
---
|
||||
|
||||
## Phase 2: War Room — Pending
|
||||
|
||||
**Goal:** Populate the War Room template files with real strategic content and validate the ledger schema.
|
||||
|
||||
**Files to create/modify:**
|
||||
- `war-room/constitution.md` — long-term goals (populate with real content)
|
||||
- `war-room/crisis_handbook.txt` — tactical playbook (populate with real content)
|
||||
- `src/shared/schemas.ts` — Zod schema for StrategicLedger (add to existing)
|
||||
- `src/brain/war-room-reader.ts` — read + validate all War Room files
|
||||
|
||||
**Sub-tasks:**
|
||||
- [ ] Write constitution content (long-term goals, identity, constraints)
|
||||
- [ ] Write crisis handbook content (tactical doctrines, procedures)
|
||||
- [ ] Define Zod StrategicLedger schema
|
||||
- [ ] Implement War Room reader (read all files, validate, return typed context)
|
||||
|
||||
---
|
||||
|
||||
## Phase 2.5: Advisor — Pending
|
||||
|
||||
**Goal:** Query the in-game advisor and scrape the response into the Brain's context.
|
||||
|
||||
**Files to create/modify:**
|
||||
- `src/hand/advisor.ts` — type query into advisor box, wait for response, extract text
|
||||
- `src/hand/index.ts` — barrel export
|
||||
|
||||
**Sub-tasks:**
|
||||
- [ ] Identify advisor box selectors (need DevTools — human task)
|
||||
- [ ] Implement advisor query function (type → submit → wait → scrape response)
|
||||
- [ ] Add advisor response to Brain context assembly
|
||||
|
||||
---
|
||||
|
||||
## Phase 3: Brain — Pending
|
||||
|
||||
**Goal:** Assemble all context, call Claude API, generate a validated batch of actions.
|
||||
|
||||
**Files to create/modify:**
|
||||
- `src/brain/context-assembler.ts` — read all inputs, build prompt
|
||||
- `src/brain/llm-client.ts` — Anthropic Claude API wrapper
|
||||
- `src/brain/action-generator.ts` — call LLM, parse + validate ActionBatch
|
||||
- `src/shared/schemas.ts` — Zod schema for ActionBatch (add to existing)
|
||||
- `src/brain/index.ts` — barrel export
|
||||
|
||||
**Sub-tasks:**
|
||||
- [ ] Define ActionBatch Zod schema
|
||||
- [ ] Implement context assembler (GameState + War Room files + advisor → prompt)
|
||||
- [ ] Implement Claude API client
|
||||
- [ ] Implement action generator (prompt → ActionBatch)
|
||||
- [ ] Update strategic_ledger.json with new plans after generation
|
||||
|
||||
---
|
||||
|
||||
## Phase 4: Hand — Pending
|
||||
|
||||
**Goal:** Execute the action batch by typing each action into the game UI.
|
||||
|
||||
**Files to create/modify:**
|
||||
- `src/hand/executor.ts` — iterate ActionBatch, type + submit each action
|
||||
- `src/hand/index.ts` — barrel export (update)
|
||||
|
||||
**Sub-tasks:**
|
||||
- [ ] Identify action box submit selectors/mechanics (need DevTools — human task)
|
||||
- [ ] Implement batch executor (loop through actions, type + submit)
|
||||
- [ ] Implement time-jump trigger
|
||||
- [ ] Final ledger commit after execution
|
||||
- [ ] Wire full cognitive loop in `src/index.ts`
|
||||
|
||||
---
|
||||
|
||||
## Blocking / Human Tasks
|
||||
|
||||
These require a human with a browser and DevTools open:
|
||||
|
||||
- [ ] Capture `/api/simple-chat` JSON payload (Phase 1 blocker)
|
||||
- [ ] Identify diplomacy chat selector
|
||||
- [ ] Identify timeline/jump selector
|
||||
- [ ] Determine submit mechanics for each UI element (button? Enter? both?)
|
||||
|
||||
---
|
||||
|
||||
## Logs
|
||||
|
||||
Timestamped writeups go under `docs/logs/` (e.g. `2026-02-07-scaffold.md`, `2026-02-08-perception-debug.md`).
|
||||
Timestamped writeups go under `docs/logs/` (e.g. `2026-02-07-scaffold.md`).
|
||||
+3
-1
@@ -5,7 +5,9 @@
|
||||
"main": "dist/index.js",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"start": "ts-node src/index.ts",
|
||||
"start": "tsx src/index.ts",
|
||||
"capture-auth": "tsx scripts/capture-auth-state.ts",
|
||||
"demo-auth": "tsx scripts/demo-auth-state.ts",
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"repository": {
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
/**
|
||||
* Capture auth state for Pax Historia (Google login).
|
||||
*
|
||||
* Opens a real browser window. You log in manually (including the Google popup).
|
||||
* When you're in the game, press Enter in the terminal to save cookies + localStorage
|
||||
* to auth/auth_state.json. Your main script should use storageState: 'auth/auth_state.json'.
|
||||
*
|
||||
* Run: npm run capture-auth (or npx tsx scripts/capture-auth-state.ts)
|
||||
*/
|
||||
|
||||
import { chromium } from "playwright";
|
||||
import * as fs from "fs";
|
||||
import * as readline from "readline";
|
||||
import * as path from "path";
|
||||
|
||||
const AUTH_DIR = path.join(process.cwd(), "auth");
|
||||
const GAME_URL = "https://www.paxhistoria.co";
|
||||
const USER_DATA_DIR = path.join(AUTH_DIR, "profile");
|
||||
const STATE_PATH = path.join(AUTH_DIR, "auth_state.json");
|
||||
|
||||
async function main() {
|
||||
console.log("-------------------------------------------");
|
||||
console.log("Pax Historia — Auth state capture");
|
||||
console.log("-------------------------------------------");
|
||||
console.log("1. A browser window will open.");
|
||||
console.log("2. Log in to the game (use 'Sign in with Google' if needed).");
|
||||
console.log("3. When you see the game and are fully logged in, come back here.");
|
||||
console.log("4. Press ENTER in this terminal to save auth state and exit.");
|
||||
console.log("-------------------------------------------\n");
|
||||
|
||||
fs.mkdirSync(AUTH_DIR, { recursive: true });
|
||||
|
||||
const context = await chromium.launchPersistentContext(USER_DATA_DIR, {
|
||||
headless: false,
|
||||
slowMo: 50,
|
||||
args: [
|
||||
"--disable-blink-features=AutomationControlled",
|
||||
"--start-maximized",
|
||||
],
|
||||
});
|
||||
|
||||
const page = context.pages()[0] ?? (await context.newPage());
|
||||
await page.goto(GAME_URL, { waitUntil: "domcontentloaded" });
|
||||
|
||||
await new Promise<void>((resolve) => {
|
||||
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
||||
rl.question("Press ENTER after you are logged in to save auth state... ", () => {
|
||||
rl.close();
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
|
||||
await context.storageState({ path: STATE_PATH });
|
||||
await context.close();
|
||||
|
||||
console.log(`\nAuth state saved to: ${STATE_PATH}`);
|
||||
console.log("Use it in your runner: newContext({ storageState: 'auth/auth_state.json' })");
|
||||
}
|
||||
|
||||
main().catch((err) => {
|
||||
console.error("Error:", err);
|
||||
process.exit(1);
|
||||
});
|
||||
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* Demo: load saved auth state and open Pax Historia (no manual login).
|
||||
*
|
||||
* Uses auth/auth_state.json. If you're logged in, you should see the game
|
||||
* or your dashboard instead of a login page.
|
||||
*
|
||||
* Run: npx tsx scripts/demo-auth-state.ts
|
||||
*/
|
||||
|
||||
import { chromium } from "playwright";
|
||||
import * as path from "path";
|
||||
import * as fs from "fs";
|
||||
|
||||
const AUTH_DIR = path.join(process.cwd(), "auth");
|
||||
const STATE_PATH = path.join(AUTH_DIR, "auth_state.json");
|
||||
const GAME_URL = "https://www.paxhistoria.co";
|
||||
|
||||
async function main() {
|
||||
if (!fs.existsSync(STATE_PATH)) {
|
||||
console.error("No auth state found. Run: npm run capture-auth");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
console.log("Loading saved auth state from auth/auth_state.json ...");
|
||||
const browser = await chromium.launch({ headless: false });
|
||||
const context = await browser.newContext({
|
||||
storageState: STATE_PATH,
|
||||
});
|
||||
|
||||
const page = await context.newPage();
|
||||
console.log("Navigating to", GAME_URL, "...");
|
||||
await page.goto(GAME_URL, { waitUntil: "domcontentloaded", timeout: 15000 });
|
||||
|
||||
await page.waitForTimeout(3000);
|
||||
|
||||
const url = page.url();
|
||||
const title = await page.title();
|
||||
console.log("\n--- Result ---");
|
||||
console.log("URL:", url);
|
||||
console.log("Title:", title);
|
||||
console.log("If you see the game (not a login page), auth state is working.");
|
||||
console.log("Browser will close in 5 seconds ...");
|
||||
|
||||
await page.waitForTimeout(5000);
|
||||
await browser.close();
|
||||
}
|
||||
|
||||
main().catch((err) => {
|
||||
console.error("Error:", err);
|
||||
process.exit(1);
|
||||
});
|
||||
Reference in new issue
Block a user