Skip to content

Contact-details profile schema + wizard + Filler.profile arg (bd-ic1 Phase 1) - #65

Merged
MukhammadIbrokhimov merged 1 commit into
mainfrom
feat/kleinanzeigen-structured-fields
May 19, 2026
Merged

Contact-details profile schema + wizard + Filler.profile arg (bd-ic1 Phase 1)#65
MukhammadIbrokhimov merged 1 commit into
mainfrom
feat/kleinanzeigen-structured-fields

Conversation

@MukhammadIbrokhimov

Copy link
Copy Markdown
Owner

Summary

Phase 1 of bd-ic1: additive groundwork so a future kleinanzeigen filler can fill structured contact-form fields (Anrede, Vorname, etc.) from profile.contact_details. The actual iterate-and-fill work is filed as a follow-up bead — it needs empirical capture of the live kleinanzeigen contact-form HTML to pick selectors against, which we don't have yet.

What's in this PR:

  • Profile.contact_details — new optional ContactDetails sub-model with eight fields: anrede (frau/herr/divers/keine_angabe), given_name, surname, phone, street, plz, schufa_status (available/no/on_request), household_type (single/couple/family/wg/other). Each is independently optional and defaults to None. profile.example.json gets the block with every value null. Every existing profile loads unchanged.
  • Wizard prompts for the block in a new "Kleinanzeigen contact details (optional)" section. The whole block is gated behind a Confirm so users who don't care can skip; inside the block each prompt accepts blank → None.
  • Filler.fill protocol now accepts profile: Profile | None = None as a kw-only argument. Both existing fillers (kleinanzeigen, wg-gesucht) take and ignore it. apply.py threads the loaded Profile into every filler.fill() call site — both dry-run and live.

What's NOT in this PR (follow-up bead)

The actual kleinanzeigen filler logic that iterates form fields and fills them from profile.contact_details. That work needs empirical capture of the live form's HTML in two variants (full 15-field, message-only) before selectors can be picked. Filed as a P3 follow-up.

Test plan

  • pytest — 575/575 pass, coverage 80%.
  • ruff check on touched files — clean.
  • New tests/test_contact_details_schema.py covers defaults, full payload, unknown-field rejection, invalid enums, and Profile.load_example() round-trip.
  • New tests/test_wizard_contact_details.py covers the Confirm-gate skip path, all-blank → all-None, and a full answer-set round-trip.
  • Updated apply-orchestrator stub now accepts the new profile kwarg and asserts apply_to_flat passes a Profile instance through to the filler.
  • Updated apply-lock fake_fill stubs likewise accept the new kwarg.

…ofile

Adds the optional ContactDetails sub-model on Profile so kleinanzeigen-
style contact forms can be filled from a single source of truth. All
eight fields are independently optional — every existing profile loads
unchanged.

- Profile.contact_details: anrede, given_name, surname, phone, street,
  plz, schufa_status, household_type (each None by default).
- profile.example.json gets the block with every value set to null.
- Wizard adds a 'Kleinanzeigen contact details (optional)' section
  that's gated behind a Confirm prompt; blank answers stay None.
- Filler protocol now accepts profile=None as a kw-only argument. Both
  existing fillers take and ignore it; apply.py threads the loaded
  Profile into every filler.fill() call site.

Phase 1 ships the additive infrastructure only. The kleinanzeigen
filler still relies on account-prefill for structured fields; the
actual iterate-and-fill work is tracked separately as a follow-up
bead so it can land alongside empirical capture of the live form's
HTML.
Copilot AI review requested due to automatic review settings May 19, 2026 13:42
@MukhammadIbrokhimov
MukhammadIbrokhimov merged commit f9e4fec into main May 19, 2026
4 checks passed
@MukhammadIbrokhimov
MukhammadIbrokhimov deleted the feat/kleinanzeigen-structured-fields branch May 19, 2026 13:44

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR lays the Phase 1 groundwork for future Kleinanzeigen structured contact-form filling by adding profile.contact_details, prompting for it in the init wizard, and threading a profile object through the filler API and apply orchestration.

Changes:

  • Added ContactDetails sub-model to Profile (plus example JSON) and corresponding schema tests.
  • Extended flatpilot init wizard to optionally collect Kleinanzeigen contact details (with tests).
  • Extended the Filler.fill() protocol with a kw-only profile argument and threaded the loaded Profile through apply_to_flat(); updated fillers and apply-related tests accordingly.

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/flatpilot/profile.py Introduces ContactDetails model and adds Profile.contact_details.
src/flatpilot/profile.example.json Adds contact_details block to the shipped example profile.
src/flatpilot/wizard/init.py Adds optional wizard section + prompt loop to collect contact details.
src/flatpilot/fillers/base.py Extends filler protocol with `profile: Profile
src/flatpilot/fillers/kleinanzeigen.py Accepts new profile kwarg (currently unused) for forward compatibility.
src/flatpilot/fillers/wg_gesucht.py Accepts new profile kwarg (ignored) for protocol compatibility.
src/flatpilot/apply.py Threads loaded Profile through to filler.fill() (dry-run + submit).
tests/test_contact_details_schema.py Adds validation and example-load coverage for ContactDetails.
tests/test_wizard_contact_details.py Adds unit tests for the contact-details wizard prompt loop.
tests/test_apply_orchestrator.py Updates filler stub + asserts apply orchestrator passes a Profile to the filler.
tests/test_apply_lock.py Updates filler fakes to accept new profile kwarg.
.beads/issues.jsonl Updates beads tracking entries related to ic1/ko1 follow-ups and repo memories.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 60 to 63
SubmitVerificationError,
)
from flatpilot.profile import Profile
from flatpilot.scrapers.kleinanzeigen import CONSENT_SELECTORS, HOST, WARMUP_URL
Comment thread src/flatpilot/profile.py
Comment on lines 229 to 234
exclude_short_term: bool = True

wbs: WBS = Field(default_factory=WBS)
contact_details: ContactDetails = Field(default_factory=ContactDetails)
notifications: Notifications = Field(default_factory=Notifications)
attachments: Attachments = Field(default_factory=Attachments)


def _prompt_optional_str(out: Console, prompt: str, *, default: str) -> str | None:
raw = Prompt.ask(prompt, default=default)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants