@etiquekit/etq 1.0.13 → 1.0.15

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.
Files changed (143) hide show
  1. package/AGENTS.md +26 -19
  2. package/LICENSE +3 -2
  3. package/NOTICE +4 -6
  4. package/QuickStart.md +46 -35
  5. package/README.md +57 -55
  6. package/bin/etiquette +5 -1
  7. package/bin/etiquette-core +5 -1
  8. package/docs/ARCHITECTURE.md +17 -20
  9. package/docs/CONCEPTS.md +5 -5
  10. package/docs/CORE_PROFILE.md +15 -7
  11. package/docs/LANE_PROVISIONING.md +2 -7
  12. package/docs/README.md +14 -13
  13. package/docs/RELEASE_SURFACE_AUDIT.md +6 -7
  14. package/docs/SEAT_DISCIPLINE.md +91 -55
  15. package/docs/SEAT_PROVISIONING.md +19 -16
  16. package/docs/TEAM_HANDOFF.md +21 -21
  17. package/docs/WORKTREE_QOL.md +0 -7
  18. package/docs/contracts/ledger-entry/README.md +11 -11
  19. package/docs/contracts/ledger-entry/ledger-entry.v0.2.md +2 -2
  20. package/docs/contracts/ledger-entry/ledger-entry.v0.md +8 -8
  21. package/lib/etiquette-core.js +313 -0
  22. package/lib/etiquette.js +1151 -0
  23. package/package.json +13 -12
  24. package/templates/etiquette-vanilla-v0/README.md +3 -2
  25. package/templates/etiquette-vanilla-v0/source/control-seat/README.md +6 -0
  26. package/templates/etiquette-vanilla-v0/source/control-seat/bin/access-assurance-check +55 -0
  27. package/templates/etiquette-vanilla-v0/source/control-seat/bin/seat-doctor +5 -0
  28. package/templates/etiquette-vanilla-v0/source/control-seat/docs/work/access/ACCESS-ASSURANCE.md +39 -0
  29. package/templates/etiquette-vanilla-v0/source/control-seat/docs/work/access/workspace-secure-profile.v0.json +53 -0
  30. package/templates/etiquette-vanilla-v0/validate-vanilla.sh +5 -0
  31. package/templates/hosted-receiver/README.md +41 -0
  32. package/templates/hosted-receiver/w1-github-webhook-receiver.mjs +129 -0
  33. package/templates/seat-packs-v0/README.md +2 -3
  34. package/templates/seat-packs-v0/source/claude-code-seat/README.md +3 -3
  35. package/templates/seat-packs-v0/source/codex-seat/README.md +3 -3
  36. package/templates/seat-packs-v0/source/gemini-seat/README.md +3 -3
  37. package/templates/seat-packs-v0/source/ollama-seat/README.md +3 -3
  38. package/templates/seat-packs-v0/source/openrouter-seat/README.md +3 -3
  39. package/docs/CONCEPT_STATUS.md +0 -66
  40. package/packages/control/src/authority/lease.ts +0 -261
  41. package/packages/control/src/authority/node-delegation.ts +0 -257
  42. package/packages/control/src/authority/rig-conductor.ts +0 -632
  43. package/packages/control/src/cli/argv.ts +0 -155
  44. package/packages/control/src/cli/commands/console.ts +0 -200
  45. package/packages/control/src/cli/commands/dispatch-core.ts +0 -89
  46. package/packages/control/src/cli/commands/dispatch.ts +0 -279
  47. package/packages/control/src/cli/commands/harness.ts +0 -89
  48. package/packages/control/src/cli/commands/hook.ts +0 -50
  49. package/packages/control/src/cli/commands/ledger.ts +0 -91
  50. package/packages/control/src/cli/commands/local-workflow.ts +0 -4686
  51. package/packages/control/src/cli/commands/memory.ts +0 -445
  52. package/packages/control/src/cli/commands/release.ts +0 -108
  53. package/packages/control/src/cli/commands/rubric.ts +0 -103
  54. package/packages/control/src/cli/commands/seat.ts +0 -179
  55. package/packages/control/src/cli/commands/session.ts +0 -127
  56. package/packages/control/src/cli/commands/supervision.ts +0 -246
  57. package/packages/control/src/cli/commands/sync.ts +0 -119
  58. package/packages/control/src/cli/commands/workflow.ts +0 -86
  59. package/packages/control/src/cli/commands/workspace.ts +0 -50
  60. package/packages/control/src/cli/core-usage.ts +0 -34
  61. package/packages/control/src/cli/prompt.ts +0 -67
  62. package/packages/control/src/cli/supervision-deps.ts +0 -44
  63. package/packages/control/src/cli/usage.ts +0 -241
  64. package/packages/control/src/cli.ts +0 -207
  65. package/packages/control/src/core-cli.ts +0 -50
  66. package/packages/control/src/dispatch/decision.ts +0 -202
  67. package/packages/control/src/dispatch/projection.ts +0 -293
  68. package/packages/control/src/dispatch/record.ts +0 -153
  69. package/packages/control/src/engagement/project.ts +0 -170
  70. package/packages/control/src/fs.ts +0 -19
  71. package/packages/control/src/harness/pruning.ts +0 -406
  72. package/packages/control/src/hooks/dispatcher.ts +0 -117
  73. package/packages/control/src/hooks/outbox.ts +0 -86
  74. package/packages/control/src/hooks/sanitize.ts +0 -6
  75. package/packages/control/src/hooks/types.ts +0 -34
  76. package/packages/control/src/index.ts +0 -384
  77. package/packages/control/src/ledger/entry.ts +0 -303
  78. package/packages/control/src/ledger/indexer.ts +0 -542
  79. package/packages/control/src/memory/context.ts +0 -149
  80. package/packages/control/src/memory/drain-import.ts +0 -207
  81. package/packages/control/src/memory/indexer.ts +0 -284
  82. package/packages/control/src/memory/query.ts +0 -75
  83. package/packages/control/src/memory/sanitize.ts +0 -50
  84. package/packages/control/src/memory/sharded-drain-import.ts +0 -212
  85. package/packages/control/src/memory/status.ts +0 -211
  86. package/packages/control/src/memory/store-lifecycle.ts +0 -509
  87. package/packages/control/src/memory/store.ts +0 -284
  88. package/packages/control/src/memory/types.ts +0 -146
  89. package/packages/control/src/parity/surfaces.ts +0 -748
  90. package/packages/control/src/project.ts +0 -141
  91. package/packages/control/src/projection/local-ledger-view.ts +0 -373
  92. package/packages/control/src/projection/return-enforcement.ts +0 -48
  93. package/packages/control/src/projection/timeline-preview.ts +0 -539
  94. package/packages/control/src/projection/timeline.ts +0 -708
  95. package/packages/control/src/release/readiness.ts +0 -831
  96. package/packages/control/src/rubric/loader.ts +0 -326
  97. package/packages/control/src/rubric/promotion.ts +0 -54
  98. package/packages/control/src/rubric/runner.ts +0 -159
  99. package/packages/control/src/rubric/types.ts +0 -158
  100. package/packages/control/src/seat/owner-card.ts +0 -388
  101. package/packages/control/src/seat/readiness.ts +0 -834
  102. package/packages/control/src/session/runbook.ts +0 -431
  103. package/packages/control/src/shared/sanitize.ts +0 -49
  104. package/packages/control/src/supervision/action-classes.ts +0 -192
  105. package/packages/control/src/supervision/command-apply.ts +0 -378
  106. package/packages/control/src/supervision/errors.ts +0 -14
  107. package/packages/control/src/supervision/event-replay.ts +0 -155
  108. package/packages/control/src/supervision/events.ts +0 -109
  109. package/packages/control/src/supervision/index.ts +0 -16
  110. package/packages/control/src/supervision/manifest.ts +0 -127
  111. package/packages/control/src/supervision/paths.ts +0 -49
  112. package/packages/control/src/supervision/projection-adapter.ts +0 -274
  113. package/packages/control/src/supervision/projection.ts +0 -75
  114. package/packages/control/src/supervision/rebuild.ts +0 -99
  115. package/packages/control/src/supervision/session-open.ts +0 -131
  116. package/packages/control/src/supervision/session-read.ts +0 -99
  117. package/packages/control/src/supervision/sqlite-impl.ts +0 -71
  118. package/packages/control/src/supervision/sqlite.ts +0 -121
  119. package/packages/control/src/supervision/store-rows.ts +0 -371
  120. package/packages/control/src/supervision/turn-close.ts +0 -154
  121. package/packages/control/src/supervision/turn-open.ts +0 -284
  122. package/packages/control/src/sync/event-log-merge-driver.ts +0 -263
  123. package/packages/control/src/sync/join-plan.ts +0 -375
  124. package/packages/control/src/sync/outbox.ts +0 -492
  125. package/packages/control/src/workflow/evaluator.ts +0 -140
  126. package/packages/control/src/workflow/loader.ts +0 -200
  127. package/packages/control/src/workflow/types.ts +0 -90
  128. package/packages/control/src/workspace/authority.ts +0 -499
  129. package/packages/protocol/src/guards.ts +0 -119
  130. package/packages/protocol/src/huddle-board.ts +0 -198
  131. package/packages/protocol/src/huddle.ts +0 -295
  132. package/packages/protocol/src/incident.ts +0 -251
  133. package/packages/protocol/src/index.ts +0 -8
  134. package/packages/protocol/src/interfaces.ts +0 -107
  135. package/packages/protocol/src/packet-profile.ts +0 -195
  136. package/packages/protocol/src/state.ts +0 -81
  137. package/packages/protocol/src/types.ts +0 -434
  138. package/release/lineage.v0.json +0 -14
  139. package/scripts/release-candidate-verify.sh +0 -175
  140. package/scripts/release-checksum.sh +0 -25
  141. package/scripts/release-pack-canary.sh +0 -97
  142. package/scripts/release-scan.sh +0 -249
  143. package/scripts/release-sign.sh +0 -34
