Files
product-54354138-1/.agent-work/ledger.json
T
Tool Backend 2e8e70e765
Repository Validate / repository-checks (pull_request) Successful in 19s
change: Implement 7: Document the tool-calling contract, statuses, exit codes and native-process usage
Rewrote README.md as the delivered tool-calling contract for the calling AI agent and added tests/test_readme.py to keep it synchronized with the implementation.

README.md now documents:
- Native-process usage only: `python -m tools.example` with no Docker, container image or packaging stage, Python >= 3.11, no runtime third-party dependencies.
- Every parameter exactly as produced by `--help`: positional `REQUEST.json`, `-t/--topic`, `--width`, `--height`, `-f/--format` (`png|ico`), `-s/--source` (default `wikimedia_commons`), `-c/--count` (1-50, default 10), `--download`, `-o/--output-dir`, `--resize`, `--dry-run`; width/height documented as minimums and the "document XOR flags" rule.
- The JSON request document form used by `examples/input.json`: field table, types, defaults, optional `version`, and the document-level invalid_request rules.
- The single-document JSON response schema: fixed keys `status`, `source`, `request`, `items`, `error`; item fields (actual format/width/height, `url`/`file_url`, `size_bytes`), download record, resize fragment and the verified-save failure record.
- The fixed status vocabulary with its exit codes: `ok`=0, `dry_run`=0, `invalid_request`=2, `no_format`=3, `no_size`=4, `access_error`=5, `partial_download`=6, plus why no_match/outage are distinguishable.
- Approved free sources (`wikimedia_commons`, `openverse`) with no API keys, tokens or registration, the approved HTTPS host allowlist, and the registry extension point (`SourceAdapter`, `SourceRegistry.register/unregister`, `build_registry()`/`default_registry()`, host allowlist extension).
- Both decided behaviours: `--download` without `--output-dir` is an invalid request (invalid_request / exit 2), and partial saves are reported as `partial_download` (exit 6) with `download_incomplete` details while saved paths are still reported.
- The real test entrypoint `pytest` plus the compileall/help/smoke commands.

tests/test_readme.py asserts the README documents every long option the real parser accepts, the accepted formats, every status with its exit code from STATUS_EXIT_CODES, the response keys, every registered source id, the registry extension names, both product decisions, native-process wording, and the real pytest/compileall/help/smoke commands.

Tests:
Ran the facade check set with .venv/bin on PATH after `prepare_environment(component=tools, mode=restore)`:
- `pytest -q` -> 163 passed, 1 skipped (pre-existing tests/test_live_source.py live-network skip: Wikimedia upload host returns HTTP 429 from this sandbox).
- `python -m compileall -q tools tests` -> ok.
- `python -m tools.example --help` -> exit 0.
- `python -m tools.example examples/input.json` -> exit 0, one JSON dry_run envelope.
- `pytest tests/test_readme.py -q` -> 5 passed.
Also confirmed `git merge-base --is-ancestor origin/task/1-task HEAD` (target branch already integrated, zero diff), so no integration step was required.

Progress:
Delivered the documentation slice for issue 9. README.md was a two-line placeholder; it is now the full tool-calling contract: CLI parameters matching `--help` output, the JSON request-document form for examples/input.json, the single-document response schema, the fixed status vocabulary with exit codes (ok/dry_run=0, invalid_request=2, no_format=3, no_size=4, access_error=5, partial_download=6), credential-free sources and the registry extension point, the decided --download-without---output-dir invalid-request behaviour, partial_download reporting for incomplete saves, and plain native-process execution with the real pytest entrypoint. Added tests/test_readme.py (5 tests) so CI fails if documentation drifts from build_parser(), STATUS_EXIT_CODES, ACCEPTED_FORMATS or the default registry. No protected facade paths or source behaviour changed; existing obligations preserved (full suite green apart from the pre-existing live-source skip).

Published by developer-agent through Tool Backend.

Closes #9
2026-11-03 02:40:29 +00:00

42 lines
6.5 KiB
JSON

