DARP: Durable Activity Record Protocol

By

I created DARP so coding agents can send meaningful work records to Factory Log through a small, open protocol without surveillance.

~~~

Why I created DARP

I recently created Factory Log, an app that gives me a journal of the work I do across all my projects.

It shows me what moved forward, when it happened, and which projects have momentum. It does not watch my screen or inspect every command I run.

People often ask me: where does Factory Log get this data?

It does not come from the local Git repository. It does not come from GitHub. Factory Log does not scan the local filesystem.

The coding agents send it directly.

When an agent starts working, reaches a meaningful milestone, gets blocked, or completes a task, it sends Factory Log a small structured record. That record identifies the project and task, and includes a short description of the outcome.

No source code. No diffs. No prompts. No terminal output.

I built this mechanism for Factory Log, but it should not belong to one app. Any agent should be able to produce these records. Any compatible app should be able to read them.

This is why I created DARP: the Durable Activity Record Protocol.

Here is what Factory Log looks like right now:

Factory Log showing project activity reported by coding agents

A simple overview

The flow looks like this:

coding agent -> DARP record -> Factory Log

DARP defines the record and the lifecycle around it. A task can start, progress, get blocked, complete, or be abandoned.

Factory Log consumes those records and turns them into a daily timeline and a project overview. Another app could consume the same records and present them differently.

DARP is not an analytics tracker. It only records meaningful outcomes reported by the agent. It does not define the transport, storage, or interface.

The rest of this page is the first public draft of the protocol.


The RFC

FieldValue
DocumentDARP-0001
StatusDraft
CategoryStandards Track
Version1.0.0-draft.1
DateAugust 2026
EditorFlavio Copes

Status of this document

This is a project Request for Comments. It uses familiar RFC conventions, but it is not an IETF publication or Internet Standard.

Discussion and implementations are welcome. Version 1 stays a draft until at least two independent producers and two independent consumers can exchange the same records.

Abstract

Developer work now happens across people, coding agents, editors, terminals, CI systems, and project tools. Each system can show part of the work, but there is no small shared format for saying, “this task moved forward, and here is the durable outcome.”

The Durable Activity Record Protocol, or DARP, defines that format.

A DARP producer emits short, factual records at meaningful task transitions. A consumer can store those records, build a daily chronicle, count activity, or show project momentum. The protocol records claims about outcomes. It does not inspect source code, collect terminal output, or assign a productivity score.

The key idea is simple:

Measure meaningful reported outcomes, not keystrokes, tokens, files, or busyness.

1. Introduction

Common developer metrics usually start from what a tool can observe. They count commits, pull requests, lines changed, tickets closed, deployments, or time spent in an editor.

Those signals can help. They also miss planning, debugging, documentation, research, configuration, review, and changes made by AI agents. Worse, they invite people to optimize the measurement instead of the work.

DARP starts from a different primitive: the durable activity record.

A durable activity record says that a task started, reached a meaningful milestone, became blocked, completed, or stopped. It includes enough context to group the record by task and project. It also carries a short outcome summary written for a person.

DARP standardizes the record, its lifecycle, and the way activity counts are derived. It does not standardize a dashboard, command-line interface, storage engine, transport, or management score.

Factory Log is the first reference application. It is not part of the protocol.

2. Goals

DARP has six goals:

  1. Let humans and software agents report work through the same format.
  2. Make records portable across tools and readable without a specific app.
  3. Count meaningful task activity without reading source code or surveillance data.
  4. Preserve a chronological explanation of what changed.
  5. Support local-first, append-oriented storage and concurrent producers.
  6. Keep the core small enough to implement in an afternoon.

3. Non-goals

DARP does not try to:

  • prove that an outcome is correct or valuable;
  • measure the full productivity of a person or team;
  • replace DORA, SPACE, DevEx, or business outcome metrics;
  • record every tool call, file edit, command, prompt, or token;
  • move source code, diffs, terminal output, or secrets;
  • define task planning, assignment, priority, or percentage complete;
  • define a network transport or central service;
  • create an employee-ranking system.

4. Conventions and terminology

The key words MUST, MUST NOT, REQUIRED, SHOULD, SHOULD NOT, and MAY are interpreted as described by BCP 14 when, and only when, they appear in capitals.

4.1 Producer

A producer creates a DARP record. A producer can be a person, coding agent, editor extension, command-line tool, CI job, or adapter.