package/package.json CHANGED
@@ -1,7 +1,8 @@
1
1
  {
2
2
  "name": "@etiquekit/etq",
3
- "version": "1.0.13",
4
- "description": "Governance and evidence CLI for AI-assisted engineering seats.",
3
+ "version": "1.0.15",
4
+ "license": "Apache-2.0",
5
+ "description": "Thin local execution plane for Etiquette Core governance contracts.",
5
6
  "private": false,
6
7
  "type": "module",
7
8
  "bin": {
@@ -15,16 +16,15 @@
15
16
  },
16
17
  "files": [
17
18
  "LICENSE",
18
- "AGENTS.md",
19
19
  "NOTICE",
20
+ "AGENTS.md",
20
21
  "QuickStart.md",
21
22
  "README.md",
22
23
  "bin/",
24
+ "lib/",
23
25
  "docs/",
24
- "packages/control/src/",
25
- "packages/protocol/src/",
26
- "release/lineage.v0.json",
27
- "scripts/",
26
+ "scripts/install.sh",
27
+ "scripts/uninstall.sh",
28
28
  "templates/",
29
29
  "!docs/work/"
30
30
  ],
@@ -35,25 +35,26 @@
35
35
  "core:cli": "bun packages/control/src/core-cli.ts",
36
36
  "release:scan": "sh scripts/release-scan.sh",
37
37
  "release:pack": "sh scripts/release-pack-canary.sh",
38
- "release:candidate": "sh scripts/release-candidate-verify.sh",
39
38
  "release:checksum": "sh scripts/release-checksum.sh",
40
- "release:sign": "sh scripts/release-sign.sh"
39
+ "release:sign": "sh scripts/release-sign.sh",
40
+ "release:build": "sh scripts/release-build.sh",
41
+ "prepack": "sh scripts/release-build.sh"
41
42
  },
42
43
  "devDependencies": {
43
44
  "@types/bun": "^1.2.17",
44
45
  "typescript": "^5.7.3"
45
46
  },
46
47
  "dependencies": {
48
+ "@etiquekit/core": "0.1.0",
47
49
  "yaml": "2.8.3",
48
50
  "zod": "4.3.6"
49
51
  },
50
- "license": "Apache-2.0",
51
52
  "homepage": "https://etiquekit.com",
52
53
  "repository": {
53
54
  "type": "git",
54
- "url": "git+https://github.com/leepickdev/etq-devkit.git"
55
+ "url": "git+https://github.com/leepickdev/etq.git"
55
56
  },
56
57
  "bugs": {
57
- "url": "https://github.com/leepickdev/etq-devkit/issues"
58
+ "url": "https://github.com/leepickdev/etq/issues"
58
59
  }
59
60
  }
@@ -11,7 +11,7 @@ default_surface:
11
11
  ```
12
12
 
13
13
  It does not create runtime seats, product repos, backplanes, hosted services, dashboards, or sample products.
14
- It starts local and unauthenticated. Seat identity, readiness, and task authority stay in the local workflow records.
14
+ It starts unauthenticated: `workspace-secure-profile.v0` is `open`, with upgrade paths for `screening-warn`, `screening-enforced`, and `enterprise-reactor`.
15
15
 
16
16
  ## Quick Start
17
17
 
@@ -23,6 +23,7 @@ sh /tmp/etiquette-start/validate-vanilla.sh
23
23
  ```
24
24
 
25
25
  The first person who claims the stamped `control-seat` reports readiness before assigning work.
26
+ For restricted seats, change the secure profile, add provider-derived policy/claims, then run `sh source/control-seat/bin/access-assurance-check`.
26
27
 
27
28
  ## Local Receipt Proof
28
29
 
@@ -54,7 +55,7 @@ cannot:
54
55
  - clone product repos before assignment
55
56
  - bypass validation
56
57
  - treat chat as evidence
57
- - grant authority from local profile metadata
58
+ - grant access from the secure profile or reactor
58
59
  ```
59
60
 
60
61
  Provision these later only after the control seat grants them:
@@ -8,3 +8,9 @@ For local-only proof, append events with `bin/local-event` and compact them with
8
8
 
9
9
  Inside a live runtime session, run `bin/session-init` after `bin/seat-init`
10
10
  to prepare the local ledger, receipts, tasks, outbox, and session state.
11
+
12
+ Access assurance is explicit and optional. The default profile is
13
+ `docs/work/access/workspace-secure-profile.v0.json` with `mode: open`. Run
14
+ `bin/access-assurance-check` before routing restricted seats, and switch to
15
+ `screening-warn`, `screening-enforced`, or `enterprise-reactor` only when the
16
+ workspace actually needs provider-backed screening.
@@ -0,0 +1,55 @@
1
+ #!/bin/sh
2
+ set -eu
3
+
4
+ ROOT=$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd)
5
+ PROFILE="$ROOT/docs/work/access/workspace-secure-profile.v0.json"
6
+ POLICY="$ROOT/docs/work/access/seat-access-policy.v0.json"
7
+ CLAIMS="$ROOT/docs/work/access/access-assurance-claims.v0.json"
8
+
9
+ json_string_field() {
10
+ sed -n "s/.*\"$2\"[[:space:]]*:[[:space:]]*\"\\([^\"]*\\)\".*/\\1/p" "$1" | head -n 1
11
+ }
12
+
13
+ json_bool_field() {
14
+ sed -n "s/.*\"$2\"[[:space:]]*:[[:space:]]*\\(true\\|false\\).*/\\1/p" "$1" | head -n 1
15
+ }
16
+
17
+ if [ ! -f "$PROFILE" ]; then
18
+ echo "access-assurance: fail missing docs/work/access/workspace-secure-profile.v0.json" >&2
19
+ exit 1
20
+ fi
21
+
22
+ mode=$(json_string_field "$PROFILE" mode)
23
+ case "$mode" in
24
+ open|screening-warn|screening-enforced|enterprise-reactor) ;;
25
+ *)
26
+ echo "access-assurance: fail invalid mode=${mode:-missing}" >&2
27
+ exit 1
28
+ ;;
29
+ esac
30
+
31
+ if [ "$mode" = "open" ]; then
32
+ echo "access-assurance: pass mode=open policy=not-required"
33
+ exit 0
34
+ fi
35
+
36
+ if [ ! -f "$POLICY" ] || [ ! -f "$CLAIMS" ]; then
37
+ message="access-assurance: missing policy or claims for mode=$mode"
38
+ if [ "$mode" = "screening-warn" ]; then
39
+ echo "$message"
40
+ exit 0
41
+ fi
42
+ echo "$message" >&2
43
+ exit 1
44
+ fi
45
+
46
+ if [ "$mode" = "enterprise-reactor" ]; then
47
+ tighten_only=$(json_bool_field "$PROFILE" tighten_only)
48
+ reactor_can_grant=$(json_bool_field "$PROFILE" reactor_can_grant_or_loosen_access)
49
+ if [ "$tighten_only" != "true" ] || [ "$reactor_can_grant" != "false" ]; then
50
+ echo "access-assurance: fail enterprise-reactor requires tighten_only=true and reactor_can_grant_or_loosen_access=false" >&2
51
+ exit 1
52
+ fi
53
+ fi
54
+
55
+ echo "access-assurance: pass mode=$mode"
@@ -5,11 +5,16 @@ ROOT=$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd)
5
5
 
6
6
  test -f "$ROOT/.llm-substrate/HANDOFF.md"
7
7
  test -f "$ROOT/docs/work/ledger/LEDGER.md"
8
+ test -f "$ROOT/docs/work/access/workspace-secure-profile.v0.json"
9
+ test -f "$ROOT/docs/work/access/ACCESS-ASSURANCE.md"
8
10
  test -f "$ROOT/docs/work/playbacks/PLAYBACK_TEMPLATE.md"
9
11
  test -f "$ROOT/docs/work/tasks/CONTROL-001.yaml"
10
12
  test -d "$ROOT/docs/work/receipts"
13
+ test -f "$ROOT/bin/access-assurance-check"
11
14
  test -f "$ROOT/bin/session-init"
12
15
  test -f "$ROOT/bin/local-event"
13
16
  test -f "$ROOT/bin/compact-local-events"
14
17
 
18
+ sh "$ROOT/bin/access-assurance-check" >/dev/null
19
+
15
20
  echo "control-seat: ok"
@@ -0,0 +1,39 @@
1
+ # Access Assurance
2
+
3
+ The vanilla control seat starts in `open` mode. That keeps Etiquette usable as a
4
+ local-first workflow kit without authentication, screening, hosted services, or
5
+ a daemon.
6
+
7
+ The workspace mode lives in `workspace-secure-profile.v0.json`.
8
+
9
+ Modes:
10
+
11
+ - `open`: no access-assurance gate is required.
12
+ - `screening-warn`: restricted-seat policy and claims are checked, but failures
13
+ warn instead of blocking.
14
+ - `screening-enforced`: restricted seats fail closed when policy or claims are
15
+ missing, expired, revoked, or not provider-backed.
16
+ - `enterprise-reactor`: `screening-enforced` plus an optional tighten-only
17
+ daemon for revocation sync, badge refresh, kill-switch writes, and outbox
18
+ drain.
19
+
20
+ The reactor may tighten access only. It must not grant access, authorize
21
+ actions, close work, merge, or rewrite the ledger.
22
+
23
+ Provider-backed secure deployments should keep raw identity material outside the
24
+ repo:
25
+
26
+ ```text
27
+ Persona / Scandit / SSO -> Supabase derived claims -> local access check
28
+ ```
29
+
30
+ Repo-safe fields are provider refs, status, policy eligibility class, evidence
31
+ hash, expiry, and audit timestamps. Passport images, document photos, full
32
+ document numbers, ethnicity, provider secrets, and raw webhook payloads do not
33
+ belong in Git.
34
+
35
+ Check the mode:
36
+
37
+ ```sh
38
+ sh bin/access-assurance-check
39
+ ```
@@ -0,0 +1,53 @@
1
+ {
2
+ "schema": "workspace-secure-profile.v0",
3
+ "workspace_id": "vanilla-control-seat",
4
+ "mode": "open",
5
+ "allowed_modes": [
6
+ "open",
7
+ "screening-warn",
8
+ "screening-enforced",
9
+ "enterprise-reactor"
10
+ ],
11
+ "mode_meanings": {
12
+ "open": "No access-assurance gate is required. Etiquette core remains local and unauthenticated.",
13
+ "screening-warn": "Restricted-seat claims are checked and reported, but missing or failed claims do not block local entry.",
14
+ "screening-enforced": "Restricted-seat claims are required before routing or entering restricted seats.",
15
+ "enterprise-reactor": "screening-enforced plus an optional tighten-only reactor for revocation sync, badge refresh, kill-switch writes, and outbox drain."
16
+ },
17
+ "identity_model": {
18
+ "authenticate": "operator_principals",
19
+ "assign_to": "seat_ids",
20
+ "authorize": "per_action_grants",
21
+ "workspace_role": "policy_scope",
22
+ "linear_role": "external_backlog_projection_only"
23
+ },
24
+ "claim_source": {
25
+ "kind": "none-required-for-open-mode",
26
+ "live_replacement": "Supabase Auth plus derived Persona and Scandit claim export",
27
+ "raw_pii_allowed_in_repo": false
28
+ },
29
+ "reactor": {
30
+ "required_for_mode": "enterprise-reactor",
31
+ "default_enabled": false,
32
+ "tighten_only": true,
33
+ "may_write": [
34
+ "kill_switch_entries",
35
+ "expired_assurance_markers",
36
+ "badge_refresh_cache",
37
+ "sync_outbox"
38
+ ],
39
+ "must_not": [
40
+ "grant_access",
41
+ "close_work",
42
+ "merge",
43
+ "rewrite_ledger",
44
+ "authorize_actions"
45
+ ]
46
+ },
47
+ "authority_boundary": {
48
+ "profile_can_authorize_work": false,
49
+ "profile_can_grant_seat": false,
50
+ "profile_can_merge_or_close": false,
51
+ "reactor_can_grant_or_loosen_access": false
52
+ }
53
+ }
@@ -7,17 +7,22 @@ test -f "$ROOT/README.md"
7
7
  test -d "$ROOT/source/etiquette-kernel"
8
8
  test -d "$ROOT/source/control-seat"
9
9
  grep -Fq ".etiquette/events/*.ndjson" "$ROOT/source/control-seat/.gitignore"
10
+ grep -q '"schema": "workspace-secure-profile.v0"' "$ROOT/source/control-seat/docs/work/access/workspace-secure-profile.v0.json"
11
+ grep -q '"mode": "open"' "$ROOT/source/control-seat/docs/work/access/workspace-secure-profile.v0.json"
12
+ grep -q "enterprise-reactor" "$ROOT/source/control-seat/docs/work/access/ACCESS-ASSURANCE.md"
10
13
  grep -q "Controlled drills require one operator approval per drill" "$ROOT/source/etiquette-kernel/contracts/playback.v0.md"
11
14
  grep -q "batch_approval_allowed: false" "$ROOT/source/control-seat/docs/work/playbacks/PLAYBACK_TEMPLATE.md"
12
15
 
13
16
  sh "$ROOT/source/etiquette-kernel/bin/kernel-doctor"
14
17
  sh "$ROOT/source/control-seat/bin/seat-doctor"
18
+ sh "$ROOT/source/control-seat/bin/access-assurance-check" | grep -q "mode=open"
15
19
 
16
20
  tmp_root=$(mktemp -d "${TMPDIR:-/tmp}/etiquette-vanilla-compact.XXXXXX")
17
21
  trap 'rm -rf "$tmp_root"' EXIT
18
22
 
19
23
  cp -R "$ROOT/source/control-seat/." "$tmp_root/control-seat/"
20
24
  sh "$tmp_root/control-seat/bin/seat-init" --execution-seat control-seat >/dev/null
25
+ sh "$tmp_root/control-seat/bin/access-assurance-check" | grep -q "mode=open"
21
26
  sh "$tmp_root/control-seat/bin/session-init" --task-id SESSION-INIT --operator local-operator >/tmp/session-init.out
22
27
  test -f "$tmp_root/control-seat/.etiquette/state/session.json"
23
28
  grep -q "session_opened" "$tmp_root/control-seat/docs/work/ledger/LEDGER.md"
@@ -0,0 +1,41 @@
1
+ # Hosted Receiver Templates
2
+
3
+ Opt-in templates for teams that want to expose Etiquette's W1 GitHub webhook
4
+ receiver behind their own hosting layer.
5
+
6
+ ## W1 GitHub Receiver
7
+
8
+ `w1-github-webhook-receiver.mjs` is a small Node HTTP server:
9
+
10
+ - `GET /health` returns a readiness probe.
11
+ - `POST /github` accepts GitHub `ping` and `push` webhook deliveries.
12
+ - `ping` returns `200` only after the delivery is signature-verified.
13
+ - `push` delegates to `etiquette notify webhook github`.
14
+ - raw payloads are written only to a temporary file for the CLI call, then
15
+ removed.
16
+ - emitted records stay pointer-only and authority-false.
17
+
18
+ Run it with:
19
+
20
+ ```sh
21
+ export ETIQUETTE_GITHUB_WEBHOOK_SECRET='<webhook-secret>'
22
+ export ETIQUETTE_CLI='etiquette'
23
+ node w1-github-webhook-receiver.mjs
24
+ ```
25
+
26
+ Optional:
27
+
28
+ ```sh
29
+ export PORT=8080
30
+ export ETIQUETTE_WAKE_OUT_DIR=/var/lib/etiquette/wake
31
+ ```
32
+
33
+ `ETIQUETTE_WAKE_OUT_DIR` stores only the verified pointer output, never the raw
34
+ webhook body.
35
+
36
+ ## Boundary
37
+
38
+ This template does not create a public endpoint, register repository webhooks,
39
+ provision cloud infrastructure, start remote execution, or grant authority. Host
40
+ selection, webhook registration, secret rotation, and retention policy remain
41
+ operator decisions.
@@ -0,0 +1,129 @@
1
+ #!/usr/bin/env node
2
+ import { createServer } from 'node:http';
3
+ import { randomUUID } from 'node:crypto';
4
+ import { mkdirSync, rmSync, writeFileSync } from 'node:fs';
5
+ import { tmpdir } from 'node:os';
6
+ import { join } from 'node:path';
7
+ import { spawnSync } from 'node:child_process';
8
+
9
+ const port = Number(process.env.PORT || '8080');
10
+ const etiquetteCli = process.env.ETIQUETTE_CLI || 'etiquette';
11
+ const secret = process.env.ETIQUETTE_GITHUB_WEBHOOK_SECRET;
12
+ const outDir = process.env.ETIQUETTE_WAKE_OUT_DIR || '';
13
+
14
+ if (!secret) throw new Error('ETIQUETTE_GITHUB_WEBHOOK_SECRET is required');
15
+
16
+ function readRaw(req) {
17
+ return new Promise((resolve, reject) => {
18
+ const chunks = [];
19
+ req.on('data', (chunk) => chunks.push(chunk));
20
+ req.on('end', () => resolve(Buffer.concat(chunks)));
21
+ req.on('error', reject);
22
+ });
23
+ }
24
+
25
+ function writeJson(res, status, value) {
26
+ res.writeHead(status, {
27
+ 'content-type': 'application/json',
28
+ 'cache-control': 'no-store',
29
+ });
30
+ res.end(`${JSON.stringify(value, null, 2)}\n`);
31
+ }
32
+
33
+ function publicRecord(record) {
34
+ return {
35
+ ok: true,
36
+ schema: record.schema,
37
+ event: record.event,
38
+ delivery_id: record.delivery_id,
39
+ repository: record.repository.full_name,
40
+ ref: record.ref || null,
41
+ after: record.after || null,
42
+ signature_verified: record.transport.signature_verified,
43
+ pointers_only: record.payload_boundary.pointers_only,
44
+ notification_is_authority: record.authority_boundary.notification_is_authority,
45
+ next_action: record.next_action,
46
+ };
47
+ }
48
+
49
+ async function verifyDelivery(req, event, delivery, signature) {
50
+ const raw = await readRaw(req);
51
+ const payloadPath = join(tmpdir(), `etiquette-webhook-${delivery}-${randomUUID()}.json`);
52
+ writeFileSync(payloadPath, raw);
53
+ try {
54
+ const result = spawnSync(etiquetteCli, [
55
+ 'notify',
56
+ 'webhook',
57
+ 'github',
58
+ '--payload',
59
+ payloadPath,
60
+ '--delivery',
61
+ delivery,
62
+ '--event',
63
+ event,
64
+ '--signature-256',
65
+ signature,
66
+ '--json',
67
+ ], {
68
+ encoding: 'utf8',
69
+ env: {
70
+ ...process.env,
71
+ ETIQUETTE_GITHUB_WEBHOOK_SECRET: secret,
72
+ },
73
+ });
74
+ if (result.status !== 0) {
75
+ return {
76
+ ok: false,
77
+ status: 401,
78
+ body: {
79
+ ok: false,
80
+ error: 'signature_or_payload_rejected',
81
+ detail: result.stderr.trim().slice(0, 200),
82
+ },
83
+ };
84
+ }
85
+ const record = JSON.parse(result.stdout);
86
+ if (outDir) {
87
+ mkdirSync(outDir, { recursive: true });
88
+ writeFileSync(join(outDir, 'latest.json'), `${JSON.stringify(record, null, 2)}\n`);
89
+ writeFileSync(join(outDir, `${delivery}.json`), `${JSON.stringify(record, null, 2)}\n`);
90
+ }
91
+ return { ok: true, status: 200, body: publicRecord(record) };
92
+ } finally {
93
+ rmSync(payloadPath, { force: true });
94
+ }
95
+ }
96
+
97
+ const server = createServer(async (req, res) => {
98
+ try {
99
+ if (req.method === 'GET' && req.url === '/health') {
100
+ writeJson(res, 200, { ok: true, authority: false });
101
+ return;
102
+ }
103
+ if (req.method !== 'POST' || req.url !== '/github') {
104
+ writeJson(res, 404, { ok: false, error: 'not_found' });
105
+ return;
106
+ }
107
+
108
+ const event = String(req.headers['x-github-event'] || '');
109
+ const delivery = String(req.headers['x-github-delivery'] || randomUUID());
110
+ const signature = String(req.headers['x-hub-signature-256'] || '');
111
+ if (event !== 'push' && event !== 'ping') {
112
+ writeJson(res, 400, { ok: false, error: 'unsupported_event', event });
113
+ return;
114
+ }
115
+ if (!signature.startsWith('sha256=')) {
116
+ writeJson(res, 401, { ok: false, error: 'missing_signature' });
117
+ return;
118
+ }
119
+
120
+ const result = await verifyDelivery(req, event, delivery, signature);
121
+ writeJson(res, result.status, result.body);
122
+ } catch (error) {
123
+ writeJson(res, 500, { ok: false, error: String(error?.message || error) });
124
+ }
125
+ });
126
+
127
+ server.listen(port, '0.0.0.0', () => {
128
+ console.log(`etiquette_w1_receiver: listening on ${port}`);
129
+ });
@@ -62,9 +62,8 @@ project head-start surfaces before pickup:
62
62
  - `docs/work/manuals/SEAT_OPERATING_MANUAL.md`
63
63
  - `docs/work/cookbooks/ADD_A_LANE.md` when routing work
64
64
 
65
- After interrupted sessions, cwd/worktree ambiguity, role changes, or vendor
66
- swaps, rerun `whereami`, `doctor`, and `notify poll` before pickup.
67
- Lifecycle/readiness checks are evidence only; they do not authorize work.
65
+ Re-orient with `etiquette whereami` before pickup after stale context, resume,
66
+ runner/model/profile swaps, or workflow migration.
68
67
 
69
68
  ## Validate Catalog
70
69
 
@@ -14,6 +14,6 @@ Before pickup in the target project, read:
14
14
  4. `docs/work/manuals/SEAT_OPERATING_MANUAL.md`
15
15
  5. `docs/work/cookbooks/ADD_A_LANE.md` when routing new work
16
16
 
17
- After interrupted sessions, cwd/worktree ambiguity, role changes, or vendor
18
- swaps, rerun `whereami`, `doctor`, and `notify poll` before pickup. Hooks and
19
- readiness are evidence only; the task envelope is the work authority.
17
+ Re-orient with `etiquette whereami` before pickup after stale context, resume,
18
+ runner/model/profile swaps, or workflow migration. Hooks and readiness are
19
+ evidence only; the task envelope is the work authority.
@@ -14,9 +14,9 @@ Before pickup in the target project, read:
14
14
  4. `docs/work/manuals/SEAT_OPERATING_MANUAL.md`
15
15
  5. `docs/work/cookbooks/ADD_A_LANE.md` when routing new work
16
16
 
17
- After interrupted sessions, cwd/worktree ambiguity, role changes, or vendor
18
- swaps, rerun `whereami`, `doctor`, and `notify poll` before pickup. Hooks and
19
- readiness are evidence only; the task envelope is the work authority.
17
+ Re-orient with `etiquette whereami` before pickup after stale context, resume,
18
+ runner/model/profile swaps, or workflow migration. Hooks and readiness are
19
+ evidence only; the task envelope is the work authority.
20
20
 
21
21
  For bounded, cursor-based wake checks use the portable core command
22
22
  `etiquette notify poll --seat <id> --after-seq <n>` instead of raw `tail -F` monitors.
@@ -14,6 +14,6 @@ Before pickup in the target project, read:
14
14
  4. `docs/work/manuals/SEAT_OPERATING_MANUAL.md`
15
15
  5. `docs/work/cookbooks/ADD_A_LANE.md` when routing new work
16
16
 
17
- After interrupted sessions, cwd/worktree ambiguity, role changes, or vendor
18
- swaps, rerun `whereami`, `doctor`, and `notify poll` before pickup. Hooks and
19
- readiness are evidence only; the task envelope is the work authority.
17
+ Re-orient with `etiquette whereami` before pickup after stale context, resume,
18
+ runner/model/profile swaps, or workflow migration. Hooks and readiness are
19
+ evidence only; the task envelope is the work authority.
@@ -14,6 +14,6 @@ Before pickup in the target project, read:
14
14
  4. `docs/work/manuals/SEAT_OPERATING_MANUAL.md`
15
15
  5. `docs/work/cookbooks/ADD_A_LANE.md` when routing new work
16
16
 
17
- After interrupted sessions, cwd/worktree ambiguity, role changes, or vendor
18
- swaps, rerun `whereami`, `doctor`, and `notify poll` before pickup. Hooks and
19
- readiness are evidence only; the task envelope is the work authority.
17
+ Re-orient with `etiquette whereami` before pickup after stale context, resume,
18
+ runner/model/profile swaps, or workflow migration. Hooks and readiness are
19
+ evidence only; the task envelope is the work authority.
@@ -14,6 +14,6 @@ Before pickup in the target project, read:
14
14
  4. `docs/work/manuals/SEAT_OPERATING_MANUAL.md`
15
15
  5. `docs/work/cookbooks/ADD_A_LANE.md` when routing new work
16
16
 
17
- After interrupted sessions, cwd/worktree ambiguity, role changes, or vendor
18
- swaps, rerun `whereami`, `doctor`, and `notify poll` before pickup. Hooks and
19
- readiness are evidence only; the task envelope is the work authority.
17
+ Re-orient with `etiquette whereami` before pickup after stale context, resume,
18
+ runner/model/profile swaps, or workflow migration. Hooks and readiness are
19
+ evidence only; the task envelope is the work authority.
@@ -1,66 +0,0 @@
1
- # Concept Status Matrix
2
-
3
- Etiquette uses a few strong workflow concepts. Some are core behavior today,
4
- some belong to the optional secure plane, and some are still operating patterns
5
- that need a concrete consumer before they become default workflow.
6
-
7
- Use this page when writing portal copy, onboarding material, release notes, or
8
- manager runbooks. Do not promote a concept beyond the status shown here.
9
-
10
- ## Edition Boundary
11
-
12
- | Surface | Purpose | Authority Posture |
13
- | --- | --- | --- |
14
- | Etiquette Core | Repo-local coordination, task envelopes, receipts, allowed writes, read models, manuals, and canaries. | Transparent by default; authority comes from tracked task/grant records and receipts. |
15
- | Etiquette Secure | Restricted-seat admission, external assurance claims, revocation, policy state, and optional tightening reactor. | Tightens standing and eligibility; it must not grant workflow authority by itself. |
16
- | Hosted/portal plane | Setup passes, workspace visibility, onboarding, board/read-model display, and operational observability. | Portal RBAC authorizes portal operations only. Workflow authority stays local and grant-backed. |
17
-
18
- ## Concept Matrix
19
-
20
- | Concept | Core Status | Secure Status | Portal Surface | Caveat |
21
- | --- | --- | --- | --- | --- |
22
- | Ledger | Shipped. Repo-local task records, events, and receipts carry durable workflow truth. | May receive signed or protected replication later. | Board and console render ledger-derived read models. | Git-backed truth is durable and auditable; call it cryptographic only when signing/protected append-only is actually configured. |
23
- | Receipts | Shipped. Work returns must cite changed files, validation, blockers, and next owner. | May include action authorization stamps and external verifier receipts. | Evidence drawers and manager views point to receipts. | A receipt proves evidence; it does not grant, merge, close, or promote by itself. |
24
- | Seats and agents | Shipped. A seat is a stable responsibility; an occupant/runtime can change. Owner cards derive accountability, diet, boundaries, review cadence, and failure modes from source contracts plus live readiness. | Secure posture is parked; seats use local readiness and explicit task routing. | Roster and owner cards show lifecycle, readiness, ownership, and posture. | Model cards, owner cards, and roster posture help routing but do not authorize work or transfer ownership. |
25
- | Task envelopes | Shipped. Tasks declare owner, mode, allowed writes, forbidden writes, validation, stop conditions, and receipt expectations. | Secure admission is parked; task routing remains explicit. | Manager manuals and pickup surfaces show the envelope. | Allowed writes are a cooperative boundary unless paired with OS/container enforcement or audit gates. |
26
- | Rubrics and validation | Shipped as acceptance criteria and conformance gates. | Can be bound to restricted workflows and verifier receipts. | Manager/operator docs list required validation and stop conditions. | Do not claim every runtime is hard-blocked from returning unless the specific flow enforces that gate. |
27
- | Authorization | Shipped as grant-backed workflow discipline: authentication seats an actor; authorization gates consequential action. | Secure posture is parked; grant leases, kill-switch state, and action stamps remain the admission-time authority model. | Hosted pass docs and workspace authority contracts describe the boundary. | A verified occupant has standing, not blanket authority. Grants are effective only while standing is current. |
28
- | Portal / management console | Core read model, docs site, screenshots, and read-only `console serve` are shipped. | Secure portal may manage policy state and revocation signals. | Console and board are read-only by default. | Portal RBAC is not workflow authority. Browser actions remain out of scope in Core. |
29
- | Distribution and plugins | Core CLI, docs, templates, MCP resources/prompts, and outbox-backed proposal staging are portable. | Secure can ship as an optional add-on. | Codex and Claude Code plugins may launch workflows and portal views. | Plugins are convenience packaging, not authority. MCP proposal tools must not mutate the ledger directly. |
30
- | Remote execution | Supported as evidence-first design. | Secure runtimes may require admission, revocation, and verifier identity before execution. Org-remote workspaces use session outboxes, sharded drains, candidate imports, and authority promotion gates. | Manager docs should treat remote receipts as evidence. | Start remote as witness, not worker. Remote receipts and drain imports do not authorize promotion. |
31
- | Managed-agent parity | Parity map exists for agents, environments, sessions, events, tools, MCP, memory, outcomes, and scheduling. | Secure runtime admission is parked. | Docs site and portal docs may expose the map. | Compatibility is not dependency. The runner executes; Etiquette governs and records. |
32
- | Architecture boundary | Core, runtime, harness, adapter, and reactor roles are documented and import-boundary tested. | Secure adds admission policy without forking doctrine. | Hosted consumes projected views without becoming authority. | New reverse imports are architectural changes, not convenience edits. |
33
- | Memory | Shipped as cited context, filesystem-shaped candidate stores, SQLite FTS recall, and `memory status` capability reporting. Evidence consolidation/rollup is the memory compaction lifecycle; it is not doctrine marination. | Secure deployments may restrict what crosses org/workspace boundaries. | Docs may surface references, summaries, archive pointers, and shipped/reserved memory status. | Memory proposes; ledger authorizes. Do not claim full semantic/vector memory parity until the adapter ships. Do not rewrite shared truth through background consolidation. |
34
- | Marination | Operating pattern. Use for doctrine sabbaticals: scheduled fresh-attention review of rules, errata, and proposed revisions. | Can be run under Secure as an advisory process with cited evidence. | Not yet a default portal workflow. | Deltas only. It produces proposals, not silent lane mutations. |
35
- | Sabbaticals / parking | Partially reflected as `park`, `held`, and deferred dispositions. | Secure deployments may freeze standing or grants while work is parked. | Manager cadence can show parked/held work. | Do not promise automatic stash/cleanup unless the workspace implements that runbook. |
36
- | Tightening reactor | Not part of default Core. | Optional off-by-default listener that writes only fail-closed signals such as revocation or kill-switch state. | Secure operations may show reactor health. | It may tighten, never loosen. If it stops, local admission still fails or proceeds from last known policy according to the configured gate. |
37
-
38
- ## Primitive Loop
39
-
40
- Core records, validates, gates, and dispatches. Full remembers, consolidates,
41
- marinates, and projects. Execution is not the gate: Core execution is the local
42
- shell/worktree, Full execution is a runtime cell or managed runner, and both
43
- remain authority-false until the promotion gate accepts evidence.
44
-
45
- | Layer | Core | Full |
46
- | --- | --- | --- |
47
- | Record | identity, seats, task envelopes, session runbooks, ledger, receipts | memory stores, recall capsules, org/workspace projections |
48
- | Reflect | rubrics, local validation, reconciliation by review | consolidation rollups, marination, drift and failure trend review |
49
- | Gate | human/Git promotion gate over receipts and grants | same gate, enriched by secure admission and policy checks |
50
- | Execute | local shell, local worktree, local runner | runtime cells, EKS/kind sandboxes, managed runners |
51
- | Act | dispatch, receipt return, next-owner routing | hosted portal views, observability, adapter projections |
52
-
53
- ## Writing Rule
54
-
55
- Use shipped language for shipped behavior, design language for parked behavior,
56
- and edition language for Secure behavior:
57
-
58
- ```text
59
- Core records, validates, gates, and dispatches.
60
- Full remembers, consolidates, marinates, and projects.
61
- Secure admits and revokes restricted standing.
62
- Portals display and coordinate.
63
- Grants authorize consequential actions.
64
- Receipts prove what happened.
65
- Execution returns evidence; it never mints authority.
66
- ```