Skip to content

[Bug]: Explainer delivery/finalize sidecars overwrite local JSON dependencies #1060

Closed

Description

@To3akaRin

Archify version or commit

dev at f90a1930fec2822443d5db5d0d7e05bfdbe61267 (3.2.1-dev.1), Git checkout, macOS / Node.js 22.23.1.

Problem and user impact

Explainer local JSON dependencies are not included in the protected input paths for delivery/finalize sidecars. A normal deliver can report success while replacing its chart data file with provenance. finalize can overwrite chart data or an external native-diagram specification with its full receipt or summary and only then fail because the frozen dependency changed. Failed-delivery recording has the same gap when an HTML artifact already exists.

This is data loss in the input-preservation boundary. It does not require a renderer or layout change.

Exact command and minimal reproduction

Portable three-case script and measured SHA256/exit results. The script creates a new temporary directory and uses only synthetic data; no live Skill is installed.

In a new directory, save this as draft.json:

{
  "schema_version": 1,
  "diagram_type": "explainer",
  "meta": {"id": "source-preservation", "title": "Recorded values", "locale": "en"},
  "answer": {"summary": "Compare the recorded values."},
  "panels": [{
    "id": "data", "title": "Which values differ?",
    "blocks": [{"id": "measurements", "type": "chart", "data": {
      "path": "page.delivery.json", "kind": "bar", "x": "name", "y": ["value"]
    }}]
  }],
  "sources": []
}

Save page.delivery.json with these exact data bytes, including a final newline:

[{"name":"North","value":60},{"name":"South","value":40}]
node /path/to/archify/archify/bin/archify.mjs deliver explainer draft.json page.html --json

Actual behavior / receipt

Exit 0, ok: true; the HTML exists, but page.delivery.json is now a delivery receipt (status: "current") rather than the original JSON array. Before: 58 bytes, SHA256 3c9e0c065492160425f92a4356920765826ee7a4125a638a3abaff157177ac9f. The reproduction script retains complete before/after bytes and receipts.

The same input-boundary gap is reproducible with:

Local dependency / command Observed result
page.finalize.json, default finalize Data overwritten, then exit 1 with explainer/dependency-changed
page.finalize-summary.json, default finalize Data overwritten, then the same failure
values.json, finalize --receipt values.json Data overwritten, then the same failure
External native-diagram JSON at receipt/summary path Specification overwritten, then failure
Existing HTML; invalid numeric data at page.delivery.json; failed redelivery Old HTML preserved, but original data overwritten by failed provenance

The twelve-case local matrix includes CSV/PNG extension-rejection controls and invalid first delivery with no existing HTML; those preserve input bytes. The bug is not a claim that every resource format is vulnerable.

Expected behavior and proposed bounded scope

Please confirm whether one focused PR is welcome to:

  • Protect declared local Explainer JSON chart/native-diagram dependencies from delivery provenance and finalize receipt/summary publication, using the existing physical path/alias rules.
  • Reject collisions with actionable diagnostics before any destructive write, including preparation-error and failed-delivery-record paths. A successful prepared bundle alone is insufficient for the invalid-data redelivery case.
  • Preserve input bytes and existing HTML/evidence on rejection; retain ordinary success, legitimate failed-delivery recording, receipt schemas, sidecar naming, resource freezing and containment behavior.
  • Add public-CLI regressions for default/explicit paths, aliases, failure preservation and non-colliding repeat delivery, plus extracted-package checks and a short contract note. Keep renderer/Viewer/vendor behavior and dependencies unchanged.

Implementation, regressions and documentation are estimated at roughly 250–500 necessary lines, excluding the generated ZIP; no line-count target is proposed. I can prepare the focused PR after scope agreement. Focused filesystem/CLI comparisons should establish this input-preservation fix; it does not claim independent Agent-generation benefit.

Investigation and related work

  • archify/bin/finalize.mjs: reservedFinalizePaths omits local Explainer dependencies; persistReceipts() runs before the first assertPreparedDependencies().
  • archify/bin/archify.mjs: delivery provenance path resolution protects only the primary input; failed-provenance recording checks only input/artifact aliases.
  • Searched existing open/closed issues and PRs. feat: add artifact evidence index command #1056 is a read-only provenance projection; test(recovery): preserve publication on invalid CLI arguments #858 tests invalid recovery arguments. Neither changes these sidecar write boundaries.
  • Origin: code inspection and synthetic probes, with Codex investigation assistance under @To3akaRin's direction. No private repository or customer data is used.

Activity

  1. BlueboxC commented on Oct 22, 2026

    @BlueboxC

    Reproduced this in our 3.2.0-based fork and applied a focused fix: verified fork commit.

    Before any publication, deliver/finalize collect the declared local chart-data and external-diagram paths and protect them alongside the primary input. We reuse the existing physical-path collision checks, including symlink/hardlink aliases. Discovery happens before resource preparation, so invalid numeric data on a repeated delivery cannot be overwritten by failure provenance. An uninspectable draft refuses evidence publication and preserves previous output.

    Ten regressions pass, covering delivery/finalize sidecars, explicit receipts, invalid redelivery, aliases, an external native Tree JSON and noncolliding repeat delivery. Neighboring tests, real Chrome tests (313 pass, eight conditional skips) and final canonical-package/reproducibility checks pass. The source checkout and installed Skill are updated; all 213 managed hashes/modes match the canonical package and all ten regressions pass against the installed CLI. Existing generated user HTML is not rewritten. This is a downstream adaptation of your report, not a new competing upstream PR.

    BlueboxC

  2. tt-a1i commented on Oct 23, 2026

    @tt-a1i
    Owner

    Thank you for the clear report, minimal reproduction, and careful investigation. We independently reproduced the delivery-side overwrite on current main and dev, and the finalize receipt/summary collisions on dev. The non-colliding control preserved the input.

    Please proceed with a focused PR targeting dev: protect declared local Explainer JSON chart data and external native-diagram specifications using the existing physical-path/alias checks, and reject collisions before any destructive write. Please include preparation-error and failed-redelivery paths, preserving input bytes and existing artifacts/evidence on rejection.

    Keep ordinary non-colliding delivery, receipt formats, and renderer/Viewer behavior unchanged. Focused public-CLI before/after regressions, alias checks, and an extracted-package check are sufficient for this filesystem boundary fix; a new Agent-generation benchmark is not needed. Existing evidence and the downstream investigation can be reused with attribution where applicable.

    Thanks again for helping protect users' source data and for keeping the proposed scope bounded.

  3. tt-a1i commented on Oct 25, 2026

    @tt-a1i
    Owner

    Completed on dev through #1094, integrated by #1102 at commit 10b4dd5. Original contribution history is retained.

    Delivery/finalize sidecars protect local chart data and external diagram inputs, including failure paths.

    The exact integrated candidate 98efbfc passed CI run 40177166414: 19 successful jobs, no failures, two deployment-only skips. Closing as completed in the development branch; this does not announce a release or a live installation.

  4. added a commit that references this issue on Oct 25, 2026
    337c767
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions