@oneie/claude 0.3.2 → 0.5.0
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 +29 -19
- package/agents/w1-recon.md +9 -2
- package/agents/w2-decide.md +40 -9
- package/agents/w3-edit.md +34 -4
- package/agents/w4-verify.md +112 -15
- package/commands/do-autonomous.md +1 -1
- package/commands/do.md +84 -46
- package/commands/skill-create.md +4 -4
- package/commands/sync.md +7 -7
- package/hooks/scripts/stop-reflect.sh +3 -3
- package/hooks/scripts/sync-todo-docs.sh +1 -1
- package/package.json +2 -1
- package/rules/documentation.md +18 -18
- package/rules/engine.md +48 -192
- package/scripts/do-auto.sh +5 -5
- package/scripts/do-folder.sh +1 -1
- package/scripts/do-prove.sh +10 -27
- package/scripts/do-reconcile.sh +212 -19
- package/scripts/do-smoke.sh +65 -25
- package/scripts/do-survey.sh +1 -1
- package/scripts/do-tier.sh +1 -1
- package/scripts/w4-rubric.ts +2 -2
- package/skills/oneie/SKILL.md +4 -4
- package/skills/signal/SKILL.md +2 -2
- package/skills/sui/SKILL.md +1 -1
- package/templates/template-agent.md +63 -0
- package/templates/template-feature.md +31 -0
- package/templates/template-plan.md +80 -0
- package/templates/template-teach.md +124 -0
- package/templates/template-tests.md +43 -0
- package/templates/template-todo.md +783 -0
package/rules/engine.md
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
---
|
|
2
2
|
paths:
|
|
3
|
-
- "
|
|
3
|
+
- "packages/sdk/src/**/*.ts"
|
|
4
|
+
- "channels/src/**/*.ts"
|
|
5
|
+
- "one.ie/web/src/lib/pheromone.ts"
|
|
6
|
+
- "one.ie/web/src/workers/**/*.ts"
|
|
4
7
|
---
|
|
5
8
|
|
|
6
9
|
# Engine Rules
|
|
7
10
|
|
|
8
|
-
Apply to
|
|
11
|
+
Apply to substrate code — the SDK verbs, the pheromone world, and every worker that consumes them.
|
|
9
12
|
|
|
10
13
|
---
|
|
11
14
|
|
|
@@ -16,17 +19,20 @@ These three rules compound. Breaking any one breaks the flywheel.
|
|
|
16
19
|
### Rule 1 — Closed Loop
|
|
17
20
|
|
|
18
21
|
**Every signal closes its loop.** `mark()` on result, `warn()` on failure,
|
|
19
|
-
`dissolve` on missing
|
|
22
|
+
`dissolve` on missing receiver. No silent returns. No orphan signals.
|
|
20
23
|
|
|
21
24
|
```typescript
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
// ask() resolves to one of 4 outcomes (packages/sdk/src/types.ts — Outcome<T>)
|
|
26
|
+
const outcome = await one.ask(receiver, data)
|
|
27
|
+
switch (outcome.kind) {
|
|
28
|
+
case "result": await one.mark(edge); break // success → path strengthens
|
|
29
|
+
case "timeout": /* neutral — not the agent's fault */ break
|
|
30
|
+
case "dissolved": await one.warn(edge, 0.5); break // mild — receiver doesn't exist
|
|
31
|
+
case "failure": await one.warn(edge, 1); break // failure — produced nothing
|
|
32
|
+
}
|
|
27
33
|
```
|
|
28
34
|
|
|
29
|
-
Why:
|
|
35
|
+
Why: path strength is the only thing that compounds. A handler that returns
|
|
30
36
|
silently leaks learning. Width (parallelism) only compounds if every
|
|
31
37
|
parallel branch deposits a mark or warn on the path it used.
|
|
32
38
|
|
|
@@ -36,10 +42,10 @@ parallel branch deposits a mark or warn on the path it used.
|
|
|
36
42
|
or any wall-clock unit.
|
|
37
43
|
|
|
38
44
|
```
|
|
39
|
-
task = atomic unit of work (one
|
|
45
|
+
task = atomic unit of work (one receiver handler, one file edit)
|
|
40
46
|
wave = phase within a cycle (W1 recon → W2 decide → W3 edit → W4 verify)
|
|
41
47
|
cycle = full W0-W4 sandwich, exits at rubric >= 0.65
|
|
42
|
-
path = what remembers across cycles (
|
|
48
|
+
path = what remembers across cycles (strength / resistance)
|
|
43
49
|
```
|
|
44
50
|
|
|
45
51
|
Why: the substrate measures **width** by tasks-per-wave, **depth** by
|
|
@@ -52,7 +58,7 @@ from outside the substrate.
|
|
|
52
58
|
|
|
53
59
|
**Every loop reports verified numbers, not vibes.** Tests passed/total.
|
|
54
60
|
Build time in ms. Deploy time per service. Health check latency. Rubric
|
|
55
|
-
dimension scores. These are the deterministic signals that calibrate
|
|
61
|
+
dimension scores. These are the deterministic signals that calibrate path strength.
|
|
56
62
|
|
|
57
63
|
```typescript
|
|
58
64
|
// Every loop ends like this — not "done", but "done with receipts"
|
|
@@ -60,8 +66,8 @@ dimension scores. These are the deterministic signals that calibrate pheromone.
|
|
|
60
66
|
passed: 320,
|
|
61
67
|
failed: 0,
|
|
62
68
|
buildMs: 22995,
|
|
63
|
-
deployMs: {
|
|
64
|
-
health: {
|
|
69
|
+
deployMs: { web: 13705, sync: 8249, channels: 9163, api: 17391 },
|
|
70
|
+
health: { web: 292, sync: 270, channels: 270 },
|
|
65
71
|
// /do code rubric — security/stability/simplicity/speed, gate ≥ 0.65
|
|
66
72
|
rubric: { security: 0.92, stability: 0.85, simplicity: 0.90, speed: 0.80 }
|
|
67
73
|
}
|
|
@@ -73,153 +79,48 @@ it's learning. A loop that can't report deterministic results can't
|
|
|
73
79
|
sandwich applied to every automation skill.
|
|
74
80
|
|
|
75
81
|
**Where it shows up:**
|
|
76
|
-
- `/
|
|
77
|
-
- `/
|
|
82
|
+
- `/do` — W4 reports tests passed/total, reconcile canons, rubric scores
|
|
83
|
+
- `/close` — reports rubric score (security + stability + simplicity + speed, composite ≥ 0.65) + learnings entry
|
|
78
84
|
- `/sync` — reports tasks synced, hash-delta, KV writes
|
|
79
85
|
- `/deploy` — reports W0 results, build ms, per-service deploy ms, health
|
|
80
|
-
- `/done` — reports rubric score (security + stability + simplicity + speed, composite ≥ 0.65)
|
|
81
|
-
- growth tick — reports per-loop timings (L1-L7 lastAtMs, nextAtMs)
|
|
82
86
|
|
|
83
87
|
If you can't measure it, you can't route around it.
|
|
84
88
|
|
|
85
89
|
---
|
|
86
90
|
|
|
87
|
-
## The Substrate
|
|
88
|
-
|
|
89
|
-
```
|
|
90
|
-
~90 lines. Zero returns. Two fields. Queue.
|
|
91
|
-
|
|
92
|
-
{ receiver, data }
|
|
93
|
-
|
|
94
|
-
That's all that flows.
|
|
95
|
-
The runtime moves signals. TypeDB remembers.
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
---
|
|
99
|
-
|
|
100
|
-
## Two Layers
|
|
101
|
-
|
|
102
|
-
```
|
|
103
|
-
NERVOUS SYSTEM (runtime) BRAIN (TypeDB)
|
|
104
|
-
signals, strength, resistance, queue paths, units, skills, knowledge
|
|
105
|
-
loops L1-L3 (ms to minutes) loops L4-L7 (hours to weeks)
|
|
106
|
-
```
|
|
107
|
-
|
|
108
|
-
The runtime handles what moves. TypeDB handles what remains.
|
|
109
|
-
|
|
110
|
-
---
|
|
111
|
-
|
|
112
|
-
## Tasks = Handlers, Dependencies = Continuations
|
|
113
|
-
|
|
114
|
-
```typescript
|
|
115
|
-
// Tasks are .on() handlers on units
|
|
116
|
-
// Dependencies are .then() continuations
|
|
117
|
-
const bob = net.add('bob')
|
|
118
|
-
.on('schema', async (data, emit) => buildSchema(data))
|
|
119
|
-
.then('schema', r => ({ receiver: 'bob:api', data: r }))
|
|
120
|
-
.on('api', async (data, emit) => buildAPI(data))
|
|
121
|
-
.then('api', r => ({ receiver: 'bob:test', data: r }))
|
|
122
|
-
|
|
123
|
-
// No task entities. No dependency relations. No trail relations.
|
|
124
|
-
// Pheromone accumulates on paths automatically.
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
---
|
|
128
|
-
|
|
129
|
-
## Agent Self-Improvement
|
|
130
|
-
|
|
131
|
-
Units have `model`, `system-prompt`, `generation`.
|
|
132
|
-
The substrate measures performance. When it's bad enough, the agent evolves.
|
|
133
|
-
|
|
134
|
-
```typescript
|
|
135
|
-
// TypeDB detects
|
|
136
|
-
needs_evolution(unit) → success-rate < 0.50, sample-count >= 20
|
|
137
|
-
|
|
138
|
-
// Agent responds
|
|
139
|
-
unit.system-prompt = rewrite(old-prompt, failures)
|
|
140
|
-
unit.generation++
|
|
141
|
-
```
|
|
142
|
-
|
|
143
|
-
Two layers of learning:
|
|
144
|
-
- **Substrate** — pheromone on paths. World gets smarter.
|
|
145
|
-
- **Agent** — prompt/model evolution. Individual gets smarter.
|
|
146
|
-
|
|
147
|
-
---
|
|
148
|
-
|
|
149
91
|
## Signal
|
|
150
92
|
|
|
151
93
|
```typescript
|
|
152
94
|
type Signal = {
|
|
153
|
-
receiver: string // "
|
|
154
|
-
data?: unknown //
|
|
95
|
+
receiver: string // "family" or "family:action"
|
|
96
|
+
data?: unknown // typed per receiver via RECEIVERS catalog
|
|
155
97
|
}
|
|
156
98
|
```
|
|
157
99
|
|
|
158
|
-
The universal primitive
|
|
159
|
-
|
|
100
|
+
The universal primitive — `{ receiver, data }` is frozen. Capability contracts
|
|
101
|
+
live in the receiver registry (`@oneie/sdk/receivers`); the schema is truth for data.
|
|
160
102
|
|
|
161
103
|
---
|
|
162
104
|
|
|
163
|
-
##
|
|
164
|
-
|
|
165
|
-
```typescript
|
|
166
|
-
unit(id, route?)
|
|
167
|
-
.on(name, fn) // define task (handler)
|
|
168
|
-
.then(name, template) // define continuation (dependency)
|
|
169
|
-
.role(name, task, ctx) // context-bound task
|
|
170
|
-
.has(name) // introspection
|
|
171
|
-
.list() // introspection
|
|
172
|
-
.id // identity
|
|
173
|
-
```
|
|
174
|
-
|
|
175
|
-
### Task Signature
|
|
105
|
+
## World (the pheromone primitives)
|
|
176
106
|
|
|
177
|
-
|
|
178
|
-
(
|
|
179
|
-
|
|
180
|
-
data // the data
|
|
181
|
-
send // (signal) => void — fan out
|
|
182
|
-
ctx // { from: string, self: string }
|
|
183
|
-
```
|
|
184
|
-
|
|
185
|
-
---
|
|
186
|
-
|
|
187
|
-
## World
|
|
107
|
+
Shipped surface — `createWorld()` in `one.ie/web/src/lib/pheromone.ts`
|
|
108
|
+
(vendored in-RAM for DO bundles; mirrors the SDK verb semantics):
|
|
188
109
|
|
|
189
110
|
```typescript
|
|
190
|
-
world()
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
.sense(edge) // read strength
|
|
200
|
-
.danger(edge) // read resistance
|
|
201
|
-
.follow(type) // best path (deterministic)
|
|
202
|
-
.select(type?) // best path (probabilistic, ant-like)
|
|
203
|
-
.fade(rate?) // decay all paths (resistance 2x faster)
|
|
204
|
-
.highways(limit?) // top weighted paths
|
|
205
|
-
.has(id) // introspection
|
|
206
|
-
.list() // introspection
|
|
207
|
-
.get(id) // direct access
|
|
111
|
+
world.mark(edge, w?) // strengthen path
|
|
112
|
+
world.warn(edge, w?) // weaken path (resistance)
|
|
113
|
+
world.sense(edge) // read strength
|
|
114
|
+
world.follow(from) // best path (deterministic)
|
|
115
|
+
world.select(from) // best path (probabilistic, ant-like)
|
|
116
|
+
world.highways(prefix?, n?) // top weighted paths
|
|
117
|
+
world.fade(rate?) // decay all paths (resistance 2x faster)
|
|
118
|
+
world.serialize() // snapshot for KV
|
|
119
|
+
world.restore(snapshot) // rehydrate
|
|
208
120
|
```
|
|
209
121
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
## Persist
|
|
213
|
-
|
|
214
|
-
```typescript
|
|
215
|
-
persist() // extends world with TypeDB
|
|
216
|
-
.actor(id, kind?, opts?) // add + persist
|
|
217
|
-
.flow(from, to) // mark/warn wrapper
|
|
218
|
-
.open(n?) // top paths as {from, to, strength}
|
|
219
|
-
.blocked() // toxic paths
|
|
220
|
-
.know() // promote highways to knowledge
|
|
221
|
-
.recall(match?) // query knowledge from TypeDB
|
|
222
|
-
```
|
|
122
|
+
Over HTTP the same verbs are `SubstrateClient` methods (`packages/sdk/src/client.ts`).
|
|
123
|
+
`harden` is exposed via `signal("learning:know")`.
|
|
223
124
|
|
|
224
125
|
---
|
|
225
126
|
|
|
@@ -228,70 +129,25 @@ persist() // extends world with TypeDB
|
|
|
228
129
|
Positive flow only. Silence is valid.
|
|
229
130
|
|
|
230
131
|
```typescript
|
|
231
|
-
// GOOD
|
|
232
|
-
|
|
233
|
-
next[name] && route?.(next[name](result), receiver)
|
|
234
|
-
)
|
|
132
|
+
// GOOD — missing handler? Signal dissolves. World continues.
|
|
133
|
+
handler?.(data, send, ctx)
|
|
235
134
|
|
|
236
135
|
// BAD
|
|
237
|
-
if (!
|
|
136
|
+
if (!handler) return reject(...)
|
|
238
137
|
if (!target) throw new Error(...)
|
|
239
138
|
```
|
|
240
139
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
---
|
|
244
|
-
|
|
245
|
-
## The Tick
|
|
246
|
-
|
|
247
|
-
```typescript
|
|
248
|
-
const next = net.select() // follow pheromone
|
|
249
|
-
next && net.signal({ receiver: next }) // execute
|
|
250
|
-
net.drain() // process queue
|
|
251
|
-
net.fade(0.05) // decay
|
|
252
|
-
// evolve every 10min, know every hour
|
|
253
|
-
```
|
|
254
|
-
|
|
255
|
-
---
|
|
256
|
-
|
|
257
|
-
## Signal Flow
|
|
258
|
-
|
|
259
|
-
```
|
|
260
|
-
signal(sig, from='entry')
|
|
261
|
-
→ unit(sig, from)
|
|
262
|
-
→ task(data, send, {from, self})
|
|
263
|
-
→ send(sig) // fan out
|
|
264
|
-
→ signal(sig, from=self)
|
|
265
|
-
→ mark(edge) // path remembers
|
|
266
|
-
→ .then(task) // continuation fires
|
|
267
|
-
→ signal(next) // chain continues
|
|
268
|
-
```
|
|
269
|
-
|
|
270
|
-
Concurrency safe. No global state.
|
|
271
|
-
|
|
272
|
-
---
|
|
273
|
-
|
|
274
|
-
## Multi-Machine Collaboration
|
|
275
|
-
|
|
276
|
-
```
|
|
277
|
-
Machine A Machine B
|
|
278
|
-
┌──────────┐ ┌──────────┐
|
|
279
|
-
│ router │──signal──→ TypeDB ←──signal──│ router │
|
|
280
|
-
│ │←─paths───→ ←──paths──│ │
|
|
281
|
-
└──────────┘ └──────────┘
|
|
282
|
-
```
|
|
283
|
-
|
|
284
|
-
Each machine runs one router process. TypeDB is shared.
|
|
285
|
-
Pheromone builds across machines. The substrate learns end-to-end paths.
|
|
140
|
+
A dissolved signal still closes its loop — the *caller* sees `kind: "dissolved"`
|
|
141
|
+
and warns the edge (Rule 1). Dissolve is an outcome, not an exception.
|
|
286
142
|
|
|
287
143
|
---
|
|
288
144
|
|
|
289
|
-
*
|
|
145
|
+
*The 6 verbs: signal · mark · warn · fade · follow · harden.*
|
|
290
146
|
|
|
291
147
|
---
|
|
292
148
|
|
|
293
149
|
## Verb Contracts
|
|
294
150
|
|
|
295
|
-
Each of the 6 verbs has a **pre / post / invariant** contract. Spec lives in `
|
|
151
|
+
Each of the 6 verbs has a **pre / post / invariant** contract. Spec lives in `text/contracts.md` — loaded only when editing a verb implementation, not every session.
|
|
296
152
|
|
|
297
|
-
New verb? You need: contract block in `
|
|
153
|
+
New verb? You need: contract block in `text/contracts.md`, row in `one-ie/CLAUDE.md` § The 6 verbs, contract gate in `.claude/agents/w4-verify.md` step 2.5. If you can't write the contract, you can't ship the verb.
|
package/scripts/do-auto.sh
CHANGED
|
@@ -36,11 +36,11 @@ if ! printf '%s' "$SLUG" | grep -qE '^[a-zA-Z0-9][a-zA-Z0-9_-]*$'; then
|
|
|
36
36
|
fi
|
|
37
37
|
|
|
38
38
|
# Trust boundary: this script runs in the developer's own workspace, invoked by /do
|
|
39
|
-
# which resolves the slug from a
|
|
39
|
+
# which resolves the slug from a text/ file the developer controls. The spawned
|
|
40
40
|
# claude subprocess uses --dangerously-skip-permissions because it is non-interactive
|
|
41
41
|
# — it cannot prompt the human for tool approvals. The workspace is the isolation
|
|
42
42
|
# boundary. Do not expose this script to untrusted input or run it in shared environments.
|
|
43
|
-
[ -f "
|
|
43
|
+
[ -f "text/${SLUG}-todo.md" ] || { echo "[do-auto] text/${SLUG}-todo.md not found — run /do $SLUG first" >&2; exit 1; }
|
|
44
44
|
|
|
45
45
|
# ── Worktree isolation (one per plan) ────────────────────────────────────────
|
|
46
46
|
# The loop's existence IS the trigger: do-auto only runs for multi-cycle plans
|
|
@@ -78,7 +78,7 @@ _setup_worktree() {
|
|
|
78
78
|
# from HEAD wouldn't have them. Copy only this slug's files — never unrelated
|
|
79
79
|
# working-tree changes — then commit them as the branch baseline.
|
|
80
80
|
local f changed=0
|
|
81
|
-
for f in "
|
|
81
|
+
for f in "text/${SLUG}.md" "text/${SLUG}-todo.md" ".w4-improvements.json"; do
|
|
82
82
|
if [ -f "$f" ]; then
|
|
83
83
|
mkdir -p "$WT/$(dirname "$f")"
|
|
84
84
|
if ! cmp -s "$f" "$WT/$f" 2>/dev/null; then cp "$f" "$WT/$f"; changed=1; fi
|
|
@@ -93,10 +93,10 @@ _setup_worktree() {
|
|
|
93
93
|
if ! $DRY_RUN; then
|
|
94
94
|
_setup_worktree
|
|
95
95
|
# All loop state now lives in the worktree — read the boxes the subprocess ticks.
|
|
96
|
-
TODO="$WT/
|
|
96
|
+
TODO="$WT/text/${SLUG}-todo.md"
|
|
97
97
|
TRUST="$WT/.do-trust.json"
|
|
98
98
|
else
|
|
99
|
-
TODO="
|
|
99
|
+
TODO="text/${SLUG}-todo.md"
|
|
100
100
|
TRUST=".do-trust.json"
|
|
101
101
|
fi
|
|
102
102
|
|
package/scripts/do-folder.sh
CHANGED
package/scripts/do-prove.sh
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
|
-
# do-prove.sh — PROVE (
|
|
3
|
-
#
|
|
4
|
-
#
|
|
5
|
-
# Usage: do-prove.sh [--promise text/<f>.md] <changed-path>...
|
|
2
|
+
# do-prove.sh — PROVE (pure). Promise-check moved to do-reconcile.sh (design canon).
|
|
3
|
+
# Auto-detects surface from changed files → emits the proof action to run.
|
|
4
|
+
# Usage: do-prove.sh <changed-path>... | git diff --name-only | do-prove.sh
|
|
6
5
|
set -euo pipefail
|
|
7
6
|
|
|
8
|
-
promise=""
|
|
9
|
-
if [ "${1:-}" = "--promise" ]; then promise="$2"; shift 2; fi
|
|
10
|
-
|
|
11
7
|
paths=()
|
|
12
|
-
if [ "$#" -gt 0 ]; then
|
|
8
|
+
if [ "$#" -gt 0 ]; then
|
|
9
|
+
paths=("$@")
|
|
10
|
+
else
|
|
11
|
+
while IFS= read -r l; do [ -n "$l" ] && paths+=("$l"); done
|
|
12
|
+
fi
|
|
13
13
|
[ "${#paths[@]}" -eq 0 ] && { echo "PROVE: no changes"; exit 0; }
|
|
14
14
|
|
|
15
|
-
#
|
|
15
|
+
# Surface detection — substrate wins (upstream), then api, then frontend, else backend
|
|
16
16
|
surface=backend
|
|
17
17
|
for p in "${paths[@]}"; do
|
|
18
18
|
case "$p" in
|
|
@@ -28,24 +28,7 @@ case "$surface" in
|
|
|
28
28
|
backend) proof="curl against the DEPLOYED runtime (local verify is necessary, not sufficient)" ;;
|
|
29
29
|
substrate) proof="/sync reconcile (TypeDB↔KV↔D1↔SUI) + TypeQL returns the new shape + types compile downhill" ;;
|
|
30
30
|
esac
|
|
31
|
+
|
|
31
32
|
echo "surface: $surface"
|
|
32
33
|
echo "proof: $proof"
|
|
33
|
-
|
|
34
|
-
# promise-check: at least one substantive term from the P0 copy must appear in the shipped files
|
|
35
|
-
if [ -n "$promise" ] && [ -f "$promise" ]; then
|
|
36
|
-
# drop code keywords + generic verbs so the check keys on domain terms, not coincidences
|
|
37
|
-
stop='export|function|return|const|class|import|async|await|value|string|number|default|users|allow|enable|create|update|delete|where|which|their'
|
|
38
|
-
terms=$(grep -oiE '[a-z]{5,}' "$promise" | tr 'A-Z' 'a-z' | sort -u | grep -vwE "$stop" | head -40)
|
|
39
|
-
hit=0
|
|
40
|
-
for t in $terms; do
|
|
41
|
-
for p in "${paths[@]}"; do
|
|
42
|
-
if [ -f "$p" ] && grep -qi "$t" "$p" 2>/dev/null; then hit=1; break 2; fi
|
|
43
|
-
done
|
|
44
|
-
done
|
|
45
|
-
if [ "$hit" -eq 0 ]; then
|
|
46
|
-
echo "PROMISE-CHECK: FAIL — shipped artifact mentions none of the promise's terms (over-promise → back to P4 or re-FRAME)"
|
|
47
|
-
exit 1
|
|
48
|
-
fi
|
|
49
|
-
echo "PROMISE-CHECK: ok"
|
|
50
|
-
fi
|
|
51
34
|
echo "PROVE: pass"; exit 0
|