{
"tasks": {
"projects/product-54354138-1#3": {
"events": [
"Created tools package (tools/__init__.py, tools/example.py), examples/input.json, tests/test_example.py, .gitignore, .env.example; updated pyproject.toml (metadata, setuptools packages, dev pytest extra, pytest pythonpath/testpaths, requires-python >=3.11 due to approved-mirror exceptiongroup constraint) and generated uv.lock via prepare_environment update. Facade validate/test/smoke and --help all pass locally."
]
},
"projects/product-54354138-1#4": {
"events": [
"Implemented tools/errors.py, tools/sources.py and tests/test_sources.py for the credential-free source registry and HTTPS fetch layer. Verified with the facade commands tools.validate, tools.test (54 passed) and tools.smoke, all green on the integrated branch (target task/1-task was already at HEAD). No protected facade paths touched."
]
},
"projects/product-54354138-1#5": {
"events": [
"Implemented envelope status/exit-code table and response builder, request errors, the full flag/JSON-document CLI in tools/example.py, canonical offline examples/input.json, and CLI tests; facade validate/test/smoke and --help all pass (76 tests).",
"Addressed the changes-requested review on PR #13: requested width/height are now a minimum target size (selection no longer depends on --resize), and --resize now actually downscales downloaded images (stdlib PNG codec + ICO/PNG container support, shrink-to-fit, never upscaling) with per-item resize metadata and typed ImageResizeError for undecodable payloads. Updated tests/test_cli.py with minimum-size and offline resize/download contract tests (83 passed). Facade validate/test/smoke/help all green; examples/input.json stays the canonical dry_run request."
]
},
"projects/product-54354138-1#6": {
"events": [
"Implemented byte-based format and minimum-size filtering for the image search path. New tools/images.py: detect_format (png/ico plus jpeg/gif/bmp/webp so \"other format\" is distinguishable from \"unreadable\"), read_png_dimensions (IHDR), read_ico_dimensions (ICONDIR entries, 0 => 256, largest entry), inspect_image/ImageInfo, ImageFormatError (code image_unreadable), and png_bytes/ico_bytes builders. tools/example.py: candidate_cap(count) bounded window (count*4, max 50) requested from the source, _select() fetches and parses every candidate, KeptImage.to_item() reports source/url/format/actual width+height/size_bytes, _download() writes the already verified bytes, and _execute() distinguishes ok/no_format/no_size/access_error/partial_download with the existing exit codes; metadata-based filtering removed. tests/test_images.py added (31 tests) and tests/test_cli.py fixtures aligned to real image bytes. All facade commands pass: compileall, pytest (114 passed), smoke, help, package import.",
"Addressed changes-requested review on PR #14: the CLI no longer turns common live-source results into partial_download/access_error. Any payload whose real format is not the requested png/ico (jpeg, gif, bmp, webp, svg, tiff, pdf, or an unrecognised body such as an HTML page) is now a format mismatch feeding no_format, with observed_formats/other_format_candidates detail; only unfetchable candidates are failures, and access_error is emitted only when nothing at all could be fetched. images.detect_format gained svg/tiff/pdf recognition and ImageFormatError is scoped to genuinely unusable png/ico payloads. Statuses/exits unchanged (no_format 3, no_size 4, access_error 5). Tests extended in tests/test_images.py (svg/tiff/pdf detection, mixed-format window stays ok, ico-only-foreign yields no_format, no_size preserved alongside other formats, non-image body is no_format, unfetchable candidate does not demote a search, corrupt png does not hide a match, empty window) and tests/test_cli.py aligned. Facade validate/test/smoke/help all green (129 passed) on the integrated branch; no protected facade paths touched."
]
},
"projects/product-54354138-1#7": {
"events": [
"Completed issue 7: stdlib PNG/ICO decode/encode/wrap/unwrap plus resample helpers live in tools/images.py; tools/example.py saves selected images into the caller directory, requires --output-dir with --download (invalid_request otherwise), verifies every stored file by decoding it before reporting its path, downscales to exactly the requested width/height in the requested format only when --resize is set (never upscaling, otherwise byte-identical), and reports a per-item save failure with the partial_download status/exit code. New tests in tests/test_download_resize.py cover all of that; tests/test_cli.py resize expectation aligned with the exact-size requirement. Facade validate/smoke/help/import all pass and `pytest` reports 142 passed on the revision that already contains target task/1-task."
]
},
"projects/product-54354138-1#8": {
"events": [
"Added tests/test_status_branches.py (subprocess-driven checks for ok, no_format, no_size, access_error x2, invalid_request/unknown-source, partial_download: status + exit code + source/request echo + single JSON document, distinctness, saved-path truthfulness, shipped example run) and tests/test_live_source.py (credential-free live Commons png search with recorded observation and real-dimension/URL re-verification, explicit unresolved skip with observed reason when egress is unusable). Facade validate/test/smoke all succeed; target branch already integrated; no product or protected facade files touched."
]
},
"projects/product-54354138-1#9": {
"events": [
"Delivered the documentation slice for issue 9. README.md was a two-line placeholder; it is now the full tool-calling contract: CLI parameters matching `--help` output, the JSON request-document form for examples/input.json, the single-document response schema, the fixed status vocabulary with exit codes (ok/dry_run=0, invalid_request=2, no_format=3, no_size=4, access_error=5, partial_download=6), credential-free sources and the registry extension point, the decided --download-without---output-dir invalid-request behaviour, partial_download reporting for incomplete saves, and plain native-process execution with the real pytest entrypoint. Added tests/test_readme.py (5 tests) so CI fails if documentation drifts from build_parser(), STATUS_EXIT_CODES, ACCEPTED_FORMATS or the default registry. No protected facade paths or source behaviour changed; existing obligations preserved (full suite green apart from the pre-existing live-source skip)."
]
}
}
}