Files
Jyotisha/.superpowers/sdd/task-4-report.md
T
2026-07-20 16:01:35 +08:00

121 lines
7.8 KiB
Markdown

# Task 4 Report — Selection-Only Dynamic Choice Generation
## Outcome
Task 4 now implements the approved hybrid boundary:
- the deterministic engine creates opportunities, candidate partitions, selectable answer
semantics, localized prompts, and localized labels;
- the Agent may only select one exact server opportunity ID or return advisory
`no_useful_question`;
- the server validates and renders all public copy, attaches private score vectors, creates
public UUIDs, and decides retry, fallback, and termination behavior; and
- the raw unmatched-answer note remains available to later workflow layers but is completely
omitted from the Agent prompt.
The Agent cannot author a question, option, label, partition ID, birth-time claim, confidence
claim, or control instruction. Those fields are unrepresentable in its strict output schema.
This supersedes the keyword-filter/substring-grounding design reviewed in
`.omo/evidence/task-4-rereview.md` and the earlier interim `CLEAR` narrative.
The final acceptance correction has been implemented and independently re-audited by the
executor, but the main acceptance reviewer remains authoritative for completion status.
## RED evidence
Artifact: `.omo/evidence/task-4-finite-red.log`
Tests were changed before production code:
- TypeScript: 14 tests, 9 expected failures. The failures demonstrated that the note still
crossed the prompt, selection-only output was rejected, old free-copy output remained
possible, selected server copy was not rendered, and duplicate server labels were accepted.
- Python: 7 tests, 1 expected failure. Two distinct same-year windows both rendered as the
indistinguishable label `2012—2012 年`.
Final-fix RED artifact: `.omo/evidence/task-4-final-red.log`.
- TypeScript: 17 tests, 2 expected failures. Exact and NFKC/whitespace-equivalent primary
labels matching either reserved choice were accepted by both binder and service instead of
failing before ID allocation.
- Python: 4/4 passed, including the new same-month/day-precision regression, confirming that
the production behavior existed but previously lacked durable coverage.
Standards-axis RED artifact: `.omo/evidence/task-4-axis-red.log`.
- TypeScript: 19 tests, 2 expected failures. Server prompts of 121 and 240 characters were
accepted by binder and service instead of failing before ID allocation and commit.
- Python: 4/4 passed after replacing localized precision glyph assertions with numeric-boundary
structure and normalized uniqueness checks.
## Implementation
- `birth-time-dynamic-question-copy.ts` now contains only server-copy structural validation,
NFKC/whitespace label normalization, the note-free opportunity-selection projection, and
deterministic server-copy fingerprinting. The former note blacklist and substring
grounding logic were removed. Shared constants cap server questions at 120 characters and
labels at 80 across the API adapter, public schema, internal model, persisted schema, and
binding guard.
- `birth-time-dynamic-question-validator.ts` accepts only strict selection objects. Binding
resolves the selected server opportunity, validates the prompt and normalized uniqueness
across every primary and reserved visible label, validates every matching private
partition, and only then allocates IDs. Malformed
server copy, private bindings, UUIDs, and persisted records raise
`BirthTimeDynamicBindingError` and cannot be retried into a false low result.
- Fallback sorts opportunities by information gain descending and then opportunity ID,
independent of packet order. Repeated fingerprints alone are skipped as recoverable.
- `dynamic_rectification_copy.py` owns localized contexts and the least detailed
year/month/day range representation needed to distinguish visible windows. Cross-year
ranges stay concise; same-year or same-month collisions gain month or day precision.
Its precision discriminator is the exhaustive `Literal["year", "month", "day"]` domain;
unknown precision cannot silently fall through. `dynamic_rectification_opportunities.py`
remains below the 250-pure-LOC boundary.
- The Mastra contract describes selection only and forbids prompt/options/labels/partition
fields in Agent output.
The real Python-shaped fixture retains structural CJK/no-ASCII copy, normalized label
uniqueness, partition count, opportunity ID, fingerprint, and partition-ID seam checks without
pinning exact natural-language prose. It is parsed through the Task 3 adapter and exercised
through the Task 4 service. Task 5 persistence was not changed.
The service-level adversarial-note regression independently parses every captured Agent prompt
and requires the exact `task`/`opportunities` projection and exact safe opportunity keys. It
does not call the production serializer or search for literal note prose.
## Verification
| Gate | Result | Artifact |
| --- | --- | --- |
| Standards-axis RED | expected 2 TS failures; Python 4/4 | `.omo/evidence/task-4-axis-red.log` |
| Focused dynamic/guide TypeScript | 40/40 pass | `.omo/evidence/task-4-axis-focused-ts.log` |
| Public dynamic-choice schema TypeScript | 7/7 pass | `.omo/evidence/task-4-axis-public-schema-ts.log` |
| Dynamic adapter boundary TypeScript | 8/8 pass | `.omo/evidence/task-4-axis-adapter-ts.log` |
| Focused Task 2 Python | 26/26 pass | `.omo/evidence/task-4-axis-focused-python.log` |
| Legacy Python rectification | 22/22 pass | `.omo/evidence/task-4-axis-legacy-python.log` |
| All birth-time TypeScript | 229/229 pass | `.omo/evidence/task-4-axis-birth-time.log` |
| Full frontend | 304/304 pass | `.omo/evidence/task-4-axis-frontend-full.log` |
| Cumulative changed TypeScript ESLint | pass, zero diagnostics | `.omo/evidence/task-4-axis-eslint.log` |
| Cumulative changed Python Ruff | pass | `.omo/evidence/task-4-axis-ruff.log` |
| Diff check and all changed TS/Python LOC | pass; every audited file <=250 | `.omo/evidence/task-4-axis-quality.log` |
| Full TypeScript check | only known unrelated `profile-persistence.test.ts:7` TS1501 | `.omo/evidence/task-4-axis-tsc.log` |
| Structural prompt focused TypeScript | 40/40 pass | `.omo/evidence/task-4-structural-focused-ts.log` |
| Structural prompt ESLint | pass, zero diagnostics | `.omo/evidence/task-4-structural-eslint.log` |
| Structural prompt diff/LOC audit | pass; cumulative files <=250 | `.omo/evidence/task-4-structural-quality.log` |
| Structural prompt TypeScript check | only known unrelated TS1501 | `.omo/evidence/task-4-structural-tsc.log` |
| Fresh structural-prompt review | CLEAR / APPROVE; no blockers | `.omo/evidence/task-4-structural-prompt-code-review.md` |
The TypeScript command remains non-zero solely because the pre-existing profile-persistence
test uses a regular-expression flag newer than the configured target. No Task 4 file reports
a type error.
The earlier `.omo/evidence/task-4-selection-boundary-code-review.md` `CLEAR` is explicitly
superseded by `.omo/evidence/task-4-final-review.md`; it is not cited as current acceptance.
The earlier `.omo/evidence/task-4-final-fix-code-review.md` `CLEAR` is explicitly superseded by
the standards-axis review and is not cited as current acceptance. The new tests contain no
localized month/day or domain-word assertions; precision is verified through distinct normalized
labels and the number of numeric range-boundary tokens.
The earlier `.omo/evidence/task-4-axis-fix-code-review.md` `CLEAR` is explicitly superseded by
the main acceptance test finding; it is retained only as historical evidence. The shared
120/80 boundary remains verified through the public schema, API adapter, internal and persisted
schemas, and binding guard.
The fresh reviewer independently verified the adversarial structural projection assertion,
40/40 focused tests, zero-diagnostic ESLint, the 250-pure-LOC boundary, and both required
programming/remove-slops perspectives with no remaining blocker.