Skip to content

[feat] Publish privacy-preserving workflow run records and stats #1083

Closed

Description

@hsuchifeng

Parent: #818

Goal

Give every driver the same durable, privacy-preserving run history on teamai-reports, starting from the command-only runtime.

Scope

  • Define a versioned run-record schema.
  • Publish once when a run starts and once when it ends.
  • Store workflow, step, driver, optional agent/tool/model, outcome, named end, iterations, duration, tokens, team revision, PR URL, and CI job URL when available.
  • Store no prompts, outputs, diffs, secret values, or local workspace paths.
  • Treat sub-workflows as part of the parent record when introduced.
  • Write through the existing reports-branch abstraction.
  • Queue failed publications locally and retry on the next pull.
  • Return record: pending when publication fails.
  • Add workflow totals to per-user stats and teamai digest.
  • Preserve unrelated stats, sessions, votes, and members fields.

Out of scope

State snapshots, publish/resume, scorers, dashboard UI, traces, and intermediate-step pushes.

Dependencies

Acceptance criteria

  • A machine that dies after start remains visible as started but not ended.
  • Retries do not duplicate logical records.
  • Publication failure does not corrupt local state.
  • Pending records survive process restart.
  • Stats preserve every unrelated field.
  • Command and future agent drivers use one schema.

Verification

Focused schema, redaction, idempotency, queue, and stats-merge tests; build/typecheck/lint; one real-git/real-CLI E2E inspecting the reports branch. Update bilingual reporting documentation.

Activity

  1. kittimzhe commented on Oct 14, 2026

    @kittimzhe
    Contributor

    Now that the command-only runtime base (#1096/#1097) has landed — is this one takeable by a community contributor?

    I'd like to take it, and it's a natural continuation of the stats-privacy work I did in #1056 (which touched reportUsageToTeam, the skills catalog allowlist, and the per-user stats merge on the reports branch). My implementation read, before writing any code:

    • Schema: one versioned run-record shape shared by all drivers, published exactly twice per run (start / end), with a stable run id as the logical record key.
    • Redaction: allowlist, not blocklist — the record carries workflow, step, driver, optional agent/tool/model, outcome, named end, iterations, duration, tokens, team revision, PR/CI URLs when available, and structurally cannot carry prompts, outputs, diffs, secret values, or workspace paths (nothing outside the allowlist has a field to land in).
    • Idempotency: retries upsert by run id, so "a machine that dies after start" stays visible as started-but-not-ended and a later retry cannot duplicate the logical record.
    • Queue: failed publications land in a local pending queue that survives restart and drains on the next pull (mirroring the existing reports-branch retry semantics), with record: pending surfaced on failure.
    • Stats merge: workflow totals added to per-user stats additively, preserving every unrelated field — the same preservation discipline fix(push): publish only team-shared skill names in stats #1056's fixtures pinned.

    Verification plan per the issue: focused schema/redaction/idempotency/queue/stats-merge unit tests, one real-git E2E inspecting the reports branch, bilingual reporting docs update.

    If you're reserving the series for core work, no problem — a one-word answer here settles it and I'll steer elsewhere.

  2. added
    enhancementNew feature or request
    help wantedExtra attention is needed
    and removed
    help wantedExtra attention is needed
    on Oct 14, 2026
  3. jeff-r2026 commented on Oct 14, 2026

    @jeff-r2026
    Collaborator

    Now that the command-only runtime base (#1096/#1097) has landed — is this one takeable by a community contributor?

    I'd like to take it, and it's a natural continuation of the stats-privacy work I did in #1056 (which touched reportUsageToTeam, the skills catalog allowlist, and the per-user stats merge on the reports branch). My implementation read, before writing any code:

    • Schema: one versioned run-record shape shared by all drivers, published exactly twice per run (start / end), with a stable run id as the logical record key.
    • Redaction: allowlist, not blocklist — the record carries workflow, step, driver, optional agent/tool/model, outcome, named end, iterations, duration, tokens, team revision, PR/CI URLs when available, and structurally cannot carry prompts, outputs, diffs, secret values, or workspace paths (nothing outside the allowlist has a field to land in).
    • Idempotency: retries upsert by run id, so "a machine that dies after start" stays visible as started-but-not-ended and a later retry cannot duplicate the logical record.
    • Queue: failed publications land in a local pending queue that survives restart and drains on the next pull (mirroring the existing reports-branch retry semantics), with record: pending surfaced on failure.
    • Stats merge: workflow totals added to per-user stats additively, preserving every unrelated field — the same preservation discipline fix(push): publish only team-shared skill names in stats #1056's fixtures pinned.

    Verification plan per the issue: focused schema/redaction/idempotency/queue/stats-merge unit tests, one real-git E2E inspecting the reports branch, bilingual reporting docs update.

    If you're reserving the series for core work, no problem — a one-word answer here settles it and I'll steer elsewhere.

    Please take this

  4. SaulMoro commented on Oct 14, 2026

    @SaulMoro
    Collaborator

    Some details that are hard to change once records are on teamai-reports.

    • Model. The record could keep tool, the concrete model, and modelAlias when the agent or step asked for one (Proposal: model aliases so one agent works in every tool #830). The concrete model comes from the report. When the tool does not report it, the delivery ledger has it, because it already records the model each agent got per tool (AgentModelRecords in src/types.ts). The alias makes implementer@strong comparable across Claude and Codex, and the concrete model lets model-pricing.ts estimate cost.
    • Run id. r plus 8 hex digits (src/workflow/store.ts) works on one machine. As a key shared by the whole team, it reaches about 1% collision odds by 10,000 runs, and a collision overwrites another member's record. A 16-digit id, with the regex still accepting the old form, avoids that.
    • Scorer labels. If stats sum the labels from [feat] Add workflow scorers and recorded quality labels #1085 per scorer, agent and model, with a source field (workflow now, session later), labels from outside workflows fit later without a migration.

    Added once #1120 was approved:

    Also, the token counts in reports from #1120 currently come from the agent's own result.json, so they can be invented. I raised it on #1120.

    Update: resolved in #1120 (39a7dc1). Model, session and token counts now come only from the tool's own output.

  5. SaulMoro commented on Oct 14, 2026

    @SaulMoro
    Collaborator

    @kittimzhe the schema notes above affect the record shape, so worth a look before the first push to teamai-reports.

  6. SaulMoro commented on Oct 14, 2026

    @SaulMoro
    Collaborator

    Notes from #1078 (#1129, independent of #1126) that change what a run record reads:

    • One settlement point. A run ends only in settleRun, and report no longer settles: after a failed report, the next next skips the dependents and settles the run. Records should hook settleRun, not report.
    • Step ids are paths (ship.check.classify), so definitions are looked up by path, not by top-level id.
    • New statuses. Steps can be skipped, and a run can carry end (the named end it reached). Counts that only know succeeded and failed undercount.
    • New run fields. A run stores inputs and a snapshot of every child definition. Neither belongs in a published record without a privacy decision.
    • One timestamp. settleRun and the save in withRun each stamp updatedAt. Pass one now through, so a record and the run file agree.
    • A failed workflow step has no failure or message of its own; the child steps carry theirs.

    The adaptation is ready on https://github.com/SaulMoro/teamai-cli/commits/records-on-graph-runs (details in #1126 (comment)); whichever of #1126 and #1129 merges second takes it.

    The engine rules that span files are in docs/dev/workflow-engine.md, added by #1129.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions