Commit Graph

30 Commits

Author SHA1 Message Date
gilesb
b599b59d44 Use IPFS CID as primary output_cid instead of cache_id hash 2026-01-13 05:01:26 +00:00
gilesb
d7d7cd28c2 Store cache items by IPFS CID, index by cache_id
- Files in /data/cache/nodes/ are now stored by IPFS CID only
- cache_id parameter creates index from cache_id -> IPFS CID
- Removed deprecated node_id parameter behavior
- get_by_cid(cache_id) still works via index lookup

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 04:20:34 +00:00
gilesb
2c3f943e5a Save plan_cid to database immediately after plan creation
- Add plan_cid column to pending_runs table schema
- Add update_pending_run_plan() function to save plan_cid
- Update get_pending_run() to return plan_cid
- Save plan_cid right after storing plan to IPFS (before execution)
- Plan is now available even if run fails

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 04:13:10 +00:00
gilesb
7813eb081a Fail run if output cannot be uploaded to IPFS
- Upload final output to IPFS after execution completes
- Return success=False if IPFS upload fails
- Previously the run would succeed with output_ipfs_cid=None

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 03:57:36 +00:00
gilesb
3ee4dc1efb Restore effect:identity executor shortcut
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 03:18:26 +00:00
gilesb
c5d70f61c8 Add debug logging for effect executor lookup
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 03:11:33 +00:00
gilesb
c3d6427883 Fix effect loading from IPFS and improve COMPOUND handling
- Remove effect:identity shortcut executor so effects load from IPFS by CID
- COMPOUND nodes now fall back to generic EFFECT executor for dynamic effects
- EFFECT nodes also fall back to generic executor when specific not found
- Update test assertions to match current implementation
- Raise error instead of silently skipping when effect executor not found

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 03:04:52 +00:00
gilesb
ad15ef1ce7 Add explicit EFFECT node handling with case-insensitive lookup
- EFFECT nodes now handled explicitly like SOURCE, COMPOUND, SEQUENCE
- Case-insensitive node type matching throughout
- Fallback executor lookup tries both upper and original case

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 02:21:30 +00:00
gilesb
164f1291ac Add SEQUENCE node handling for concatenating clips
Uses FFmpeg concat demuxer. Falls back to re-encoding if
stream copy fails (different codecs/formats).

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 02:20:04 +00:00
gilesb
f28edf7ab6 Fix DogExecutor to use new process() API instead of effect_dog()
The dog effect was updated to use process() but DogExecutor
was still importing the old effect_dog() function.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 02:05:15 +00:00
gilesb
be4d0da84f Fix case sensitivity bug: S-expression node types are lowercase
Bug: S-expression plans produce lowercase node types (source, compound)
but code was checking uppercase (SOURCE, COMPOUND).

Fix: Use .upper() for node type comparisons.

Add TestNodeTypeCaseSensitivity tests to catch this regression.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 01:58:34 +00:00
gilesb
bfe96a431c Fail recipe if no output produced, add tests
- execute_recipe now returns success=False if output_cid is None
- Add TestRecipeOutputRequired tests to catch missing output
- Recipe must produce valid output to be considered successful

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 01:55:23 +00:00
gilesb
6c4b850487 Add COMPOUND node handling and fix cache lookups by code-addressed hash
- Add COMPOUND node handling in execute_recipe for collapsed effect chains
- Index cache entries by node_id (cache_id) when different from IPFS CID
- Fix test_cache_manager.py to unpack put() tuple returns

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 01:47:20 +00:00
gilesb
d08fbfc0bd Fix SOURCE node resolution for user inputs in execute_recipe
- SOURCE nodes with :input true now resolve CID from input_hashes
- Tries multiple name formats: exact, lowercase-dashes, lowercase-underscores
- Only return "completed" status for runs with actual output
- Add integration tests for SOURCE CID resolution

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 01:36:48 +00:00
gilesb
bf188f4671 Remove dead code: execute_level, render_dog_from_cat, duplicate file_hash
- Remove execute_level() from tasks/execute.py (defined but never called)
- Remove render_dog_from_cat() from legacy_tasks.py (test convenience, never used)
- Remove duplicate file_hash() from legacy_tasks.py, import from cache_manager
- Remove unused hashlib import

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 01:21:55 +00:00
gilesb
d603485d40 Refactor to S-expression based execution with code-addressed cache IDs
Major changes:
- Add execute_recipe task that uses S-expression planner
- Recipe S-expression unfolds into plan S-expression with code-addressed cache IDs
- Cache IDs computed from Merkle tree of plan structure (before execution)
- Add ipfs_client.add_string() for storing S-expression plans
- Update run_service.create_run() to use execute_recipe when recipe_sexp available
- Add _sexp_to_steps() to parse S-expression plans for UI visualization
- Plan endpoint now returns both sexp content and parsed steps