The producer reports a claim. The producer does not need to be the only contributor to the work.

4.2 Consumer

A consumer reads DARP records. A consumer can validate, store, aggregate, display, export, or relay them.

4.3 Ledger

A ledger is an ordered collection of accepted records. A newline-delimited local file is a ledger. A database table or remote event stream can also be a ledger.

4.4 Task

A task is a bounded thread of work with one lifecycle. It starts once and ends at most once.

4.5 Durable outcome

A durable outcome remains useful or observable after the work session ends.

Examples include:

  • code, configuration, content, or documentation saved to a project;
  • a reviewed decision or plan saved for later use;
  • a completed code review with actionable feedback;
  • a deployment or external project-system change;
  • an investigation that resolves uncertainty and changes the next decision;
  • a verified repair, migration, or release.

Reading a file, running a command, invoking a tool, generating tokens, or thinking about a problem is not a durable outcome by itself.

4.6 Meaningful milestone

A meaningful milestone is the smallest coherent outcome worth telling a collaborator about.

One file edit is usually too small. “Added validation, migration fixtures, and tests for schema version 2” is a meaningful milestone.

4.7 Effective record

An effective record is a valid record that remains after duplicate removal and amendments are applied.

5. The protocol model

DARP uses immutable event records. Each record belongs to one project and one task.

A task follows this lifecycle:

missing --started--> active
active --progressed--> active
active --blocked--> blocked
blocked --progressed--> active
active | blocked --completed--> completed
active | blocked --abandoned--> abandoned

The record kinds are:

KindMeaningCounts as outcome activity
task.startedThe producer committed to a task.No
task.progressedThe task reached a meaningful durable milestone.Yes
task.blockedWork cannot continue without new input or external change.No
task.completedThe requested outcome was delivered.Yes
task.abandonedThe task stopped without completion.No

task.progressed moves a blocked task back to active. task.completed and task.abandoned are terminal.

An amendment can replace or retract an earlier record. Amendments preserve the historical record while fixing the effective view.

Lifecycle rules apply to normal records. An amendment carries its target’s kind for validation, but it does not repeat that lifecycle transition.

6. Record format

A DARP record is a UTF-8 JSON object conforming to RFC 8259.

An encoded record MUST NOT exceed 65,536 bytes. This limit keeps local tools predictable and gives network bindings a common minimum capacity.

The normative JSON Schema is included in Section 19.

Example:

{
  "specVersion": "1.0",
  "id": "019cb40b-b30e-72f2-8fb1-2c413b9f544a",
  "sequence": 2,
  "previousID": "019cb409-79d2-7f31-9f52-7b1a63128b97",
  "occurredAt": "2026-08-28T15:12:00+02:00",
  "recordedAt": "2026-08-28T15:12:03+02:00",
  "kind": "task.progressed",
  "project": {
    "id": "urn:uuid:eb0d9db1-82aa-4d44-8e45-a71452c0214c",
    "name": "Factory Log"
  },
  "task": {
    "id": "task_6b8d9c1780e24ac5a76c88f52fb51d35",
    "title": "Define developer activity protocol"
  },
  "source": {
    "tool": "codex",
    "sessionID": "019cb408-76c9-7c2d-92f5-3c650e643b72"
  },
  "summary": "Defined the task lifecycle, activity measure, and privacy boundary.",
  "outcome": {
    "category": "documentation",
    "verification": {
      "status": "verified",
      "methods": ["manual-review"]
    }
  }
}

6.1 specVersion

specVersion identifies the DARP major and minor version. Producers conforming to this document MUST use 1.0.

Patch changes clarify the specification and do not change this value.

6.2 id

id uniquely identifies the record. Producers MUST NOT reuse an ID for a different record.

A UUID conforming to RFC 9562 is RECOMMENDED. UUIDv7 is useful when an implementation also wants roughly time-sortable identifiers.

Consumers MUST treat a repeated id as a duplicate. If the repeated content differs, the consumer MUST surface an integrity error.

6.3 sequence

sequence is a positive integer scoped to the pair (project.id, task.id).

The start record MUST use 1. Each later record MUST increment the last accepted sequence by one.

The largest valid sequence is 9,007,199,254,740,991 so it round-trips safely through common JSON implementations.

Sequence numbers define task order. Timestamps do not.

6.4 previousID

The start record MUST omit previousID. Every later record MUST set previousID to the preceding accepted record ID for that task.

