- export_with_trees.sh: Bash wrapper for Outline export - outline_export_fixed.py: Python export implementation - IMPORT_SCRIPT.MD: PRD for import script (to be built) - RALPH_PROMPT.md: Ralph Loop prompt for building import script - CLAUDE.md: Project documentation Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
203 lines
6.0 KiB
Markdown
203 lines
6.0 KiB
Markdown
# Outline Import Script - Ralph Loop Prompt
|
|
|
|
## Your Mission
|
|
|
|
Build `import_to_outline.sh` and `outline_import.py` - companion scripts to the existing export tools that import markdown files back into Outline wiki.
|
|
|
|
**Requirements Document:** Read `IMPORT_SCRIPT.MD` for full specifications.
|
|
|
|
**Reference Implementation:** Study `export_with_trees.sh` and `outline_export_fixed.py` for patterns.
|
|
|
|
---
|
|
|
|
## Iteration Protocol
|
|
|
|
Each iteration, follow this cycle:
|
|
|
|
### 1. Assess Current State
|
|
```bash
|
|
# Check what exists
|
|
ls -la *.sh *.py 2>/dev/null
|
|
git status
|
|
git log --oneline -5 2>/dev/null || echo "No git history"
|
|
```
|
|
|
|
### 2. Read Requirements (if needed)
|
|
- Review `IMPORT_SCRIPT.MD` for specifications
|
|
- Review `outline_export_fixed.py` for API patterns and settings.json structure
|
|
- Review `settings.json` for configuration format
|
|
|
|
### 3. Implement Next Phase
|
|
Work on the current phase until complete, then move to the next.
|
|
|
|
### 4. Test Your Work
|
|
- Run syntax checks: `python3 -m py_compile outline_import.py`
|
|
- Run bash checks: `bash -n import_to_outline.sh`
|
|
- Test `--help` output
|
|
- Test `--dry-run` mode against `outline_export/` directory
|
|
|
|
### 5. Commit Progress
|
|
```bash
|
|
git add -A && git commit -m "Phase X: description"
|
|
```
|
|
|
|
---
|
|
|
|
## Implementation Phases
|
|
|
|
### Phase 1: Core Python Structure
|
|
Create `outline_import.py` with:
|
|
- [ ] `OutlineImporter` class with settings loading (copy pattern from `outline_export_fixed.py`)
|
|
- [ ] API helper methods: `_api_request()`, `_get_collections()`, `_create_collection()`
|
|
- [ ] Argument parsing with all CLI options from spec
|
|
- [ ] Basic logging setup
|
|
|
|
**Verification:** `python3 -m py_compile outline_import.py` passes
|
|
|
|
### Phase 2: Metadata Loading
|
|
- [ ] Load `_collection_metadata.json` from each collection directory
|
|
- [ ] Build document tree from `documents` array
|
|
- [ ] Implement topological sort for parent-before-child ordering
|
|
- [ ] Handle missing/invalid metadata gracefully
|
|
|
|
**Verification:** Can parse metadata from `outline_export/*/`
|
|
|
|
### Phase 3: Collection Import Logic
|
|
- [ ] Check if collection exists via `/api/collections.list`
|
|
- [ ] Create collection via `/api/collections.create`
|
|
- [ ] Handle `--force` mode (delete and recreate)
|
|
- [ ] Skip existing collections by default
|
|
|
|
**Verification:** `--dry-run` shows correct collection operations
|
|
|
|
### Phase 4: Document Import with Hierarchy
|
|
- [ ] Read markdown content from files
|
|
- [ ] Create documents via `/api/documents.create`
|
|
- [ ] Maintain ID mapping: `old_id -> new_id`
|
|
- [ ] Set `parentDocumentId` using mapped IDs
|
|
- [ ] Handle missing parent (create as root-level)
|
|
|
|
**Verification:** `--dry-run` shows correct document hierarchy
|
|
|
|
### Phase 5: Single Collection Mode
|
|
- [ ] Implement `--single` flag
|
|
- [ ] Create timestamped collection name `import_YYYYMMDD_HHMMSS`
|
|
- [ ] Convert original collection folders to parent documents
|
|
- [ ] Preserve nested hierarchy under these parents
|
|
|
|
**Verification:** `--dry-run --single` shows consolidated structure
|
|
|
|
### Phase 6: Progress Visualization
|
|
- [ ] Tree-style output matching spec (├──, └──, │)
|
|
- [ ] Status indicators (✓ created, ✗ error, ○ skipped)
|
|
- [ ] Summary statistics (collections/documents created/skipped/errors)
|
|
- [ ] Duration tracking
|
|
|
|
**Verification:** Output matches examples in IMPORT_SCRIPT.MD Section 7
|
|
|
|
### Phase 7: Bash Wrapper Script
|
|
Create `import_to_outline.sh` with:
|
|
- [ ] Docker execution (matching `export_with_trees.sh` pattern)
|
|
- [ ] CLI argument passthrough
|
|
- [ ] Help text
|
|
- [ ] Pre-flight checks (settings.json exists, source directory exists)
|
|
|
|
**Verification:** `./import_to_outline.sh --help` works
|
|
|
|
### Phase 8: Error Handling & Polish
|
|
- [ ] Retry logic for API failures (3 attempts, exponential backoff)
|
|
- [ ] Proper error messages for all failure modes
|
|
- [ ] Rate limiting delay between API calls
|
|
- [ ] Verbose/debug output levels
|
|
|
|
**Verification:** All error scenarios from spec handled
|
|
|
|
---
|
|
|
|
## Success Criteria
|
|
|
|
All of the following must be true:
|
|
|
|
1. **Files exist:** `import_to_outline.sh` and `outline_import.py`
|
|
2. **Syntax valid:** Both pass syntax checks without errors
|
|
3. **Help works:** `./import_to_outline.sh --help` shows usage
|
|
4. **Dry-run works:** `./import_to_outline.sh --dry-run` parses `outline_export/` and shows planned operations
|
|
5. **Single mode:** `./import_to_outline.sh --dry-run --single` shows consolidated import plan
|
|
6. **Matches spec:** Output format matches IMPORT_SCRIPT.MD Section 7 examples
|
|
|
|
---
|
|
|
|
## Completion Signal
|
|
|
|
When ALL success criteria are met, output:
|
|
|
|
```
|
|
<promise>IMPORT SCRIPT COMPLETE</promise>
|
|
```
|
|
|
|
**Do not output this promise until:**
|
|
- Both files exist and pass syntax checks
|
|
- `--help` displays properly
|
|
- `--dry-run` successfully parses metadata and shows planned operations
|
|
- Output format matches the specification
|
|
|
|
---
|
|
|
|
## Anti-Patterns to Avoid
|
|
|
|
1. **Don't skip phases** - Complete each phase before moving on
|
|
2. **Don't forget commits** - Commit after each successful phase
|
|
3. **Don't ignore errors** - Fix syntax/import errors before proceeding
|
|
4. **Don't deviate from spec** - Follow IMPORT_SCRIPT.MD precisely
|
|
5. **Don't over-engineer** - Implement exactly what's specified, no more
|
|
|
|
---
|
|
|
|
## Helpful Context
|
|
|
|
### API Endpoint Examples (from spec)
|
|
```python
|
|
# Create collection
|
|
POST /api/collections.create
|
|
{"name": "Bewerbungen", "permission": "read_write"}
|
|
|
|
# Create document
|
|
POST /api/documents.create
|
|
{
|
|
"collectionId": "col-uuid",
|
|
"title": "Document Title",
|
|
"text": "# Content\n\nMarkdown here...",
|
|
"parentDocumentId": "parent-uuid-or-null",
|
|
"publish": true
|
|
}
|
|
```
|
|
|
|
### Docker Execution Pattern
|
|
```bash
|
|
docker run --rm --network domnet \
|
|
--user "$(id -u):$(id -g)" \
|
|
-e HOME=/tmp \
|
|
-v "$WORK_DIR:/work" \
|
|
-w /work \
|
|
python:3.11-slim \
|
|
bash -c "pip install -qqq requests 2>/dev/null && python3 outline_import.py $CLI_ARGS"
|
|
```
|
|
|
|
### Settings Structure (existing in settings.json)
|
|
```json
|
|
{
|
|
"source": {
|
|
"url": "http://outline:3000",
|
|
"token": "ol_api_xxx"
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Current Iteration
|
|
|
|
Read the files, check git history, determine which phase you're on, and continue from there.
|
|
|
|
If starting fresh: Begin with Phase 1.
|