@hasna/contracts 0.1.0 → 0.1.1

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.
package/README.md CHANGED
@@ -143,6 +143,7 @@ Common resource-kind mappings:
143
143
  | `open-todos` | `task`, `project`, `verification`, `proof_bundle` |
144
144
  | `open-loops` | `loop`, `workflow`, `run`, `artifact` |
145
145
  | `open-actions` | `action`, `tool`, `event`; decisions are emitted as `DecisionEnvelope` contracts, not resource kinds |
146
+ | `open-automations` | `action`, `tool`, `event`; deterministic recipe decisions are emitted as `DecisionEnvelope` contracts |
146
147
  | `open-sessions` | `session`, `run`, `machine`, `artifact` |
147
148
  | `open-context` | `context_pack`, `file`, `url`, `knowledge` |
148
149
  | `open-knowledge` / `open-mementos` | `knowledge`, `memento`, `context_pack` |
@@ -158,10 +159,17 @@ helpers. Owning packages still own storage and behavior.
158
159
 
159
160
  - `open-todos` owns tasks, task plans, locks, comments, and task evidence.
160
161
  - `open-loops` owns loop and workflow execution.
162
+ - `open-events` owns event envelopes, channels, delivery, replay, and
163
+ notification semantics.
161
164
  - `open-actions` owns executable action manifests.
165
+ - `open-automations` owns deterministic product/app automations and
166
+ connector/action recipes. It does not own agent workflow invocation,
167
+ admission queues, task/PR/review worker routing, or canonical workflow run
168
+ artifacts.
162
169
  - `open-sessions` owns transcript and trajectory ingestion.
163
170
  - `open-context` owns context-pack construction and retrieval.
164
- - `open-knowledge` owns durable knowledge records and promotion workflows.
171
+ - `open-knowledge` owns durable knowledge records and promotion workflows under
172
+ `.hasna/knowledge`.
165
173
  - `open-files` owns artifact storage, file indexing, and dereference logic.
166
174
  - `open-mementos` owns memory lifecycle and recall.
167
175
  - `open-reports` owns rendered reports and proof presentation.
@@ -179,10 +187,16 @@ native domain objects immediately.
179
187
  records, versions, signed URLs, source manifests, and evidence assets.
180
188
  - `open-todos`: expose task refs as `ResourceRef`; verification evidence as
181
189
  `ProofBundle`; task execution receipts as `WorkRun`; review gates as
182
- `ValidationPlan`.
190
+ `ValidationPlan`; and workflow/run manifest pointers as compact task fields,
191
+ not embedded handoff artifacts.
183
192
  - `open-loops`: emit loop/workflow runs as `WorkRun`, audit traces as
184
193
  `AgentTrajectory`, logs/artifacts as `EvidenceRef`, and verifier output as
185
- `ProofBundle`.
194
+ `ProofBundle`. OpenLoops owns `WorkflowInvocation`, admission/work-item
195
+ queues, leases, workflow runs, retries, cancellation, worktrees, and run
196
+ artifacts.
197
+ - `open-events`: emit and replay validated event envelopes to channels.
198
+ OpenEvents delivers notifications only; it does not create workflow
199
+ invocations, own queue state, or retry agent work.
186
200
  - `open-sessions`: convert messages/tool calls to `AgentTrajectory`, token
187
201
  usage to `CostEstimate`, and transcript paths to `EvidenceRef`.
188
202
  - `open-context`: serialize built context as `ContextPack` with citations as
@@ -202,10 +216,91 @@ native domain objects immediately.
202
216
  - `open-actions`: keep domain action manifests, but expose shared `ActorRef`,
203
217
  `EvidenceRef`, `CapabilityCard`, `DecisionEnvelope`, and `WorkRun` adapter
204
218
  views.
219
+ - `open-automations`: keep deterministic app/product automation recipes and
220
+ connector/action recipes. Any agentic task, PR, review, or evaluation flow
221
+ must hand off to OpenLoops rather than creating a second workflow queue.
205
222
  - `open-reports`: consume `ProofBundle`, `WorkRun`, `ContextPack`,
206
223
  `CostEstimate`, and `EvidenceRef` to render compact Markdown/JSON/HTML proof
207
224
  reports.
208
225
 
226
+ ## WorkflowInvocation And App Storage Boundary
227
+
228
+ The canonical agent-work root is a `WorkflowInvocation`, not a todo task.
229
+ Only actionable unfinished work needs a todo. OpenTodos remains the
230
+ human-visible intent ledger; OpenLoops owns the durable workflow root,
231
+ admission queue, execution lifecycle, and canonical run artifacts.
232
+
233
+ A workflow invocation should carry these fields at the boundary:
234
+
235
+ - `id`
236
+ - `templateId` or `workflowId`
237
+ - `sourceRef`: a WorkflowInvocation-local source kind such as `task`, `event`,
238
+ `schedule`, `manual`, `pull_request`, `review`, or `knowledge`, plus an id
239
+ and dedupe key
240
+ - `subjectRef`: a WorkflowInvocation-local subject kind such as `repo`,
241
+ `pull_request`, `task`, `document`, `run`, or `metric`, plus a path, URL, or
242
+ id
243
+ - `intent`: `route`, `mutate`, `review`, `evaluate`, or `report`
244
+ - `scope`: project path, worktree policy, permissions, account policy, and
245
+ concurrency group
246
+ - `outputPolicy`: when to write reports and when to create a follow-up task
247
+
248
+ OpenLoops admission/work items are first-class records with route key,
249
+ idempotency key, source/subject refs, project key/group, priority, status,
250
+ attempts, next-attempt time, lease expiry, loop/workflow/run ids, and last
251
+ reason. Status values should be explicit: `queued`, `deferred`, `admitted`,
252
+ `running`, `succeeded`, `failed`, `dead_letter`, or `cancelled`.
253
+
254
+ Run artifacts live under:
255
+
256
+ ```text
257
+ .hasna/loops/runs/<project-slug>/<subject-key>/<run-id>/manifest.json
258
+ .hasna/loops/runs/<project-slug>/<subject-key>/<run-id>/triage.md
259
+ .hasna/loops/runs/<project-slug>/<subject-key>/<run-id>/plan.md
260
+ .hasna/loops/runs/<project-slug>/<subject-key>/<run-id>/worker-report.md
261
+ .hasna/loops/runs/<project-slug>/<subject-key>/<run-id>/evaluation.md
262
+ .hasna/loops/runs/<project-slug>/<subject-key>/<run-id>/evidence/
263
+ ```
264
+
265
+ The `<subject-key>` is never the raw subject reference. It must be a safe path
266
+ segment derived as `kind-safeSlug-shortHash`. Recommended normalization:
267
+ lowercase ASCII, replace non-alphanumeric runs with `-`, trim separators, cap
268
+ the slug portion at 72 characters, and append at least 12 hex characters from a
269
+ SHA-256 hash of the canonical raw `subjectRef`. Reject `.`/`..`, reserved device
270
+ names, path separators, empty keys, and path traversal. Store the raw
271
+ `subjectRef` only inside `manifest.json`.
272
+
273
+ OpenEvents webhooks/channels are notifications. A `task.created` notification
274
+ can be delivered through OpenEvents, but OpenLoops consumes the envelope and
275
+ upserts/admits work items. OpenEvents must not import OpenLoops or own
276
+ admission, retries, leases, verifier execution, or workflow run artifacts.
277
+
278
+ Every Hasna app stores local state under `.hasna/<app>/...`. The obsolete
279
+ `.hasna/apps/<app>` layout is not an operational read path. OpenKnowledge's
280
+ canonical storage is `.hasna/knowledge`, not `.hasna/apps/knowledge`.
281
+
282
+ No-backcompat migrations must preserve data without keeping legacy shims:
283
+
284
+ 1. Create a read-only backup or export before moving data.
285
+ 2. Atomically copy or rename into the canonical `.hasna/<app>` path.
286
+ 3. Verify JSON item counts, SQLite integrity and table counts, artifact counts,
287
+ hashes, and any storage-object or sync-snapshot evidence.
288
+ 4. Leave only a diagnostic tombstone at the old path.
289
+ 5. Treat mismatched counts, hash failures, or SQLite integrity failures as
290
+ blockers.
291
+
292
+ Unattended automatic routes must fail closed when the configured sandbox cannot
293
+ be proven. Acceptable sandbox evidence includes a successful preflight receipt
294
+ that names the isolation provider, filesystem/network policy, writable roots,
295
+ tool allowlist, environment redaction result, and timestamp for the exact route
296
+ or run. `danger-full-access` plus a worktree is a manual break-glass mode, not a
297
+ safe auto-route default.
298
+
299
+ `WorkflowInvocation` is documented here as the architecture boundary used by
300
+ OpenLoops and neighboring packages. It is not yet a wire schema in the current
301
+ catalog; add a `hasna.workflow_invocation.v1` schema only when at least two
302
+ packages need to validate the object directly at a shared boundary.
303
+
209
304
  ## Enforcement Model