The sequence and previous ID form a small causal chain. They let a consumer detect missing records and concurrent writers without relying on synchronized clocks.

6.5 occurredAt

occurredAt records when the reported activity happened. It MUST be an RFC 3339 timestamp with an explicit UTC offset.

Activity views use this field to place work in a time window.

6.6 recordedAt

recordedAt records when the producer created the record. It MUST be an RFC 3339 timestamp with an explicit UTC offset.

For live reporting, occurredAt and recordedAt will usually be close. Importers MAY preserve an older occurredAt while setting recordedAt to the import time.

6.7 kind

kind declares the lifecycle transition described in Section 5.

A producer MUST NOT emit task.progressed for routine operations. It emits one only after a meaningful milestone.

6.8 project

project.id is a stable, opaque identifier. It MUST stay stable when the project moves to a different local path.

project.name is the human-readable name.

project.locator is OPTIONAL. When present, it MUST be a URI. A local app can use a file: URI, but it SHOULD omit that locator from shared exports because paths often reveal usernames and directory structures.

6.9 task

task.id is stable inside the project. task.title is a short human-readable description.

The unique task key is (project.id, task.id). Consumers MUST NOT assume a task ID is globally unique by itself.

6.10 source

source.tool names the reporting tool. Values are open strings so a new agent or editor does not require a protocol revision.

source.sessionID is OPTIONAL. It links back to a session when the source exposes a safe, stable identifier.

The source says who produced the record. It does not claim sole authorship of the outcome.

6.11 summary

summary is a short factual description written for a person.

For task.progressed and task.completed, it SHOULD start with the outcome: “Added,” “Fixed,” “Documented,” “Deployed,” or another concrete past-tense verb.

A summary MUST NOT contain:

  • source code or diff hunks;
  • raw terminal output or prompts;
  • credentials, tokens, or other secrets;
  • a guessed percentage complete;
  • a score assigned to a person.

6.12 outcome

outcome is REQUIRED for normal and replacement task.progressed and task.completed records. A retraction and every other kind MUST omit it.

outcome.category is an open lowercase token. Version 1 defines these common values:

  • code
  • configuration
  • content
  • decision
  • deployment
  • documentation
  • external-change
  • plan
  • review
  • other

Applications MAY define namespaced categories such as com.acme.security-review.

outcome.verification.status is either verified or not-verified. A verified outcome MUST include at least one method. Common methods include automated-tests, build, lint, manual-review, runtime-check, deployment-check, and external-acknowledgement.

Verification remains a producer claim. A DARP record is not cryptographic proof.

6.13 amendment

amendment fixes an earlier record without rewriting history.

It contains:

  • targetID: the record being amended;
  • action: replace or retract;
  • reason: a short explanation.

An amendment MUST use the same project, task, and kind as its target. It MUST target the current effective version of that record. It still takes the next task sequence number and points previousID at the latest accepted record.

For replace, the new record replaces the target in effective views. It carries the corrected summary and, when required by the kind, a corrected outcome. For retract, neither the target nor the amendment contributes to activity metrics, and the amendment omits outcome.

A replacement SHOULD preserve the target’s occurredAt unless the timestamp itself was wrong. A start record MUST NOT be retracted while later effective records exist. Retracting the only record removes the empty task from effective views.

An amendment does not repeat the target’s lifecycle transition. It only changes the effective record.

6.14 extensions

extensions carries optional application data. Every extension key MUST use a reverse-domain name, such as dev.factorylog.threadURL.

Consumers MUST preserve unknown extensions when relaying a full record. Consumers MUST NOT change core behavior based on an unknown extension.

Sensitive values SHOULD NOT be placed in extensions.

7. Producer behavior

A conforming producer MUST:

  1. Emit exactly one normal task.started record before other task records.
  2. Use contiguous sequence numbers and the correct previous record ID.
  3. Emit task.progressed only for meaningful milestones.
  4. Emit no records after a terminal record, except amendments.
  5. Keep summaries factual and free of prohibited content.
  6. Reuse the same record ID when retrying an uncertain delivery.

A producer SHOULD report soon after the outcome occurs. It SHOULD combine tightly related edits, tests, and documentation into one milestone.

A producer MUST NOT create one activity record per command, file, commit, token interval, or elapsed-time interval. Those patterns measure instrumentation volume, not useful output.

8. Consumer and ledger behavior

A conforming consumer MUST validate the JSON shape and task lifecycle before accepting a record.

For each task, it MUST check:

  • sequence 1 is a normal task.started record;
  • later sequences are contiguous;
  • previousID matches the prior accepted record;
  • no normal record follows completion or abandonment;
  • blocked, completed, and abandoned transitions start from a valid state;
  • amendments point to an existing record in the same task.

A consumer MUST make invalid records visible to the operator. It MUST NOT silently reinterpret them as valid records.

A ledger SHOULD append accepted records atomically. When several producers can write at once, the ledger MUST serialize validation and append as one transaction.

If two different records claim the same next sequence, the ledger MUST accept at most one. The losing producer can reload the task head and retry with a new sequence and ID.

A consumer MAY compact old detail. If it does, it MUST preserve enough information to reproduce every published aggregate, and it MUST disclose which narrative detail is no longer available.

9. Serialization and exchange

9.1 Single record

A single record is serialized as one JSON object.

9.2 Local or append-oriented stream

A local ledger MAY use newline-delimited JSON with one complete record per line and a final newline. String line breaks MUST be escaped so a physical line contains exactly one record.

The RECOMMENDED file extension is .jsonl. This profile favors simple inspection and recovery with common command-line tools.

Implementations that need the registered application/json-seq media type MAY use the record separator format defined by RFC 7464.

9.3 Transport

DARP is transport-independent. A record can travel through standard input and output, a local socket, HTTP, a message queue, or file synchronization.

Transport bindings are separate specifications. They MUST preserve the complete record and MUST NOT weaken validation rules.

9.4 CloudEvents binding

Systems that already use CloudEvents 1.0 MAY place the complete DARP record in data.

The binding uses:

CloudEvents attributeDARP value
specversion1.0
idDARP id
sourceA URI identifying the DARP producer
typedev.darp. plus the DARP kind
subjectproject.id plus task.id
timeDARP recordedAt
datacontenttypeapplication/json
dataThe complete DARP record

DARP does not require CloudEvents. The binding exists to avoid inventing another envelope where one already exists.

10. Activity measurement profile

DARP measures reported outcome activity. It does not measure total productivity.

This distinction matters. The SPACE framework shows that developer productivity has several dimensions and cannot be reduced to one activity metric. DORA measures software delivery throughput and stability at the application or service level. DARP complements those approaches with a portable personal or project chronicle.

10.1 Input set

An activity view MUST declare:

  • the inclusive start and exclusive end timestamps;
  • the IANA time zone used for calendar days;
  • project filters, if any;
  • source filters, if any;
  • whether late-arriving records are included;
  • whether compacted aggregates are included.

The view MUST validate records, remove duplicates, and apply amendments before counting.

10.2 Core measures

For an input set of effective records, DARP defines:

MeasureDefinition
activityCountNumber of task.progressed and task.completed records whose occurredAt falls in the window.
tasksTouchedNumber of distinct task keys with any effective record in the window.
completedTasksNumber of effective task.completed records in the window.
blockedTasksNumber of tasks whose last effective record at the window end is task.blocked.
verifiedOutcomesNumber of counted activity records with verification status verified.
activeDaysNumber of local calendar days containing at least one counted activity record.

The list of human-readable outcome summaries is part of the view. Counts without their outcomes lose the most useful context.

10.3 Daily Activity Statement

A Daily Activity Statement is the standard personal view for one local calendar day.

Example:

{
  "date": "2026-08-28",
  "timeZone": "Europe/Paris",
  "activityCount": 3,
  "tasksTouched": 2,
  "completedTasks": 1,
  "blockedTasks": 0,
  "verifiedOutcomes": 2,
  "outcomes": [
    "Defined the DARP lifecycle and record format.",
    "Added a machine-readable schema and valid example stream.",
    "Published the protocol from the Factory Log documentation."
  ]
}

This object is an application view, not a DARP wire record.

10.4 Interpretation

Higher activity can mean more meaningful milestones. It can also mean smaller task boundaries, easier work, or a more talkative producer.

For this reason, a conforming activity view:

  • MUST label the measure as activity, outcomes, or momentum;
  • MUST NOT label activityCount as a productivity score;
  • MUST keep outcome summaries available beside counts;
  • SHOULD compare the same person or project with its own history;
  • SHOULD use trends as prompts for reflection, not targets;
  • MUST NOT use DARP counts alone to rank, compensate, discipline, or evaluate people.

The protocol gives us a shared ruler. It does not decide what is worth building.

11. Privacy and data minimization

DARP is designed for semantic reports, not behavioral surveillance.

A conforming core record MUST NOT contain source code, diffs, raw terminal output, prompts, credentials, or secrets. Producers SHOULD collect the smallest amount of identity and location data needed by the application.

Local filesystem paths are sensitive. Session IDs can also become correlators across exports. Exporters SHOULD remove project.locator, source.sessionID, and private extensions unless the user explicitly includes them.

Applications SHOULD default to local storage. Remote synchronization requires a visible destination, retention policy, and access model.

12. Security considerations

DARP records are claims supplied by producers. A malicious or misconfigured producer can fabricate outcomes, verification, timestamps, identities, and task history.

Consumers MUST validate structure and lifecycle, but validation does not establish truth.

Implementations SHOULD:

  • restrict who can append to a ledger;
  • use atomic writes and cross-process locking for local files;
  • authenticate remote producers;
  • encrypt records in transit;
  • cap record size before parsing;
  • reject invalid UTF-8 and malformed JSON;
  • avoid rendering summaries as HTML;
  • escape values before displaying or exporting them;
  • keep a visible audit trail for amendments.

Append-only storage improves recoverability. It does not make a ledger tamper-proof. Digital signatures and hash-chain integrity are candidates for a future extension.

13. Versioning and extensions

Version 1 consumers MUST accept specVersion equal to 1.0.

New optional behavior belongs in namespaced extensions. A change that removes a field, changes a field’s meaning, changes lifecycle semantics, or makes an optional field required needs a new major version.

Consumers receiving an unsupported major version MUST preserve the raw record when safe, report the unsupported version, and exclude the record from derived metrics.

14. Conformance

An implementation can claim one or more roles.

14.1 DARP 1.0 producer

A conforming producer:

  • emits records valid against the version 1 schema;
  • follows task lifecycle and chaining rules;
  • reports meaningful milestones instead of tool operations;
  • follows the content and privacy restrictions.

14.2 DARP 1.0 consumer

A conforming consumer:

  • validates records and surfaces errors;
  • deduplicates by record ID;
  • derives state from sequence and previous ID;
  • applies amendments;
  • preserves unknown namespaced extensions when relaying records.

14.3 DARP 1.0 activity view

A conforming activity view:

  • publishes its time window, time zone, and filters;
  • computes the core measures exactly as defined;
  • keeps outcome text available;
  • follows the interpretation safeguards in Section 10.4.

15. Factory Log application profile

Factory Log schema version 1 predates DARP. It already implements the central idea, but it is not wire-compatible without an adapter.

The mapping is:

Factory Log v1DARP 1.0
schemaVersionAdapter emits specVersion
idid
File order per taskAdapter derives sequence and previousID
timestampoccurredAt; export time becomes recordedAt
task.startedtask.started
task.reportedtask.progressed
Explicit task.archivedtask.completed when completion was claimed
Automatic or non-completion archivetask.abandoned
project.pathLocal project identity; export SHOULD replace it with an opaque project.id
project.nameproject.name
taskID, taskTitletask.id, task.title
sourcesource
summarysummary

Factory Log currently counts every stored lifecycle event as an update. A strict DARP activity view counts only progressed and completed outcomes. The two values SHOULD have different labels until Factory Log implements the DARP measurement profile.

Factory Log remains free to use JSONL, local storage, a macOS dashboard, and its own command-line interface. Those are application choices, not protocol requirements.

DARP builds on existing ideas instead of replacing them:

  • ActivityStreams 2.0 defines a rich JSON model for social activities. DARP has a narrower developer-work lifecycle and measurement profile.
  • CloudEvents defines a portable event envelope. DARP can use it as a binding.
  • W3C PROV-O models entities, activities, agents, and provenance. DARP uses a smaller operational record and can be mapped to PROV later.
  • OpenTelemetry events describe meaningful point-in-time occurrences. DARP applies the idea to durable developer outcomes without becoming telemetry.
  • SPACE frames productivity across satisfaction, performance, activity, communication, and efficiency. DARP covers only a careful part of the activity dimension.
  • DORA measures software delivery performance through throughput and instability. DARP records work before, after, and outside deployment.

