feat: sync latest ARR implementation

This commit is contained in:
Wyndham ARR
2026-07-31 15:11:42 +08:00
parent d6f8a747fa
commit bf7939dd1a
185 changed files with 17527 additions and 2260 deletions

View File

@@ -1,6 +1,6 @@
# ADR-001: Automatic Monthly Trigger And TOTAL PRICE Formula
- Status: Accepted
- Status: Implemented
- Date: 2026-07-29
- Source: User correction in the current session
@@ -11,21 +11,26 @@ Earlier discussion incorrectly treated monthly-report generation as a separate u
## Decision
1. The user's workflow begins and ends with uploading the XML.
2. The Agent processes the XML and returns structured data for validation and database persistence.
3. Only after that structured result is successfully committed does the business system automatically trigger the monthly-report processing program.
4. `report_year`, `report_month`, `as_of_date`, or equivalent values may remain as internal execution and audit fields, but the backend must derive them. They are not user inputs in the primary workflow.
2. ARR's frozen processor produces structured data for independent validation and database persistence; the production path has no Agent/MCP dependency.
3. Only after that structured result is successfully committed does the business system emit `arr.daily_version_committed`; a dedicated worker process consumes it and runs the monthly-report program.
4. `report_year`, `report_month`, `as_of_date`, or equivalent values may remain as internal execution and audit fields, but the backend must derive them. The worker uses committed retained `ARRIVAL` facts to select the affected month, and the greatest `ARRIVAL` actually included in the snapshot is the report's `as_of_date`/“更新至”. The XML filename and wall clock are never authorities for this value.
5. The report keeps the `TOTAL PRICE` dimension/field. Each XLSX data-row cell must contain a formula with the business meaning:
`TOTAL PRICE = REAL PRICE × NIGHTS × NO_OF_ROOMS`
With the current 19-column layout, this is equivalent to `=R2*C2*G2` for row 2 and must fill relatively for later rows.
6. The monthly page automatically discovers newly published versions. A user must not need a separate refresh action
after the worker finishes.
## Consequences
- A manual month/as-of form or endpoint is not the primary product flow and must not be presented as a required user step.
- The monthly processor may still accept internally supplied month/cutoff arguments from its orchestrator.
- Existing manual-trigger UI/API code and static-cell workbook generation are implementation gaps, not the accepted requirement.
- The exact internal event/outbox/worker mechanism and cutoff derivation policy remain implementation details to design and verify; they must not be delegated to the user.
- The monthly processor may still accept internally supplied month/cutoff arguments through a controlled recovery CLI/API, but the primary page exposes none of them.
- The dedicated worker leases outbox rows, retries transient publication failures, dead-letters exhausted events, and acknowledges success only after both registered artifacts are active/downloadable.
- Durable `reporting` metadata records the snapshot identity, Finance daily-version lineage, channel manifest and local artifact identities without duplicating monthly business rows.
- The implemented workbook writes and reopens one exact row-relative `TOTAL PRICE` formula per data row.
- The portal uses a visibility-aware, non-overlapping list poll while the monthly tab is open and reloads immediately
when the tab becomes active again. A transient background error keeps the last good list and retries automatically.
## Supersedes

View File

@@ -0,0 +1,41 @@
# ADR-002: Controlled Agent Delegates Validation To System Boundaries
- Status: Accepted
- Date: 2026-07-29
- Source: User clarification in the current session
## Context
The ARR data-processing Agent is a dedicated Agent that accepts only business-system messages from a fixed,
controlled entrypoint. Earlier Main Prompt revisions repeated contract, attachment, identity, hash and source
checks already enforced by ARR code. A manual SuperAgent chat test also encouraged chat-input rejection logic,
even though that entrypoint is outside the production contract.
The implementation already has three authoritative boundaries:
1. `ProcessingRequest` and `OssProcessingMessageBuilder` validate and construct the fixed PROGRAM_INPUT.
2. `arr-opera-daily-ingest` owns deterministic business processing and output validation.
3. ARR MCP validates the grant and payload, independently replays the source XML, and commits in a database
transaction.
## Decision
1. Main Prompt trusts PROGRAM_INPUT supplied by the controlled ARR entrypoint and does not repeat field,
attachment, source, identity, hash or Schema validation.
2. The Agent performs only fixed orchestration: one OSS fetch, one Skill run, one result read, at most one MCP
submission, and one final output.
3. Processing failure does not call MCP. MCP `committed` or `already_committed` remains the only successful
submission outcome recognized by the Agent.
4. Manual chat-upload behavior is not a production acceptance criterion. End-to-end testing starts at ARR Web
or the equivalent controlled business-system entrypoint.
5. If the Agent is ever exposed to untrusted/general inputs, validation must be added at the API/gateway boundary
and this decision revisited; prompt prose must not be treated as the security boundary.
## Consequences
- The Main Prompt is shorter and avoids redundant LLM work and token/latency overhead.
- Business and security validation remains deterministic in code rather than probabilistic in the Agent.
- The fixed entrypoint and its access controls become an explicit operational prerequisite.
- Direct SuperAgent chat tests may be useful for isolated Skill experiments but cannot prove or invalidate the
production ingestion flow.

View File

@@ -0,0 +1,59 @@
# ADR-003: Public-read source URL for fetch_oss_file
## Status
Accepted
## Date
2026-07-30
## Context
Controlled SuperAgent traces showed that `fetch_oss_file` accepts `object_uri` and `filename`. An `oss://`
request failed with `public_endpoint_missing`, while earlier HTTPS attempts reached file-type handling. The user
confirmed that the installed Tool reads a publicly accessible OSS address without a Provider and that the OSS
deployment is `public-read`.
The previous ARR adapter explicitly wrote every object with object ACL `private`. That overrides a public-read
bucket and would make a generated public URL unusable. At the same time, making every processing output public
would unnecessarily widen exposure.
## Decision
1. ARR requires the integration bucket to report bucket ACL `public-read`; anonymous writes remain forbidden.
2. Only `committed/source_xml/source.xml` is written with object ACL `public-read`. Staged objects, generated
reports, result JSON and exchange objects remain explicitly `private`.
3. `arr-opera-daily-program-input-3` includes a required `oss.url` generated by ARR as
`https://{bucket}.oss-{region}.aliyuncs.com/{encoded-object-key}`. It contains no query signature or secret.
4. The Main Prompt passes `oss.url` unchanged as `fetch_oss_file.object_uri` and the canonical attachment name
as `filename`, exactly once. It must not construct `oss://`, sign or substitute another URL.
5. XML extension/MIME acceptance remains a separate platform Tool configuration requirement.
## Rationale
ARR owns the bucket, endpoint and immutable object key, so it can generate one deterministic address without
asking the Agent to infer storage semantics. Object-level ACL selection satisfies anonymous source download
while keeping intermediate and output artifacts private.
## Consequences
- `fetch_oss_file` needs no OSS Provider, AccessKey or signed URL for this flow.
- A committed source XML is anonymously readable to anyone who has its URL; the URL is not a secret or an
authorization mechanism. Retention, access logging and public-source privacy review remain deployment duties.
- Readiness now rejects a private bucket for this integration.
- Deploying code and Prompt changes does not by itself allow XML; the platform must permit `.xml` and
`application/xml` if it still returns `extension_not_allowed`.
## Supersedes
- The private-object/credential-backed Provider assumption in earlier implementation notes and the historical
`oss://` Prompt experiment.
## Related
- `arr_processing/source_message.py`
- `arr_storage/aliyun_oss_v2.py`
- `prompts/arr_opera_daily_program_input.schema.json`
- `prompts/arr_opera_daily_main_agent_prompt.md`
- `.project-docs/50-evidence/topics/2026-07-30-superagent-fetch-oss-prompt-experiment.md`

View File

@@ -0,0 +1,52 @@
# ADR-004: ARR owns deterministic processing and terminal ingestion
## Status
Accepted
## Date
2026-07-30
## Context
The remote Agent successfully fetched the exact XML and ran the deterministic processor, but model-mediated MCP
arguments reduced a valid 135-record result to 20 records. Prompt changes could guide tool use but could not guarantee
lossless transport of a large structured payload. The user authorized a separate ARR2.0 workspace whose production XML
path has no Agent involvement.
## Decision
ARR2.0 runs the frozen `process_daily.py` itself after upload. It stores source and output artifacts as private immutable
objects, validates a canonical `DeliveryEnvelope` with the existing independent validator, and commits through
`PostgresIngestionRepository` in one transaction. The upload request waits for a terminal success or failure result.
The active runtime does not call SuperAgent, expose MCP, issue submission/read grants, use prompts or require a public
source URL. Existing 009/010 database tables remain for historical compatibility but are not used by this path.
## Rationale
This keeps deterministic business logic, source/artifact identity checks, independent validation, version activation,
idempotent delivery replay and atomic Finance writes while removing the unreliable model-serialization boundary.
## Consequences
- Upload latency now includes processing, validation and database commit.
- Controlled processor failures are persisted through the normal failed-delivery contract; infrastructure failures use
explicit run/attempt terminal transitions and an outbox event.
- Fresh user uploads create fresh jobs and follow existing business-date versioning; replay of the same delivery remains
idempotent.
- All ARR-managed object ACLs are private even when the bucket itself is public-read.
- The original `/Users/chillishark/ARR项目0727` workspace remains unchanged as the ARR1 rollback baseline.
## Supersedes
- ADR-002 for the ARR2.0 production XML path only.
- ADR-003 for the ARR2.0 production XML path only.
## Related
- `arr_web/programmatic.py`
- `arr_processing/local.py`
- `arr_web/processing_runtime.py`
- `tests/test_arr_programmatic.py`

View File

@@ -4,21 +4,15 @@
| ID | Decision | Status | Date | Applies To | Detail |
|---|---|---|---|---|---|
| ADR-001 | 月报在 Agent 结构化结果成功入库后由业务系统自动触发;`TOTAL PRICE` 为 Excel 公式字段 | Accepted | 2026-07-29 | 上传链路、月报触发、XLSX 输出 | [ADR-001](ADR-001-automatic-monthly-trigger-and-total-price-formula.md) |
| ADR-004 | ARR2.0 owns deterministic processing, artifact validation and terminal ingestion; no Agent/MCP in production XML flow | Accepted | 2026-07-30 | Upload, processing runtime, OSS ACL, validation, deployment | [ADR-004](ADR-004-arr-owned-programmatic-processing.md) |
| ADR-001 | 月报由独立 worker 自动触发;“更新至”取最新纳入的 `ARRIVAL`;发布后页面自动新增;`TOTAL PRICE` 为公式字段 | Implemented | 2026-07-29 | 月报触发、持久化、页面同步、XLSX 输出 | [ADR-001](ADR-001-automatic-monthly-trigger-and-total-price-formula.md) |
## Superseded Decisions
## Superseded For ARR2.0
| ID | Decision | Superseded By | Date |
|---|---|---|---|
| Conversation draft | 用户点击月报按钮并提交或选择年月/截止范围;金额写静态值 | ADR-001 | 2026-07-29 |
| ADR-003 | Public-read source URL passed to `fetch_oss_file` | ADR-004 | 2026-07-30 |
| ADR-002 | Controlled Agent orchestrates Skill and MCP submission | ADR-004 | 2026-07-30 |
| Conversation draft | Manual monthly parameters and static total values | ADR-001 | 2026-07-29 |
## Decision Criteria
Create or update an ADR when a choice affects:
- project positioning
- architecture boundaries
- public behavior
- data model
- long-term maintenance
- user-facing workflow
ADR-002/003 remain factual history for the separate ARR1 rollback workspace; they are not ARR2.0 runtime decisions.