210
305
 
211
306
  Validate at every boundary where another package, agent, process, or machine can
package/dist/cli/index.js CHANGED
@@ -992,7 +992,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
992
992
  this._exitCallback = (err) => {
993
993
  if (err.code !== "commander.executeSubCommandAsync") {
994
994
  throw err;
995
- }
995
+ } else {}
996
996
  };
997
997
  }
998
998
  return this;
@@ -6074,7 +6074,7 @@ var coerce = {
6074
6074
  };
6075
6075
  var NEVER = INVALID;
6076
6076
  // src/schemas.ts
6077
- var CONTRACTS_PACKAGE_VERSION = "0.1.0";
6077
+ var CONTRACTS_PACKAGE_VERSION = "0.1.1";
6078
6078
  var SCHEMA_IDS = {
6079
6079
  actorRef: "hasna.actor_ref.v1",
6080
6080
  resourceRef: "hasna.resource_ref.v1",
package/dist/index.js CHANGED
@@ -3989,7 +3989,7 @@ var coerce = {
3989
3989
  var NEVER = INVALID;
3990
3990
  // src/schemas.ts
3991
3991
  var CONTRACTS_PACKAGE_NAME = "@hasna/contracts";
3992
- var CONTRACTS_PACKAGE_VERSION = "0.1.0";
3992
+ var CONTRACTS_PACKAGE_VERSION = "0.1.1";
3993
3993
  var SCHEMA_IDS = {
3994
3994
  actorRef: "hasna.actor_ref.v1",
3995
3995
  resourceRef: "hasna.resource_ref.v1",
package/dist/schemas.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { z } from "zod";
2
2
  export declare const CONTRACTS_PACKAGE_NAME = "@hasna/contracts";
3
- export declare const CONTRACTS_PACKAGE_VERSION = "0.1.0";
3
+ export declare const CONTRACTS_PACKAGE_VERSION = "0.1.1";
4
4
  export declare const SCHEMA_IDS: {
5
5
  readonly actorRef: "hasna.actor_ref.v1";
6
6
  readonly resourceRef: "hasna.resource_ref.v1";
package/dist/schemas.js CHANGED
@@ -3989,7 +3989,7 @@ var coerce = {
3989
3989
  var NEVER = INVALID;
3990
3990
  // src/schemas.ts
3991
3991
  var CONTRACTS_PACKAGE_NAME = "@hasna/contracts";
3992
- var CONTRACTS_PACKAGE_VERSION = "0.1.0";
3992
+ var CONTRACTS_PACKAGE_VERSION = "0.1.1";
3993
3993
  var SCHEMA_IDS = {
3994
3994
  actorRef: "hasna.actor_ref.v1",
3995
3995
  resourceRef: "hasna.resource_ref.v1",
@@ -3989,7 +3989,7 @@ var coerce = {
3989
3989
  var NEVER = INVALID;
3990
3990
  // src/schemas.ts
3991
3991
  var CONTRACTS_PACKAGE_NAME = "@hasna/contracts";
3992
- var CONTRACTS_PACKAGE_VERSION = "0.1.0";
3992
+ var CONTRACTS_PACKAGE_VERSION = "0.1.1";
3993
3993
  var SCHEMA_IDS = {
3994
3994
  actorRef: "hasna.actor_ref.v1",
3995
3995
  resourceRef: "hasna.resource_ref.v1",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hasna/contracts",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Shared schemas and validators for Hasna open-source agent infrastructure contracts.",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -47,7 +47,7 @@
47
47
  "lint": "tsc --noEmit",
48
48
  "verify:release": "bun run typecheck && bun test && bun run build && bun run smoke:dist && bun run pack:check",
49
49
  "smoke:dist": "bun scripts/smoke-dist.ts",
50
- "pack:check": "npm pack --dry-run --json --ignore-scripts",
50
+ "pack:check": "bun pm pack --dry-run --ignore-scripts",
51
51
  "dev:cli": "bun run src/cli/index.ts",
52
52
  "prepack": "bun run verify:release",
53
53
  "prepublishOnly": "bun run typecheck && bun test"