The code-addressed hashing means each plan step's cache_id is:
  sha3_256({node_type, config, sorted(input_cache_ids)})

This creates deterministic "buckets" for computation results computed
entirely from the plan structure, enabling automatic cache reuse.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-13 00:27:24 +00:00
gilesb
1ad8fe9890 Fix plan storage path to match get_by_cid lookup
Store plan directly in CACHE_DIR/{cid} instead of CACHE_DIR/legacy/{cid},
which matches what cache_manager.get_by_cid() checks at line 396-398.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-12 23:50:46 +00:00
gilesb
9a1ed2adea Fetch source content from IPFS if not in local cache
When the Celery worker can't find source content in the local cache,
fetch it from IPFS using the CID. This ensures workers can execute
DAGs even when they don't share the same filesystem as the web server.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-12 21:15:08 +00:00
gilesb
2e3d3a5c6d Store DAG plan to IPFS and track plan_cid in run_cache
- Add plan_cid column to run_cache schema
- Store DAG JSON to IPFS during execute_dag task
- Return plan_cid in run status and list APIs

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-12 18:43:48 +00:00
gilesb
a0b113923e Fix IPFS CID detection in legacy_tasks node caching
- Rename misleading ipfs_cid variable to content_cid
- Detect IPFS CIDs by prefix (Qm or bafy) instead of truthy check
- Add clearer logging to show whether IPFS or local hash is used

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-12 17:13:25 +00:00
gilesb
ee8719ac0b Fix media friendly names, metadata display, output recording, and plan display
- Add friendly name display to media detail and list pages
- Unpack nested meta fields to top level for template access
- Fix output_cid mismatch: use IPFS CID consistently between cache and database
- Add dual-indexing in cache_manager to map both IPFS CID and local hash
- Fix plan display: accept IPFS CIDs (Qm..., bafy...) not just 64-char hashes
- Add friendly names to recipe listing
- Add recipe upload button and handler to recipes list
- Add debug logging to recipe listing

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-12 14:21:39 +00:00
gilesb
60344b34f4 Fix registry lookups to use cid, remove dead legacy code
- Fix all registry lookups to use "cid" instead of "hash" key
  - app/routers/recipes.py: asset and effect resolution
  - tasks/execute_sexp.py: effect config lookups
  - server_legacy.py references (now deleted)
- Prefer IPFS CID over local hash in cache operations
  - cache_service.py: import_from_ipfs, upload_content
  - orchestrate.py: plan caching
  - legacy_tasks.py: node hash tracking

Remove ~7800 lines of dead code:
- server_legacy.py: replaced by modular app/ structure
- tasks/*_cid.py: unused refactoring only imported by server_legacy

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-12 09:09:40 +00:00
gilesb
92d26b2b72 Rename content_hash/output_hash to cid throughout
Refactor to use IPFS CID as the primary content identifier:
- Update database schema: content_hash -> cid, output_hash -> output_cid
- Update all services, routers, and tasks to use cid terminology
- Update HTML templates to display CID instead of hash
- Update cache_manager parameter names
- Update README documentation

This completes the transition to CID-only content addressing.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-12 08:02:44 +00:00
gilesb
db3faa6a2c Fix dog effect import for new single-file format
Dog effect now uses process() instead of effect_dog().

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-12 06:58:59 +00:00
gilesb
c6fadea090 Save run output to user's media collection
When a recipe run completes, save the output to the user's media
with description and source tracking.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-11 21:56:59 +00:00
gilesb
95ffe9fa69 Fix run detail page and recipe name
- Render HTML template for run detail (not just JSON)
- Get recipe name from pending_runs instead of hardcoding "dag"

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-11 21:56:08 +00:00
gilesb
eb1de433b1 Get actor_id from pending_runs when saving completed run
When a DAG task completes, look up actor_id from pending_runs
(where it was saved when the run started) and include it in
run_cache. Also clean up pending_runs entry after completion.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-11 21:43:44 +00:00
gilesb
0f18e5de8d Fix DAG output attribute: output -> output_id
The artdag library DAG class uses output_id not output.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-11 19:10:42 +00:00
giles
4b22fb6588 Index all DAG node outputs by content_hash and upload to IPFS
- Process all node_results after DAG execution
- Store each intermediate/effect output in cache_manager
- Upload all node outputs to IPFS (not just final output)
- Track node_hashes and node_ipfs_cids mappings
- Save run result to database with run_id
- Include nodes with content_hash + ipfs_cid in provenance
- Return node_hashes and node_ipfs_cids in task result

All DAG nodes are now content-addressable via /cache/{content_hash}

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-11 14:08:41 +00:00
gilesb
eaff758395 Rename tasks.py to legacy_tasks.py to avoid conflict with tasks/ package
The tasks/ directory for 3-phase execution was shadowing the old tasks.py.
Renamed to legacy_tasks.py and updated all imports.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-10 12:05:27 +00:00