Transpilation to an Intermediate Rule-List / AST #117
Closed
opened 2026-05-16 19:22:34 +00:00 by guettli
·
1 comment
No Branch/Tag Specified
main
issue-563-agentloop-validation
dummy-pr-test
issue-560-fix-firebase-run-url
issue-539-stable-imap-uid
issue-533-shared-email-list
plan-issue-555
drop-nix
plan-issue-484
plan-issue-539
plan-issue-535
plan-issue-474
plan-issue-533
fix-dagger-engineless-precommit
issue-521-fix-deploy-yml-wait-time-api
issue-502-fix-email-id-collision-mailbox
issue-492-eliminate-duplicate-build-runner
issue-494-website-change-detection
issue-491-parallelize-check
issue-478-fix-stalwart-dual-stack-bind
issue-475-allowed-addresses-glob
issue-473-search-result-reorder
issue-453-update-agentloop-defaults
issue-466-structured-search
issue-505-exclude-chaos-monkey-from-regular-ci
issue-509-fix-search-result-sorting
fix-ink-sparkle-remaining-tests
issue-506-fix-search-emails-tests
issue-504-runner-wait-time
issue-488-search-notes
issue-472-changelog-issue-links
issue-501-folder-search-local-sqlite
issue-486-fix-stale-test-shader-mismatch
fix/prevent-settled-search-rerun-473
issue-467-fix-search-stale-results
issue-446-installed-versions-in-changelog
issue-462-fix-pr
issue-448-chaos-monkey-test
issue-436-notes-on-emails
issue-429-unify-mail-display
issue-422-move-to-folder-create-new
issue-414-ensure-not-run-as-root
issue-424-unify-email-list-views
issue-419-trusted-senders-page
issue-425-fix-prs
test-foo
issue-421-bug-report
issue-383-fix-ci
issue-394-fix-deploy-flutter-version
issue-391-fix-ci-double-trigger
issue-376-combined-inbox-v2
issue-376-combined-inbox
issue-384-fix-open-prs
sops-migrate
issue-339-safe-first-on-imap-fetch
issue-340-try-catch-measure-height
issue-342-pin-intl-version
issue-341-guard-threademails-last
issue-335-agentloop-code-test
issue-329-fix
issue-315-fix
issue-320-fix
issue-325-fix
issue-312-fix
issue-311-fix
issue-305-fix
issue-304-fix
issue-299-fix
issue-300-fix
issue-298-fix
issue-296-fix
issue-294-fix
issue-289-fix
issue-288-fix
issue-287-fix
issue-286-fix
issue-277-fix
issue-282-fix
issue-280-fix
issue-272-fix
issue-268-fix
issue-267-fix
issue-266-fix
issue-258-fix
issue-260-fix
issue-257-fix
issue-253-fix
issue-216-fix
issue-251-fix
issue-249-fix
issue-question-fixes
issue-235-fix
issue-236-fix-v2
issue-237-fix
issue-236-fix
issue-228-fix
issue-217-fix
issue-214-fix
issue-213-fix
issue-208-fix
issue-205-fix
issue-204-fix
issue-203-fix
issue-202-fix
issue-129-fix
issue-161-fix
issue-160-fix
issue-201-fix
issue-210-fix
issue-198-fix
issue-200-fix
issue-144-fix
issue-199-fix
fix/playstore-upload-use-requests
issue-193-fix
issue-186-fix
issue-185-fix
issue-192-fix
issue-183-fix
issue-175-fix
issue-172-fix
issue-171-fix
issue-167-fix
issue-136-fix
issue-162-fix
issue-179-fix
issue-155-fix
issue-154-fix
issue-152-fix
issue-151-fix
issue-141-fix
issue-150-fix
issue-164-fix
migrate-to-dagger
task/d1-ci-matrix
task/a4-typeconverter-json
task/u7-onboarding-walkthrough
task/d3-sync-doc
task/a5-layer-boundary-lint
task/t5-golden-tests
task/p5-date-cache
task/s4-link-handling
task/p3-html-parse-isolate
task/u8-mark-all-read
task/u3-recent-searches
task/a3-jmap-injectable-http-client
task/r5-tls-error-handling
fix/playstore-redirect-retry
task/t3-repository-contract-tests
task/p2-email-list-pagination
task/p1-fts5-search
fix/playstore-upload-timeout
task/a1-email-detail-notifier
fix/upgrade-workmanager-0.9
fix/android-core-library-desugaring
task/p4-db-indexes
task/r3-html-error-boundary
task/d2-check-coverage
task/a2-email-tile
task/t4-migration-tests
task/t2-widget-tests
task/t1-email-repo-coverage
task/u6-connection-status
task/u4-push-notifications
task/u2-draft-sync
task/u1-list-unsubscribe
task/s2-hostname-validation
task/r6-reliability-fuzz-tests
task/r4-sync-error-banner
task/r2-force-resync
task/r1-undo-history-persistence
No results found.
Labels
Clear labels
NeedSupervisor
State/InProgress
State/Later
State/Planned
automerge
ci-failure
do-not-merge
loop/code
loop/code-ci-pending
loop/code-done
loop/code-in-process
loop/merge
loop/merge-done
loop/merge-in-process
loop/plan
loop/plan-done
loop/plan-in-process
Issue escalated to a human supervisor; agentloop will skip it until cleared.
Eligible for automatic merge by CI
Issue opened by agentloop to track a failing CI workflow; used for deduplication.
Plan PR — review only, do not merge.
Add to run the built-in "code" prompt; override at prompts/code.md.
Prompt "code" finished; waiting for the PR's CI to pass before advancing.
Prompt "code" finished successfully.
Agent for the "code" prompt is currently running on this issue.
Managed by agentloop
Managed by agentloop
Managed by agentloop
Add to run the built-in "plan" prompt; override at prompts/plan.md.
Prompt "plan" finished successfully.
Agent for the "plan" prompt is currently running on this issue.
No labels
Milestone
No items
No Milestone
Projects
Clear projects
No projects
No Assignees
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: guettli/sharedinbox#117
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Follow-up from #90
Transpilation to an Intermediate Rule-List / AST
Since Sieve is a declarative language, the plan is broken down into three logical phases: Parsing (converting text to an Abstract Syntax Tree), Lowering (converting the AST to your flat rule-list), and Execution (running the rules against an email object).
Phase 1: Define the Data Models (The Target Format)
Before parsing, you need to define what your intermediate rule-list looks like in pure Dart. This format should closely mirror the subset of features you support.
1.1 Action Models
Represent the specific side-effects your engine allows.
FileIntoAction(String folder)KeepAction()DiscardAction()MarkAsSeenAction()// Often mapped to a flag actionFlagAction(List<String> flags)1.2 Condition Models
Represent how matches are evaluated.
HeaderCondition(List<String> headers, String matchType, List<String> keyList)SizeCondition(String comparison, int bytes)1.3 Rule Container
A structured rule pairs conditions with actions.
Phase 2: The Parser & Compiler (Text to Data)
Instead of writing a regex-heavy parser from scratch, use a parser combinator library like
petitparserin Dart. It makes tokenizing Sieve commands incredibly robust.2.1 Lexing Tokenizer
Build rules to recognize Sieve grammar tokens:
if,elsif,else,requireaddress,header,exists,allof,anyof,true:contains,:is,:matches,:comparatortext:multi-line), and Lists (["a", "b"])2.2 AST Generation & Normalization
As the parser reads the Sieve script, map it directly to your
SieveRuleobjects.keepoccurs. Your compiler should append aKeepAction()to the end of the script execution loop if no terminal action (discardorfileinto) is met.elsifandelseblocks into standard, sequentialSieveRuleblocks to simplify evaluation logic.Phase 3: The Execution Engine (Data to Action)
The execution engine takes an incoming email representation (e.g., a
MimeMessageobject) and your compiled list ofSieveRuleobjects.3.1 Context State Tracker
Create an execution context object to track the state of the email as it passes through rules.
3.2 Evaluation Loop
Iterate through your compiled
SieveRuleobjects sequentially:fileinto, add the folder totargetFoldersand setkeepInInbox = false.discard, setisCancelled = trueand break the loop.mark-as-seenorflag, add those flags toflagsToAdd.SieveExecutionContextto determine the final routing and state modifications to apply to the email store.Phase 4: Verification & Testing Strategy
Because email filtering can destructive (e.g., a bug causing unintended
discardactions), implement a two-tiered testing suite:SieveRuleDart objects and mock emails into the execution engine to verify string matchers (:contains,:is), case insensitivity, and action outcomes.SieveExecutionContextmatches expected states.Example Sieve Test Case Matrix
Ensure your tests cover your specific subset boundary limits:
Implemented in commit
606958e. Added a complete Sieve transpilation pipeline in lib/core/sieve/: sealed data models (SieveCondition, SieveAction, SieveRule), SieveParser (hand-written recursive-descent, RFC 5228 subset), and SieveInterpreter. 40 unit tests pass.