@open-agent-toolkit/cli 0.2.76 → 0.2.79
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/assets/agents/recon-worker.md +12 -12
- package/assets/bundle-metadata.json +1 -1
- package/assets/docs/workflows/skills/recon.md +53 -27
- package/assets/public-package-versions.json +4 -4
- package/assets/skills/explainer-kit/SKILL.md +1 -1
- package/assets/skills/explainer-kit/scripts/bundle.mjs +26 -2
- package/assets/skills/explainer-kit/scripts/record.mjs +26 -3
- package/assets/skills/explainer-kit/scripts/verify.mjs +26 -3
- package/assets/skills/oat-explainer-kit/SKILL.md +1 -1
- package/assets/skills/oat-explainer-kit/scripts/check-terminal-outcome.mjs +25 -5
- package/assets/skills/oat-project-complete/SKILL.md +1 -1
- package/assets/skills/oat-project-complete/scripts/consume-persisted-recap-intent.mjs +26 -6
- package/assets/skills/oat-project-complete/scripts/execute-synced-archive-entry.mjs +26 -6
- package/assets/skills/oat-project-complete/scripts/finalize-synced-archive.mjs +7 -0
- package/assets/skills/oat-project-complete/scripts/parse-completion-retry-fields.mjs +26 -5
- package/assets/skills/oat-project-complete/scripts/parse-synced-archive-resume-fields.mjs +26 -5
- package/assets/skills/oat-project-complete/scripts/recover-completion-receipts.mjs +26 -6
- package/assets/skills/oat-project-complete/scripts/resolve-completion-retry.mjs +26 -6
- package/assets/skills/oat-project-complete/scripts/resolve-synced-archive-entry.mjs +26 -5
- package/assets/skills/oat-project-complete/scripts/validate-durable-archive-receipt.mjs +7 -0
- package/assets/skills/oat-project-complete/scripts/validate-nonarchive-lifecycle-receipt.mjs +126 -95
- package/assets/skills/oat-project-implement/SKILL.md +1 -1
- package/assets/skills/oat-project-implement/scripts/capture-dirty-tree.mjs +3 -0
- package/assets/skills/recon/SKILL.md +37 -19
- package/assets/skills/recon/references/packet-contract.md +33 -30
- package/assets/skills/recon/references/profiles.md +18 -15
- package/assets/skills/recon/references/worker-contract.md +87 -7
- package/assets/skills/recon/scripts/create-review-brief.mjs +2 -5
- package/assets/skills/recon/scripts/lib/cli-entry.mjs +21 -0
- package/assets/skills/recon/scripts/lib/contracts.mjs +144 -38
- package/assets/skills/recon/scripts/lib/routing.mjs +2 -5
- package/assets/skills/recon/scripts/lib/validated-run.mjs +1 -1
- package/assets/skills/recon/scripts/prepare-routing.mjs +2 -2
- package/assets/skills/recon/scripts/reconcile-ledger.mjs +269 -2
- package/assets/skills/recon/scripts/render-packet.mjs +2 -5
- package/assets/skills/recon/scripts/validate-artifact.mjs +2 -5
- package/assets/skills/recon/scripts/validate-packet.mjs +73 -23
- package/package.json +2 -2
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: recon-worker
|
|
3
|
-
version: 1.0.
|
|
3
|
+
version: 1.0.2
|
|
4
4
|
description: Executes one bounded recon packet assignment as a non-interactive leaf worker and writes exactly one declared artifact.
|
|
5
5
|
tools: Read, Bash, Grep, Glob, Write, WebSearch, WebFetch
|
|
6
6
|
color: cyan
|
|
7
|
+
is_background: true
|
|
7
8
|
---
|
|
8
9
|
|
|
9
10
|
## Role
|
|
10
11
|
|
|
11
12
|
You are a non-interactive recon leaf worker. Execute exactly one assignment in
|
|
12
|
-
one declared mode: `map`, `gather`, `compile`, `verify`, `adversary`,
|
|
13
|
-
|
|
13
|
+
one declared mode: `map`, `gather`, `compile`, `verify`, `adversary`, or
|
|
14
|
+
`coverage`. No other mode is valid.
|
|
14
15
|
|
|
15
16
|
The controller maps approved manifest waves to this closed vocabulary:
|
|
16
17
|
|
|
@@ -22,7 +23,6 @@ The controller maps approved manifest waves to this closed vocabulary:
|
|
|
22
23
|
| `semantic-verification` | `verify` |
|
|
23
24
|
| `adversarial` | `adversary` |
|
|
24
25
|
| `coverage` | `coverage` |
|
|
25
|
-
| `reconciliation` | `reconcile` |
|
|
26
26
|
| `redundant-gather` | `gather` |
|
|
27
27
|
| `redundant-verification` | `verify` |
|
|
28
28
|
| `contradiction-resolution` | `adversary` |
|
|
@@ -75,7 +75,9 @@ canonical claim status.
|
|
|
75
75
|
|
|
76
76
|
Consume only the designated dossiers. Deduplicate their findings into a
|
|
77
77
|
provisional claim-ledger candidate and cite direct input artifacts. Do not
|
|
78
|
-
reopen excluded sources or invent evidence.
|
|
78
|
+
reopen excluded sources or invent evidence. Every persisted display excerpt
|
|
79
|
+
must be an exact contiguous substring of the cited source, except for the
|
|
80
|
+
declared `redacted-exact` representation.
|
|
79
81
|
|
|
80
82
|
### `verify`
|
|
81
83
|
|
|
@@ -99,13 +101,6 @@ Compare the declared scope and questions with the permitted ledger projection.
|
|
|
99
101
|
Emit covered items, missing areas, and material gaps. Do not read gatherer
|
|
100
102
|
reasoning.
|
|
101
103
|
|
|
102
|
-
### `reconcile`
|
|
103
|
-
|
|
104
|
-
Apply permitted review dispositions and contradiction outcomes to a new ledger
|
|
105
|
-
candidate. Preserve the prior revision, legal state transitions, evidence
|
|
106
|
-
links, qualifications, and unresolved issues. Never invent evidence or update
|
|
107
|
-
the existing ledger in place.
|
|
108
|
-
|
|
109
104
|
## Output
|
|
110
105
|
|
|
111
106
|
Write one JSON artifact using only the supplied closed schema's fields. A
|
|
@@ -121,6 +116,11 @@ Do not add a second mode field or any other unknown field. The controller
|
|
|
121
116
|
validates `waveId` and `mode`, or `reviewerLane` and `reviewKind`, against the
|
|
122
117
|
approved manifest wave before promoting the artifact.
|
|
123
118
|
|
|
119
|
+
Before returning, run the supplied deterministic validator against the sole
|
|
120
|
+
unpromoted `writePath`. Correct an invalid candidate within this same accepted
|
|
121
|
+
task and validate it again. If it remains invalid, return terminal
|
|
122
|
+
`PASS_FAILED`; the controller must not retry or replace the worker.
|
|
123
|
+
|
|
124
124
|
Return only the artifact path and compact outcome. Do not return source bodies,
|
|
125
125
|
worker reasoning, or dossier contents to the controller.
|
|
126
126
|
|
|
@@ -69,19 +69,21 @@ context source, output directory, or strict authority:
|
|
|
69
69
|
The default profile is `standard`. Each homogeneous wave has an independently
|
|
70
70
|
selected and approved exact target. Bounded mapping, extraction, citation
|
|
71
71
|
reopening, counterexample search, and mechanical dossier compilation start with
|
|
72
|
-
economical qualified routes.
|
|
73
|
-
|
|
74
|
-
cost of unrelated evidence waves.
|
|
72
|
+
economical qualified routes. Reconciliation is deterministic controller work
|
|
73
|
+
rather than a separately approved worker target.
|
|
75
74
|
|
|
76
75
|
| Profile | Use it for | Required assurance work | Claim ceiling |
|
|
77
76
|
| ---------- | ------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ | ------------- |
|
|
78
77
|
| `quick` | Bounded orientation | Mapping, gathering, compilation, schema validation, and locator validation; no independent semantic pass by design | `supported` |
|
|
79
|
-
| `standard` | Load-bearing evidence | Quick work plus blind semantic verification, adversarial review, coverage, and
|
|
78
|
+
| `standard` | Load-bearing evidence | Quick work plus blind semantic verification, adversarial review, coverage, and deterministic reconciliation | `verified` |
|
|
80
79
|
| `thorough` | Expensive failure or correlated blind spots | Standard work plus required redundant gathering and redundant verification | `verified` |
|
|
81
80
|
|
|
82
81
|
A thorough run may additionally predeclare an optional, condition-bound
|
|
83
82
|
`contradiction-resolution` evidence wave. It runs only when its approved
|
|
84
83
|
predicate triggers and is not required when that branch is not triggered.
|
|
84
|
+
Gather and redundant-gather waves may partition source work across lanes. Each
|
|
85
|
+
typed review wave uses exactly one lane so deterministic reconciliation has one
|
|
86
|
+
result per review kind, at the fixed path bound by the approved manifest.
|
|
85
87
|
|
|
86
88
|
The approval manifest shows each wave's exact target, task class, class floor,
|
|
87
89
|
selection rationale, adaptive lane count, conditional rule, concurrency,
|
|
@@ -93,11 +95,16 @@ change requires renewed approval; there is no silent substitution after
|
|
|
93
95
|
approval.
|
|
94
96
|
|
|
95
97
|
Before any worker launches, recon confirms that the live launch surface can run
|
|
96
|
-
the approved role, model, effort, and authority level.
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
98
|
+
the approved role, model, effort, and authority level. A materialized Cursor
|
|
99
|
+
role file is configuration, not evidence that the current Task catalog exposes
|
|
100
|
+
that role; the live catalog controls eligibility, with the approved generic
|
|
101
|
+
fallback used when needed. If the launch surface cannot run the selected
|
|
102
|
+
target, the run stays at `awaiting-approval` with a provider/dispatch diagnostic
|
|
103
|
+
and nothing is launched. Every Cursor leaf runs in the background so later
|
|
104
|
+
parent-chat messages cannot interrupt multi-minute evidence work. Deadlines are
|
|
105
|
+
approved execution limits chosen for the task class, not short watchdogs; an
|
|
106
|
+
accepted lane is never interrupted by hand because a displayed deadline
|
|
107
|
+
elapsed.
|
|
101
108
|
|
|
102
109
|
### Preview and Check Routing
|
|
103
110
|
|
|
@@ -117,29 +124,30 @@ compare the constructed target with that wave's approved exact target:
|
|
|
117
124
|
node .agents/skills/recon/scripts/prepare-routing.mjs --manifest manifest.json --wave gather-1 --check-target candidate-target.json
|
|
118
125
|
```
|
|
119
126
|
|
|
120
|
-
These commands validate structure, approval integrity, and exact identity.
|
|
121
|
-
|
|
122
|
-
|
|
127
|
+
These commands validate structure, approval integrity, and exact identity. Like
|
|
128
|
+
the other recon command-line helpers, they use a shared realpath-aware entry
|
|
129
|
+
check, so direct and symlinked invocations execute identically. They do not
|
|
130
|
+
launch a worker, rank model names, attest actual runtime identity, or measure
|
|
131
|
+
cost.
|
|
123
132
|
|
|
124
133
|
### Bounded Conditional Evidence
|
|
125
134
|
|
|
126
|
-
Standard and thorough may predeclare
|
|
127
|
-
`contradiction-resolution` evidence
|
|
128
|
-
|
|
135
|
+
Standard and thorough may each predeclare at most one conditional
|
|
136
|
+
`contradiction-resolution` evidence wave. A completed predecessor can trigger
|
|
137
|
+
that wave to seek discriminating evidence; accepted failure, cancellation,
|
|
129
138
|
timeout, or missing output cannot trigger a replacement. Triggered,
|
|
130
139
|
not-triggered, and unresolved dispositions remain visible. Both branches feed
|
|
131
|
-
the same
|
|
140
|
+
the same deterministic controller reconciliation.
|
|
132
141
|
|
|
133
142
|
A triggered condition must cite complete, digest-bound evidence from an approved
|
|
134
143
|
predecessor in the same run. Evidence copied from another run cannot activate
|
|
135
144
|
the destination wave and fails packet validation with
|
|
136
145
|
`CONDITION_EVIDENCE_RUN_MISMATCH`.
|
|
137
146
|
|
|
138
|
-
If a need for
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
or launches a second reconciliation.
|
|
147
|
+
If reconciliation exposes a need for new semantic judgment, recon preserves
|
|
148
|
+
completed evidence and returns an unresolved, out-of-envelope gap for renewed
|
|
149
|
+
approval or a new run. It never converts deterministic reconciliation into a
|
|
150
|
+
worker wave or silently retries an accepted worker.
|
|
143
151
|
|
|
144
152
|
## Destination Precedence
|
|
145
153
|
|
|
@@ -173,8 +181,8 @@ non-publishable candidate generation withdraws any existing `packet.md`:
|
|
|
173
181
|
- `claims.json` is the canonical claim ledger.
|
|
174
182
|
- `manifest.json` records request, source, approved execution envelope, and
|
|
175
183
|
gap provenance.
|
|
176
|
-
- `reviews/` contains compact semantic, adversarial, coverage, and
|
|
177
|
-
reconciliation
|
|
184
|
+
- `reviews/` contains compact semantic, adversarial, coverage, and the
|
|
185
|
+
controller-produced reconciliation record.
|
|
178
186
|
- `raw/` contains worker dossiers, candidate artifacts, and safe failure
|
|
179
187
|
diagnostics. It is not normal consumer input.
|
|
180
188
|
|
|
@@ -198,6 +206,20 @@ ledger must reference every completed primary and redundant gather dossier by
|
|
|
198
206
|
exact path and digest before review briefs are created. Missing provenance fails
|
|
199
207
|
with `MISSING_THOROUGH_GATHER_LEDGER_INPUT`.
|
|
200
208
|
|
|
209
|
+
Compile workers copy each evidence excerpt as one contiguous exact substring of
|
|
210
|
+
the reopened source. A source-required redaction may replace only the sensitive
|
|
211
|
+
span while preserving the surrounding bytes and recording the redaction. Recon
|
|
212
|
+
does not repair stale locators after compilation. Each accepted worker validates
|
|
213
|
+
its own closed artifact schema once, within the same accepted task, before
|
|
214
|
+
returning. An invalid accepted artifact is terminal; the controller neither
|
|
215
|
+
retries the schema nor substitutes another worker.
|
|
216
|
+
|
|
217
|
+
When an accepted lane has already written a schema-valid, lane-matching artifact
|
|
218
|
+
at its approved path, that durable artifact remains the result even if the
|
|
219
|
+
provider stream later closes with an error. Recon records the stream failure as
|
|
220
|
+
a provider diagnostic and does not relaunch the lane. A missing or invalid
|
|
221
|
+
artifact remains a failed pass.
|
|
222
|
+
|
|
201
223
|
The ledger compiler and packet validator enforce categorical referential
|
|
202
224
|
integrity on `synthesis.keyClaimIds` and `synthesis.unresolvedQuestionIds`. Any
|
|
203
225
|
reference to an unknown claim or question ID fails validation with
|
|
@@ -228,10 +250,14 @@ the caller assesses sufficiency and conclusions. Stronger profiles can promote
|
|
|
228
250
|
claims only when their required independent review artifacts validate and were
|
|
229
251
|
written by approved lanes.
|
|
230
252
|
|
|
231
|
-
When an independent semantic review rejects a proposed claim,
|
|
232
|
-
transitions it to `unsupported` rather than deleting
|
|
233
|
-
|
|
234
|
-
|
|
253
|
+
When an independent semantic review rejects a proposed claim, deterministic
|
|
254
|
+
controller reconciliation transitions it to `unsupported` rather than deleting
|
|
255
|
+
it. The controller validates the digest-bound input ledger and required review
|
|
256
|
+
set, writes `raw/drafts/claims-v2.json` and
|
|
257
|
+
`reviews/reconciliation.json`, validates both, then atomically promotes the
|
|
258
|
+
candidate ledger to `claims.json`. This preserves the claim statement, cited
|
|
259
|
+
evidence, and transition history and renders the finding under Contradictions
|
|
260
|
+
and Qualifications.
|
|
235
261
|
|
|
236
262
|
An adversarial challenge transitions a claim to `contested`. A run with
|
|
237
263
|
contested claims may publish as `complete` when all declared questions and
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
import { createHash } from 'node:crypto';
|
|
4
|
+
import { realpathSync } from 'node:fs';
|
|
4
5
|
import {
|
|
5
6
|
lstat,
|
|
6
7
|
mkdir,
|
|
@@ -20,8 +21,9 @@ import {
|
|
|
20
21
|
isAbsolute,
|
|
21
22
|
join,
|
|
22
23
|
relative,
|
|
24
|
+
resolve,
|
|
23
25
|
} from 'node:path';
|
|
24
|
-
import {
|
|
26
|
+
import { fileURLToPath } from 'node:url';
|
|
25
27
|
|
|
26
28
|
import {
|
|
27
29
|
harvestNumericTokens,
|
|
@@ -704,7 +706,29 @@ function bundleError(message) {
|
|
|
704
706
|
return error;
|
|
705
707
|
}
|
|
706
708
|
|
|
707
|
-
|
|
709
|
+
/**
|
|
710
|
+
* Direct invocation, compared as canonical paths on both sides. Comparing a raw
|
|
711
|
+
* `process.argv[1]` against `import.meta.url` makes this script a silent no-op
|
|
712
|
+
* that exits 0 whenever the skill is reached through a symlinked install root,
|
|
713
|
+
* and canonicalizing only one side has the same effect under
|
|
714
|
+
* `--preserve-symlinks-main`, which keeps the link in `import.meta.url`.
|
|
715
|
+
* A path that cannot be canonicalized is not a module Node loaded as the entry
|
|
716
|
+
* point, so a thrown `realpathSync` means "not invoked directly" and returns
|
|
717
|
+
* `false`; it never masks a direct run.
|
|
718
|
+
*/
|
|
719
|
+
function isDirectInvocation(invokedPath) {
|
|
720
|
+
if (!invokedPath) return false;
|
|
721
|
+
try {
|
|
722
|
+
return (
|
|
723
|
+
realpathSync(fileURLToPath(import.meta.url)) ===
|
|
724
|
+
realpathSync(resolve(invokedPath))
|
|
725
|
+
);
|
|
726
|
+
} catch {
|
|
727
|
+
return false;
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
if (isDirectInvocation(process.argv[1])) {
|
|
708
732
|
runBundle(process.argv.slice(2)).catch((error) => {
|
|
709
733
|
console.error(error.message);
|
|
710
734
|
process.exitCode = 1;
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
import { createHash, randomUUID } from 'node:crypto';
|
|
4
|
+
import { realpathSync } from 'node:fs';
|
|
4
5
|
import { access, readFile, readdir, rename, writeFile } from 'node:fs/promises';
|
|
5
|
-
import { join } from 'node:path';
|
|
6
|
-
import {
|
|
6
|
+
import { join, resolve } from 'node:path';
|
|
7
|
+
import { fileURLToPath } from 'node:url';
|
|
7
8
|
|
|
8
9
|
import { validateContract } from './lib/contracts.mjs';
|
|
9
10
|
import {
|
|
@@ -327,7 +328,29 @@ function recordError(code, message) {
|
|
|
327
328
|
return error;
|
|
328
329
|
}
|
|
329
330
|
|
|
330
|
-
|
|
331
|
+
/**
|
|
332
|
+
* Direct invocation, compared as canonical paths on both sides. Comparing a raw
|
|
333
|
+
* `process.argv[1]` against `import.meta.url` makes this script a silent no-op
|
|
334
|
+
* that exits 0 whenever the skill is reached through a symlinked install root,
|
|
335
|
+
* and canonicalizing only one side has the same effect under
|
|
336
|
+
* `--preserve-symlinks-main`, which keeps the link in `import.meta.url`.
|
|
337
|
+
* A path that cannot be canonicalized is not a module Node loaded as the entry
|
|
338
|
+
* point, so a thrown `realpathSync` means "not invoked directly" and returns
|
|
339
|
+
* `false`; it never masks a direct run.
|
|
340
|
+
*/
|
|
341
|
+
function isDirectInvocation(invokedPath) {
|
|
342
|
+
if (!invokedPath) return false;
|
|
343
|
+
try {
|
|
344
|
+
return (
|
|
345
|
+
realpathSync(fileURLToPath(import.meta.url)) ===
|
|
346
|
+
realpathSync(resolve(invokedPath))
|
|
347
|
+
);
|
|
348
|
+
} catch {
|
|
349
|
+
return false;
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
if (isDirectInvocation(process.argv[1])) {
|
|
331
354
|
runRecord(process.argv.slice(2)).catch((error) => {
|
|
332
355
|
console.error(`${error.code}: ${error.message}`);
|
|
333
356
|
process.exitCode = 1;
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
import { createHash } from 'node:crypto';
|
|
4
|
+
import { realpathSync } from 'node:fs';
|
|
4
5
|
import { mkdir, readFile, rm, writeFile } from 'node:fs/promises';
|
|
5
|
-
import { join } from 'node:path';
|
|
6
|
-
import {
|
|
6
|
+
import { join, resolve } from 'node:path';
|
|
7
|
+
import { fileURLToPath } from 'node:url';
|
|
7
8
|
|
|
8
9
|
import { writeFailure } from './bundle.mjs';
|
|
9
10
|
import {
|
|
@@ -640,7 +641,29 @@ function verifyError(code, message) {
|
|
|
640
641
|
return error;
|
|
641
642
|
}
|
|
642
643
|
|
|
643
|
-
|
|
644
|
+
/**
|
|
645
|
+
* Direct invocation, compared as canonical paths on both sides. Comparing a raw
|
|
646
|
+
* `process.argv[1]` against `import.meta.url` makes this script a silent no-op
|
|
647
|
+
* that exits 0 whenever the skill is reached through a symlinked install root,
|
|
648
|
+
* and canonicalizing only one side has the same effect under
|
|
649
|
+
* `--preserve-symlinks-main`, which keeps the link in `import.meta.url`.
|
|
650
|
+
* A path that cannot be canonicalized is not a module Node loaded as the entry
|
|
651
|
+
* point, so a thrown `realpathSync` means "not invoked directly" and returns
|
|
652
|
+
* `false`; it never masks a direct run.
|
|
653
|
+
*/
|
|
654
|
+
function isDirectInvocation(invokedPath) {
|
|
655
|
+
if (!invokedPath) return false;
|
|
656
|
+
try {
|
|
657
|
+
return (
|
|
658
|
+
realpathSync(fileURLToPath(import.meta.url)) ===
|
|
659
|
+
realpathSync(resolve(invokedPath))
|
|
660
|
+
);
|
|
661
|
+
} catch {
|
|
662
|
+
return false;
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
if (isDirectInvocation(process.argv[1])) {
|
|
644
667
|
runVerify(process.argv.slice(2)).catch((error) => {
|
|
645
668
|
console.error(`${error.code ?? 'verify-error'}: ${error.message}`);
|
|
646
669
|
process.exitCode = 1;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { createHash } from 'node:crypto';
|
|
2
|
+
import { realpathSync } from 'node:fs';
|
|
2
3
|
import { lstat, readFile, realpath } from 'node:fs/promises';
|
|
3
4
|
import {
|
|
4
5
|
basename,
|
|
@@ -9,7 +10,7 @@ import {
|
|
|
9
10
|
resolve,
|
|
10
11
|
sep,
|
|
11
12
|
} from 'node:path';
|
|
12
|
-
import {
|
|
13
|
+
import { fileURLToPath } from 'node:url';
|
|
13
14
|
|
|
14
15
|
import { validateContract } from '../../explainer-kit/scripts/lib/contracts.mjs';
|
|
15
16
|
import { isFlowFailureStage } from '../../explainer-kit/scripts/lib/failure.mjs';
|
|
@@ -324,10 +325,29 @@ function recapOutcomeError(message) {
|
|
|
324
325
|
return error;
|
|
325
326
|
}
|
|
326
327
|
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
328
|
+
/**
|
|
329
|
+
* Direct invocation, compared as canonical paths on both sides. Comparing a raw
|
|
330
|
+
* `process.argv[1]` against `import.meta.url` makes this script a silent no-op
|
|
331
|
+
* that exits 0 whenever the skill is reached through a symlinked install root,
|
|
332
|
+
* and canonicalizing only one side has the same effect under
|
|
333
|
+
* `--preserve-symlinks-main`, which keeps the link in `import.meta.url`.
|
|
334
|
+
* A path that cannot be canonicalized is not a module Node loaded as the entry
|
|
335
|
+
* point, so a thrown `realpathSync` means "not invoked directly" and returns
|
|
336
|
+
* `false`; it never masks a direct run.
|
|
337
|
+
*/
|
|
338
|
+
function isDirectInvocation(invokedPath) {
|
|
339
|
+
if (!invokedPath) return false;
|
|
340
|
+
try {
|
|
341
|
+
return (
|
|
342
|
+
realpathSync(fileURLToPath(import.meta.url)) ===
|
|
343
|
+
realpathSync(resolve(invokedPath))
|
|
344
|
+
);
|
|
345
|
+
} catch {
|
|
346
|
+
return false;
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
if (isDirectInvocation(process.argv[1])) {
|
|
331
351
|
main(process.argv.slice(2))
|
|
332
352
|
.then((result) => {
|
|
333
353
|
process.stdout.write(`${JSON.stringify(result)}\n`);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import { realpathSync } from 'node:fs';
|
|
1
2
|
import { readdir, realpath } from 'node:fs/promises';
|
|
2
|
-
import { join } from 'node:path';
|
|
3
|
-
import {
|
|
3
|
+
import { join, resolve } from 'node:path';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
4
5
|
|
|
5
6
|
import { readPersistedIntent } from '../../oat-explainer-kit/scripts/persist-intent.mjs';
|
|
6
7
|
|
|
@@ -110,10 +111,29 @@ async function main(argv) {
|
|
|
110
111
|
return consumePersistedRecapIntent({ projectPath: argv[0] });
|
|
111
112
|
}
|
|
112
113
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
114
|
+
/**
|
|
115
|
+
* Direct invocation, compared as canonical paths on both sides. Comparing a raw
|
|
116
|
+
* `process.argv[1]` against `import.meta.url` makes this script a silent no-op
|
|
117
|
+
* that exits 0 whenever the skill is reached through a symlinked install root,
|
|
118
|
+
* and canonicalizing only one side has the same effect under
|
|
119
|
+
* `--preserve-symlinks-main`, which keeps the link in `import.meta.url`.
|
|
120
|
+
* A path that cannot be canonicalized is not a module Node loaded as the entry
|
|
121
|
+
* point, so a thrown `realpathSync` means "not invoked directly" and returns
|
|
122
|
+
* `false`; it never masks a direct run.
|
|
123
|
+
*/
|
|
124
|
+
function isDirectInvocation(invokedPath) {
|
|
125
|
+
if (!invokedPath) return false;
|
|
126
|
+
try {
|
|
127
|
+
return (
|
|
128
|
+
realpathSync(fileURLToPath(import.meta.url)) ===
|
|
129
|
+
realpathSync(resolve(invokedPath))
|
|
130
|
+
);
|
|
131
|
+
} catch {
|
|
132
|
+
return false;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (isDirectInvocation(process.argv[1])) {
|
|
117
137
|
main(process.argv.slice(2))
|
|
118
138
|
.then((result) => process.stdout.write(`${JSON.stringify(result)}\n`))
|
|
119
139
|
.catch((error) => {
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { execFile as execFileCallback } from 'node:child_process';
|
|
2
|
+
import { realpathSync } from 'node:fs';
|
|
2
3
|
import { readFile } from 'node:fs/promises';
|
|
3
|
-
import { isAbsolute, posix, relative, sep } from 'node:path';
|
|
4
|
-
import {
|
|
4
|
+
import { isAbsolute, posix, relative, sep, resolve } from 'node:path';
|
|
5
|
+
import { fileURLToPath } from 'node:url';
|
|
5
6
|
import { promisify } from 'node:util';
|
|
6
7
|
|
|
7
8
|
import { validateSyncedArchiveTerminalReport } from './finalize-synced-archive.mjs';
|
|
@@ -261,10 +262,29 @@ async function main(argv) {
|
|
|
261
262
|
});
|
|
262
263
|
}
|
|
263
264
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
265
|
+
/**
|
|
266
|
+
* Direct invocation, compared as canonical paths on both sides. Comparing a raw
|
|
267
|
+
* `process.argv[1]` against `import.meta.url` makes this script a silent no-op
|
|
268
|
+
* that exits 0 whenever the skill is reached through a symlinked install root,
|
|
269
|
+
* and canonicalizing only one side has the same effect under
|
|
270
|
+
* `--preserve-symlinks-main`, which keeps the link in `import.meta.url`.
|
|
271
|
+
* A path that cannot be canonicalized is not a module Node loaded as the entry
|
|
272
|
+
* point, so a thrown `realpathSync` means "not invoked directly" and returns
|
|
273
|
+
* `false`; it never masks a direct run.
|
|
274
|
+
*/
|
|
275
|
+
function isDirectInvocation(invokedPath) {
|
|
276
|
+
if (!invokedPath) return false;
|
|
277
|
+
try {
|
|
278
|
+
return (
|
|
279
|
+
realpathSync(fileURLToPath(import.meta.url)) ===
|
|
280
|
+
realpathSync(resolve(invokedPath))
|
|
281
|
+
);
|
|
282
|
+
} catch {
|
|
283
|
+
return false;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
if (isDirectInvocation(process.argv[1])) {
|
|
268
288
|
main(process.argv.slice(2))
|
|
269
289
|
.then((result) => process.stdout.write(`${JSON.stringify(result)}\n`))
|
|
270
290
|
.catch((error) => {
|
|
@@ -92,6 +92,10 @@ async function main(argv) {
|
|
|
92
92
|
projectName,
|
|
93
93
|
getArchiveReport: async () => {
|
|
94
94
|
try {
|
|
95
|
+
// Stdin is read to EOF with no timeout. Every caller pipes the archive
|
|
96
|
+
// report in (`printf '%s\n' "$ARCHIVE_OUTPUT" | node ...`), so EOF
|
|
97
|
+
// always arrives; a timeout would turn a slow producer into a false
|
|
98
|
+
// failure, and a caller that leaves stdin open is a caller bug.
|
|
95
99
|
return JSON.parse(readFileSync(0, 'utf8'));
|
|
96
100
|
} catch (error) {
|
|
97
101
|
throw finalizationError(
|
|
@@ -119,6 +123,9 @@ async function main(argv) {
|
|
|
119
123
|
* `--preserve-symlinks-main`, which keeps the link in `import.meta.url`. Either
|
|
120
124
|
* way the caller reads "exited 0" as "verified" — the fail-open shape this
|
|
121
125
|
* finalizer exists to prevent.
|
|
126
|
+
* A path that cannot be canonicalized is not a module Node loaded as the entry
|
|
127
|
+
* point, so a thrown `realpathSync` means "not invoked directly" and returns
|
|
128
|
+
* `false`; it never masks a direct run.
|
|
122
129
|
*/
|
|
123
130
|
function isDirectInvocation(invokedPath) {
|
|
124
131
|
if (!invokedPath) return false;
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { realpathSync } from 'node:fs';
|
|
2
|
+
import { resolve } from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
2
4
|
|
|
3
5
|
const FULL_SHA = /^[0-9a-f]{40}$/;
|
|
4
6
|
const PR_ARTIFACT = /^pr\/project-pr-[^/\s]+\.md$/;
|
|
@@ -217,10 +219,29 @@ function main(argv) {
|
|
|
217
219
|
return parseCompletionRetryFields(argv[0]);
|
|
218
220
|
}
|
|
219
221
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
222
|
+
/**
|
|
223
|
+
* Direct invocation, compared as canonical paths on both sides. Comparing a raw
|
|
224
|
+
* `process.argv[1]` against `import.meta.url` makes this script a silent no-op
|
|
225
|
+
* that exits 0 whenever the skill is reached through a symlinked install root,
|
|
226
|
+
* and canonicalizing only one side has the same effect under
|
|
227
|
+
* `--preserve-symlinks-main`, which keeps the link in `import.meta.url`.
|
|
228
|
+
* A path that cannot be canonicalized is not a module Node loaded as the entry
|
|
229
|
+
* point, so a thrown `realpathSync` means "not invoked directly" and returns
|
|
230
|
+
* `false`; it never masks a direct run.
|
|
231
|
+
*/
|
|
232
|
+
function isDirectInvocation(invokedPath) {
|
|
233
|
+
if (!invokedPath) return false;
|
|
234
|
+
try {
|
|
235
|
+
return (
|
|
236
|
+
realpathSync(fileURLToPath(import.meta.url)) ===
|
|
237
|
+
realpathSync(resolve(invokedPath))
|
|
238
|
+
);
|
|
239
|
+
} catch {
|
|
240
|
+
return false;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
if (isDirectInvocation(process.argv[1])) {
|
|
224
245
|
try {
|
|
225
246
|
process.stdout.write(`${main(process.argv.slice(2))}\n`);
|
|
226
247
|
} catch (error) {
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { realpathSync } from 'node:fs';
|
|
2
|
+
import { resolve } from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
2
4
|
|
|
3
5
|
function fieldsError(message) {
|
|
4
6
|
const error = new Error(message);
|
|
@@ -92,10 +94,29 @@ function main(argv) {
|
|
|
92
94
|
return formatShellAssignments(parseSyncedArchiveResumeFields(result));
|
|
93
95
|
}
|
|
94
96
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
97
|
+
/**
|
|
98
|
+
* Direct invocation, compared as canonical paths on both sides. Comparing a raw
|
|
99
|
+
* `process.argv[1]` against `import.meta.url` makes this script a silent no-op
|
|
100
|
+
* that exits 0 whenever the skill is reached through a symlinked install root,
|
|
101
|
+
* and canonicalizing only one side has the same effect under
|
|
102
|
+
* `--preserve-symlinks-main`, which keeps the link in `import.meta.url`.
|
|
103
|
+
* A path that cannot be canonicalized is not a module Node loaded as the entry
|
|
104
|
+
* point, so a thrown `realpathSync` means "not invoked directly" and returns
|
|
105
|
+
* `false`; it never masks a direct run.
|
|
106
|
+
*/
|
|
107
|
+
function isDirectInvocation(invokedPath) {
|
|
108
|
+
if (!invokedPath) return false;
|
|
109
|
+
try {
|
|
110
|
+
return (
|
|
111
|
+
realpathSync(fileURLToPath(import.meta.url)) ===
|
|
112
|
+
realpathSync(resolve(invokedPath))
|
|
113
|
+
);
|
|
114
|
+
} catch {
|
|
115
|
+
return false;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
if (isDirectInvocation(process.argv[1])) {
|
|
99
120
|
try {
|
|
100
121
|
process.stdout.write(`${main(process.argv.slice(2))}\n`);
|
|
101
122
|
} catch (error) {
|