Fills the gap confirmed during the 2026-07-11 regularization: the write skill had no document-attach op, so rehearsed invoices carried no PDF (PAF: originals hash-addressed in the GED).
document-attach.sh — POST /documents/upload (base64, overwriteifexists always 0), addressed by object_id or ref (cross-checked; ambiguous ref aborts). Idempotent by (object, filename, sha256) — own check, not Dolibarr's overwrite flag: same bytes → deduped:true no-op; different bytes under the same name → abort (refuse-never-repair). Post-upload read-back: re-list + download + sha256 verify; download paths derived from the listing's fullname (supplier invoices carry an id-derived get_exdir prefix — live-verified 9/2/, 2/1/, 4/1/, 5/1/).
Promote op attach in promote-plan/promote-apply with @ref/#lookup object resolution; file resolves relative to the manifest; plan prints each file's sha256 at review time.
bin/arcodange sandbox attach subcommand + SKILL.md workflow 7 + offline test case 12 + live attach op in tests/replay-idempotency.sh.
Replay pack manifest-C-ged-attach.json (portable #supplierinvoice:ref_supplier= lookups); PDFs re-fetched from Zoho (arcodange-email-ingest), sha256s match the golden-set sidecars 4/4.
Acceptance (live on the sandbox, in the #43 evidence comment): run 1 4 created, run 2 4 deduped (no-op), API listing shows exactly one file per invoice (FAF2026010–013), each downloaded back with stored sha256 == source sha256. Conflict abort live-proven.
Remaining human-gated step (out of scope here): prod replay of manifest-C via the promote gate.
Closes #43.
Fills the gap confirmed during the 2026-07-11 regularization: the write skill had no document-attach op, so rehearsed invoices carried no PDF (PAF: originals hash-addressed in the GED).
- `document-attach.sh` — `POST /documents/upload` (base64, `overwriteifexists` always 0), addressed by `object_id` or `ref` (cross-checked; ambiguous ref aborts). **Idempotent by (object, filename, sha256) — own check**, not Dolibarr's overwrite flag: same bytes → `deduped:true` no-op; different bytes under the same name → abort (refuse-never-repair). Post-upload read-back: re-list + download + sha256 verify; download paths derived from the listing's `fullname` (supplier invoices carry an id-derived `get_exdir` prefix — live-verified `9/2/`, `2/1/`, `4/1/`, `5/1/`).
- Promote op `attach` in `promote-plan`/`promote-apply` with `@ref`/`#lookup` object resolution; `file` resolves relative to the manifest; plan prints each file's sha256 at review time.
- `bin/arcodange sandbox attach` subcommand + SKILL.md workflow 7 + offline test case 12 + live attach op in `tests/replay-idempotency.sh`.
- Replay pack `manifest-C-ged-attach.json` (portable `#supplierinvoice:ref_supplier=` lookups); PDFs re-fetched from Zoho (`arcodange-email-ingest`), sha256s match the golden-set sidecars 4/4.
**Acceptance (live on the sandbox, in the [#43 evidence comment](https://gitea.arcodange.lab/arcodange-org/erp/issues/43)):** run 1 `4 created`, run 2 `4 deduped` (no-op), API listing shows exactly one file per invoice (FAF2026010–013), each downloaded back with stored sha256 == source sha256. Conflict abort live-proven.
Remaining human-gated step (out of scope here): prod replay of manifest-C via the promote gate.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
https://claude.ai/code/session_01VRShc4QhLLU73FLHx9vskh
document-attach.sh uploads a source piece (the supplier's own PDF) onto an
invoice's GED via POST /documents/upload — idempotent by (object, filename,
sha256): before any POST the object's GED is listed and a same-named entry is
downloaded back and sha256-compared. Identical → deduped no-op; different
content → ABORT (refuse-never-repair, overwriteifexists always 0, never
Dolibarr's overwrite flag). Read-back after upload: re-list + download +
sha256-verify. Module-relative download paths are derived from the listing's
fullname (supplier invoices carry an id-derived get_exdir prefix like
9/2/FAF2026013/…, so reconstruction would be wrong).
Promote integration: new `attach` op in promote-plan/promote-apply (OP_SCRIPT),
object_id resolvable via @ref and #supplierinvoice lookups; a relative `file`
resolves against the manifest's directory (replay packs carry pdfs/ beside the
manifest, gitignored — README documents the books@ re-fetch message ids).
promote-plan prints each file's sha256 (or a loud MISSING) at review time.
CLI: `arcodange sandbox attach`.
Proof: offline case 12 in tests/run-tests.sh (upload body, dedupe, conflict
abort, field refusal, manifest-relative resolution via stubbed /documents);
live: manifest-C-ged-attach.json applied twice on the sandbox — run 1 four
created, run 2 four deduped, one GED file per FAF2026010-013, stored sha256s
equal to the re-fetched sources; tests/replay-idempotency.sh extended with an
attach op (4 created → 4 deduped, ged_files count unchanged) and a live
same-name/different-bytes abort verified.
Closes erp#43
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01VRShc4QhLLU73FLHx9vskh
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Closes #43.
Fills the gap confirmed during the 2026-07-11 regularization: the write skill had no document-attach op, so rehearsed invoices carried no PDF (PAF: originals hash-addressed in the GED).
document-attach.sh—POST /documents/upload(base64,overwriteifexistsalways 0), addressed byobject_idorref(cross-checked; ambiguous ref aborts). Idempotent by (object, filename, sha256) — own check, not Dolibarr's overwrite flag: same bytes →deduped:trueno-op; different bytes under the same name → abort (refuse-never-repair). Post-upload read-back: re-list + download + sha256 verify; download paths derived from the listing'sfullname(supplier invoices carry an id-derivedget_exdirprefix — live-verified9/2/,2/1/,4/1/,5/1/).attachinpromote-plan/promote-applywith@ref/#lookupobject resolution;fileresolves relative to the manifest; plan prints each file's sha256 at review time.bin/arcodange sandbox attachsubcommand + SKILL.md workflow 7 + offline test case 12 + live attach op intests/replay-idempotency.sh.manifest-C-ged-attach.json(portable#supplierinvoice:ref_supplier=lookups); PDFs re-fetched from Zoho (arcodange-email-ingest), sha256s match the golden-set sidecars 4/4.Acceptance (live on the sandbox, in the #43 evidence comment): run 1
4 created, run 24 deduped(no-op), API listing shows exactly one file per invoice (FAF2026010–013), each downloaded back with stored sha256 == source sha256. Conflict abort live-proven.Remaining human-gated step (out of scope here): prod replay of manifest-C via the promote gate.
🤖 Generated with Claude Code
https://claude.ai/code/session_01VRShc4QhLLU73FLHx9vskh