@ours.network/fleet 2.2.1 → 2.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,9 +1,9 @@
1
1
  {
2
- "version": "2.2.1",
3
- "buildId": "31d6e72bc212",
4
- "commit": "14d8f16953e773c6806d9df5661b8a4fe08af2b4",
2
+ "version": "2.2.2",
3
+ "buildId": "b0c5de2e0887",
4
+ "commit": "ebe447505d63119b299e3619d12a6399f1e2e49f",
5
5
  "dirty": false,
6
- "builtAt": "2026-10-29T07:06:09.148Z",
6
+ "builtAt": "2026-10-29T07:51:29.222Z",
7
7
  "capabilities": [
8
8
  "service.refresh-v1",
9
9
  "managed-cli.codex-reasoning-effort-v1",
@@ -11,6 +11,10 @@ export declare class TaskReviewError extends Error {
11
11
  export declare function reviewArtifactMime(name: string): string;
12
12
  export declare function checkArtifactName(name: string): string;
13
13
  export declare function listTaskProgress(taskId: string): TaskProgressEntry[];
14
+ /** Browser snapshot: entry bodies and their saved read state come from one task record. */
15
+ export declare function taskProgressSnapshot(taskId: string): Array<Omit<TaskProgressEntry, 'request_key'> & {
16
+ unread: boolean;
17
+ }>;
14
18
  /**
15
19
  * Append one milestone. Text is kept exactly as written; whitespace-only text is
16
20
  * rejected. A retry with the same author-scoped request_key returns the original
@@ -73,6 +73,16 @@ export function listTaskProgress(taskId) {
73
73
  assertTaskId(taskId);
74
74
  return getTask(taskId).progress ?? [];
75
75
  }
76
+ /** Browser snapshot: entry bodies and their saved read state come from one task record. */
77
+ export function taskProgressSnapshot(taskId) {
78
+ assertTaskId(taskId);
79
+ const task = getTask(taskId);
80
+ const reads = task.contribution_reads;
81
+ const seen = new Set(reads?.progress_read);
82
+ return (task.progress ?? []).map(entry => ({
83
+ ...publicProgressEntry(entry), unread: !!reads && !seen.has(entry.id),
84
+ }));
85
+ }
76
86
  /**
77
87
  * Append one milestone. Text is kept exactly as written; whitespace-only text is
78
88
  * rejected. A retry with the same author-scoped request_key returns the original
@@ -384,13 +384,15 @@ export class FleetResourceViews {
384
384
  // otherwise reserved for an independent task receipt.
385
385
  if (this.scope.configPath && resolve(path) === resolve(this.scope.configPath))
386
386
  return true;
387
- // Adopted Codex history, telemetry and cache commits are not canonical
388
- // Fleet preview inputs. Keep credentials, unknown paths and directory-level
389
- // events conservative, and never override explicit config or role roots.
387
+ // These projections read role config/private status and conversation ledgers,
388
+ // not adopted Codex telemetry or this gateway's auth/audit bookkeeping. Those
389
+ // writes otherwise invalidate every in-flight directory capture on a busy host.
390
+ // Keep explicit config, declared role roots and unknown/ancestor wakes fenced.
390
391
  const roots = this.scope.roots ?? [agentsRoot(), tmpRoot()];
391
- if (descriptor.resource === 'previews'
392
- && /^(?:history\.jsonl|models_cache\.json|(?:thread_history|state|logs|queue|goals)_\d+\.sqlite(?:-wal|-shm|-journal)?)$/.test(relative(resolve(homedir(), '.codex'), path))
393
- && !roots.some(root => { const local = relative(resolve(root), path); return local === '' || (local !== '..' && !local.startsWith('..' + sep)); }))
392
+ const roleProjection = ['directory', 'roles', 'previews'].includes(descriptor.resource);
393
+ const inRoleRoot = roots.some(root => { const local = relative(resolve(root), path); return local === '' || (local !== '..' && !local.startsWith('..' + sep)); });
394
+ if (roleProjection && !inRoleRoot && (/^(?:history\.jsonl|models_cache\.json|(?:thread_history|state|logs|queue|goals)_\d+\.sqlite(?:-wal|-shm|-journal)?)$/.test(relative(resolve(homedir(), '.codex'), path))
395
+ || /^(?:workspace-devices\.db(?:-wal|-shm|-journal)?|audit[/\\]audit\.jsonl)$/.test(relative(resolve(stateRoot(), 'web'), path))))
394
396
  return false;
395
397
  // Preview selection reads role config/state and conversation ledgers, never
396
398
  // task layout run/operation/brief receipts. A worker may commit several of
@@ -27,7 +27,7 @@ import { FleetEventBus } from './events.js';
27
27
  import { ROLE_NAME_RE } from '../config.js';
28
28
  import { TaskListError } from '../rooms-tasks/task-lists.js';
29
29
  import { acknowledgeTaskProgress, acknowledgeTaskReview, contributionUnread, TaskStateError } from '../rooms-tasks/task-state.js';
30
- import { appendTaskProgress, getTaskReview, listTaskProgress, publicProgressEntry, publicReview, readTaskReviewArtifact, setTaskReviewMarkdown, taskContributionSummary, TaskReviewError, } from '../rooms-tasks/task-review.js';
30
+ import { appendTaskProgress, getTaskReview, taskProgressSnapshot, publicProgressEntry, publicReview, readTaskReviewArtifact, setTaskReviewMarkdown, taskContributionSummary, TaskReviewError, } from '../rooms-tasks/task-review.js';
31
31
  import { isProvider } from '../subscriptions/store.js';
32
32
  const ONBOARDING_WORK = ['coordination', 'development', 'review'];
33
33
  const statusFor = (code) => ({
@@ -608,7 +608,7 @@ export async function buildWebServer(services, boundary, options = {}) {
608
608
  });
609
609
  app.get('/api/v1/tasks/:id/progress', async (request) => {
610
610
  auth.authenticate(request);
611
- return { progress: (await reviewApi(() => listTaskProgress(request.params.id))).map(publicProgressEntry) };
611
+ return { progress: await reviewApi(() => taskProgressSnapshot(request.params.id)) };
612
612
  });
613
613
  app.post('/api/v1/tasks/:id/progress', async (request, reply) => {
614
614
  auth.authenticate(request, true);
@@ -4,7 +4,10 @@ Every task can carry two optional sections next to its description. Tasks create
4
4
  before this feature, or that never use it, have neither and behave as before.
5
5
 
6
6
  - **Progress** is an append-only, chronological milestone log: free-form text
7
- entries, each with a stable ID, the time it was recorded and its author. It is
7
+ entries, each with a stable ID, the time it was recorded and its author. The
8
+ browser response also includes `unread` per entry from the same task snapshot,
9
+ based on persisted entry-ID acknowledgments. Legacy records without read state
10
+ report all existing entries as read; retry keys remain private. It is
8
11
  for significant verified milestones (root cause found, PR opened with its link,
9
12
  a measured result with its honest scope, final deliverable ready), not for room
10
13
  chat, routine status, handoffs or ordinary review rounds. Entries cannot be
@@ -99,7 +102,7 @@ workspace-device bearer. `GET /api/v1/meta` reports API minor version 1.
99
102
  | Route | Result |
100
103
  | --- | --- |
101
104
  | `GET /tasks`, `GET /tasks/:id` and other task payloads | `progress_count` and `review: {has_markdown, artifact_count, revision, updated_at?}`; `revision` grows with every package change (0 without a package). Bodies are not inlined. |
102
- | `GET /tasks/:id/progress` | `{progress: [{id, at, author, text}]}`, oldest first. |
105
+ | `GET /tasks/:id/progress` | `{progress: [{id, at, author, text, unread}]}`, oldest first. |
103
106
  | `POST /tasks/:id/progress` | `{text, requestKey?}` (or an `Idempotency-Key` header): 201 new, 200 replay, 409 conflicting replay. |
104
107
  | `GET /tasks/:id/review` | `{review: {markdown, updated_at, updated_by, artifacts: [{id, name, mime, size, sha256, added_at, added_by}]}}` or `{review: null}`. |
105
108
  | `PUT /tasks/:id/review` | `{markdown, expectedMarkdown}`; 409 when the Markdown changed meanwhile. |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ours.network/fleet",
3
- "version": "2.2.1",
3
+ "version": "2.2.2",
4
4
  "description": "Harness-agnostic fleet of persistent, identity-bound AI agents. Declarative fleet.yaml, managed native/ACP sessions, supervision, and ours.network messaging.",
5
5
  "type": "module",
6
6
  "license": "FSL-1.1-Apache-2.0",