The related standards reviewed for this draft do not define the same combination of agent-issued outcome records, task lifecycle, local-first privacy boundary, and activity measurement profile.

17. IANA considerations

This draft requests no IANA action. DARP does not register a media type.

18. Open questions before 1.0

The draft needs implementation feedback on:

  1. Whether task.blocked belongs in the core lifecycle.
  2. Whether sequence and previousID are both worth their cost.
  3. Whether verification needs a registry of common methods.
  4. Whether a standard HTTP binding would improve interoperability.
  5. Whether signed records and hash chaining belong in a separate integrity profile.
  6. How compacted ledgers should exchange historical aggregates.
  7. Whether project identity needs a standard derivation method.

19. Reference files

Normative JSON Schema: darp-1.0.schema.json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "DARP 1.0 record",
  "description": "A Durable Activity Record Protocol record for developer work.",
  "type": "object",
  "required": [
    "specVersion",
    "id",
    "sequence",
    "occurredAt",
    "recordedAt",
    "kind",
    "project",
    "task",
    "source",
    "summary"
  ],
  "properties": {
    "specVersion": {
      "const": "1.0"
    },
    "id": {
      "type": "string",
      "minLength": 1,
      "maxLength": 255
    },
    "sequence": {
      "type": "integer",
      "minimum": 1,
      "maximum": 9007199254740991
    },
    "previousID": {
      "type": "string",
      "minLength": 1,
      "maxLength": 255
    },
    "occurredAt": {
      "type": "string",
      "format": "date-time"
    },
    "recordedAt": {
      "type": "string",
      "format": "date-time"
    },
    "kind": {
      "enum": [
        "task.started",
        "task.progressed",
        "task.blocked",
        "task.completed",
        "task.abandoned"
      ]
    },
    "project": {
      "$ref": "#/$defs/project"
    },
    "task": {
      "$ref": "#/$defs/task"
    },
    "source": {
      "$ref": "#/$defs/source"
    },
    "summary": {
      "type": "string",
      "minLength": 1,
      "maxLength": 1000,
      "pattern": "^[^\\r\\n]+$"
    },
    "outcome": {
      "$ref": "#/$defs/outcome"
    },
    "amendment": {
      "$ref": "#/$defs/amendment"
    },
    "extensions": {
      "type": "object",
      "propertyNames": {
        "pattern": "^[a-z0-9]+(?:\\.[a-z0-9-]+)+$"
      },
      "additionalProperties": true
    }
  },
  "additionalProperties": false,
  "allOf": [
    {
      "if": {
        "properties": {
          "sequence": {
            "const": 1
          }
        },
        "required": ["sequence"]
      },
      "then": {
        "properties": {
          "kind": {
            "const": "task.started"
          }
        },
        "not": {
          "required": ["previousID"]
        }
      },
      "else": {
        "required": ["previousID"]
      }
    },
    {
      "if": {
        "properties": {
          "amendment": {
            "properties": {
              "action": {
                "const": "retract"
              }
            },
            "required": ["action"]
          }
        },
        "required": ["amendment"]
      },
      "then": {
        "not": {
          "required": ["outcome"]
        }
      },
      "else": {
        "if": {
          "properties": {
            "kind": {
              "enum": ["task.progressed", "task.completed"]
            }
          },
          "required": ["kind"]
        },
        "then": {
          "required": ["outcome"]
        },
        "else": {
          "not": {
            "required": ["outcome"]
          }
        }
      }
    }
  ],
  "$defs": {
    "project": {
      "type": "object",
      "required": ["id", "name"],
      "properties": {
        "id": {
          "type": "string",
          "minLength": 1,
          "maxLength": 512
        },
        "name": {
          "type": "string",
          "minLength": 1,
          "maxLength": 200
        },
        "locator": {
          "type": "string",
          "format": "uri",
          "maxLength": 2048
        }
      },
      "additionalProperties": false
    },
    "task": {
      "type": "object",
      "required": ["id", "title"],
      "properties": {
        "id": {
          "type": "string",
          "minLength": 1,
          "maxLength": 255
        },
        "title": {
          "type": "string",
          "minLength": 1,
          "maxLength": 300,
          "pattern": "^[^\\r\\n]+$"
        }
      },
      "additionalProperties": false
    },
    "source": {
      "type": "object",
      "required": ["tool"],
      "properties": {
        "tool": {
          "type": "string",
          "minLength": 1,
          "maxLength": 100,
          "pattern": "^[a-z0-9][a-z0-9._-]*$"
        },
        "sessionID": {
          "type": "string",
          "minLength": 1,
          "maxLength": 255
        }
      },
      "additionalProperties": false
    },
    "outcome": {
      "type": "object",
      "required": ["category", "verification"],
      "properties": {
        "category": {
          "type": "string",
          "minLength": 1,
          "maxLength": 100,
          "pattern": "^[a-z][a-z0-9.-]*$"
        },
        "verification": {
          "$ref": "#/$defs/verification"
        }
      },
      "additionalProperties": false
    },
    "verification": {
      "type": "object",
      "required": ["status"],
      "properties": {
        "status": {
          "enum": ["verified", "not-verified"]
        },
        "methods": {
          "type": "array",
          "minItems": 1,
          "maxItems": 20,
          "uniqueItems": true,
          "items": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100,
            "pattern": "^[a-z][a-z0-9.-]*$"
          }
        }
      },
      "additionalProperties": false,
      "allOf": [
        {
          "if": {
            "properties": {
              "status": {
                "const": "verified"
              }
            },
            "required": ["status"]
          },
          "then": {
            "required": ["methods"]
          },
          "else": {
            "not": {
              "required": ["methods"]
            }
          }
        }
      ]
    },
    "amendment": {
      "type": "object",
      "required": ["targetID", "action", "reason"],
      "properties": {
        "targetID": {
          "type": "string",
          "minLength": 1,
          "maxLength": 255
        },
        "action": {
          "enum": ["replace", "retract"]
        },
        "reason": {
          "type": "string",
          "minLength": 1,
          "maxLength": 500,
          "pattern": "^[^\\r\\n]+$"
        }
      },
      "additionalProperties": false
    }
  }
}
Example task stream: darp-task.jsonl
{"specVersion":"1.0","id":"019cb409-79d2-7f31-9f52-7b1a63128b97","sequence":1,"occurredAt":"2026-08-28T14:33:39+02:00","recordedAt":"2026-08-28T14:33:39+02:00","kind":"task.started","project":{"id":"urn:uuid:eb0d9db1-82aa-4d44-8e45-a71452c0214c","name":"Factory Log"},"task":{"id":"task_6b8d9c1780e24ac5a76c88f52fb51d35","title":"Define developer activity protocol"},"source":{"tool":"codex","sessionID":"019cb408-76c9-7c2d-92f5-3c650e643b72"},"summary":"Started a portable RFC for durable developer activity."}
{"specVersion":"1.0","id":"019cb40b-b30e-72f2-8fb1-2c413b9f544a","sequence":2,"previousID":"019cb409-79d2-7f31-9f52-7b1a63128b97","occurredAt":"2026-08-28T15:12:00+02:00","recordedAt":"2026-08-28T15:12:03+02:00","kind":"task.progressed","project":{"id":"urn:uuid:eb0d9db1-82aa-4d44-8e45-a71452c0214c","name":"Factory Log"},"task":{"id":"task_6b8d9c1780e24ac5a76c88f52fb51d35","title":"Define developer activity protocol"},"source":{"tool":"codex","sessionID":"019cb408-76c9-7c2d-92f5-3c650e643b72"},"summary":"Defined the task lifecycle, activity measure, and privacy boundary.","outcome":{"category":"documentation","verification":{"status":"verified","methods":["manual-review"]}}}
{"specVersion":"1.0","id":"019cb40d-88ca-7bf3-965c-1c18fcd84d69","sequence":3,"previousID":"019cb40b-b30e-72f2-8fb1-2c413b9f544a","occurredAt":"2026-08-28T15:31:00+02:00","recordedAt":"2026-08-28T15:31:01+02:00","kind":"task.completed","project":{"id":"urn:uuid:eb0d9db1-82aa-4d44-8e45-a71452c0214c","name":"Factory Log"},"task":{"id":"task_6b8d9c1780e24ac5a76c88f52fb51d35","title":"Define developer activity protocol"},"source":{"tool":"codex","sessionID":"019cb408-76c9-7c2d-92f5-3c650e643b72"},"summary":"Published the RFC, schema, and example task stream.","outcome":{"category":"documentation","verification":{"status":"verified","methods":["schema-validation","manual-review"]}}}
Tagged: AI, Tools · All topics

Want me to talk about your product? You can sponsor this site.

~~~

Related posts about ai: