Skip to content

feat(triage): classify important emails into Stanier action categories on Asana - #7

Merged
br4vesirrobin merged 1 commit into
mainfrom
feat/email-to-asana-triage
Jun 28, 2026
Merged

feat(triage): classify important emails into Stanier action categories on Asana#7
br4vesirrobin merged 1 commit into
mainfrom
feat/email-to-asana-triage

Conversation

@br4vesirrobin

Copy link
Copy Markdown
Contributor

Summary

Adds an email → Asana management-action triage capability, integrated into kontor-cli process. Important emails are scored for importance (sender tiers + customer/escalation boosts), classified by an LLM into one of four Stanier management-action categories — Information Gathering, Nudging, Being the Example, Taking Decision (from Becoming an Effective Software Engineering Manager) — and each becomes an idempotent Asana task in that category's dedicated project, with a target date extracted from the email's deadline, category standard text, and a definition-of-done.

Built via deep-interview → ralplan consensus (Architect + Critic APPROVE) → team execution → code-review loop. Plan: .omc/plans/email-to-asana-triage.md.

What's included

  • triage.py — deterministic sender-tier scoring (matches by name + address), customer (external-domain) boost, escalation/asked-of-me boost for internal colleagues, recall-biased body fetch, one LLM boundary for category + deadline, idempotent task assembly. 4 category templates encoded verbatim (standard text + done-when).
  • asana_client.py — module-level httpx, validate-only (never auto-creates projects/fields), paginated dedup search by kontor-id:<message-id|uid> marker, create_task.
  • himalaya.py — read-only body (--no-headers --preview, no seen flag) + Message-ID header read; Email gains from_name from the envelope.
  • pipeline.py — triage fires on content after classification, independent of the move outcome; LOUD up-front project validation; per-email errors skip+log with triage_tasks_created / triage_skipped_dedup / triage_skipped_errors counters in the run summary.
  • cli.py — preview-only kontor-cli triage --dry-run.
  • config — optional asana + triage sections with conditional fail-fast validation (_validate_required); config.example.yaml seeded with sender tiers.
  • .agents/skills/email-to-asana/SKILL.md — rubric, the 4 category templates, config + dry-run-first runbook, failure boundary.

Safety / invariants

  • Dry-run-first: standalone triage is preview-only; writes happen only via process.
  • Two-tier failure boundary: credential/config errors fail loud up front; per-email runtime errors are caught and counted, never break the move loop.
  • No auto-create, no delete: Asana projects validated (GET only); mailbox is read-only in triage (move-never-delete preserved).
  • Idempotent: re-runs dedup by a stable Message-ID marker scoped to the target project.
  • No secrets in git: PAT lives in gitignored config.yaml; example uses a placeholder.

Tests

TDD throughout — 236 tests pass, coverage 93% (≥90 gate), ruff check + ruff format --check + mypy --strict all clean.

🤖 Generated with Claude Code

…s on Asana

Add an email -> Asana management-action triage capability integrated into the
`process` pipeline. Important emails (scored by sender tier + customer/escalation
boosts) are classified by an LLM into one of four Stanier management-action
categories (Information Gathering, Nudging, Being the Example, Taking Decision),
each mapped to a dedicated Asana project. An idempotent rich task is created with
a target date extracted from the email's deadline, category standard text, and a
definition-of-done.

- triage.py: deterministic sender-tier scoring (name+address match), customer
  (external-domain) + escalation/asked-of-me boosts, recall-biased body fetch,
  one mocked LLM boundary for category + deadline, idempotent task assembly
- asana_client.py: module-level httpx, validate-only (never auto-creates),
  paginated dedup search by kontor-id:<message-id|uid> marker, create_task
- himalaya.py: read-only body (--no-headers --preview) + Message-ID header read;
  Email gains from_name from the envelope
- pipeline.py: triage fires on content after classification, before/independent
  of the move; LOUD up-front project validation; per-email errors skip+log with
  triage_tasks_created/skipped_dedup/skipped_error counters in the summary
- cli.py: preview-only `kontor-cli triage --dry-run`
- config: optional asana + triage sections, conditional fail-fast validation
- .agents/skills/email-to-asana/SKILL.md: rubric, 4 category templates, runbook

TDD throughout: 236 tests pass, coverage 93% (>=90 gate), ruff + mypy strict clean.
@br4vesirrobin
br4vesirrobin merged commit 0e8d0f6 into main Jun 28, 2026
11 checks passed
@br4vesirrobin
br4vesirrobin deleted the feat/email-to-asana-triage branch June 28, 2026 17:58
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.

1 participant