Implement 8: Verify assembled product against the effective requirements #10

Open
opened 2026-11-02 22:44:52 +00:00 by ai-team-lead · 0 comments
Member

Workflow

  • Repository: projects/product-54354138-1
  • Repository intent: existing_repository
  • Base branch: master
  • Target branch: task/1-task
  • Facade: .agent/project.yaml (initialized)
  • CI: created
  • Created repository: false
  • Created branch: true
  • Facade template: script_toolkit_python
  • Facade action: initialize
  • Project shape: project_kind=script_toolkit, languages=['python'], runtimes=['command_line'], interfaces=['cli'], delivery_kind=native_process
  • Project shape requirement refs: project_kind=['REQ-001', 'REQ-011'], languages=['REQ-001', 'REQ-011'], runtimes=['REQ-001', 'REQ-011'], interfaces=['REQ-001', 'REQ-002', 'REQ-009'], delivery_kind=['REQ-011']
  • Facade placement: kind=repository_root

Team-lead source issue: #2
Parent architecture issue: #1

Developer Task

Verify assembled product against the effective requirements

Scope

Perform final product acceptance after all implementation tasks are accepted. Fix discovered discrepancies and publish a PR, including when only verification evidence changes.

Acceptance Criteria

  • Requirement R1 is satisfied: REQ-001 REQ-001 Утилита является консольным приложением, запускаемым как обычный исполняемый процесс; параметры запуска задают тему поиска, желаемый размер, формат, источник, флаг скачивания и флаг масштабирования.
  • Requirement R2 is satisfied: REQ-002 REQ-002 Результат работы выводится в машиночитаемом структурированном виде, пригодном для tool calling ИИ-агентом: перечень найденных изображений с источником, URL, форматом и фактическими размерами, а также однозначное различие между успехом, отсутствием подходящих изображений и ошибкой.
  • Requirement R3 is satisfied: REQ-003 REQ-003 Доступ к источникам бесплатный, без API-ключей, регистрации и иных учётных данных; поиск выполняется без настройки секретов.
  • Requirement R4 is satisfied: REQ-004 REQ-004 Источник изображений выбирается вызывающей стороной через параметр; схема допускает подключение нескольких источников, и в поставку входит как минимум один рабочий бесплатный источник; неизвестный источник даёт явную ошибку с перечнем доступных источников.
  • Requirement R5 is satisfied: REQ-005 REQ-005 Поиск выполняется по теме (текстовому запросу), задаваемой вызывающей стороной; количество возвращаемых результатов может быть ограничено вызывающей стороной.
  • Requirement R6 is satisfied: REQ-006 REQ-006 Вызывающая сторона задаёт желаемый размер изображения (ширина/высота); в результатах по каждому изображению указываются его фактические размеры.
  • Requirement R7 is satisfied: REQ-007 REQ-007 Формат изображения выбирается из начального набора png и ico; возвращаются только файлы запрошенного формата, а при отсутствии таких изображений у источника выдаётся явное сообщение, что изображений такого формата нет, отличимое от ошибки доступа к источнику.
  • Requirement R8 is satisfied: REQ-008 REQ-008 Возвращаются только изображения, размер которых не меньше желаемого по обоим измерениям; если у источника по теме нет изображений подходящего размера, выдаётся явное сообщение, что подходящих по размеру нет, отличимое от сообщения об отсутствии формата и от ошибки доступа.
  • Requirement R9 is satisfied: REQ-009 REQ-009 По флагу скачивания найденные изображения сохраняются в каталог, указанный вызывающей стороной, а в результате сообщаются пути сохранённых файлов.
  • Requirement R10 is satisfied: REQ-010 REQ-010 При наличии флага масштабирования изображения, доступные только в размере больше желаемого, уменьшаются до желаемого размера; без этого флага изображения сохраняются без изменения размеров.
  • Requirement R11 is satisfied: REQ-011 REQ-011 Утилита поставляется и запускается как обычный исполняемый процесс, без Docker и контейнеров.
  • Acceptance criterion AC-001 is satisfied: AC-001 Для заданной темы утилита возвращает машиночитаемый список результатов, в каждом элементе есть URL, формат и фактические размеры; успешный поиск, отсутствие подходящих изображений и сбой различимы по коду завершения и структуре вывода.
  • Acceptance criterion AC-002 is satisfied: AC-002 Поиск успешно выполняется в окружении, где не задано ни одного API-ключа или учётных данных.
  • Acceptance criterion AC-003 is satisfied: AC-003 Указание источника в параметрах приводит к использованию соответствующего источника, и использованный источник явно отражён в выводе; неизвестный источник даёт явную ошибку с перечнем доступных источников.
  • Acceptance criterion AC-004 is satisfied: AC-004 Запрос формата png возвращает только реальные png-файлы; запрос ico при отсутствии ico у источника даёт явное сообщение о том, что изображений такого формата нет, и это сообщение отличимо от сообщения об ошибке доступа к источнику.
  • Acceptance criterion AC-005 is satisfied: AC-005 При запросе желаемого размера в выдаче присутствуют только изображения, размер которых не меньше желаемого по обоим измерениям, и для каждого указаны фактические размеры.
  • Acceptance criterion AC-006 is satisfied: AC-006 Если по теме у источника есть только изображения меньше желаемого размера, вывод содержит явное сообщение, что подходящих по размеру нет, и это сообщение отличимо от сообщения об отсутствии формата и от ошибки доступа.
  • Acceptance criterion AC-007 is satisfied: AC-007 При указании флага скачивания файлы физически сохранены в заданном каталоге, пути в выводе соответствуют существующим файлам, и файлы открываются как изображения заявленного формата.
  • Acceptance criterion AC-008 is satisfied: AC-008 При наличии флага масштабирования изображение, найденное в размере больше желаемого, сохраняется с размерами, равными желаемым; без этого флага фактические размеры сохранённого файла совпадают с исходными.
  • Acceptance criterion AC-009 is satisfied: AC-009 Утилита запускается как обычный исполняемый процесс без Docker и без контейнерной обвязки.
  • Acceptance criterion AC-010 is satisfied: AC-010 Реальная проверка на известном результате: запрос по теме, для которой у выбранного источника заведомо есть изображения, возвращает непустой список с рабочими ссылками на файлы (проверка на живом источнике, а не только на синтетических данных).
  • Acceptance criterion AC-011 is satisfied: AC-011 При запрещённом сетевом доступе к источнику утилита завершается явной ошибкой доступа и не выдаёт результат, выглядящий как успешный поиск.

Test Hints

  • Run the complete standard CI entrypoint and executable documentation/examples in a clean environment without undeclared path or environment overrides. Add missing acceptance tests to that entrypoint; report commands and observed results.
  • Add or update focused tests for the changed behavior.
  • Ensure those tests run through the repository's standard CI test entrypoint; a local-only test run is not sufficient.
  • Verification mechanisms declare their executor, phase, prerequisites and evidence format in verification_execution. Task acceptance and final product acceptance are separate phases; service code does not imply an additional artifact publication stage.

Requirement References

  • R1: REQ-001 REQ-001 Утилита является консольным приложением, запускаемым как обычный исполняемый процесс; параметры запуска задают тему поиска, желаемый размер, формат, источник, флаг скачивания и флаг масштабирования.
  • R2: REQ-002 REQ-002 Результат работы выводится в машиночитаемом структурированном виде, пригодном для tool calling ИИ-агентом: перечень найденных изображений с источником, URL, форматом и фактическими размерами, а также однозначное различие между успехом, отсутствием подходящих изображений и ошибкой.
  • R3: REQ-003 REQ-003 Доступ к источникам бесплатный, без API-ключей, регистрации и иных учётных данных; поиск выполняется без настройки секретов.
  • R4: REQ-004 REQ-004 Источник изображений выбирается вызывающей стороной через параметр; схема допускает подключение нескольких источников, и в поставку входит как минимум один рабочий бесплатный источник; неизвестный источник даёт явную ошибку с перечнем доступных источников.
  • R5: REQ-005 REQ-005 Поиск выполняется по теме (текстовому запросу), задаваемой вызывающей стороной; количество возвращаемых результатов может быть ограничено вызывающей стороной.
  • R6: REQ-006 REQ-006 Вызывающая сторона задаёт желаемый размер изображения (ширина/высота); в результатах по каждому изображению указываются его фактические размеры.
  • R7: REQ-007 REQ-007 Формат изображения выбирается из начального набора png и ico; возвращаются только файлы запрошенного формата, а при отсутствии таких изображений у источника выдаётся явное сообщение, что изображений такого формата нет, отличимое от ошибки доступа к источнику.
  • R8: REQ-008 REQ-008 Возвращаются только изображения, размер которых не меньше желаемого по обоим измерениям; если у источника по теме нет изображений подходящего размера, выдаётся явное сообщение, что подходящих по размеру нет, отличимое от сообщения об отсутствии формата и от ошибки доступа.
  • R9: REQ-009 REQ-009 По флагу скачивания найденные изображения сохраняются в каталог, указанный вызывающей стороной, а в результате сообщаются пути сохранённых файлов.
  • R10: REQ-010 REQ-010 При наличии флага масштабирования изображения, доступные только в размере больше желаемого, уменьшаются до желаемого размера; без этого флага изображения сохраняются без изменения размеров.
  • R11: REQ-011 REQ-011 Утилита поставляется и запускается как обычный исполняемый процесс, без Docker и контейнеров.

Affected Repos / Files

  • Public entrypoints, tests, CI entrypoint, README and shipped examples

Facade Slice Contract

The facade is the global CI contract for the whole task branch. This task may implement only a slice, but it must not contradict the facade layout or modify protected facade/control paths.

  • Task kind: acceptance
  • Facade path: .agent/project.yaml (initialized)
  • Required facade paths: examples/input.json, tests, tests/test_example.py, tools, tools/example.py
  • Support facade paths: .env.example, pyproject.toml, uv.lock
  • Facade commands: tools.dependencies.restore: /opt/agent-environment/bin/python -I -m agent_environment_executor.cli --workspace "$PWD" --component 'tools' --mode restore, tools.validate: python -m compileall tools tests, tools.test: pytest, tools.smoke: python -m tools.example examples/input.json
  • Facade acceptance: import-package (package_import), help-command (cli_command)
  • Protected paths: .agent/acceptance.yaml, .agent/project.yaml, .gitea/workflows/

Acceptance Checks

  • runtime-bound-evidence-001 facade_command_result facade_command:tools.smoke expected=succeeds
  • R1 requirement_result requirement:R1 expected=satisfied
  • R2 requirement_result requirement:R2 expected=satisfied
  • R3 requirement_result requirement:R3 expected=satisfied
  • R4 requirement_result requirement:R4 expected=satisfied
  • R5 requirement_result requirement:R5 expected=satisfied
  • R6 requirement_result requirement:R6 expected=satisfied
  • R7 requirement_result requirement:R7 expected=satisfied
  • R8 requirement_result requirement:R8 expected=satisfied
  • R9 requirement_result requirement:R9 expected=satisfied
  • R10 requirement_result requirement:R10 expected=satisfied
  • R11 requirement_result requirement:R11 expected=satisfied

Facade Refs

  • Commands: tools.smoke

  • Paths: none

  • Acceptance: none

