Skip to content

feat(event): emit typed error envelopes across the event domain#1289

Open
evandance wants to merge 1 commit into
mainfrom
feat/errs-migrate-event
Open

feat(event): emit typed error envelopes across the event domain#1289
evandance wants to merge 1 commit into
mainfrom
feat/errs-migrate-event

Conversation

@evandance
Copy link
Copy Markdown
Collaborator

@evandance evandance commented Jun 5, 2026

Summary

The event domain still returned command-facing failures through legacy output.Err* helpers and final bare fmt.Errorf paths, so callers had to recover validation, auth, local file, lock, and WebSocket failure semantics from prose. This migrates every event error producer — the event consume / event schema command layer, the event +subscribe shortcut, the EventKey definitions under events/, and the consume orchestration in internal/event/ (event list / status / stop already produced no envelope errors of their own) — to typed errs.* envelopes, giving scripts and AI agents stable type, subtype, param, missing_scopes, and cause-preserving errors.

This PR is intentionally scoped to the event domain's own command-returned error producers. The event domain has no batch partial-failure flows, so there is no OutPartialFailure migration in this change. Failures inside the long-running WebSocket callback (malformed event JSON, per-event file write errors) remain non-fatal stderr diagnostics: a single bad event must not terminate the subscriber. event status --fail-on-orphan keeps its bare exit-code signal in both output modes; event stop keeps it only in text mode — with --json the per-target outcomes are already on stdout and the command exits 0. Bus-daemon-internal errors (protocol frames, probe/handshake intermediates, the remote-connection check that degrades to a stderr warning) never reach a command envelope and stay as wrapped intermediates; every command exit lifts them into a typed error with the cause preserved.

Changes

Command layer (cmd/event/):

  • Migrate event consume preflight failures to typed errors:
    • missing bot scopes -> authorization / missing_scope with missing_scopes, identity, and an identity-appropriate grant hint (wire type changes from auth to authorization; exit code stays 3)
    • event types not subscribed in console -> validation / failed_precondition with a console subscription hint
  • Migrate event consume input validation to validation / invalid_argument with param: --jq, --param, and --output-dir; sentinel errors stay errors.Is-comparable as typed causes.
  • Migrate tenant token resolution failures to authentication / token_missing, passing through already-typed credential errors unchanged.
  • Migrate the consume API runtime boundary (consumeRuntime.CallAPI): transport failures classify as network / transport, non-JSON HTTP errors and unparsable response bodies as internal / invalid_response; already-typed errors pass through unchanged. OAPI envelope failures were already typed via errclass.BuildAPIError.
  • Migrate unknown-EventKey and schema resolution failures to typed validation / internal errors.

Consume orchestration (internal/event/consume/) and EventKey definitions (events/):

  • Migrate consume.Run fatal exits to typed errors: unknown EventKey and --param validation -> validation / invalid_argument with param and an event schema hint; jq compile failures -> validation / invalid_argument with param: --jq; bus handshake / pre-consume / daemon startup failures -> typed internal errors with causes and recovery hints; output-dir creation -> internal / file_io.
  • Migrate the global single-bus guard ("another event bus is already connected to this app") to validation / failed_precondition with an event status / event stop hint.
  • Migrate EventKey pre-consume failures (events/vc, events/minutes, events/whiteboard): missing whiteboard_id -> validation / invalid_argument with param: --param and a hint; missing runtime client invariants -> typed internal errors.
  • Fix events/vc note-detail retry: it matched the not-found API code through the legacy *output.ExitError shape, which typed API errors no longer carry, so the retry never fired; it now reads errs.ProblemOf(err).Code.
  • Scope lint/errscontract's legacy-runtime-API rule to files importing shortcuts/common, so same-named typed methods (the event domain's APIClient.CallAPI) do not false-positive.
  • Exit codes change for previously-bare failures: they exited 1 with a plain-text Error: line and now exit with their category code (validation 2, authentication/authorization 3, network 4, internal 5) alongside the typed stderr envelope.
  • Lift the hidden event _bus daemon command's logger-setup and run-loop exits into typed internal errors (visible in bus.log only).
  • Update the skills/lark-event exit-code table: startup/runtime failures are documented as typed JSON envelopes with per-category exit codes, steering agents to parse error.type / error.subtype / error.param / error.hint instead of message text.

Shortcut layer (shortcuts/event/):

  • Add shortcuts/event/errors.go with event-local typed helpers for validation, file I/O, and WebSocket transport failures. Cause-wrapping helpers take the cause as their first argument, append it to the message, and preserve it for errors.Unwrap.
  • Migrate event +subscribe setup failures from legacy output.ErrValidation / output.ErrNetwork / final bare wrapping to typed errs.* builders:
    • unsafe --output-dir -> validation / invalid_argument with param: --output-dir
    • invalid --filter -> validation / invalid_argument with param: --filter
    • subscriber lock contention -> validation / failed_precondition with a recovery hint; param stays empty because the user supplied no offending flag
    • lock file creation/acquisition failures -> internal / file_io
    • WebSocket start failure -> network / transport
  • Migrate route parsing in ParseRoutes to typed validation errors with param: --route, preserving regex/path-validation causes.
  • Migrate event pipeline output-directory creation failures to internal / file_io.
  • Migrate duplicate processor registration from final bare fmt.Errorf to a typed internal error.

Guards and tests:

  • Rewrite the AGENTS.md error-handling convention from the legacy output.Err* helpers to the typed errs.* contract: a constructor cheat sheet, exact signatures for the three easiest-to-misuse primitives (CallAPITyped, ProblemOf, WithParam scope), the pass-through rule, and the param / hint / cause conventions, linked to errs/ERROR_CONTRACT.md — so new contributions emit typed envelopes from the start.
  • Add cmd/event/, events/, and shortcuts/event/ to the migrated-path guards (errs-typed-only, errs-no-bare-wrap, errs-no-legacy-helper) and the errscontract manifests; internal/event/consume/ joins errs-typed-only and the manifests while keeping wrapped intermediates, matching the cmd/auth / cmd/config precedent.
  • Flip preflight tests from *output.ExitError shape assertions to typed assertions, including the missing_scopes wire field; lock the note-detail not-found retry on typed API codes, the single-bus guard's failed_precondition, the daemon logger file_io exit, and the pre-consume typed shapes.
  • Extend unit coverage to assert typed metadata (category / subtype / param) and cause preservation across consume input validation, EventKey param validation, jq compilation, token resolution, the consume API runtime boundary (stubbed transport), subscriber lock contention, router parsing, registry registration, and pipeline directory creation.
  • Add e2e coverage: a dry-run test locking event +subscribe dry-run output shape, and two error-path tests asserting the stderr typed envelope (type / subtype / param / message / hint) for invalid --route input and an unknown event consume EventKey. None of them opens a WebSocket connection.

Test Plan

  • make build
  • go test ./cmd/event ./shortcuts/event ./events/... ./internal/event/...
  • go test ./tests/cli_e2e/event/... -run 'DryRun|Regression'
  • go vet ./...
  • go run -C lint . ..
  • go test -C lint ./...
  • go run github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.1.6 run --new-from-rev=origin/main — 0 issues
  • make unit-test

Related Issues

N/A

@github-actions github-actions Bot added the size/M Single-domain feat or fix with limited business impact label Jun 5, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jun 5, 2026

Looking for one thing? Review this PR in Change Stack to search files, summaries, diffs, and code without losing your place.

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Refactors shortcuts/event and cmd/event to use project-typed errs across validation, network, and internal/file-IO paths; adds event-scoped error helpers; updates lint exclusions and lint-contract lists for shortcuts/event; and extends unit and e2e tests to assert structured errors and preserved causes.

Changes

Event error handling standardization

