{ "facade_contract": { "acceptance": [ { "component": "tools", "id": "import-package", "kind": "package_import", "verification_roles": [ "artifact_validation" ] }, { "component": "tools", "id": "help-command", "kind": "cli_command", "verification_roles": [ "interface_acceptance" ] } ], "command_paths": [ "examples/input.json", "tests", "tests/test_example.py", "tools", "tools/example.py" ], "commands": [ { "command": "/opt/agent-environment/bin/python -I -m agent_environment_executor.cli --workspace \"$PWD\" --component 'tools' --mode restore", "id": "tools.dependencies.restore", "owner": "infrastructure", "repair_role": "infrastructure", "required_paths": [], "stage": "dependency_preparation", "verification_roles": [] }, { "command": "python -m compileall tools tests", "id": "tools.validate", "owner": "project", "repair_role": "developer", "required_paths": [ "pyproject.toml", "tools", "tests" ], "stage": "command", "verification_roles": [ "artifact_validation", "quality_gate" ] }, { "command": "pytest", "id": "tools.test", "owner": "project", "repair_role": "developer", "required_paths": [ "pyproject.toml", "tests/test_example.py" ], "stage": "command", "verification_roles": [ "automated_test", "quality_gate" ] }, { "command": "python -m tools.example examples/input.json", "id": "tools.smoke", "owner": "project", "repair_role": "developer", "required_paths": [ "pyproject.toml", "tools/example.py", "examples/input.json" ], "stage": "command", "verification_roles": [ "behavior_smoke", "integration_validation" ] } ], "components": [ { "commands": { "smoke": "python -m tools.example examples/input.json", "test": "pytest", "validate": "python -m compileall tools tests" }, "id": "tools", "interfaces": [ "cli" ], "kind": "toolkit", "languages": [ "python" ], "runtime": "command_line" } ], "delivery": null, "dependency_preparation": [ { "component": "tools", "contract": { "manager": "uv", "manifests": [ "pyproject.toml" ], "model": "language/python@1:uv_project", "operations": { "restore": { "phases": [ { "command": "uv sync --locked --no-default-groups --extra dev", "failure_disposition": "recreate_session", "id": "materialize" } ], "status": "supported" }, "update": { "phases": [ { "command": "uv lock", "failure_disposition": "continue_session", "id": "resolve" }, { "command": "uv sync --locked --no-default-groups --extra dev", "failure_disposition": "recreate_session", "id": "materialize" } ], "status": "supported" } }, "reproducibility": "lockfile", "requirements": [ { "dependency_role": "test", "id": "python_pytest", "package": { "ecosystem": "python", "name": "pytest" }, "profile": "tool/python_pytest@1", "provision_source": "project_dependency" } ], "resolution_files": [ "uv.lock" ], "working_directory": "." }, "declaration_state": "satisfied", "execution_status": "not_checked", "manifest_paths": [ "pyproject.toml" ], "missing_inputs": [], "missing_resolution_files": [ "uv.lock" ], "paths": { "configuration_files": [], "manifests": [ "pyproject.toml" ], "resolution_files": [ "uv.lock" ] }, "requirements": [ { "dependency_role": "test", "id": "python_pytest", "kind": "project_dependency_requirement", "manifest_path": "pyproject.toml", "package": { "ecosystem": "python", "name": "pytest" }, "profile": "tool/python_pytest@1", "provision_source": "project_dependency", "state": "satisfied" } ] } ], "external_secrets": [], "path": ".agent/project.yaml", "present_paths": [ "pyproject.toml" ], "project": { "kind": "script_toolkit", "name": "product-54354138-1" }, "protected_paths": { "exact": [ ".agent/acceptance.yaml", ".agent/project.yaml" ], "prefixes": [ ".gitea/workflows/" ] }, "required_paths": [ "examples/input.json", "tests", "tests/test_example.py", "tools", "tools/example.py" ], "schema_version": "agent.facade_contract.v5", "status": "initialized", "support_paths": [ ".env.example", "pyproject.toml", "uv.lock" ], "test_resources": [], "verification_execution": [ { "evidence_kind": "facade_command_result", "evidence_schema": "agent.ci_result.v1", "executor": "ci", "mechanism_id": "tools.validate", "mechanism_kind": "facade_command", "phase": "task_acceptance", "required_paths": [ "pyproject.toml", "tests", "tools" ], "revision_binding": "exact_commit" }, { "evidence_kind": "facade_command_result", "evidence_schema": "agent.ci_result.v1", "executor": "ci", "mechanism_id": "tools.test", "mechanism_kind": "facade_command", "phase": "task_acceptance", "required_paths": [ "pyproject.toml", "tests/test_example.py" ], "revision_binding": "exact_commit" }, { "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" }, { "evidence_kind": "facade_acceptance_result", "evidence_schema": "agent.ci_result.v1", "executor": "ci", "mechanism_id": "help-command", "mechanism_kind": "facade_acceptance", "phase": "task_acceptance", "required_paths": [ "examples/input.json", "tools/example.py" ], "revision_binding": "exact_commit" } ] }, "plan_body": "\n## Architecture Plan\n\n### Context\nProduct 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\n\n### Decision\nShape: 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 \n\n### Constraints\n- 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.\n- Delivery must be a plain executable process (REQ-011, AC-009): no Dockerfile, compose file or container entrypoint.\n- Only free, credential-free sources; no API keys, tokens, registration or secret configuration may be required or read at runtime (REQ-003, OOS-003).\n- Only Wikimedia Commons and Openverse over HTTPS 443 (incl. subdomains) are approved network destinations; no other hosts and no public-download fallbacks.\n- Format support limited to png and ico (REQ-007, OOS-002); no other formats and no editing beyond downscaling (OOS-001).\n- 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).\n- 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.\n- Resizing may only downscale to the desired size and must be off by default (REQ-010, AC-008).\n\n### Risks\n- 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.\n- 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.\n- 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.\n- 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.\n- UNK-005: partial download success reporting is an open product decision affecting REQ-009 and REQ-002 status semantics.\n- 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.\n- 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.\n- Exit-code and status vocabulary must be fixed once and reused by all branches, otherwise AC-001/AC-006 distinguishability degrades.\n\n### Team Lead Handoff\n- 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).\n- 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.\n- 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.\n- 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.\n- 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.\n- 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.\n- 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.\n- 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.", "product_contract": { "acceptance_criteria": [ { "id": "AC-001", "source": "product-manager", "text": "AC-001 Для заданной темы утилита возвращает машиночитаемый список результатов, в каждом элементе есть URL, формат и фактические размеры; успешный поиск, отсутствие подходящих изображений и сбой различимы по коду завершения и структуре вывода.", "verifies": [] }, { "id": "AC-002", "source": "product-manager", "text": "AC-002 Поиск успешно выполняется в окружении, где не задано ни одного API-ключа или учётных данных.", "verifies": [] }, { "id": "AC-003", "source": "product-manager", "text": "AC-003 Указание источника в параметрах приводит к использованию соответствующего источника, и использованный источник явно отражён в выводе; неизвестный источник даёт явную ошибку с перечнем доступных источников.", "verifies": [] }, { "id": "AC-004", "source": "product-manager", "text": "AC-004 Запрос формата png возвращает только реальные png-файлы; запрос ico при отсутствии ico у источника даёт явное сообщение о том, что изображений такого формата нет, и это сообщение отличимо от сообщения об ошибке доступа к источнику.", "verifies": [] }, { "id": "AC-005", "source": "product-manager", "text": "AC-005 При запросе желаемого размера в выдаче присутствуют только изображения, размер которых не меньше желаемого по обоим измерениям, и для каждого указаны фактические размеры.", "verifies": [] }, { "id": "AC-006", "source": "product-manager", "text": "AC-006 Если по теме у источника есть только изображения меньше желаемого размера, вывод содержит явное сообщение, что подходящих по размеру нет, и это сообщение отличимо от сообщения об отсутствии формата и от ошибки доступа.", "verifies": [] }, { "id": "AC-007", "source": "product-manager", "text": "AC-007 При указании флага скачивания файлы физически сохранены в заданном каталоге, пути в выводе соответствуют существующим файлам, и файлы открываются как изображения заявленного формата.", "verifies": [] }, { "id": "AC-008", "source": "product-manager", "text": "AC-008 При наличии флага масштабирования изображение, найденное в размере больше желаемого, сохраняется с размерами, равными желаемым; без этого флага фактические размеры сохранённого файла совпадают с исходными.", "verifies": [] }, { "id": "AC-009", "source": "product-manager", "text": "AC-009 Утилита запускается как обычный исполняемый процесс без Docker и без контейнерной обвязки.", "verifies": [] }, { "id": "AC-010", "source": "product-manager", "text": "AC-010 Реальная проверка на известном результате: запрос по теме, для которой у выбранного источника заведомо есть изображения, возвращает непустой список с рабочими ссылками на файлы (проверка на живом источнике, а не только на синтетических данных).", "verifies": [] }, { "id": "AC-011", "source": "product-manager", "text": "AC-011 При запрещённом сетевом доступе к источнику утилита завершается явной ошибкой доступа и не выдаёт результат, выглядящий как успешный поиск.", "verifies": [] } ], "artifacts": [], "delivery_requirements": [ { "kind": "native_process", "requirement_ids": [ "REQ-011" ] } ], "external_inputs": [], "out_of_scope": [ { "id": "OOS-001", "text": "Генерация изображений и любые операции редактирования, кроме уменьшения до желаемого размера" }, { "id": "OOS-002", "text": "Форматы изображений вне начального набора png/ico" }, { "id": "OOS-003", "text": "Платные и требующие API-ключей источники изображений" }, { "id": "OOS-004", "text": "Запуск в Docker/контейнерах" }, { "id": "OOS-005", "text": "Графический интерфейс пользователя" } ], "readiness": "ready_for_architecture", "requirements": [ { "id": "REQ-001", "priority": "must", "source": "product-manager", "text": "REQ-001 Утилита является консольным приложением, запускаемым как обычный исполняемый процесс; параметры запуска задают тему поиска, желаемый размер, формат, источник, флаг скачивания и флаг масштабирования." }, { "id": "REQ-002", "priority": "must", "source": "product-manager", "text": "REQ-002 Результат работы выводится в машиночитаемом структурированном виде, пригодном для tool calling ИИ-агентом: перечень найденных изображений с источником, URL, форматом и фактическими размерами, а также однозначное различие между успехом, отсутствием подходящих изображений и ошибкой." }, { "id": "REQ-003", "priority": "must", "source": "product-manager", "text": "REQ-003 Доступ к источникам бесплатный, без API-ключей, регистрации и иных учётных данных; поиск выполняется без настройки секретов." }, { "id": "REQ-004", "priority": "must", "source": "product-manager", "text": "REQ-004 Источник изображений выбирается вызывающей стороной через параметр; схема допускает подключение нескольких источников, и в поставку входит как минимум один рабочий бесплатный источник; неизвестный источник даёт явную ошибку с перечнем доступных источников." }, { "id": "REQ-005", "priority": "must", "source": "product-manager", "text": "REQ-005 Поиск выполняется по теме (текстовому запросу), задаваемой вызывающей стороной; количество возвращаемых результатов может быть ограничено вызывающей стороной." }, { "id": "REQ-006", "priority": "must", "source": "product-manager", "text": "REQ-006 Вызывающая сторона задаёт желаемый размер изображения (ширина/высота); в результатах по каждому изображению указываются его фактические размеры." }, { "id": "REQ-007", "priority": "must", "source": "product-manager", "text": "REQ-007 Формат изображения выбирается из начального набора png и ico; возвращаются только файлы запрошенного формата, а при отсутствии таких изображений у источника выдаётся явное сообщение, что изображений такого формата нет, отличимое от ошибки доступа к источнику." }, { "id": "REQ-008", "priority": "must", "source": "product-manager", "text": "REQ-008 Возвращаются только изображения, размер которых не меньше желаемого по обоим измерениям; если у источника по теме нет изображений подходящего размера, выдаётся явное сообщение, что подходящих по размеру нет, отличимое от сообщения об отсутствии формата и от ошибки доступа." }, { "id": "REQ-009", "priority": "must", "source": "product-manager", "text": "REQ-009 По флагу скачивания найденные изображения сохраняются в каталог, указанный вызывающей стороной, а в результате сообщаются пути сохранённых файлов." }, { "id": "REQ-010", "priority": "must", "source": "product-manager", "text": "REQ-010 При наличии флага масштабирования изображения, доступные только в размере больше желаемого, уменьшаются до желаемого размера; без этого флага изображения сохраняются без изменения размеров." }, { "id": "REQ-011", "priority": "must", "source": "product-manager", "text": "REQ-011 Утилита поставляется и запускается как обычный исполняемый процесс, без Docker и контейнеров." } ], "schema": "agent.product_contract.v1", "summary": "Нужно консольное приложение (CLI), запускаемое как обычный исполняемый процесс, которое по заданной теме находит изображения в бесплатных источниках и по флагу скачивает их. Инструмент предназначен для вызова ИИ-агентом через tool calling, поэтому результат должен быть машиночитаемым и однозначно различать успех, отсутствие подходящих изображений и ошибку. Доступ бесплатный, без API-ключей и регистрации. Источник не принципиален, но выбирается вызывающей стороной, схема допускает несколько подключаемых источников, и в поставку входит как минимум один рабочий бесплатный источник. Задаются тема, желаемый размер и формат из начального набора png/ico. Возвращаются только изображения запрошенного формата, не меньшие желаемого размера; если таких форматов нет — явное сообщение, что изображений такого формата нет; если подходящих по размеру нет — явное сообщение, что подходящих по размеру нет. При наличии флага масштабирования изображения больше желаемого размера уменьшаются до желаемого. Запуск — как обычный процесс, без Docker. Сетевой доступ к бесплатным источникам согласован пользователем вне этого обсуждения (Wikimedia Commons и Openverse, HTTPS 443, включая поддомены).", "title": "Консольная утилита поиска и скачивания изображений для вызова ИИ-агентом", "unknowns": [ { "id": "UNK-001", "text": "Какой именно бесплатный источник реализуется первым и покрывает ли его API фильтрацию по размеру/формату или фильтрация выполняется на стороне клиента (влияет на объём загружаемых данных)" }, { "id": "UNK-002", "text": "Практическая доступность файлов формата ico у бесплатных источников: ожидаемо такие запросы будут часто возвращать сообщение об отсутствии формата" }, { "id": "UNK-003", "text": "Ограничения частоты запросов и требования к идентификации клиента (user agent) у выбранного бесплатного источника" }, { "id": "UNK-004", "text": "Каталог сохранения по умолчанию, если вызывающая сторона не задала его явно" }, { "id": "UNK-005", "text": "Как сообщать частичный успех скачивания, когда часть файлов сохранилась, а часть нет" } ], "verification_obligations": [ { "acceptance_criterion_ids": [ "AC-001" ], "id": "VO-001", "proof_class": "behavior_execution", "requirement_ids": [ "REQ-001", "REQ-002" ] }, { "acceptance_criterion_ids": [ "AC-002", "AC-010" ], "id": "VO-002", "proof_class": "integration_check", "requirement_ids": [ "REQ-003" ] }, { "acceptance_criterion_ids": [ "AC-003" ], "id": "VO-003", "proof_class": "behavior_execution", "requirement_ids": [ "REQ-004" ] }, { "acceptance_criterion_ids": [ "AC-004" ], "id": "VO-004", "proof_class": "behavior_execution", "requirement_ids": [ "REQ-005", "REQ-006", "REQ-007" ] }, { "acceptance_criterion_ids": [ "AC-005", "AC-006" ], "id": "VO-005", "proof_class": "behavior_execution", "requirement_ids": [ "REQ-008" ] }, { "acceptance_criterion_ids": [ "AC-007" ], "id": "VO-006", "proof_class": "behavior_execution", "requirement_ids": [ "REQ-009" ] }, { "acceptance_criterion_ids": [ "AC-008" ], "id": "VO-007", "proof_class": "behavior_execution", "requirement_ids": [ "REQ-010" ] }, { "acceptance_criterion_ids": [ "AC-009" ], "id": "VO-008", "proof_class": "behavior_execution", "requirement_ids": [ "REQ-011" ] }, { "acceptance_criterion_ids": [ "AC-011" ], "id": "VO-009", "proof_class": "integration_check", "requirement_ids": [ "REQ-003", "REQ-007", "REQ-008" ] } ], "workflow": { "generated_by": "product-manager-agent", "transcript": "https://git.p2prod.ru/platform/product-requests/issues/1" } }, "schema": "agent.architecture_handoff.v1", "source_issue": { "number": 1, "title": "Консольная утилита поиска и скачивания изображений для вызова ИИ-агентом" }, "verification_bindings": [ { "binding_status": "bound", "mechanism_refs": [ { "id": "tools.smoke", "kind": "facade_command" } ], "proof_class": "behavior_execution", "satisfaction_policy": "any_of", "task_local_evidence_kinds": [ "test_result", "facade_command_result", "facade_acceptance_result" ], "verification_obligation_id": "VO-001" }, { "binding_status": "bound", "mechanism_refs": [ { "id": "tools.smoke", "kind": "facade_command" } ], "proof_class": "integration_check", "satisfaction_policy": "any_of", "task_local_evidence_kinds": [ "test_result", "facade_command_result", "facade_acceptance_result" ], "verification_obligation_id": "VO-002" }, { "binding_status": "bound", "mechanism_refs": [ { "id": "tools.smoke", "kind": "facade_command" } ], "proof_class": "behavior_execution", "satisfaction_policy": "any_of", "task_local_evidence_kinds": [ "test_result", "facade_command_result", "facade_acceptance_result" ], "verification_obligation_id": "VO-003" }, { "binding_status": "bound", "mechanism_refs": [ { "id": "tools.smoke", "kind": "facade_command" } ], "proof_class": "behavior_execution", "satisfaction_policy": "any_of", "task_local_evidence_kinds": [ "test_result", "facade_command_result", "facade_acceptance_result" ], "verification_obligation_id": "VO-004" }, { "binding_status": "bound", "mechanism_refs": [ { "id": "tools.smoke", "kind": "facade_command" } ], "proof_class": "behavior_execution", "satisfaction_policy": "any_of", "task_local_evidence_kinds": [ "test_result", "facade_command_result", "facade_acceptance_result" ], "verification_obligation_id": "VO-005" }, { "binding_status": "bound", "mechanism_refs": [ { "id": "tools.smoke", "kind": "facade_command" } ], "proof_class": "behavior_execution", "satisfaction_policy": "any_of", "task_local_evidence_kinds": [ "test_result", "facade_command_result", "facade_acceptance_result" ], "verification_obligation_id": "VO-006" }, { "binding_status": "bound", "mechanism_refs": [ { "id": "tools.smoke", "kind": "facade_command" } ], "proof_class": "behavior_execution", "satisfaction_policy": "any_of", "task_local_evidence_kinds": [ "test_result", "facade_command_result", "facade_acceptance_result" ], "verification_obligation_id": "VO-007" }, { "binding_status": "bound", "mechanism_refs": [ { "id": "tools.smoke", "kind": "facade_command" } ], "proof_class": "behavior_execution", "satisfaction_policy": "any_of", "task_local_evidence_kinds": [ "test_result", "facade_command_result", "facade_acceptance_result" ], "verification_obligation_id": "VO-008" }, { "binding_status": "bound", "mechanism_refs": [ { "id": "tools.smoke", "kind": "facade_command" } ], "proof_class": "integration_check", "satisfaction_policy": "any_of", "task_local_evidence_kinds": [ "test_result", "facade_command_result", "facade_acceptance_result" ], "verification_obligation_id": "VO-009" } ], "workflow": { "base_branch": "master", "ci_status": "created", "created_branch": true, "created_repository": false, "facade_action": "initialize", "facade_path": ".agent/project.yaml", "facade_placement": { "kind": "repository_root" }, "facade_status": "initialized", "facade_template": "script_toolkit_python", "project_shape": { "delivery_kind": "native_process", "interfaces": [ "cli" ], "languages": [ "python" ], "parameters": { "cli_entrypoint": { "default": "tools/example.py", "description": "Exact implementation path required before CLI checks may run.", "type": "relative_path" }, "cli_module": { "default": "tools.example", "description": "Importable CLI module selected by the architecture contract.", "type": "python_module" }, "package_module": { "default": "tools", "description": "Importable package name used by package acceptance checks.", "type": "python_module" }, "package_path": { "default": "tools", "description": "Python package directory implemented by the project.", "type": "relative_path" }, "sample_input_path": { "default": "examples/input.json", "description": "Project-owned fixture supplied to the smoke command.", "type": "relative_path" }, "test_entrypoint": { "default": "tests/test_example.py", "description": "Exact test artifact required before the test command may run.", "type": "relative_path" }, "tests_path": { "default": "tests", "description": "Test suite directory used by the standard test command.", "type": "relative_path" } }, "placement_kinds": [ "repository_root" ], "project_kind": "script_toolkit", "runtimes": [ "command_line" ], "template": "script_toolkit_python" }, "project_shape_requirement_refs": { "delivery_kind": [ "REQ-011" ], "interfaces": [ "REQ-001", "REQ-002", "REQ-009" ], "languages": [ "REQ-001", "REQ-011" ], "project_kind": [ "REQ-001", "REQ-011" ], "runtimes": [ "REQ-001", "REQ-011" ] }, "provisioned_control_files": [ { "operation": "initialize", "path": ".agent/project.yaml", "sha256": "02a8118add68955267bd8fbb329289e2fe0525c554a38467a9d31bb71dcb3948" }, { "operation": "materialize", "path": ".gitea/workflows/ci.yaml", "sha256": "f8dbd52316fad573eb1a0aa52ceb5df8577c962fa07662670eb6f2bfcdb04c36" } ], "provisioner_warnings": [], "repository": "projects/product-54354138-1", "repository_intent": "existing_repository", "target_branch": "task/1-task", "task_branch": "task/1-task" } }