Integration Contract

  • Functional dependencies: [1, 2, 3, 4, 5, 6, 7]
  • Execution predecessors: []
  • Integrate the current target before checks; preserve active product obligations from accepted tasks.
  • Task-local criteria are not inherited. Product changes require explicit add/revise/retire declarations; revisions and retirements require approved authority.
  • Requirement changes: [{"operation": "add", "requirement_id": "R1", "from_version": 0, "to_version": 1, "scope": "product", "text": "REQ-001 REQ-001 Утилита является консольным приложением, запускаемым как обычный исполняемый процесс; параметры запуска задают тему поиска, желаемый размер, формат, источник, флаг скачивания и флаг масштабирования.", "executable_check_ids": ["runtime-bound-evidence-001"]}, {"operation": "add", "requirement_id": "R2", "from_version": 0, "to_version": 1, "scope": "product", "text": "REQ-002 REQ-002 Результат работы выводится в машиночитаемом структурированном виде, пригодном для tool calling ИИ-агентом: перечень найденных изображений с источником, URL, форматом и фактическими размерами, а также однозначное различие между успехом, отсутствием подходящих изображений и ошибкой.", "executable_check_ids": ["runtime-bound-evidence-001"]}, {"operation": "add", "requirement_id": "R3", "from_version": 0, "to_version": 1, "scope": "product", "text": "REQ-003 REQ-003 Доступ к источникам бесплатный, без API-ключей, регистрации и иных учётных данных; поиск выполняется без настройки секретов.", "executable_check_ids": ["runtime-bound-evidence-001"]}, {"operation": "add", "requirement_id": "R4", "from_version": 0, "to_version": 1, "scope": "product", "text": "REQ-004 REQ-004 Источник изображений выбирается вызывающей стороной через параметр; схема допускает подключение нескольких источников, и в поставку входит как минимум один рабочий бесплатный источник; неизвестный источник даёт явную ошибку с перечнем доступных источников.", "executable_check_ids": ["runtime-bound-evidence-001"]}, {"operation": "add", "requirement_id": "R5", "from_version": 0, "to_version": 1, "scope": "product", "text": "REQ-005 REQ-005 Поиск выполняется по теме (текстовому запросу), задаваемой вызывающей стороной; количество возвращаемых результатов может быть ограничено вызывающей стороной.", "executable_check_ids": ["runtime-bound-evidence-001"]}, {"operation": "add", "requirement_id": "R6", "from_version": 0, "to_version": 1, "scope": "product", "text": "REQ-006 REQ-006 Вызывающая сторона задаёт желаемый размер изображения (ширина/высота); в результатах по каждому изображению указываются его фактические размеры.", "executable_check_ids": ["runtime-bound-evidence-001"]}, {"operation": "add", "requirement_id": "R7", "from_version": 0, "to_version": 1, "scope": "product", "text": "REQ-007 REQ-007 Формат изображения выбирается из начального набора png и ico; возвращаются только файлы запрошенного формата, а при отсутствии таких изображений у источника выдаётся явное сообщение, что изображений такого формата нет, отличимое от ошибки доступа к источнику.", "executable_check_ids": ["runtime-bound-evidence-001"]}, {"operation": "add", "requirement_id": "R8", "from_version": 0, "to_version": 1, "scope": "product", "text": "REQ-008 REQ-008 Возвращаются только изображения, размер которых не меньше желаемого по обоим измерениям; если у источника по теме нет изображений подходящего размера, выдаётся явное сообщение, что подходящих по размеру нет, отличимое от сообщения об отсутствии формата и от ошибки доступа.", "executable_check_ids": ["runtime-bound-evidence-001"]}, {"operation": "add", "requirement_id": "R9", "from_version": 0, "to_version": 1, "scope": "product", "text": "REQ-009 REQ-009 По флагу скачивания найденные изображения сохраняются в каталог, указанный вызывающей стороной, а в результате сообщаются пути сохранённых файлов.", "executable_check_ids": ["runtime-bound-evidence-001"]}, {"operation": "add", "requirement_id": "R10", "from_version": 0, "to_version": 1, "scope": "product", "text": "REQ-010 REQ-010 При наличии флага масштабирования изображения, доступные только в размере больше желаемого, уменьшаются до желаемого размера; без этого флага изображения сохраняются без изменения размеров.", "executable_check_ids": ["runtime-bound-evidence-001"]}, {"operation": "add", "requirement_id": "R11", "from_version": 0, "to_version": 1, "scope": "product", "text": "REQ-011 REQ-011 Утилита поставляется и запускается как обычный исполняемый процесс, без Docker и контейнеров.", "executable_check_ids": ["runtime-bound-evidence-001"]}]

Dependencies

Risk Notes

  • Preserve existing public behavior unless explicitly requested.
  • UNK-001: it is unverified whether the chosen first source supports server-side filtering by size/format; if not, client-side filtering against REQ-008 may require downloading many candidates and could hit timeouts or rate limits, affecting REQ-007 and REQ-008 outcomes.
  • UNK-002: ico availability on free sources is unknown; the no-format path (REQ-007) may be the common outcome and must be proven to be distinct from access errors rather than assumed.
  • UNK-003: source rate limits and User-Agent/identification requirements are unverified and could turn normal usage into access errors, affecting REQ-003 and AC-011 behavior.
  • UNK-004: the default download directory when the caller omits it is an open product decision; either a mandatory --output-dir error or a documented default must be confirmed before REQ-009 is finalized.
  • UNK-005: partial download success reporting is an open product decision affecting REQ-009 and REQ-002 status semantics.
  • Pillow (or an equivalent decoder/resizer) availability in the internal Gitea catalog is unverified; if it is not published, ICO dimension verification and downscaling (REQ-007, REQ-010) cannot be satisfied with stdlib alone and must not be replaced by a public-download fallback.
  • Live-source reachability for AC-010 depends on runtime egress to the approved hosts; if the sandbox cannot reach them, that limitation must be recorded instead of substituting synthetic results.
  • Exit-code and status vocabulary must be fixed once and reused by all branches, otherwise AC-001/AC-006 distinguishability degrades.

Parent Links

Architecture / Lead Context

The context below describes the whole product. Scope and Acceptance Criteria define local completion; the Integration Contract additionally requires preservation of active product obligations.

Team lead handoff

Parent architecture issue: #1

Source title: Консольная утилита поиска и скачивания изображений для вызова ИИ-агентом

Contract asset: agent-architecture-handoff.v1.json

Contract SHA-256: 2556d39044bc87f828704b28f39f1b136761f18330c69c087a387f1ae69fa2bf

Workflow

  • Repository: projects/product-54354138-1
  • Repository intent: existing_repository
  • Base branch: master
  • Target branch: task/1-task
  • Facade: .agent/project.yaml (initialized)
  • CI: created
  • Created repository: false
  • Created branch: true
  • Facade template: script_toolkit_python
  • Facade action: initialize
  • Project shape: project_kind=script_toolkit, languages=['python'], runtimes=['command_line'], interfaces=['cli'], delivery_kind=native_process
  • Project shape requirement refs: project_kind=['REQ-001', 'REQ-011'], languages=['REQ-001', 'REQ-011'], runtimes=['REQ-001', 'REQ-011'], interfaces=['REQ-001', 'REQ-002', 'REQ-009'], delivery_kind=['REQ-011']
  • Facade placement: kind=repository_root

Architecture Plan

Context

Product request issue #1: a console (CLI) image search/download utility invoked by an AI agent via tool calling. Contract requirements REQ-001..REQ-011: parameters for topic, desired size, format (initial set png/ico), source, download flag and resize flag; machine-readable structured output distinguishing success / no-images-of-format / no-images-of-size / source-access error (AC-001, AC-011); free access without API keys or secrets (REQ-003, AC-002); pluggable source selection with explicit unknown-source error listing available sources (REQ-004, AC-003); only requested format returned and explicit "no images of this format" message distinct from access errors (REQ-007, AC-004); only images not smaller than the desired size in both dimensions, with actual dimensions reported (REQ-006, REQ-008, AC-005, AC-006); download into a caller-specified directory with reported paths (REQ-009, AC-007); downscale-only resizing behind a flag, unchanged dimensions without the flag (REQ-010, AC-008); live-source verification on a known topic (AC-010); delivered and run as a plain executable process with no Docker/containers (REQ-011, AC-009). Approved network access is Wikimedia Commons and Open

Decision

Shape: script_toolkit (Python 3, command_line runtime, cli interface, native_process delivery, repository_root placement). This is the narrowest catalog-template-backed shape that covers every resulting language, runtime, public interface and delivery form: the deliverable is one command-line program that speaks over argv/stdout, there is no HTTP server and no second language, and REQ-011/AC-009 forbid container delivery. 'file_io' is intentionally not declared as a separate public interface: writing downloaded files into the caller-specified directory (REQ-009) and reporting the resulting paths (REQ-002) is internal behavior of the CLI invocation, not an independent repository interface, and declaring it would leave the shape without a supported facade template. Facade: initialize (currently missing) at repository_root, since no product artifact fixes a component root. Implementation direction: a single Python CLI entry module parsed with argparse (topic, desired width/height, format png|ico, source, --count limit, --download, --output-dir, --resize), a small source-adapter registry (Wikimedia Commons MediaWiki API first, Openverse as a second adapter behind the same registry) so

Constraints

  • Project shape is limited to script_toolkit/Python/command_line/cli/native_process at repository_root; do not add an HTTP service, a second language or container packaging.
  • Delivery must be a plain executable process (REQ-011, AC-009): no Dockerfile, compose file or container entrypoint.
  • Only free, credential-free sources; no API keys, tokens, registration or secret configuration may be required or read at runtime (REQ-003, OOS-003).
  • Only Wikimedia Commons and Openverse over HTTPS 443 (incl. subdomains) are approved network destinations; no other hosts and no public-download fallbacks.
  • Format support limited to png and ico (REQ-007, OOS-002); no other formats and no editing beyond downscaling (OOS-001).
  • Output must remain a single machine-readable JSON document with distinct status values and matching exit codes for success, no-format, no-size, access error and invalid request (REQ-002, AC-001, AC-011).
  • Filters must be applied on the client side to the actual downloaded/parsed image data, not trusted from source metadata alone, so reported format and dimensions are real.
  • Resizing may only downscale to the desired size and must be off by default (REQ-010, AC-008).

Risks

  • UNK-001: it is unverified whether the chosen first source supports server-side filtering by size/format; if not, client-side filtering against REQ-008 may require downloading many candidates and could hit timeouts or rate limits, affecting REQ-007 and REQ-008 outcomes.
  • UNK-002: ico availability on free sources is unknown; the no-format path (REQ-007) may be the common outcome and must be proven to be distinct from access errors rather than assumed.
  • UNK-003: source rate limits and User-Agent/identification requirements are unverified and could turn normal usage into access errors, affecting REQ-003 and AC-011 behavior.
  • UNK-004: the default download directory when the caller omits it is an open product decision; either a mandatory --output-dir error or a documented default must be confirmed before REQ-009 is finalized.
  • UNK-005: partial download success reporting is an open product decision affecting REQ-009 and REQ-002 status semantics.
  • Pillow (or an equivalent decoder/resizer) availability in the internal Gitea catalog is unverified; if it is not published, ICO dimension verification and downscaling (REQ-007, REQ-010) cannot be satisfied with stdlib alone and must not be replaced by a public-download fallback.
  • Live-source reachability for AC-010 depends on runtime egress to the approved hosts; if the sandbox cannot reach them, that limitation must be recorded instead of substituting synthetic results.
  • Exit-code and status vocabulary must be fixed once and reused by all branches, otherwise AC-001/AC-006 distinguishability degrades.

Team Lead Handoff

  • First prove the smallest end-to-end public path on the live source: run the CLI for a known topic against Wikimedia Commons requesting png, observe a non-empty JSON list with working URLs and real dimensions (AC-010), then confirm the same run with no API key/credential env vars set (AC-002).
  • Bounded check for UNK-001: issue one documented MediaWiki/Openverse search request and record whether size/mime filtering is available server-side and how many candidates must be fetched to satisfy the >= size rule; the decision between server-side parameters and client-side-only filtering (and any candidate cap) depends on that observation.
  • Bounded check for UNK-003: run a handful of sequential requests and record response codes, any 429 behaviour and whether a custom User-Agent is required; the retry/backoff design and whether a --count cap is enforced client-side depend on the result.
  • Bounded check for UNK-002: query an ico request against the chosen source and record whether the no-format status is produced while the source is reachable; this decides how the no-format message is worded and which exit code is paired with it.
  • Bounded check for Pillow availability: attempt prepare_environment with the declared manifest and record whether Pillow resolves from the internal catalog; the choice between Pillow-based ICO decode/resize and a reduced, explicitly recorded capability depends on that result. If it is missing, request operator publication; do not add public index fallbacks or credential changes.
  • Decide and document UNK-004 and UNK-005 with the product owner before finalizing REQ-009 output: default download directory behaviour and the status/exit code for partial download success.
  • All dependency changes must go through the manifests and lock files declared by the generated facade and Tool Backend prepare_environment; agents must not change package sources, credentials, network access or admission policy, and any policy exception requires human approval.
  • Preserve required coverage: every status branch (success, no-format, no-size, access error, invalid/unknown source) needs its own executed check and matching exit code, and aggregate exit 0 must not be treated as proof that the no-format and no-size outcomes work.

Parent architecture issue

Summary

Нужно консольное приложение (CLI), запускаемое как обычный исполняемый процесс, которое по заданной теме находит изображения в бесплатных источниках и по флагу скачивает их. Инструмент предназначен для вызова ИИ-агентом через tool calling, поэтому результат должен быть машиночитаемым и однозначно различать успех, отсутствие подходящих изображений и ошибку. Доступ бесплатный, без API-ключей и регистрации. Источник не принципиален, но выбирается вызывающей стороной, схема допускает несколько подключаемых источников, и в поставку входит как минимум один рабочий бесплатный источник. Задаются тема, желаемый размер и формат из начального набора png/ico. Возвращаются только изображения запрошенного формата, не меньшие желаемого размера; если таких форматов нет — явное сообщение, что изображений такого формата нет; если подходящих по размеру нет — явное сообщение, что подходящих по размеру нет. При наличии флага масштабирования изображения больше желаемого размера уменьшаются до желаемого. Запуск — как обычный процесс, без Docker. Сетевой доступ к бесплатным источникам согласован пользователем вне этого обсуждения (Wikimedia Commons и Openverse, HTTPS 443, включая поддомены).

Requirements

  • REQ-001 REQ-001 Утилита является консольным приложением, запускаемым как обычный исполняемый процесс; параметры запуска задают тему поиска, желаемый размер, формат, источник, флаг скачивания и флаг масштабирования.
  • REQ-002 REQ-002 Результат работы выводится в машиночитаемом структурированном виде, пригодном для tool calling ИИ-агентом: перечень найденных изображений с источником, URL, форматом и фактическими размерами, а также однозначное различие между успехом, отсутствием подходящих изображений и ошибкой.
  • REQ-003 REQ-003 Доступ к источникам бесплатный, без API-ключей, регистрации и иных учётных данных; поиск выполняется без настройки секретов.
  • REQ-004 REQ-004 Источник изображений выбирается вызывающей стороной через параметр; схема допускает подключение нескольких источников, и в поставку входит как минимум один рабочий бесплатный источник; неизвестный источник даёт явную ошибку с перечнем доступных источников.
  • REQ-005 REQ-005 Поиск выполняется по теме (текстовому запросу), задаваемой вызывающей стороной; количество возвращаемых результатов может быть ограничено вызывающей стороной.
  • REQ-006 REQ-006 Вызывающая сторона задаёт желаемый размер изображения (ширина/высота); в результатах по каждому изображению указываются его фактические размеры.
  • REQ-007 REQ-007 Формат изображения выбирается из начального набора png и ico; возвращаются только файлы запрошенного формата, а при отсутствии таких изображений у источника выдаётся явное сообщение, что изображений такого формата нет, отличимое от ошибки доступа к источнику.
  • REQ-008 REQ-008 Возвращаются только изображения, размер которых не меньше желаемого по обоим измерениям; если у источника по теме нет изображений подходящего размера, выдаётся явное сообщение, что подходящих по размеру нет, отличимое от сообщения об отсутствии формата и от ошибки доступа.
  • REQ-009 REQ-009 По флагу скачивания найденные изображения сохраняются в каталог, указанный вызывающей стороной, а в результате сообщаются пути сохранённых файлов.
  • REQ-010 REQ-010 При наличии флага масштабирования изображения, доступные только в размере больше желаемого, уменьшаются до желаемого размера; без этого флага изображения сохраняются без изменения размеров.
  • REQ-011 REQ-011 Утилита поставляется и запускается как обычный исполняемый процесс, без Docker и контейнеров.

Artifacts

None recorded.

Delivery Requirements

  • native_process (requirements=['REQ-011'])

External Inputs

None recorded.

Acceptance Criteria

  • AC-001 AC-001 Для заданной темы утилита возвращает машиночитаемый список результатов, в каждом элементе есть URL, формат и фактические размеры; успешный поиск, отсутствие подходящих изображений и сбой различимы по коду завершения и структуре вывода.
  • AC-002 AC-002 Поиск успешно выполняется в окружении, где не задано ни одного API-ключа или учётных данных.
  • AC-003 AC-003 Указание источника в параметрах приводит к использованию соответствующего источника, и использованный источник явно отражён в выводе; неизвестный источник даёт явную ошибку с перечнем доступных источников.
  • AC-004 AC-004 Запрос формата png возвращает только реальные png-файлы; запрос ico при отсутствии ico у источника даёт явное сообщение о том, что изображений такого формата нет, и это сообщение отличимо от сообщения об ошибке доступа к источнику.
  • AC-005 AC-005 При запросе желаемого размера в выдаче присутствуют только изображения, размер которых не меньше желаемого по обоим измерениям, и для каждого указаны фактические размеры.
  • AC-006 AC-006 Если по теме у источника есть только изображения меньше желаемого размера, вывод содержит явное сообщение, что подходящих по размеру нет, и это сообщение отличимо от сообщения об отсутствии формата и от ошибки доступа.
  • AC-007 AC-007 При указании флага скачивания файлы физически сохранены в заданном каталоге, пути в выводе соответствуют существующим файлам, и файлы открываются как изображения заявленного формата.
  • AC-008 AC-008 При наличии флага масштабирования изображение, найденное в размере больше желаемого, сохраняется с размерами, равными желаемым; без этого флага фактические размеры сохранённого файла совпадают с исходными.
  • AC-009 AC-009 Утилита запускается как обычный исполняемый процесс без Docker и без контейнерной обвязки.
  • AC-010 AC-010 Реальная проверка на известном результате: запрос по теме, для которой у выбранного источника заведомо есть изображения, возвращает непустой список с рабочими ссылками на файлы (проверка на живом источнике, а не только на синтетических данных).
  • AC-011 AC-011 При запрещённом сетевом доступе к источнику утилита завершается явной ошибкой доступа и не выдаёт результат, выглядящий как успешный поиск.

Out of Scope

  • OOS-001 Генерация изображений и любые операции редактирования, кроме уменьшения до желаемого размера
  • OOS-002 Форматы изображений вне начального набора png/ico
  • OOS-003 Платные и требующие API-ключей источники изображений
  • OOS-004 Запуск в Docker/контейнерах
  • OOS-005 Графический интерфейс пользователя

Unknowns / Risks

  • UNK-001 Какой именно бесплатный источник реализуется первым и покрывает ли его API фильтрацию по размеру/формату или фильтрация выполняется на стороне клиента (влияет на объём загружаемых данных)
  • UNK-002 Практическая доступность файлов формата ico у бесплатных источников: ожидаемо такие запросы будут часто возвращать сообщение об отсутствии формата
  • UNK-003 Ограничения частоты запросов и требования к идентификации клиента (user agent) у выбранного бесплатного источника
  • UNK-004 Каталог сохранения по умолчанию, если вызывающая сторона не задала его явно
  • UNK-005 Как сообщать частичный успех скачивания, когда часть файлов сохранилась, а часть нет

Workflow

  • Readiness: ready_for_architecture
  • Contract asset: agent-product-contract.v1.json
  • Contract SHA-256: b7622222e96d133d4c82b5d716cb2963e8b786272d2735fe9033295141b75ba6
  • Transcript: https://git.p2prod.ru/platform/product-requests/issues/1
  • Generated by: product-manager-agent

Architect plan comments

Architecture Plan

Context

Product request issue #1: a console (CLI) image search/download utility invoked by an AI agent via tool calling. Contract requirements REQ-001..REQ-011: parameters for topic, desired size, format (initial set png/ico), source, download flag and resize flag; machine-readable structured output distinguishing success / no-images-of-format / no-images-of-size / source-access error (AC-001, AC-011); free access without API keys or secrets (REQ-003, AC-002); pluggable source selection with explicit unknown-source error listing available sources (REQ-004, AC-003); only requested format returned and explicit "no images of this format" message distinct from access errors (REQ-007, AC-004); only images not smaller than the desired size in both dimensions, with actual dimensions reported (REQ-006, REQ-008, AC-005, AC-006); download into a caller-specified directory with reported paths (REQ-009, AC-007); downscale-only resizing behind a flag, unchanged dimensions without the flag (REQ-010, AC-008); live-source verification on a known topic (AC-010); delivered and run as a plain executable process with no Docker/containers (REQ-011, AC-009). Approved network access is Wikimedia Commons and Open

Decision

Shape: script_toolkit (Python 3, command_line runtime, cli interface, native_process delivery, repository_root placement). This is the narrowest catalog-template-backed shape that covers every resulting language, runtime, public interface and delivery form: the deliverable is one command-line program that speaks over argv/stdout, there is no HTTP server and no second language, and REQ-011/AC-009 forbid container delivery. 'file_io' is intentionally not declared as a separate public interface: writing downloaded files into the caller-specified directory (REQ-009) and reporting the resulting paths (REQ-002) is internal behavior of the CLI invocation, not an independent repository interface, and declaring it would leave the shape without a supported facade template. Facade: initialize (currently missing) at repository_root, since no product artifact fixes a component root. Implementation direction: a single Python CLI entry module parsed with argparse (topic, desired width/height, format png|ico, source, --count limit, --download, --output-dir, --resize), a small source-adapter registry (Wikimedia Commons MediaWiki API first, Openverse as a second adapter behind the same registry) so

Constraints

  • Project shape is limited to script_toolkit/Python/command_line/cli/native_process at repository_root; do not add an HTTP service, a second language or container packaging.
  • Delivery must be a plain executable process (REQ-011, AC-009): no Dockerfile, compose file or container entrypoint.
  • Only free, credential-free sources; no API keys, tokens, registration or secret configuration may be required or read at runtime (REQ-003, OOS-003).
  • Only Wikimedia Commons and Openverse over HTTPS 443 (incl. subdomains) are approved network destinations; no other hosts and no public-download fallbacks.
  • Format support limited to png and ico (REQ-007, OOS-002); no other formats and no editing beyond downscaling (OOS-001).
  • Output must remain a single machine-readable JSON document with distinct status values and matching exit codes for success, no-format, no-size, access error and invalid request (REQ-002, AC-001, AC-011).
  • Filters must be applied on the client side to the actual downloaded/parsed image data, not trusted from source metadata alone, so reported format and dimensions are real.
  • Resizing may only downscale to the desired size and must be off by default (REQ-010, AC-008).

Risks

  • UNK-001: it is unverified whether the chosen first source supports server-side filtering by size/format; if not, client-side filtering against REQ-008 may require downloading many candidates and could hit timeouts or rate limits, affecting REQ-007 and REQ-008 outcomes.
  • UNK-002: ico availability on free sources is unknown; the no-format path (REQ-007) may be the common outcome and must be proven to be distinct from access errors rather than assumed.
  • UNK-003: source rate limits and User-Agent/identification requirements are unverified and could turn normal usage into access errors, affecting REQ-003 and AC-011 behavior.
  • UNK-004: the default download directory when the caller omits it is an open product decision; either a mandatory --output-dir error or a documented default must be confirmed before REQ-009 is finalized.
  • UNK-005: partial download success reporting is an open product decision affecting REQ-009 and REQ-002 status semantics.
  • Pillow (or an equivalent decoder/resizer) availability in the internal Gitea catalog is unverified; if it is not published, ICO dimension verification and downscaling (REQ-007, REQ-010) cannot be satisfied with stdlib alone and must not be replaced by a public-download fallback.
  • Live-source reachability for AC-010 depends on runtime egress to the approved hosts; if the sandbox cannot reach them, that limitation must be recorded instead of substituting synthetic results.
  • Exit-code and status vocabulary must be fixed once and reused by all branches, otherwise AC-001/AC-006 distinguishability degrades.

Team Lead Handoff

  • First prove the smallest end-to-end public path on the live source: run the CLI for a known topic against Wikimedia Commons requesting png, observe a non-empty JSON list with working URLs and real dimensions (AC-010), then confirm the same run with no API key/credential env vars set (AC-002).
  • Bounded check for UNK-001: issue one documented MediaWiki/Openverse search request and record whether size/mime filtering is available server-side and how many candidates must be fetched to satisfy the >= size rule; the decision between server-side parameters and client-side-only filtering (and any candidate cap) depends on that observation.
  • Bounded check for UNK-003: run a handful of sequential requests and record response codes, any 429 behaviour and whether a custom User-Agent is required; the retry/backoff design and whether a --count cap is enforced client-side depend on the result.
  • Bounded check for UNK-002: query an ico request against the chosen source and record whether the no-format status is produced while the source is reachable; this decides how the no-format message is worded and which exit code is paired with it.
  • Bounded check for Pillow availability: attempt prepare_environment with the declared manifest and record whether Pillow resolves from the internal catalog; the choice between Pillow-based ICO decode/resize and a reduced, explicitly recorded capability depends on that result. If it is missing, request operator publication; do not add public index fallbacks or credential changes.
  • Decide and document UNK-004 and UNK-005 with the product owner before finalizing REQ-009 output: default download directory behaviour and the status/exit code for partial download success.
  • All dependency changes must go through the manifests and lock files declared by the generated facade and Tool Backend prepare_environment; agents must not change package sources, credentials, network access or admission policy, and any policy exception requires human approval.
  • Preserve required coverage: every status branch (success, no-format, no-size, access error, invalid/unknown source) needs its own executed check and matching exit code, and aggregate exit 0 must not be treated as proof that the no-format and no-size outcomes work.