Layer / File(s) Summary
GolangCI forbidigo exclusions
.golangci.yml
errs-typed-only, errs-no-bare-wrap, and errs-no-legacy-helper forbidigo path-except patterns extended to include shortcuts/event/ (and cmd/event/ where applicable).
Lint contract migrated-path lists
lint/errscontract/rule_no_legacy_common_helper_call.go, lint/errscontract/rule_no_legacy_envelope_literal.go
migratedCommonHelperPaths and migratedEnvelopePaths now include shortcuts/event/ so legacy-common-helper and legacy-envelope literal checks apply to that package.
Event error helper module
shortcuts/event/errors.go
New unexported helper constructors wrapping errs.NewValidationError, errs.NewInternalError (FileIO subtype), and errs.NewNetworkError with optional param and cause chaining.
Pipeline EnsureDirs file-I/O errors
shortcuts/event/pipeline.go
EnsureDirs returns eventFileIOError for OutputDir and per-route directory creation failures (replacing fmt.Errorf wrapping).
Registry duplicate-registration error
shortcuts/event/registry.go
Duplicate processor registration now returns errs.NewInternalError(errs.SubtypeUnknown, ...) and imports errs instead of using fmt.Errorf.
Route parsing validation errors
shortcuts/event/router.go
ParseRoutes returns eventValidationParamError/eventValidationParamErrorWithCause for malformed specs, regex compile errors, non-dir: targets, empty paths, and unsafe path failures (cause preserved); removed fmt import.
Subscribe command error paths
shortcuts/event/subscribe.go
Subscribe now returns typed errors for unsafe --output-dir, lock creation/acquisition, invalid --filter regex, route parsing returns, and WebSocket connection/start (uses eventNetworkError).
cmd/event: consume command typed errors
cmd/event/consume.go
Replaces output.* error constructions with typed errs (validation, permission, authentication) across jq, preflight, sanitizeOutputDir, resolveTenantToken, and parseParams.
cmd/event tests: consume & preflight
cmd/event/consume_test.go, cmd/event/preflight_test.go
Add shared typed-error assertion helper, import errs, and update tests to assert structured errs.ValidationError, errs.PermissionError, and errs.Problem with category/subtype and param/hint fields.
cmd/event runtime & schema & suggestions
cmd/event/runtime.go, cmd/event/schema.go, cmd/event/suggestions.go
CallAPI and response parsing now wrap/return typed network/internal errors; schema JSON parse/serialize failures return errs.NewInternalError(...).WithCause(err); suggestions unknown-key returns errs.NewValidationError(...).WithHint(...).
Tests & e2e: structured assertions and regressions
shortcuts/event/processor_test.go, cmd/event/runtime_test.go, tests/cli_e2e/event/*
Adds requireProblem helper, CallAPI unit tests, typed-error tests and cause-preservation checks, updates negative route/registry/pipeline tests to assert structured problems, and adds dry-run and invalid-route e2e tests.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • larksuite/cli#1242: Main PR extends the existing CheckNoLegacyCommonHelperCall lint rule’s migratedCommonHelperPaths to cover shortcuts/event/, directly building on the retrieved PR’s introduction of that rule and its legacy-helper scanning behavior in lint/errscontract/rule_no_legacy_common_helper_call.go.
  • larksuite/cli#984: Both PRs modify the .golangci.yml forbidigo/errs-typed-only path-exemption rules to include specific shortcuts/** subdomains (main extends for shortcuts/event/, retrieved broadens/restricts via shortcuts/** and cmd/service/** scoping).
  • larksuite/cli#1236: Similar .golangci.yml forbidigo updates adjusting path-except regexes for shortcuts/* domains.

Suggested labels

domain/calendar, feature, size/XL

Suggested reviewers

  • liangshuo-1
  • zero-my
  • syh-cpdsss

Poem

🐰 I nibbled at bugs and wrapped each cause,
Typed errs stitched threads without a pause,
Tests chase the chains, lint learns the new beat,
Event helpers hum tidy and neat,
A rabbit hops off—code and carrots, applause!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 26.56% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat(event): emit typed error envelopes across the event domain' clearly and concisely describes the main change: migrating the event domain to use typed error envelopes.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description check ✅ Passed The PR description is comprehensive, well-structured, and follows the template with all required sections (Summary, Changes, Test Plan, Related Issues).

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/errs-migrate-event

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 5, 2026

🚀 PR Preview Install Guide

🧰 CLI update

npm i -g https://pkg.pr.new/larksuite/cli/@larksuite/cli@770e93fb54624d03690090ab7c6c1aee2e867661

🧩 Skill update

npx skills add larksuite/cli#feat/errs-migrate-event -y -g

@codecov
Copy link
Copy Markdown

codecov Bot commented Jun 5, 2026

Codecov Report

❌ Patch coverage is 65.71429% with 48 lines in your changes missing coverage. Please review.
✅ Project coverage is 71.22%. Comparing base (7c50b3d) to head (770e93f).

Files with missing lines Patch % Lines
cmd/event/consume.go 73.52% 8 Missing and 1 partial ⚠️
internal/event/consume/startup.go 30.00% 7 Missing ⚠️
cmd/event/bus.go 25.00% 6 Missing ⚠️
cmd/event/runtime.go 40.00% 6 Missing ⚠️
internal/event/consume/consume.go 71.42% 6 Missing ⚠️
cmd/event/schema.go 50.00% 3 Missing ⚠️
shortcuts/event/subscribe.go 76.92% 3 Missing ⚠️
events/minutes/preconsume.go 0.00% 2 Missing ⚠️
events/vc/preconsume.go 0.00% 2 Missing ⚠️
internal/event/consume/jq.go 50.00% 2 Missing ⚠️
... and 1 more
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1289      +/-   ##
==========================================
+ Coverage   71.01%   71.22%   +0.21%     
==========================================
  Files         681      682       +1     
  Lines       65435    65489      +54     
==========================================
+ Hits        46470    46646     +176     
+ Misses      15320    15191     -129     
- Partials     3645     3652       +7     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@evandance evandance changed the title fix(event): migrate shortcut errors to typed envelopes feat(event): emit typed error envelopes across the event domain Jun 6, 2026
@evandance evandance force-pushed the feat/errs-migrate-event branch 2 times, most recently from e453130 to 2182b96 Compare June 6, 2026 04:07
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
shortcuts/event/subscribe.go (1)

145-152: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Move --output-dir, --filter, and --route validation into Validate.

These checks only run inside Execute, so event +subscribe --dry-run can still succeed for inputs that a real run will reject. That makes dry-run lie about request validity for the flags this PR is migrating. Please extract a shared validator and invoke it from Validate so dry-run and real execution fail the same way.

As per coding guidelines, "Dry-run E2E tests required for every shortcut change must validate request structure without calling real APIs ... using --dry-run flag." Based on learnings, the shortcut Validate callback runs before dry-run handling, so checks left in Execute never run under --dry-run.

Also applies to: 185-201

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@shortcuts/event/subscribe.go` around lines 145 - 152, Extract the output-dir,
filter, and route flag checks out of Execute and into the shortcut's Validate
method by creating a shared validator function (e.g., validateSubscribeParams or
similar) that is called from Validate and reused by Execute; move the
validate.SafeOutputPath call and its error handling (currently returning
eventValidationParamErrorWithCause for "--output-dir") into that shared
validator, add equivalent validation for the --filter and --route flags there,
and then call this validator from Execute to avoid duplication so both Validate
and Execute use the same logic.

Sources: Coding guidelines, Learnings

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@shortcuts/event/subscribe.go`:
- Around line 145-152: Extract the output-dir, filter, and route flag checks out
of Execute and into the shortcut's Validate method by creating a shared
validator function (e.g., validateSubscribeParams or similar) that is called
from Validate and reused by Execute; move the validate.SafeOutputPath call and
its error handling (currently returning eventValidationParamErrorWithCause for
"--output-dir") into that shared validator, add equivalent validation for the
--filter and --route flags there, and then call this validator from Execute to
avoid duplication so both Validate and Execute use the same logic.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 55228a9a-f49a-41a3-81c4-ab93a4547768

📥 Commits

Reviewing files that changed from the base of the PR and between e453130 and 2182b96.

📒 Files selected for processing (11)
  • .golangci.yml
  • lint/errscontract/rule_no_legacy_common_helper_call.go
  • lint/errscontract/rule_no_legacy_envelope_literal.go
  • shortcuts/event/errors.go
  • shortcuts/event/pipeline.go
  • shortcuts/event/processor_test.go
  • shortcuts/event/registry.go
  • shortcuts/event/router.go
  • shortcuts/event/subscribe.go
  • tests/cli_e2e/event/event_subscribe_dryrun_test.go
  • tests/cli_e2e/event/event_subscribe_error_test.go
✅ Files skipped from review due to trivial changes (1)
  • .golangci.yml
🚧 Files skipped from review as they are similar to previous changes (5)
  • tests/cli_e2e/event/event_subscribe_dryrun_test.go
  • shortcuts/event/registry.go
  • shortcuts/event/errors.go
  • shortcuts/event/router.go
  • shortcuts/event/processor_test.go

@evandance evandance force-pushed the feat/errs-migrate-event branch from 2182b96 to f7006a6 Compare June 6, 2026 04:36
@github-actions github-actions Bot added size/L Large or sensitive change across domains or core paths and removed size/M Single-domain feat or fix with limited business impact labels Jun 6, 2026
@evandance evandance force-pushed the feat/errs-migrate-event branch from f7006a6 to d08f21c Compare June 6, 2026 04:54
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
cmd/event/runtime_test.go (1)

37-52: ⚡ Quick win

Consider the established TestFactory+override pattern for HTTP stubbing.

Per coding guidelines and the learning from PR #1151, the accepted pattern for tests with custom HTTP response control is:

  1. Call cmdutil.TestFactory(t, nil) for canonical Factory wiring
  2. Set t.Setenv("LARKSUITE_CLI_CONFIG_DIR", t.TempDir()) for config isolation
  3. Override f.HttpClient with a custom http.RoundTripper

This test manually constructs the consumeRuntime and its dependencies. While this works for pure unit tests, using TestFactory ensures consistency and catches any future Factory-wiring changes.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cmd/event/runtime_test.go` around lines 37 - 52, The test helper
newTestConsumeRuntime currently constructs a consumeRuntime and its client
manually; change the test to use the canonical TestFactory wiring: call
cmdutil.TestFactory(t, nil) to get the factory, call
t.Setenv("LARKSUITE_CLI_CONFIG_DIR", t.TempDir()) to isolate config, then
override f.HttpClient (the factory's HTTP client) by setting
f.HttpClient.Transport to your custom http.RoundTripper before creating or
injecting the consumeRuntime so the test uses the factory-provided client wiring
instead of newTestConsumeRuntime's manual construction.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@cmd/event/runtime_test.go`:
- Around line 37-52: The test helper newTestConsumeRuntime currently constructs
a consumeRuntime and its client manually; change the test to use the canonical
TestFactory wiring: call cmdutil.TestFactory(t, nil) to get the factory, call
t.Setenv("LARKSUITE_CLI_CONFIG_DIR", t.TempDir()) to isolate config, then
override f.HttpClient (the factory's HTTP client) by setting
f.HttpClient.Transport to your custom http.RoundTripper before creating or
injecting the consumeRuntime so the test uses the factory-provided client wiring
instead of newTestConsumeRuntime's manual construction.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c57a4985-a126-4b11-9c08-d7bad24aa647

📥 Commits

Reviewing files that changed from the base of the PR and between f7006a6 and d08f21c.

📒 Files selected for processing (19)
  • .golangci.yml
  • cmd/event/consume.go
  • cmd/event/consume_test.go
  • cmd/event/preflight_test.go
  • cmd/event/runtime.go
  • cmd/event/runtime_test.go
  • cmd/event/schema.go
  • cmd/event/schema_test.go
  • cmd/event/suggestions.go
  • lint/errscontract/rule_no_legacy_common_helper_call.go
  • lint/errscontract/rule_no_legacy_envelope_literal.go
  • shortcuts/event/errors.go
  • shortcuts/event/pipeline.go
  • shortcuts/event/processor_test.go
  • shortcuts/event/registry.go
  • shortcuts/event/router.go
  • shortcuts/event/subscribe.go
  • tests/cli_e2e/event/event_subscribe_dryrun_test.go
  • tests/cli_e2e/event/event_subscribe_error_test.go
🚧 Files skipped from review as they are similar to previous changes (13)
  • lint/errscontract/rule_no_legacy_envelope_literal.go
  • lint/errscontract/rule_no_legacy_common_helper_call.go
  • tests/cli_e2e/event/event_subscribe_dryrun_test.go
  • cmd/event/preflight_test.go
  • shortcuts/event/registry.go
  • shortcuts/event/pipeline.go
  • shortcuts/event/router.go
  • shortcuts/event/errors.go
  • cmd/event/runtime.go
  • cmd/event/schema.go
  • .golangci.yml
  • shortcuts/event/subscribe.go
  • cmd/event/consume.go

@evandance evandance force-pushed the feat/errs-migrate-event branch 6 times, most recently from 3d0798e to 0e3746e Compare June 6, 2026 09:16
@github-actions github-actions Bot added the domain/im PR touches the im domain label Jun 6, 2026
Replace every command-facing error path in the event domain — the
consume/schema command layer, the +subscribe shortcut, EventKey
definitions, and the consume orchestration — with typed errs.*
envelopes, so consumers get stable type, subtype, param, hint, and
missing_scopes metadata for classification and recovery instead of
free-form message text.

- Input validation (--jq, --param, --output-dir, --filter, --route,
  unknown EventKey, EventKey params) reports validation /
  invalid_argument with the offending flag in param and an actionable
  hint.
- Scope preflight reports authorization / missing_scope with the
  machine-readable missing_scopes list; console-subscription and
  single-bus preconditions report failed_precondition with recovery
  hints.
- The consume API boundary passes already-typed errors through and
  classifies transport, non-JSON HTTP, and unparsable responses; the
  vc note-detail retry now matches the not-found code on typed errors
  (it silently never fired against the legacy envelope shape).
- Previously-bare failures exited 1 with a plain-text "Error:" line
  and now exit with their category code (validation 2, auth 3,
  network 4, internal 5) alongside the typed stderr envelope.
- forbidigo and errscontract guards now cover the event paths so
  regressions fail lint; AGENTS.md and the lark-event skill document
  the typed contract for agent consumers.

Validation: make unit-test (race) green; event unit and e2e suites
assert category/subtype/param/hint and cause preservation against the
real binary; errscontract and golangci lint clean.
@evandance evandance force-pushed the feat/errs-migrate-event branch from 0e3746e to 770e93f Compare June 6, 2026 10:34
@github-actions github-actions Bot removed the domain/im PR touches the im domain label Jun 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/L Large or sensitive change across domains or core paths

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant