Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* @is2b007
80 changes: 80 additions & 0 deletions .github/ISSUE_TEMPLATE/bug_report.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
name: Bug report
description: Report reproducible behavior that is wrong or unsafe
title: "[Bug]: "
labels:
- bug
body:
- type: markdown
attributes:
value: |
Thank you for helping improve Reed. Use a disposable project where possible and remove story text, tokens, repository capabilities, and connector URLs from screenshots and logs.
- type: dropdown
id: platform
attributes:
label: Platform
options:
- macOS Apple silicon
- Android / Daylight DC-1
- Android / another device
- CLI
- Local MCP
- Remote Agent Access / relay
- Export / Unity integration
validations:
required: true
- type: input
id: version
attributes:
label: Reed version or commit
placeholder: v0.1.2 or commit SHA
validations:
required: true
- type: textarea
id: problem
attributes:
label: What happened?
description: Describe the observed behavior and its effect on your work.
validations:
required: true
- type: textarea
id: steps
attributes:
label: Steps to reproduce
placeholder: |
1. Create a disposable project...
2. Open...
3. Select...
validations:
required: true
- type: textarea
id: expected
attributes:
label: Expected behavior
validations:
required: true
- type: dropdown
id: network
attributes:
label: Network state
options:
- Offline
- Online, GitHub disabled
- Online, GitHub enabled
- Remote Agent Access active
- Not relevant
validations:
required: true
- type: textarea
id: evidence
attributes:
label: Sanitized evidence
description: Add screenshots or logs only after removing private story content, tokens, paths, and connector URLs.
- type: checkboxes
id: safety
attributes:
label: Safety check
options:
- label: I have not included a GitHub token, connector capability, private repository URL, database, or private story content.
required: true
- label: This is not a security vulnerability. I will use private vulnerability reporting for security-sensitive issues.
required: true
5 changes: 5 additions & 0 deletions .github/ISSUE_TEMPLATE/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
blank_issues_enabled: false
contact_links:
- name: Security vulnerability
url: https://github.com/is2b007/Reed/security/advisories/new
about: Report vulnerabilities and credential/data exposure privately.
53 changes: 53 additions & 0 deletions .github/ISSUE_TEMPLATE/feature_request.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
name: Feature request
description: Propose a bounded improvement to Reed's authoring workflow
title: "[Feature]: "
labels:
- enhancement
body:
- type: textarea
id: workflow
attributes:
label: Authoring problem
description: What job is difficult today, and who is doing it?
validations:
required: true
- type: textarea
id: proposal
attributes:
label: Proposed behavior
description: Describe the smallest useful outcome, not only an implementation.
validations:
required: true
- type: dropdown
id: platform
attributes:
label: Primary surface
options:
- macOS editor
- Android / Daylight DC-1
- Both editors
- CLI
- MCP / external agents
- Pixel Crushers / Unity export
- Voice production
- Git / GitHub collaboration
validations:
required: true
- type: textarea
id: offline
attributes:
label: Offline behavior
description: Explain how this remains useful without a network and whether it proposes any new network boundary.
validations:
required: true
- type: textarea
id: alternatives
attributes:
label: Alternatives considered
- type: checkboxes
id: boundaries
attributes:
label: Product boundaries
options:
- label: The proposal does not require a Reed account, telemetry, cloud project storage, remote assets, or an embedded LLM.
required: true
26 changes: 26 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
## What changed

Describe the user-visible change and why Reed needs it.

## Offline and data-safety impact

- Does opening Reed or an idle workspace start any network process?
- Does this touch SQLite, migrations, permanent IDs, backups, Git credentials, or Remote Agent Access?
- What happens when the network is unavailable?

## Validation

- [ ] Type checking passed.
- [ ] Targeted tests passed.
- [ ] Full serial Vitest suite passed.
- [ ] Offline smoke test passed, or this change cannot affect a runtime boundary.
- [ ] Android unit/lint/build checks passed, or Android is unaffected.
- [ ] Visual changes include screenshots made with disposable/demo data.
- [ ] English, Greek, Griko, Italian, and German content remains intact where relevant.
- [ ] Documentation is updated.

List the exact commands and any checks you could not run.

## Screenshots or recordings

Add before/after evidence for interface changes. Do not include private projects, repository capabilities, tokens, or connector URLs.
52 changes: 52 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
name: CI

on:
push:
branches: [main]
pull_request:
branches: [main]

permissions:
contents: read

concurrency:
group: ci-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
typescript:
name: TypeScript, tests, and offline contract
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@v7
- uses: pnpm/action-setup@v6
with:
version: 11.8.0
- uses: actions/setup-node@v7
with:
node-version: 22.22.0
cache: pnpm
- run: pnpm install --frozen-lockfile
- run: pnpm typecheck
- run: pnpm build:runtime
- name: Run test files serially
run: pnpm exec vitest run --no-file-parallelism --maxWorkers=1
- run: pnpm test:offline

android:
name: Android unit, lint, and APK build
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@v7
- uses: actions/setup-java@v5
with:
distribution: temurin
java-version: "21"
- uses: android-actions/setup-android@v4
- name: Install Android SDK 36
run: sdkmanager "platforms;android-36" "build-tools;36.0.0"
- name: Test, lint, and assemble
working-directory: apps/android
run: ./gradlew testDebugUnitTest lintDebug assembleDebug
106 changes: 106 additions & 0 deletions ARCHITECTURE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
# Reed architecture

Reed is an offline-first authoring system with two application shells and one shared project contract. The macOS implementation is TypeScript/Electron; Android is Kotlin/Compose. Both keep SQLite in WAL mode as the canonical store and preserve the same permanent IDs, versioned mutations, production guardrails, and deterministic export semantics.

## System view

```mermaid
flowchart TB
subgraph Desktop["macOS"]
Editor["Electron + React editor"]
CLI["Local CLI"]
MCP["Local stdio MCP"]
TSCore["@reed/core"]
Editor --> TSCore
CLI --> TSCore
MCP --> TSCore
end

subgraph Tablet["Android / Daylight DC-1"]
Compose["Kotlin + Compose editor"]
AgentService["Optional foreground agent service"]
AndroidCore["com.reed.core.ReedCore"]
Compose --> AndroidCore
AgentService --> AndroidCore
end

TSCore --> DesktopDB["SQLite + WAL"]
AndroidCore --> AndroidDB["SQLite + WAL"]
TSCore --> DesktopExports["Deterministic local exports"]
AndroidCore --> AndroidExports["Deterministic local exports"]

Editor -. "explicit Git action" .-> DesktopGit["git + gh"]
Compose -. "explicit Git action" .-> JGit["JGit + Android Keystore"]
Claude["External agent"] -. "expiring connector" .-> Relay["Memory-only relay"]
Relay -. "HTTPS long poll" .-> AgentService
```

Solid lines are local calls. Dotted lines are optional network boundaries that require an explicit user action.

## Sources of truth

- A project's SQLite database is canonical.
- SQLite uses WAL mode for crash resilience and concurrent local readers.
- `exports/reed-project.json` is deterministic, reviewable output, not a second database.
- Unity/Pixel Crushers JSON is generated output and never imported back as canonical state.
- Line IDs and Pixel Crushers numeric mappings are permanent once allocated.
- Every mutation increments the project version and records history.
- Mutations accept `expectedVersion` where stale writes could overwrite newer work.

## Desktop implementation

`apps/editor` contains the Electron shell and React interface. The renderer has no raw filesystem, SQL, Git, or network authority; privileged operations cross the typed preload/IPC boundary and are implemented by the main process through `@reed/core`.

`packages/core` owns the TypeScript domain model, SQLite migrations, validation, history, backups, production rules, Git orchestration, and export generation. `packages/cli` and `apps/mcp` are thin clients over that core.

Desktop GitHub operations invoke bundled or system `git` and `gh`. GitHub CLI owns authentication through the operating-system credential store. Reed does not copy tokens into project files, preferences, SQLite, logs, or Git configuration.

## Android implementation

`apps/android/app` contains the Compose application, responsive workspace, input handling, and foreground agent service. `apps/android/core` is the Android implementation of the Reed snapshot and mutation contracts. It owns Room/SQLite access and platform-parity tests.

Android cannot rely on child-process Git, so `apps/android/git` uses JGit. A repository token is optional, encrypted through Android Keystore, and supplied to JGit only for the operation the user requested.

`apps/android/remote` implements the narrow Remote Agent Access transport. It is disabled by default, scoped to one open project, expires within 24 hours, and runs only as an Android foreground service with a persistent Disconnect action.

## Remote Agent Access boundary

The relay in `apps/relay` coordinates one tablet channel in process memory. It does not have a Reed account system, database, object store, durable queue, analytics pipeline, or LLM client. Restarting it drops active channels.

Remote tools may call guarded ReedCore operations. They cannot access Git, raw SQL, arbitrary files, shell execution, or credentials. Agents cannot promote text beyond `Polished`, mutate Final content, or bypass version conflicts and exact destructive confirmations.

See [Remote MCP from Claude Android](docs/REMOTE_MCP_ANDROID.md) for the deployment and threat model.

## Mutation and production invariants

- Final content is controlled by a person.
- Editing text with recorded-or-later voice status changes voice status to `Rework`.
- Destructive actions require confirmation or a reversible undo path.
- Agent mutations are recorded with an agent source and remain reviewable.
- English, Greek, Griko, Italian, and German remain valid UTF-8 across storage, UI, MCP, CLI, and exports.
- Node type, status, validation, and speaker identity are never communicated by color alone.

## Repository map

| Path | Responsibility |
|---|---|
| `apps/editor` | Electron main process, preload boundary, React UI, macOS packaging |
| `apps/android/app` | Compose UI, adaptive input, foreground remote-agent service |
| `apps/android/core` | Android SQLite model and mutation parity |
| `apps/android/git` | JGit transport and Keystore-backed credential handling |
| `apps/android/remote` | Relay protocol and connector capability storage |
| `apps/mcp` | Local stdio MCP entrypoint |
| `apps/relay` | Optional single-process, memory-only remote MCP relay |
| `packages/core` | TypeScript canonical domain, persistence, Git, backups, exports |
| `packages/schema` | Shared TypeScript contracts and schemas |
| `packages/cli` | Local command-line interface |

## Verification layers

1. TypeScript type checking for every workspace package.
2. Unit and regression tests for core, editor logic, Git/GitHub orchestration, relay behavior, and concurrency.
3. Android unit tests and parity tests, plus lint and APK assembly.
4. An offline smoke test covering core, CLI, MCP, backups, Git-disabled operation, Unicode exports, and the editor network boundary.
5. Manual DC-1 checks for touch, keyboard, mouse, trackpad, pen hover, background agent access, and lifecycle behavior.

Read [CONTRIBUTING.md](CONTRIBUTING.md) before changing a platform boundary.
Loading