<!-- agent-developer-task {"asset": "agent-developer-task.v1.json", "renderer": "agent.developer_task_markdown.v1", "schema": "agent.developer_task.v1", "sha256": "8c550b8af5ce410b72c5a4c30e67584d1e736ec520ea5ce6509c7b265cb9d01e"} --> ## Workflow - Repository: projects/product-54354138-1 - Repository intent: existing_repository - Base branch: `master` - Target branch: `task/1-task` - Facade: `.agent/project.yaml` (`initialized`) - CI: `created` - Created repository: `false` - Created branch: `true` - Facade template: `script_toolkit_python` - Facade action: `initialize` - Project shape: `project_kind=script_toolkit, languages=['python'], runtimes=['command_line'], interfaces=['cli'], delivery_kind=native_process` - Project shape requirement refs: `project_kind=['REQ-001', 'REQ-011'], languages=['REQ-001', 'REQ-011'], runtimes=['REQ-001', 'REQ-011'], interfaces=['REQ-001', 'REQ-002', 'REQ-009'], delivery_kind=['REQ-011']` - Facade placement: `kind=repository_root` <!-- agent-provisioner:task base_branch=master target_branch=task/1-task --> <!-- teamlead-agent:child source=2 parent=1 index=8 depends_on=1,2,3,4,5,6,7 kind=acceptance criteria_scope=end_to_end --> <!-- agent-change-contract {"acceptance_checks": [{"expected": "succeeds", "id": "runtime-bound-evidence-001", "kind": "facade_command_result", "supporting_check_ids": [], "target": "tools.smoke", "target_type": "facade_command"}, {"expected": "satisfied", "id": "R1", "kind": "requirement_result", "supporting_check_ids": [], "target": "R1", "target_type": "requirement"}, {"expected": "satisfied", "id": "R2", "kind": "requirement_result", "supporting_check_ids": [], "target": "R2", "target_type": "requirement"}, {"expected": "satisfied", "id": "R3", "kind": "requirement_result", "supporting_check_ids": [], "target": "R3", "target_type": "requirement"}, {"expected": "satisfied", "id": "R4", "kind": "requirement_result", "supporting_check_ids": [], "target": "R4", "target_type": "requirement"}, {"expected": "satisfied", "id": "R5", "kind": "requirement_result", "supporting_check_ids": [], "target": "R5", "target_type": "requirement"}, {"expected": "satisfied", "id": "R6", "kind": "requirement_result", "supporting_check_ids": [], "target": "R6", "target_type": "requirement"}, {"expected": "satisfied", "id": "R7", "kind": "requirement_result", "supporting_check_ids": [], "target": "R7", "target_type": "requirement"}, {"expected": "satisfied", "id": "R8", "kind": "requirement_result", "supporting_check_ids": [], "target": "R8", "target_type": "requirement"}, {"expected": "satisfied", "id": "R9", "kind": "requirement_result", "supporting_check_ids": [], "target": "R9", "target_type": "requirement"}, {"expected": "satisfied", "id": "R10", "kind": "requirement_result", "supporting_check_ids": [], "target": "R10", "target_type": "requirement"}, {"expected": "satisfied", "id": "R11", "kind": "requirement_result", "supporting_check_ids": [], "target": "R11", "target_type": "requirement"}], "approved_changes": [], "baseline": [], "execution_after": [], "expected_obligation_state": [{"executable_check_ids": ["runtime-bound-evidence-001"], "id": "R1", "lifecycle": "active", "scope": "product", "text": "`REQ-001` REQ-001 Утилита является консольным приложением, запускаемым как обычный исполняемый процесс; параметры запуска задают тему поиска, желаемый размер, формат, источник, флаг скачивания и флаг масштабирования.", "version": 1}, {"executable_check_ids": ["runtime-bound-evidence-001"], "id": "R2", "lifecycle": "active", "scope": "product", "text": "`REQ-002` REQ-002 Результат работы выводится в машиночитаемом структурированном виде, пригодном для tool calling ИИ-агентом: перечень найденных изображений с источником, URL, форматом и фактическими размерами, а также однозначное различие между успехом, отсутствием подходящих изображений и ошибкой.", "version": 1}, {"executable_check_ids": ["runtime-bound-evidence-001"], "id": "R3", "lifecycle": "active", "scope": "product", "text": "`REQ-003` REQ-003 Доступ к источникам бесплатный, без API-ключей, регистрации и иных учётных данных; поиск выполняется без настройки секретов.", "version": 1}, {"executable_check_ids": ["runtime-bound-evidence-001"], "id": "R4", "lifecycle": "active", "scope": "product", "text": "`REQ-004` REQ-004 Источник изображений выбирается вызывающей стороной через параметр; схема допускает подключение нескольких источников, и в поставку входит как минимум один рабочий бесплатный источник; неизвестный источник даёт явную ошибку с перечнем доступных источников.", "version": 1}, {"executable_check_ids": ["runtime-bound-evidence-001"], "id": "R5", "lifecycle": "active", "scope": "product", "text": "`REQ-005` REQ-005 Поиск выполняется по теме (текстовому запросу), задаваемой вызывающей стороной; количество возвращаемых результатов может быть ограничено вызывающей стороной.", "version": 1}, {"executable_check_ids": ["runtime-bound-evidence-001"], "id": "R6", "lifecycle": "active", "scope": "product", "text": "`REQ-006` REQ-006 Вызывающая сторона задаёт желаемый размер изображения (ширина/высота); в результатах по каждому изображению указываются его фактические размеры.", "version": 1}, {"executable_check_ids": ["runtime-bound-evidence-001"], "id": "R7", "lifecycle": "active", "scope": "product", "text": "`REQ-007` REQ-007 Формат изображения выбирается из начального набора png и ico; возвращаются только файлы запрошенного формата, а при отсутствии таких изображений у источника выдаётся явное сообщение, что изображений такого формата нет, отличимое от ошибки доступа к источнику.", "version": 1}, {"executable_check_ids": ["runtime-bound-evidence-001"], "id": "R8", "lifecycle": "active", "scope": "product", "text": "`REQ-008` REQ-008 Возвращаются только изображения, размер которых не меньше желаемого по обоим измерениям; если у источника по теме нет изображений подходящего размера, выдаётся явное сообщение, что подходящих по размеру нет, отличимое от сообщения об отсутствии формата и от ошибки доступа.", "version": 1}, {"executable_check_ids": ["runtime-bound-evidence-001"], "id": "R9", "lifecycle": "active", "scope": "product", "text": "`REQ-009` REQ-009 По флагу скачивания найденные изображения сохраняются в каталог, указанный вызывающей стороной, а в результате сообщаются пути сохранённых файлов.", "version": 1}, {"executable_check_ids": ["runtime-bound-evidence-001"], "id": "R10", "lifecycle": "active", "scope": "product", "text": "`REQ-010` REQ-010 При наличии флага масштабирования изображения, доступные только в размере больше желаемого, уменьшаются до желаемого размера; без этого флага изображения сохраняются без изменения размеров.", "version": 1}, {"executable_check_ids": ["runtime-bound-evidence-001"], "id": "R11", "lifecycle": "active", "scope": "product", "text": "`REQ-011` REQ-011 Утилита поставляется и запускается как обычный исполняемый процесс, без Docker и контейнеров.", "version": 1}], "functional_dependencies": [1, 2, 3, 4, 5, 6, 7], "integration_policy": "current_target", "obligation_state_transitions": [{"executable_check_ids": ["runtime-bound-evidence-001"], "from_version": 0, "operation": "add", "requirement_id": "R1", "scope": "product", "text": "`REQ-001` REQ-001 Утилита является консольным приложением, запускаемым как обычный исполняемый процесс; параметры запуска задают тему поиска, желаемый размер, формат, источник, флаг скачивания и флаг масштабирования.", "to_version": 1}, {"executable_check_ids": ["runtime-bound-evidence-001"], "from_version": 0, "operation": "add", "requirement_id": "R2", "scope": "product", "text": "`REQ-002` REQ-002 Результат работы выводится в машиночитаемом структурированном виде, пригодном для tool calling ИИ-агентом: перечень найденных изображений с источником, URL, форматом и фактическими размерами, а также однозначное различие между успехом, отсутствием подходящих изображений и ошибкой.", "to_version": 1}, {"executable_check_ids": ["runtime-bound-evidence-001"], "from_version": 0, "operation": "add", "requirement_id": "R3", "scope": "product", "text": "`REQ-003` REQ-003 Доступ к источникам бесплатный, без API-ключей, регистрации и иных учётных данных; поиск выполняется без настройки секретов.", "to_version": 1}, {"executable_check_ids": ["runtime-bound-evidence-001"], "from_version": 0, "operation": "add", "requirement_id": "R4", "scope": "product", "text": "`REQ-004` REQ-004 Источник изображений выбирается вызывающей стороной через параметр; схема допускает подключение нескольких источников, и в поставку входит как минимум один рабочий бесплатный источник; неизвестный источник даёт явную ошибку с перечнем доступных источников.", "to_version": 1}, {"executable_check_ids": ["runtime-bound-evidence-001"], "from_version": 0, "operation": "add", "requirement_id": "R5", "scope": "product", "text": "`REQ-005` REQ-005 Поиск выполняется по теме (текстовому запросу), задаваемой вызывающей стороной; количество возвращаемых результатов может быть ограничено вызывающей стороной.", "to_version": 1}, {"executable_check_ids": ["runtime-bound-evidence-001"], "from_version": 0, "operation": "add", "requirement_id": "R6", "scope": "product", "text": "`REQ-006` REQ-006 Вызывающая сторона задаёт желаемый размер изображения (ширина/высота); в результатах по каждому изображению указываются его фактические размеры.", "to_version": 1}, {"executable_check_ids": ["runtime-bound-evidence-001"], "from_version": 0, "operation": "add", "requirement_id": "R7", "scope": "product", "text": "`REQ-007` REQ-007 Формат изображения выбирается из начального набора png и ico; возвращаются только файлы запрошенного формата, а при отсутствии таких изображений у источника выдаётся явное сообщение, что изображений такого формата нет, отличимое от ошибки доступа к источнику.", "to_version": 1}, {"executable_check_ids": ["runtime-bound-evidence-001"], "from_version": 0, "operation": "add", "requirement_id": "R8", "scope": "product", "text": "`REQ-008` REQ-008 Возвращаются только изображения, размер которых не меньше желаемого по обоим измерениям; если у источника по теме нет изображений подходящего размера, выдаётся явное сообщение, что подходящих по размеру нет, отличимое от сообщения об отсутствии формата и от ошибки доступа.", "to_version": 1}, {"executable_check_ids": ["runtime-bound-evidence-001"], "from_version": 0, "operation": "add", "requirement_id": "R9", "scope": "product", "text": "`REQ-009` REQ-009 По флагу скачивания найденные изображения сохраняются в каталог, указанный вызывающей стороной, а в результате сообщаются пути сохранённых файлов.", "to_version": 1}, {"executable_check_ids": ["runtime-bound-evidence-001"], "from_version": 0, "operation": "add", "requirement_id": "R10", "scope": "product", "text": "`REQ-010` REQ-010 При наличии флага масштабирования изображения, доступные только в размере больше желаемого, уменьшаются до желаемого размера; без этого флага изображения сохраняются без изменения размеров.", "to_version": 1}, {"executable_check_ids": ["runtime-bound-evidence-001"], "from_version": 0, "operation": "add", "requirement_id": "R11", "scope": "product", "text": "`REQ-011` REQ-011 Утилита поставляется и запускается как обычный исполняемый процесс, без Docker и контейнеров.", "to_version": 1}], "provisioned_control_files": [{"operation": "initialize", "path": ".agent/project.yaml", "sha256": "02a8118add68955267bd8fbb329289e2fe0525c554a38467a9d31bb71dcb3948"}, {"operation": "materialize", "path": ".gitea/workflows/ci.yaml", "sha256": "f8dbd52316fad573eb1a0aa52ceb5df8577c962fa07662670eb6f2bfcdb04c36"}], "required_dependency_updates": [], "schema": "agent.change_contract.v2", "source": 2, "source_requirements": {"R1": "`REQ-001` REQ-001 Утилита является консольным приложением, запускаемым как обычный исполняемый процесс; параметры запуска задают тему поиска, желаемый размер, формат, источник, флаг скачивания и флаг масштабирования.", "R10": "`REQ-010` REQ-010 При наличии флага масштабирования изображения, доступные только в размере больше желаемого, уменьшаются до желаемого размера; без этого флага изображения сохраняются без изменения размеров.", "R11": "`REQ-011` REQ-011 Утилита поставляется и запускается как обычный исполняемый процесс, без Docker и контейнеров.", "R2": "`REQ-002` REQ-002 Результат работы выводится в машиночитаемом структурированном виде, пригодном для tool calling ИИ-агентом: перечень найденных изображений с источником, URL, форматом и фактическими размерами, а также однозначное различие между успехом, отсутствием подходящих изображений и ошибкой.", "R3": "`REQ-003` REQ-003 Доступ к источникам бесплатный, без API-ключей, регистрации и иных учётных данных; поиск выполняется без настройки секретов.", "R4": "`REQ-004` REQ-004 Источник изображений выбирается вызывающей стороной через параметр; схема допускает подключение нескольких источников, и в поставку входит как минимум один рабочий бесплатный источник; неизвестный источник даёт явную ошибку с перечнем доступных источников.", "R5": "`REQ-005` REQ-005 Поиск выполняется по теме (текстовому запросу), задаваемой вызывающей стороной; количество возвращаемых результатов может быть ограничено вызывающей стороной.", "R6": "`REQ-006` REQ-006 Вызывающая сторона задаёт желаемый размер изображения (ширина/высота); в результатах по каждому изображению указываются его фактические размеры.", "R7": "`REQ-007` REQ-007 Формат изображения выбирается из начального набора png и ico; возвращаются только файлы запрошенного формата, а при отсутствии таких изображений у источника выдаётся явное сообщение, что изображений такого формата нет, отличимое от ошибки доступа к источнику.", "R8": "`REQ-008` REQ-008 Возвращаются только изображения, размер которых не меньше желаемого по обоим измерениям; если у источника по теме нет изображений подходящего размера, выдаётся явное сообщение, что подходящих по размеру нет, отличимое от сообщения об отсутствии формата и от ошибки доступа.", "R9": "`REQ-009` REQ-009 По флагу скачивания найденные изображения сохраняются в каталог, указанный вызывающей стороной, а в результате сообщаются пути сохранённых файлов."}, "task_index": 8, "verification_execution": [{"evidence_kind": "facade_command_result", "evidence_schema": "agent.ci_result.v1", "executor": "ci", "mechanism_id": "tools.smoke", "mechanism_kind": "facade_command", "phase": "task_acceptance", "required_paths": ["examples/input.json", "pyproject.toml", "tools/example.py"], "revision_binding": "exact_commit"}]} --> Team-lead source issue: #2 Parent architecture issue: #1 ## Developer Task Verify assembled product against the effective requirements ## Scope Perform final product acceptance after all implementation tasks are accepted. Fix discovered discrepancies and publish a PR, including when only verification evidence changes. ## Acceptance Criteria - Requirement `R1` is satisfied: `REQ-001` REQ-001 Утилита является консольным приложением, запускаемым как обычный исполняемый процесс; параметры запуска задают тему поиска, желаемый размер, формат, источник, флаг скачивания и флаг масштабирования. - Requirement `R2` is satisfied: `REQ-002` REQ-002 Результат работы выводится в машиночитаемом структурированном виде, пригодном для tool calling ИИ-агентом: перечень найденных изображений с источником, URL, форматом и фактическими размерами, а также однозначное различие между успехом, отсутствием подходящих изображений и ошибкой. - Requirement `R3` is satisfied: `REQ-003` REQ-003 Доступ к источникам бесплатный, без API-ключей, регистрации и иных учётных данных; поиск выполняется без настройки секретов. - Requirement `R4` is satisfied: `REQ-004` REQ-004 Источник изображений выбирается вызывающей стороной через параметр; схема допускает подключение нескольких источников, и в поставку входит как минимум один рабочий бесплатный источник; неизвестный источник даёт явную ошибку с перечнем доступных источников. - Requirement `R5` is satisfied: `REQ-005` REQ-005 Поиск выполняется по теме (текстовому запросу), задаваемой вызывающей стороной; количество возвращаемых результатов может быть ограничено вызывающей стороной. - Requirement `R6` is satisfied: `REQ-006` REQ-006 Вызывающая сторона задаёт желаемый размер изображения (ширина/высота); в результатах по каждому изображению указываются его фактические размеры. - Requirement `R7` is satisfied: `REQ-007` REQ-007 Формат изображения выбирается из начального набора png и ico; возвращаются только файлы запрошенного формата, а при отсутствии таких изображений у источника выдаётся явное сообщение, что изображений такого формата нет, отличимое от ошибки доступа к источнику. - Requirement `R8` is satisfied: `REQ-008` REQ-008 Возвращаются только изображения, размер которых не меньше желаемого по обоим измерениям; если у источника по теме нет изображений подходящего размера, выдаётся явное сообщение, что подходящих по размеру нет, отличимое от сообщения об отсутствии формата и от ошибки доступа. - Requirement `R9` is satisfied: `REQ-009` REQ-009 По флагу скачивания найденные изображения сохраняются в каталог, указанный вызывающей стороной, а в результате сообщаются пути сохранённых файлов. - Requirement `R10` is satisfied: `REQ-010` REQ-010 При наличии флага масштабирования изображения, доступные только в размере больше желаемого, уменьшаются до желаемого размера; без этого флага изображения сохраняются без изменения размеров. - Requirement `R11` is satisfied: `REQ-011` REQ-011 Утилита поставляется и запускается как обычный исполняемый процесс, без Docker и контейнеров. - Acceptance criterion `AC-001` is satisfied: AC-001 Для заданной темы утилита возвращает машиночитаемый список результатов, в каждом элементе есть URL, формат и фактические размеры; успешный поиск, отсутствие подходящих изображений и сбой различимы по коду завершения и структуре вывода. - Acceptance criterion `AC-002` is satisfied: AC-002 Поиск успешно выполняется в окружении, где не задано ни одного API-ключа или учётных данных. - Acceptance criterion `AC-003` is satisfied: AC-003 Указание источника в параметрах приводит к использованию соответствующего источника, и использованный источник явно отражён в выводе; неизвестный источник даёт явную ошибку с перечнем доступных источников. - Acceptance criterion `AC-004` is satisfied: AC-004 Запрос формата png возвращает только реальные png-файлы; запрос ico при отсутствии ico у источника даёт явное сообщение о том, что изображений такого формата нет, и это сообщение отличимо от сообщения об ошибке доступа к источнику. - Acceptance criterion `AC-005` is satisfied: AC-005 При запросе желаемого размера в выдаче присутствуют только изображения, размер которых не меньше желаемого по обоим измерениям, и для каждого указаны фактические размеры. - Acceptance criterion `AC-006` is satisfied: AC-006 Если по теме у источника есть только изображения меньше желаемого размера, вывод содержит явное сообщение, что подходящих по размеру нет, и это сообщение отличимо от сообщения об отсутствии формата и от ошибки доступа. - Acceptance criterion `AC-007` is satisfied: AC-007 При указании флага скачивания файлы физически сохранены в заданном каталоге, пути в выводе соответствуют существующим файлам, и файлы открываются как изображения заявленного формата. - Acceptance criterion `AC-008` is satisfied: AC-008 При наличии флага масштабирования изображение, найденное в размере больше желаемого, сохраняется с размерами, равными желаемым; без этого флага фактические размеры сохранённого файла совпадают с исходными. - Acceptance criterion `AC-009` is satisfied: AC-009 Утилита запускается как обычный исполняемый процесс без Docker и без контейнерной обвязки. - Acceptance criterion `AC-010` is satisfied: AC-010 Реальная проверка на известном результате: запрос по теме, для которой у выбранного источника заведомо есть изображения, возвращает непустой список с рабочими ссылками на файлы (проверка на живом источнике, а не только на синтетических данных). - Acceptance criterion `AC-011` is satisfied: AC-011 При запрещённом сетевом доступе к источнику утилита завершается явной ошибкой доступа и не выдаёт результат, выглядящий как успешный поиск. ## Test Hints - Run the complete standard CI entrypoint and executable documentation/examples in a clean environment without undeclared path or environment overrides. Add missing acceptance tests to that entrypoint; report commands and observed results. - Add or update focused tests for the changed behavior. - Ensure those tests run through the repository's standard CI test entrypoint; a local-only test run is not sufficient. - Verification mechanisms declare their executor, phase, prerequisites and evidence format in verification_execution. Task acceptance and final product acceptance are separate phases; service code does not imply an additional artifact publication stage. ## Requirement References - R1: `REQ-001` REQ-001 Утилита является консольным приложением, запускаемым как обычный исполняемый процесс; параметры запуска задают тему поиска, желаемый размер, формат, источник, флаг скачивания и флаг масштабирования. - R2: `REQ-002` REQ-002 Результат работы выводится в машиночитаемом структурированном виде, пригодном для tool calling ИИ-агентом: перечень найденных изображений с источником, URL, форматом и фактическими размерами, а также однозначное различие между успехом, отсутствием подходящих изображений и ошибкой. - R3: `REQ-003` REQ-003 Доступ к источникам бесплатный, без API-ключей, регистрации и иных учётных данных; поиск выполняется без настройки секретов. - R4: `REQ-004` REQ-004 Источник изображений выбирается вызывающей стороной через параметр; схема допускает подключение нескольких источников, и в поставку входит как минимум один рабочий бесплатный источник; неизвестный источник даёт явную ошибку с перечнем доступных источников. - R5: `REQ-005` REQ-005 Поиск выполняется по теме (текстовому запросу), задаваемой вызывающей стороной; количество возвращаемых результатов может быть ограничено вызывающей стороной. - R6: `REQ-006` REQ-006 Вызывающая сторона задаёт желаемый размер изображения (ширина/высота); в результатах по каждому изображению указываются его фактические размеры. - R7: `REQ-007` REQ-007 Формат изображения выбирается из начального набора png и ico; возвращаются только файлы запрошенного формата, а при отсутствии таких изображений у источника выдаётся явное сообщение, что изображений такого формата нет, отличимое от ошибки доступа к источнику. - R8: `REQ-008` REQ-008 Возвращаются только изображения, размер которых не меньше желаемого по обоим измерениям; если у источника по теме нет изображений подходящего размера, выдаётся явное сообщение, что подходящих по размеру нет, отличимое от сообщения об отсутствии формата и от ошибки доступа. - R9: `REQ-009` REQ-009 По флагу скачивания найденные изображения сохраняются в каталог, указанный вызывающей стороной, а в результате сообщаются пути сохранённых файлов. - R10: `REQ-010` REQ-010 При наличии флага масштабирования изображения, доступные только в размере больше желаемого, уменьшаются до желаемого размера; без этого флага изображения сохраняются без изменения размеров. - R11: `REQ-011` REQ-011 Утилита поставляется и запускается как обычный исполняемый процесс, без Docker и контейнеров. ## Affected Repos / Files - Public entrypoints, tests, CI entrypoint, README and shipped examples ## Facade Slice Contract The facade is the global CI contract for the whole task branch. This task may implement only a slice, but it must not contradict the facade layout or modify protected facade/control paths. - Task kind: `acceptance` - Facade path: `.agent/project.yaml` (`initialized`) - Required facade paths: `examples/input.json`, `tests`, `tests/test_example.py`, `tools`, `tools/example.py` - Support facade paths: `.env.example`, `pyproject.toml`, `uv.lock` - Facade commands: tools.dependencies.restore: `/opt/agent-environment/bin/python -I -m agent_environment_executor.cli --workspace "$PWD" --component 'tools' --mode restore`, tools.validate: `python -m compileall tools tests`, tools.test: `pytest`, tools.smoke: `python -m tools.example examples/input.json` - Facade acceptance: import-package (package_import), help-command (cli_command) - Protected paths: `.agent/acceptance.yaml`, `.agent/project.yaml`, `.gitea/workflows/` ## Acceptance Checks - `runtime-bound-evidence-001` `facade_command_result` `facade_command:tools.smoke` expected=`succeeds` - `R1` `requirement_result` `requirement:R1` expected=`satisfied` - `R2` `requirement_result` `requirement:R2` expected=`satisfied` - `R3` `requirement_result` `requirement:R3` expected=`satisfied` - `R4` `requirement_result` `requirement:R4` expected=`satisfied` - `R5` `requirement_result` `requirement:R5` expected=`satisfied` - `R6` `requirement_result` `requirement:R6` expected=`satisfied` - `R7` `requirement_result` `requirement:R7` expected=`satisfied` - `R8` `requirement_result` `requirement:R8` expected=`satisfied` - `R9` `requirement_result` `requirement:R9` expected=`satisfied` - `R10` `requirement_result` `requirement:R10` expected=`satisfied` - `R11` `requirement_result` `requirement:R11` expected=`satisfied` ## Facade Refs - Commands: `tools.smoke` - Paths: _none_ - Acceptance: _none_ ## Integration Contract - Functional dependencies: [1, 2, 3, 4, 5, 6, 7] - Execution predecessors: [] - Integrate the current target before checks; preserve active product obligations from accepted tasks. - Task-local criteria are not inherited. Product changes require explicit add/revise/retire declarations; revisions and retirements require approved authority. - Requirement changes: `[{"operation": "add", "requirement_id": "R1", "from_version": 0, "to_version": 1, "scope": "product", "text": "`REQ-001` REQ-001 Утилита является консольным приложением, запускаемым как обычный исполняемый процесс; параметры запуска задают тему поиска, желаемый размер, формат, источник, флаг скачивания и флаг масштабирования.", "executable_check_ids": ["runtime-bound-evidence-001"]}, {"operation": "add", "requirement_id": "R2", "from_version": 0, "to_version": 1, "scope": "product", "text": "`REQ-002` REQ-002 Результат работы выводится в машиночитаемом структурированном виде, пригодном для tool calling ИИ-агентом: перечень найденных изображений с источником, URL, форматом и фактическими размерами, а также однозначное различие между успехом, отсутствием подходящих изображений и ошибкой.", "executable_check_ids": ["runtime-bound-evidence-001"]}, {"operation": "add", "requirement_id": "R3", "from_version": 0, "to_version": 1, "scope": "product", "text": "`REQ-003` REQ-003 Доступ к источникам бесплатный, без API-ключей, регистрации и иных учётных данных; поиск выполняется без настройки секретов.", "executable_check_ids": ["runtime-bound-evidence-001"]}, {"operation": "add", "requirement_id": "R4", "from_version": 0, "to_version": 1, "scope": "product", "text": "`REQ-004` REQ-004 Источник изображений выбирается вызывающей стороной через параметр; схема допускает подключение нескольких источников, и в поставку входит как минимум один рабочий бесплатный источник; неизвестный источник даёт явную ошибку с перечнем доступных источников.", "executable_check_ids": ["runtime-bound-evidence-001"]}, {"operation": "add", "requirement_id": "R5", "from_version": 0, "to_version": 1, "scope": "product", "text": "`REQ-005` REQ-005 Поиск выполняется по теме (текстовому запросу), задаваемой вызывающей стороной; количество возвращаемых результатов может быть ограничено вызывающей стороной.", "executable_check_ids": ["runtime-bound-evidence-001"]}, {"operation": "add", "requirement_id": "R6", "from_version": 0, "to_version": 1, "scope": "product", "text": "`REQ-006` REQ-006 Вызывающая сторона задаёт желаемый размер изображения (ширина/высота); в результатах по каждому изображению указываются его фактические размеры.", "executable_check_ids": ["runtime-bound-evidence-001"]}, {"operation": "add", "requirement_id": "R7", "from_version": 0, "to_version": 1, "scope": "product", "text": "`REQ-007` REQ-007 Формат изображения выбирается из начального набора png и ico; возвращаются только файлы запрошенного формата, а при отсутствии таких изображений у источника выдаётся явное сообщение, что изображений такого формата нет, отличимое от ошибки доступа к источнику.", "executable_check_ids": ["runtime-bound-evidence-001"]}, {"operation": "add", "requirement_id": "R8", "from_version": 0, "to_version": 1, "scope": "product", "text": "`REQ-008` REQ-008 Возвращаются только изображения, размер которых не меньше желаемого по обоим измерениям; если у источника по теме нет изображений подходящего размера, выдаётся явное сообщение, что подходящих по размеру нет, отличимое от сообщения об отсутствии формата и от ошибки доступа.", "executable_check_ids": ["runtime-bound-evidence-001"]}, {"operation": "add", "requirement_id": "R9", "from_version": 0, "to_version": 1, "scope": "product", "text": "`REQ-009` REQ-009 По флагу скачивания найденные изображения сохраняются в каталог, указанный вызывающей стороной, а в результате сообщаются пути сохранённых файлов.", "executable_check_ids": ["runtime-bound-evidence-001"]}, {"operation": "add", "requirement_id": "R10", "from_version": 0, "to_version": 1, "scope": "product", "text": "`REQ-010` REQ-010 При наличии флага масштабирования изображения, доступные только в размере больше желаемого, уменьшаются до желаемого размера; без этого флага изображения сохраняются без изменения размеров.", "executable_check_ids": ["runtime-bound-evidence-001"]}, {"operation": "add", "requirement_id": "R11", "from_version": 0, "to_version": 1, "scope": "product", "text": "`REQ-011` REQ-011 Утилита поставляется и запускается как обычный исполняемый процесс, без Docker и контейнеров.", "executable_check_ids": ["runtime-bound-evidence-001"]}]` ## Dependencies - Child task #9 - Child task #8 - Child task #9 - Child task #8 - Child task #9 - Child task #8 - Child task #9 - Call out any dependency that blocks implementation. ## Risk Notes - Preserve existing public behavior unless explicitly requested. - UNK-001: it is unverified whether the chosen first source supports server-side filtering by size/format; if not, client-side filtering against REQ-008 may require downloading many candidates and could hit timeouts or rate limits, affecting REQ-007 and REQ-008 outcomes. - UNK-002: ico availability on free sources is unknown; the no-format path (REQ-007) may be the common outcome and must be proven to be distinct from access errors rather than assumed. - UNK-003: source rate limits and User-Agent/identification requirements are unverified and could turn normal usage into access errors, affecting REQ-003 and AC-011 behavior. - UNK-004: the default download directory when the caller omits it is an open product decision; either a mandatory --output-dir error or a documented default must be confirmed before REQ-009 is finalized. - UNK-005: partial download success reporting is an open product decision affecting REQ-009 and REQ-002 status semantics. - Pillow (or an equivalent decoder/resizer) availability in the internal Gitea catalog is unverified; if it is not published, ICO dimension verification and downscaling (REQ-007, REQ-010) cannot be satisfied with stdlib alone and must not be replaced by a public-download fallback. - Live-source reachability for AC-010 depends on runtime egress to the approved hosts; if the sandbox cannot reach them, that limitation must be recorded instead of substituting synthetic results. - Exit-code and status vocabulary must be fixed once and reused by all branches, otherwise AC-001/AC-006 distinguishability degrades. ## Parent Links - Team-lead issue: #2 - Parent architecture issue: #1 ## Architecture / Lead Context The context below describes the whole product. Scope and Acceptance Criteria define local completion; the Integration Contract additionally requires preservation of active product obligations. # Team lead handoff <!-- agent-architecture-handoff {"asset": "agent-architecture-handoff.v1.json", "renderer": "agent.architecture_handoff_markdown.v1", "schema": "agent.architecture_handoff.v1", "sha256": "2556d39044bc87f828704b28f39f1b136761f18330c69c087a387f1ae69fa2bf"} --> Parent architecture issue: #1 Source title: Консольная утилита поиска и скачивания изображений для вызова ИИ-агентом Contract asset: `agent-architecture-handoff.v1.json` Contract SHA-256: `2556d39044bc87f828704b28f39f1b136761f18330c69c087a387f1ae69fa2bf` ## Workflow - Repository: projects/product-54354138-1 - Repository intent: existing_repository - Base branch: `master` - Target branch: `task/1-task` - Facade: `.agent/project.yaml` (`initialized`) - CI: `created` - Created repository: `false` - Created branch: `true` - Facade template: `script_toolkit_python` - Facade action: `initialize` - Project shape: `project_kind=script_toolkit, languages=['python'], runtimes=['command_line'], interfaces=['cli'], delivery_kind=native_process` - Project shape requirement refs: `project_kind=['REQ-001', 'REQ-011'], languages=['REQ-001', 'REQ-011'], runtimes=['REQ-001', 'REQ-011'], interfaces=['REQ-001', 'REQ-002', 'REQ-009'], delivery_kind=['REQ-011']` - Facade placement: `kind=repository_root` <!-- agent-provisioner:task base_branch=master target_branch=task/1-task --> <!-- architect-agent:plan mode=llm --> ## Architecture Plan ### Context Product request issue #1: a console (CLI) image search/download utility invoked by an AI agent via tool calling. Contract requirements REQ-001..REQ-011: parameters for topic, desired size, format (initial set png/ico), source, download flag and resize flag; machine-readable structured output distinguishing success / no-images-of-format / no-images-of-size / source-access error (AC-001, AC-011); free access without API keys or secrets (REQ-003, AC-002); pluggable source selection with explicit unknown-source error listing available sources (REQ-004, AC-003); only requested format returned and explicit "no images of this format" message distinct from access errors (REQ-007, AC-004); only images not smaller than the desired size in both dimensions, with actual dimensions reported (REQ-006, REQ-008, AC-005, AC-006); download into a caller-specified directory with reported paths (REQ-009, AC-007); downscale-only resizing behind a flag, unchanged dimensions without the flag (REQ-010, AC-008); live-source verification on a known topic (AC-010); delivered and run as a plain executable process with no Docker/containers (REQ-011, AC-009). Approved network access is Wikimedia Commons and Open ### Decision Shape: script_toolkit (Python 3, command_line runtime, cli interface, native_process delivery, repository_root placement). This is the narrowest catalog-template-backed shape that covers every resulting language, runtime, public interface and delivery form: the deliverable is one command-line program that speaks over argv/stdout, there is no HTTP server and no second language, and REQ-011/AC-009 forbid container delivery. 'file_io' is intentionally not declared as a separate public interface: writing downloaded files into the caller-specified directory (REQ-009) and reporting the resulting paths (REQ-002) is internal behavior of the CLI invocation, not an independent repository interface, and declaring it would leave the shape without a supported facade template. Facade: initialize (currently missing) at repository_root, since no product artifact fixes a component root. Implementation direction: a single Python CLI entry module parsed with argparse (topic, desired width/height, format png|ico, source, --count limit, --download, --output-dir, --resize), a small source-adapter registry (Wikimedia Commons MediaWiki API first, Openverse as a second adapter behind the same registry) so ### Constraints - Project shape is limited to script_toolkit/Python/command_line/cli/native_process at repository_root; do not add an HTTP service, a second language or container packaging. - Delivery must be a plain executable process (REQ-011, AC-009): no Dockerfile, compose file or container entrypoint. - Only free, credential-free sources; no API keys, tokens, registration or secret configuration may be required or read at runtime (REQ-003, OOS-003). - Only Wikimedia Commons and Openverse over HTTPS 443 (incl. subdomains) are approved network destinations; no other hosts and no public-download fallbacks. - Format support limited to png and ico (REQ-007, OOS-002); no other formats and no editing beyond downscaling (OOS-001). - Output must remain a single machine-readable JSON document with distinct status values and matching exit codes for success, no-format, no-size, access error and invalid request (REQ-002, AC-001, AC-011). - Filters must be applied on the client side to the actual downloaded/parsed image data, not trusted from source metadata alone, so reported format and dimensions are real. - Resizing may only downscale to the desired size and must be off by default (REQ-010, AC-008). ### Risks - UNK-001: it is unverified whether the chosen first source supports server-side filtering by size/format; if not, client-side filtering against REQ-008 may require downloading many candidates and could hit timeouts or rate limits, affecting REQ-007 and REQ-008 outcomes. - UNK-002: ico availability on free sources is unknown; the no-format path (REQ-007) may be the common outcome and must be proven to be distinct from access errors rather than assumed. - UNK-003: source rate limits and User-Agent/identification requirements are unverified and could turn normal usage into access errors, affecting REQ-003 and AC-011 behavior. - UNK-004: the default download directory when the caller omits it is an open product decision; either a mandatory --output-dir error or a documented default must be confirmed before REQ-009 is finalized. - UNK-005: partial download success reporting is an open product decision affecting REQ-009 and REQ-002 status semantics. - Pillow (or an equivalent decoder/resizer) availability in the internal Gitea catalog is unverified; if it is not published, ICO dimension verification and downscaling (REQ-007, REQ-010) cannot be satisfied with stdlib alone and must not be replaced by a public-download fallback. - Live-source reachability for AC-010 depends on runtime egress to the approved hosts; if the sandbox cannot reach them, that limitation must be recorded instead of substituting synthetic results. - Exit-code and status vocabulary must be fixed once and reused by all branches, otherwise AC-001/AC-006 distinguishability degrades. ### Team Lead Handoff - First prove the smallest end-to-end public path on the live source: run the CLI for a known topic against Wikimedia Commons requesting png, observe a non-empty JSON list with working URLs and real dimensions (AC-010), then confirm the same run with no API key/credential env vars set (AC-002). - Bounded check for UNK-001: issue one documented MediaWiki/Openverse search request and record whether size/mime filtering is available server-side and how many candidates must be fetched to satisfy the >= size rule; the decision between server-side parameters and client-side-only filtering (and any candidate cap) depends on that observation. - Bounded check for UNK-003: run a handful of sequential requests and record response codes, any 429 behaviour and whether a custom User-Agent is required; the retry/backoff design and whether a --count cap is enforced client-side depend on the result. - Bounded check for UNK-002: query an ico request against the chosen source and record whether the no-format status is produced while the source is reachable; this decides how the no-format message is worded and which exit code is paired with it. - Bounded check for Pillow availability: attempt prepare_environment with the declared manifest and record whether Pillow resolves from the internal catalog; the choice between Pillow-based ICO decode/resize and a reduced, explicitly recorded capability depends on that result. If it is missing, request operator publication; do not add public index fallbacks or credential changes. - Decide and document UNK-004 and UNK-005 with the product owner before finalizing REQ-009 output: default download directory behaviour and the status/exit code for partial download success. - All dependency changes must go through the manifests and lock files declared by the generated facade and Tool Backend prepare_environment; agents must not change package sources, credentials, network access or admission policy, and any policy exception requires human approval. - Preserve required coverage: every status branch (success, no-format, no-size, access error, invalid/unknown source) needs its own executed check and matching exit code, and aggregate exit 0 must not be treated as proof that the no-format and no-size outcomes work. # Parent architecture issue <!-- agent-contract {"asset": "agent-product-contract.v1.json", "renderer": "agent.product_contract_markdown.v1", "schema": "agent.product_contract.v1", "sha256": "b7622222e96d133d4c82b5d716cb2963e8b786272d2735fe9033295141b75ba6"} --> ## Summary Нужно консольное приложение (CLI), запускаемое как обычный исполняемый процесс, которое по заданной теме находит изображения в бесплатных источниках и по флагу скачивает их. Инструмент предназначен для вызова ИИ-агентом через tool calling, поэтому результат должен быть машиночитаемым и однозначно различать успех, отсутствие подходящих изображений и ошибку. Доступ бесплатный, без API-ключей и регистрации. Источник не принципиален, но выбирается вызывающей стороной, схема допускает несколько подключаемых источников, и в поставку входит как минимум один рабочий бесплатный источник. Задаются тема, желаемый размер и формат из начального набора png/ico. Возвращаются только изображения запрошенного формата, не меньшие желаемого размера; если таких форматов нет — явное сообщение, что изображений такого формата нет; если подходящих по размеру нет — явное сообщение, что подходящих по размеру нет. При наличии флага масштабирования изображения больше желаемого размера уменьшаются до желаемого. Запуск — как обычный процесс, без Docker. Сетевой доступ к бесплатным источникам согласован пользователем вне этого обсуждения (Wikimedia Commons и Openverse, HTTPS 443, включая поддомены). ## Requirements - `REQ-001` REQ-001 Утилита является консольным приложением, запускаемым как обычный исполняемый процесс; параметры запуска задают тему поиска, желаемый размер, формат, источник, флаг скачивания и флаг масштабирования. - `REQ-002` REQ-002 Результат работы выводится в машиночитаемом структурированном виде, пригодном для tool calling ИИ-агентом: перечень найденных изображений с источником, URL, форматом и фактическими размерами, а также однозначное различие между успехом, отсутствием подходящих изображений и ошибкой. - `REQ-003` REQ-003 Доступ к источникам бесплатный, без API-ключей, регистрации и иных учётных данных; поиск выполняется без настройки секретов. - `REQ-004` REQ-004 Источник изображений выбирается вызывающей стороной через параметр; схема допускает подключение нескольких источников, и в поставку входит как минимум один рабочий бесплатный источник; неизвестный источник даёт явную ошибку с перечнем доступных источников. - `REQ-005` REQ-005 Поиск выполняется по теме (текстовому запросу), задаваемой вызывающей стороной; количество возвращаемых результатов может быть ограничено вызывающей стороной. - `REQ-006` REQ-006 Вызывающая сторона задаёт желаемый размер изображения (ширина/высота); в результатах по каждому изображению указываются его фактические размеры. - `REQ-007` REQ-007 Формат изображения выбирается из начального набора png и ico; возвращаются только файлы запрошенного формата, а при отсутствии таких изображений у источника выдаётся явное сообщение, что изображений такого формата нет, отличимое от ошибки доступа к источнику. - `REQ-008` REQ-008 Возвращаются только изображения, размер которых не меньше желаемого по обоим измерениям; если у источника по теме нет изображений подходящего размера, выдаётся явное сообщение, что подходящих по размеру нет, отличимое от сообщения об отсутствии формата и от ошибки доступа. - `REQ-009` REQ-009 По флагу скачивания найденные изображения сохраняются в каталог, указанный вызывающей стороной, а в результате сообщаются пути сохранённых файлов. - `REQ-010` REQ-010 При наличии флага масштабирования изображения, доступные только в размере больше желаемого, уменьшаются до желаемого размера; без этого флага изображения сохраняются без изменения размеров. - `REQ-011` REQ-011 Утилита поставляется и запускается как обычный исполняемый процесс, без Docker и контейнеров. ## Artifacts _None recorded._ ## Delivery Requirements - `native_process` (requirements=['REQ-011']) ## External Inputs _None recorded._ ## Acceptance Criteria - `AC-001` AC-001 Для заданной темы утилита возвращает машиночитаемый список результатов, в каждом элементе есть URL, формат и фактические размеры; успешный поиск, отсутствие подходящих изображений и сбой различимы по коду завершения и структуре вывода. - `AC-002` AC-002 Поиск успешно выполняется в окружении, где не задано ни одного API-ключа или учётных данных. - `AC-003` AC-003 Указание источника в параметрах приводит к использованию соответствующего источника, и использованный источник явно отражён в выводе; неизвестный источник даёт явную ошибку с перечнем доступных источников. - `AC-004` AC-004 Запрос формата png возвращает только реальные png-файлы; запрос ico при отсутствии ico у источника даёт явное сообщение о том, что изображений такого формата нет, и это сообщение отличимо от сообщения об ошибке доступа к источнику. - `AC-005` AC-005 При запросе желаемого размера в выдаче присутствуют только изображения, размер которых не меньше желаемого по обоим измерениям, и для каждого указаны фактические размеры. - `AC-006` AC-006 Если по теме у источника есть только изображения меньше желаемого размера, вывод содержит явное сообщение, что подходящих по размеру нет, и это сообщение отличимо от сообщения об отсутствии формата и от ошибки доступа. - `AC-007` AC-007 При указании флага скачивания файлы физически сохранены в заданном каталоге, пути в выводе соответствуют существующим файлам, и файлы открываются как изображения заявленного формата. - `AC-008` AC-008 При наличии флага масштабирования изображение, найденное в размере больше желаемого, сохраняется с размерами, равными желаемым; без этого флага фактические размеры сохранённого файла совпадают с исходными. - `AC-009` AC-009 Утилита запускается как обычный исполняемый процесс без Docker и без контейнерной обвязки. - `AC-010` AC-010 Реальная проверка на известном результате: запрос по теме, для которой у выбранного источника заведомо есть изображения, возвращает непустой список с рабочими ссылками на файлы (проверка на живом источнике, а не только на синтетических данных). - `AC-011` AC-011 При запрещённом сетевом доступе к источнику утилита завершается явной ошибкой доступа и не выдаёт результат, выглядящий как успешный поиск. ## Out of Scope - `OOS-001` Генерация изображений и любые операции редактирования, кроме уменьшения до желаемого размера - `OOS-002` Форматы изображений вне начального набора png/ico - `OOS-003` Платные и требующие API-ключей источники изображений - `OOS-004` Запуск в Docker/контейнерах - `OOS-005` Графический интерфейс пользователя ## Unknowns / Risks - `UNK-001` Какой именно бесплатный источник реализуется первым и покрывает ли его API фильтрацию по размеру/формату или фильтрация выполняется на стороне клиента (влияет на объём загружаемых данных) - `UNK-002` Практическая доступность файлов формата ico у бесплатных источников: ожидаемо такие запросы будут часто возвращать сообщение об отсутствии формата - `UNK-003` Ограничения частоты запросов и требования к идентификации клиента (user agent) у выбранного бесплатного источника - `UNK-004` Каталог сохранения по умолчанию, если вызывающая сторона не задала его явно - `UNK-005` Как сообщать частичный успех скачивания, когда часть файлов сохранилась, а часть нет ## Workflow - Readiness: `ready_for_architecture` - Contract asset: `agent-product-contract.v1.json` - Contract SHA-256: `b7622222e96d133d4c82b5d716cb2963e8b786272d2735fe9033295141b75ba6` - Transcript: `https://git.p2prod.ru/platform/product-requests/issues/1` - Generated by: `product-manager-agent` # Architect plan comments <!-- architect-agent:plan mode=llm --> ## Architecture Plan ### Context Product request issue #1: a console (CLI) image search/download utility invoked by an AI agent via tool calling. Contract requirements REQ-001..REQ-011: parameters for topic, desired size, format (initial set png/ico), source, download flag and resize flag; machine-readable structured output distinguishing success / no-images-of-format / no-images-of-size / source-access error (AC-001, AC-011); free access without API keys or secrets (REQ-003, AC-002); pluggable source selection with explicit unknown-source error listing available sources (REQ-004, AC-003); only requested format returned and explicit "no images of this format" message distinct from access errors (REQ-007, AC-004); only images not smaller than the desired size in both dimensions, with actual dimensions reported (REQ-006, REQ-008, AC-005, AC-006); download into a caller-specified directory with reported paths (REQ-009, AC-007); downscale-only resizing behind a flag, unchanged dimensions without the flag (REQ-010, AC-008); live-source verification on a known topic (AC-010); delivered and run as a plain executable process with no Docker/containers (REQ-011, AC-009). Approved network access is Wikimedia Commons and Open ### Decision Shape: script_toolkit (Python 3, command_line runtime, cli interface, native_process delivery, repository_root placement). This is the narrowest catalog-template-backed shape that covers every resulting language, runtime, public interface and delivery form: the deliverable is one command-line program that speaks over argv/stdout, there is no HTTP server and no second language, and REQ-011/AC-009 forbid container delivery. 'file_io' is intentionally not declared as a separate public interface: writing downloaded files into the caller-specified directory (REQ-009) and reporting the resulting paths (REQ-002) is internal behavior of the CLI invocation, not an independent repository interface, and declaring it would leave the shape without a supported facade template. Facade: initialize (currently missing) at repository_root, since no product artifact fixes a component root. Implementation direction: a single Python CLI entry module parsed with argparse (topic, desired width/height, format png|ico, source, --count limit, --download, --output-dir, --resize), a small source-adapter registry (Wikimedia Commons MediaWiki API first, Openverse as a second adapter behind the same registry) so ### Constraints - Project shape is limited to script_toolkit/Python/command_line/cli/native_process at repository_root; do not add an HTTP service, a second language or container packaging. - Delivery must be a plain executable process (REQ-011, AC-009): no Dockerfile, compose file or container entrypoint. - Only free, credential-free sources; no API keys, tokens, registration or secret configuration may be required or read at runtime (REQ-003, OOS-003). - Only Wikimedia Commons and Openverse over HTTPS 443 (incl. subdomains) are approved network destinations; no other hosts and no public-download fallbacks. - Format support limited to png and ico (REQ-007, OOS-002); no other formats and no editing beyond downscaling (OOS-001). - Output must remain a single machine-readable JSON document with distinct status values and matching exit codes for success, no-format, no-size, access error and invalid request (REQ-002, AC-001, AC-011). - Filters must be applied on the client side to the actual downloaded/parsed image data, not trusted from source metadata alone, so reported format and dimensions are real. - Resizing may only downscale to the desired size and must be off by default (REQ-010, AC-008). ### Risks - UNK-001: it is unverified whether the chosen first source supports server-side filtering by size/format; if not, client-side filtering against REQ-008 may require downloading many candidates and could hit timeouts or rate limits, affecting REQ-007 and REQ-008 outcomes. - UNK-002: ico availability on free sources is unknown; the no-format path (REQ-007) may be the common outcome and must be proven to be distinct from access errors rather than assumed. - UNK-003: source rate limits and User-Agent/identification requirements are unverified and could turn normal usage into access errors, affecting REQ-003 and AC-011 behavior. - UNK-004: the default download directory when the caller omits it is an open product decision; either a mandatory --output-dir error or a documented default must be confirmed before REQ-009 is finalized. - UNK-005: partial download success reporting is an open product decision affecting REQ-009 and REQ-002 status semantics. - Pillow (or an equivalent decoder/resizer) availability in the internal Gitea catalog is unverified; if it is not published, ICO dimension verification and downscaling (REQ-007, REQ-010) cannot be satisfied with stdlib alone and must not be replaced by a public-download fallback. - Live-source reachability for AC-010 depends on runtime egress to the approved hosts; if the sandbox cannot reach them, that limitation must be recorded instead of substituting synthetic results. - Exit-code and status vocabulary must be fixed once and reused by all branches, otherwise AC-001/AC-006 distinguishability degrades. ### Team Lead Handoff - First prove the smallest end-to-end public path on the live source: run the CLI for a known topic against Wikimedia Commons requesting png, observe a non-empty JSON list with working URLs and real dimensions (AC-010), then confirm the same run with no API key/credential env vars set (AC-002). - Bounded check for UNK-001: issue one documented MediaWiki/Openverse search request and record whether size/mime filtering is available server-side and how many candidates must be fetched to satisfy the >= size rule; the decision between server-side parameters and client-side-only filtering (and any candidate cap) depends on that observation. - Bounded check for UNK-003: run a handful of sequential requests and record response codes, any 429 behaviour and whether a custom User-Agent is required; the retry/backoff design and whether a --count cap is enforced client-side depend on the result. - Bounded check for UNK-002: query an ico request against the chosen source and record whether the no-format status is produced while the source is reachable; this decides how the no-format message is worded and which exit code is paired with it. - Bounded check for Pillow availability: attempt prepare_environment with the declared manifest and record whether Pillow resolves from the internal catalog; the choice between Pillow-based ICO decode/resize and a reduced, explicitly recorded capability depends on that result. If it is missing, request operator publication; do not add public index fallbacks or credential changes. - Decide and document UNK-004 and UNK-005 with the product owner before finalizing REQ-009 output: default download directory behaviour and the status/exit code for partial download success. - All dependency changes must go through the manifests and lock files declared by the generated facade and Tool Backend prepare_environment; agents must not change package sources, credentials, network access or admission policy, and any policy exception requires human approval. - Preserve required coverage: every status branch (success, no-format, no-size, access error, invalid/unknown source) needs its own executed check and matching exit code, and aggregate exit 0 must not be treated as proof that the no-format and no-size outcomes work.
ai-team-lead added the role:testerstatus:draft-acceptance labels 2026-11-02 22:44:52 +00:00
ai-dev added status:waiting-for-acceptance and removed status:draft-acceptance labels 2026-11-02 22:45:06 +00:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: projects/product-54354138-1#10