@junoflow/cli 0.6.0 → 0.9.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 +189 -73
- package/app-client.js +306 -0
- package/eslint.app.config.js +34 -0
- package/eslint.flow.config.js +4 -2
- package/package.json +9 -4
- package/src/api.js +182 -39
- package/src/app-dev/build.js +134 -0
- package/src/app-dev/harness.js +108 -0
- package/src/app-dev/panel.html +336 -0
- package/src/app-dev/panel.js +290 -0
- package/src/app-dev/server.js +347 -0
- package/src/app-dev/stream.js +224 -0
- package/src/app-dev/watch.js +47 -0
- package/src/app-project.js +133 -0
- package/src/authoring-skills.js +2 -1
- package/src/commands/app-check.js +75 -0
- package/src/commands/app-deploy.js +102 -0
- package/src/commands/app-dev.js +141 -0
- package/src/commands/app-gen-types.js +37 -0
- package/src/commands/app-init.js +46 -0
- package/src/commands/app-pull.js +106 -0
- package/src/commands/check.js +31 -15
- package/src/commands/deploy.js +57 -4
- package/src/commands/flow-check.js +4 -22
- package/src/commands/flow-deploy.js +11 -8
- package/src/commands/flow-fixture.js +67 -0
- package/src/commands/flow-gen-types.js +12 -5
- package/src/commands/flow-pull.js +69 -40
- package/src/commands/pull.js +96 -102
- package/src/errors.js +3 -3
- package/src/exit.js +2 -2
- package/src/flow-project.js +47 -97
- package/src/index.js +62 -1
- package/src/project.js +76 -8
- package/src/watch.js +48 -11
- package/src/working-copy.js +262 -0
- package/tsconfig.page.json +15 -0
- package/verbs.json +51 -2
package/README.md
CHANGED
|
@@ -66,7 +66,8 @@ Every command has one effect:
|
|
|
66
66
|
starts a run, executes code), with nothing to roll back to.
|
|
67
67
|
|
|
68
68
|
`config set` and `agent-skill install` are **local**: they write a file on your
|
|
69
|
-
machine and change nothing on the instance.
|
|
69
|
+
machine and change nothing on the instance. So is `app dev`, which serves an app
|
|
70
|
+
working copy on localhost and never connects to an instance.
|
|
70
71
|
|
|
71
72
|
No command of a lower effect is a string prefix of a command of a higher one.
|
|
72
73
|
Claude Code matches a Bash permission rule by prefix, so an allowlist can list
|
|
@@ -256,15 +257,15 @@ its own. A missing `jq` or an expression `jq` rejects exits 2.
|
|
|
256
257
|
|
|
257
258
|
One table for the whole CLI, the working-copy commands included:
|
|
258
259
|
|
|
259
|
-
| Code | When
|
|
260
|
-
| ---- |
|
|
261
|
-
| 0 | Success
|
|
262
|
-
| 1 | A tool answer with a top-level string `error`, a failed check or deploy, or any other failure
|
|
263
|
-
| 2 | Usage: an unknown command or flag, bad `--input`, input the instance rejects, a bad `--jq`
|
|
264
|
-
| 3 | The instance is unreachable
|
|
265
|
-
| 4 |
|
|
266
|
-
| 5 | `juno ask` / `session approve`: the turn is still running
|
|
267
|
-
| 6 | `juno ask` / `session approve`: the assistant is waiting for an answer or an approval
|
|
260
|
+
| Code | When |
|
|
261
|
+
| ---- | ---------------------------------------------------------------------------------------------------- |
|
|
262
|
+
| 0 | Success |
|
|
263
|
+
| 1 | A tool answer with a top-level string `error`, a failed check or deploy, or any other failure |
|
|
264
|
+
| 2 | Usage: an unknown command or flag, bad `--input`, input the instance rejects, a bad `--jq` |
|
|
265
|
+
| 3 | The instance is unreachable |
|
|
266
|
+
| 4 | A working-copy `deploy` or `check`, any kind: the instance changed since the working copy was pulled |
|
|
267
|
+
| 5 | `juno ask` / `session approve`: the turn is still running |
|
|
268
|
+
| 6 | `juno ask` / `session approve`: the assistant is waiting for an answer or an approval |
|
|
268
269
|
|
|
269
270
|
An instance that does not serve a tool the CLI names is older than the CLI; that
|
|
270
271
|
is also exit 2, and the message says so.
|
|
@@ -407,30 +408,42 @@ truth and a working copy is where you edit the next version. Its `package.json`
|
|
|
407
408
|
names the instance (`juno.target`) and the flow or install it belongs to, so a
|
|
408
409
|
fresh clone deploys with no setup.
|
|
409
410
|
|
|
410
|
-
Both kinds have the same loop and the same npm scripts
|
|
411
|
+
Both kinds have the same loop and the same npm scripts, and so does an app
|
|
412
|
+
(`juno app init`), whose `check` stores a draft to preview at its `~draft/` URL:
|
|
411
413
|
|
|
412
414
|
```bash
|
|
413
415
|
npm install
|
|
414
|
-
npm test # local tsc and
|
|
416
|
+
npm test # local tsc, eslint and vitest
|
|
415
417
|
npm run check # ... then verify against the instance, which writes nothing
|
|
416
418
|
npm run deploy # verify, commit and activate the next version
|
|
417
|
-
npm run pull #
|
|
419
|
+
npm run pull # bring the working copy up to the active version
|
|
418
420
|
```
|
|
419
421
|
|
|
420
|
-
| Script | Flow working copy
|
|
421
|
-
| -------------- |
|
|
422
|
-
| `typecheck` | `tsc --noEmit`
|
|
423
|
-
| `lint` | `eslint .`
|
|
424
|
-
| `verify-types` | (absent)
|
|
425
|
-
| `test` | `npm run typecheck && npm run lint` | `npm run verify-types && npm run typecheck && npm run lint && vitest run` |
|
|
426
|
-
| `types` | `juno flow gen-types`
|
|
427
|
-
| `check` | `juno flow check`
|
|
428
|
-
| `deploy` | `juno flow deploy`
|
|
429
|
-
| `watch` | `juno flow deploy --watch`
|
|
430
|
-
| `pull` | `juno flow pull`
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
422
|
+
| Script | Flow working copy | Integration working copy | App working copy |
|
|
423
|
+
| -------------- | ------------------------------------------------- | ------------------------------------------------------------------------- | ------------------------------------------------- |
|
|
424
|
+
| `typecheck` | `tsc --noEmit` | `tsc --noEmit` | `tsc --noEmit && tsc --noEmit -p page` |
|
|
425
|
+
| `lint` | `eslint .` | `eslint .` | `eslint .` |
|
|
426
|
+
| `verify-types` | (absent) | `juno integration verify-types` | (absent) |
|
|
427
|
+
| `test` | `npm run typecheck && npm run lint && vitest run` | `npm run verify-types && npm run typecheck && npm run lint && vitest run` | `npm run typecheck && npm run lint && vitest run` |
|
|
428
|
+
| `types` | `juno flow gen-types` | `juno integration gen-types` | `juno app gen-types` |
|
|
429
|
+
| `check` | `juno flow check` | `juno integration check` | `juno app check` |
|
|
430
|
+
| `deploy` | `juno flow deploy` | `juno integration deploy` | `juno app deploy` |
|
|
431
|
+
| `watch` | `juno flow deploy --watch` | `juno integration deploy --watch` | `juno app deploy --watch` |
|
|
432
|
+
| `pull` | `juno flow pull` | `juno integration pull` | `juno app pull` |
|
|
433
|
+
| `dev` | (absent) | (absent) | `juno app dev` |
|
|
434
|
+
|
|
435
|
+
`dev` exists only in an app working copy, because flows and integrations have no
|
|
436
|
+
page to serve. `npm run dev` serves the app on `http://localhost:8090/`
|
|
437
|
+
(`--port <n>` picks another) with no instance, no credentials and no network:
|
|
438
|
+
the page is built from `page/` on each request, the handlers run in Node through
|
|
439
|
+
the testkit's `appHarness`, and live values come from a scenario file
|
|
440
|
+
(`--scenario test/fixtures/<name>.json`). A panel beside the page sets values,
|
|
441
|
+
presses controls and switches scenarios, and saving a file rebuilds and reloads.
|
|
442
|
+
It uses the `esbuild` and `@junoflow/testkit` the working copy installs.
|
|
443
|
+
|
|
444
|
+
`init` writes these lines as the instance renders them. After that they are
|
|
445
|
+
yours: `pull` never changes `scripts`. To see the current lines, run `init` into
|
|
446
|
+
a fresh directory and compare.
|
|
434
447
|
|
|
435
448
|
The working-copy commands sit in the `flow` and `integration` groups beside the
|
|
436
449
|
commands that act on the instance, and `juno flow --help` and
|
|
@@ -439,27 +452,61 @@ commands that act on the instance, and `juno flow --help` and
|
|
|
439
452
|
argument: `juno flow deploy porch-light` exits 2 and tells you to run
|
|
440
453
|
`juno flow init porch-light` and deploy from inside it.
|
|
441
454
|
|
|
442
|
-
| Effect | Commands
|
|
443
|
-
| -------- |
|
|
444
|
-
| `read` | `init`, `gen-types`, `verify-types`, `check`, `pull`
|
|
445
|
-
| `change` | `deploy`: it adds a version to the flow's or install's history
|
|
455
|
+
| Effect | Commands |
|
|
456
|
+
| -------- | -------------------------------------------------------------------- |
|
|
457
|
+
| `read` | `init`, `gen-types`, `verify-types`, `check`, `pull`, `flow fixture` |
|
|
458
|
+
| `change` | `deploy`: it adds a version to the flow's or install's history |
|
|
459
|
+
| `local` | `app dev`: a server on localhost that touches no instance |
|
|
446
460
|
|
|
447
|
-
`init` and `
|
|
448
|
-
is `read`.
|
|
461
|
+
`init`, `pull` and `flow fixture` write local files, but change nothing in Juno,
|
|
462
|
+
so their effect is `read`.
|
|
449
463
|
|
|
450
464
|
After writing a working copy, `init` prints the skills for writing that kind,
|
|
451
465
|
one `<name> — <description>` line each, the same index Juno's in-app flow or
|
|
452
466
|
integration author is given; load one with `juno skill <name>`.
|
|
453
|
-
`juno flow --help` and `juno integration --help` list them too.
|
|
454
|
-
|
|
455
|
-
|
|
467
|
+
`juno flow --help` and `juno integration --help` list them too.
|
|
468
|
+
|
|
469
|
+
### What Juno stores, and what `pull` writes
|
|
470
|
+
|
|
471
|
+
A working copy holds three kinds of file:
|
|
472
|
+
|
|
473
|
+
| Kind | Files | Stored by Juno |
|
|
474
|
+
| --------- | ------------------------------------------------------------------------------------------------- | -------------------------------------- |
|
|
475
|
+
| artifact | `manifest.json`, `src/**`, `test/**` | yes, with every version, byte for byte |
|
|
476
|
+
| generated | `types/**` | no; generated from the manifest |
|
|
477
|
+
| project | everything else: `tsconfig.json`, `eslint.config.js`, `README.md`, `.gitignore`, `package.json` … | no |
|
|
478
|
+
|
|
479
|
+
`check` and `deploy` send the artifact files. Your tests travel with the
|
|
480
|
+
version, so a copy pulled elsewhere gets them back. Juno stores `test/**` and
|
|
481
|
+
nothing more: it never type-checks, lints or runs a test. `npm test` runs them
|
|
482
|
+
in your checkout.
|
|
483
|
+
|
|
484
|
+
`pull` makes the artifact files the active version's, exactly as Juno stores
|
|
485
|
+
them, and regenerates `types/`. It deletes a local file only when Juno deleted
|
|
486
|
+
it: the version recorded in `juno.base_version` had the file and the pulled
|
|
487
|
+
version does not. A file neither version has is one you have not deployed yet,
|
|
488
|
+
and `pull` leaves it alone. A working copy with no `base_version` has nothing to
|
|
489
|
+
compare against, so `pull` deletes nothing. It prints what it wrote and, on a
|
|
490
|
+
second line, what it removed:
|
|
491
|
+
|
|
492
|
+
```text
|
|
493
|
+
pulled porch-light v7 from http://juno.local:8080 (manifest.json, package.json, src/flow.ts)
|
|
494
|
+
removed src/old.ts
|
|
495
|
+
```
|
|
496
|
+
|
|
497
|
+
`pull` never writes or deletes a project file. In `package.json` it sets two
|
|
498
|
+
keys, `juno.base_version` and `dependencies` (from the manifest), and leaves the
|
|
499
|
+
rest as you wrote it. An integration whose manifest declares no dependencies
|
|
500
|
+
keeps them in `package.json` alone, so there `pull` leaves `dependencies` as it
|
|
501
|
+
is. It refuses to overwrite uncommitted changes in a git working tree unless you
|
|
502
|
+
pass `--force`.
|
|
456
503
|
|
|
457
504
|
## Flows as files
|
|
458
505
|
|
|
459
506
|
```bash
|
|
460
507
|
juno flow init porch-light # the flow's active version, or a stub for a new id
|
|
461
508
|
cd porch-light && npm install
|
|
462
|
-
$EDITOR flow.ts manifest.json
|
|
509
|
+
$EDITOR src/flow.ts manifest.json
|
|
463
510
|
npm test
|
|
464
511
|
npm run check
|
|
465
512
|
npm run deploy
|
|
@@ -468,33 +515,77 @@ npm run deploy
|
|
|
468
515
|
`juno flow init <id>` writes `./<id>` (or the current directory, with `--here`).
|
|
469
516
|
For a flow that has an active version, it is that version. For a new id it is a
|
|
470
517
|
stub whose only trigger is a `call` trigger, so a stub deployed by accident
|
|
471
|
-
never fires on its own.
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
|
477
|
-
|
|
|
478
|
-
| `
|
|
479
|
-
| `
|
|
480
|
-
| `
|
|
481
|
-
| `
|
|
482
|
-
|
|
|
518
|
+
never fires on its own. When the version stores no `test/**`, `init` also writes
|
|
519
|
+
a starter `test/flow.test.ts`: a conformance test against `@junoflow/testkit`'s
|
|
520
|
+
`flowHarness`, and one `it.todo` per trigger. A working copy has the same shape
|
|
521
|
+
as an integration's:
|
|
522
|
+
|
|
523
|
+
| File | What it is |
|
|
524
|
+
| --------------------- | ------------------------------------------------------------------------------------------ |
|
|
525
|
+
| `manifest.json` | the flow's manifest |
|
|
526
|
+
| `src/flow.ts` | the flow's entry |
|
|
527
|
+
| `src/**` | any other `.ts` or `.json` module the entry imports |
|
|
528
|
+
| `test/**` | your tests and their `.ts` or `.json` fixtures; stored with the flow, never compiled |
|
|
529
|
+
| `types/flow-env.d.ts` | the module the source imports its types from, generated from the manifest and the instance |
|
|
530
|
+
| `types/flow-api.d.ts` | the SDK's generic declarations, which `flow-env.d.ts` fills in; never import it directly |
|
|
531
|
+
| `tsconfig.json` | extends `@junoflow/cli/tsconfig.base.json` |
|
|
532
|
+
| `eslint.config.js` | `@junoflow/cli/eslint.flow.config.js`: the rules Juno's verify step lints flows by |
|
|
533
|
+
| `package.json` | the scripts, the dependencies, and `juno.target` / `flow_id` / `base_version` |
|
|
534
|
+
| `.gitignore` | `node_modules/` |
|
|
535
|
+
|
|
536
|
+
Every source file imports its types from the generated module:
|
|
537
|
+
|
|
538
|
+
```ts
|
|
539
|
+
// src/flow.ts
|
|
540
|
+
import type { Flow } from '../types/flow-env';
|
|
541
|
+
import { describe } from './describe';
|
|
542
|
+
|
|
543
|
+
export default {
|
|
544
|
+
triggers: {
|
|
545
|
+
onCall: async ({ status }) => status.ok(describe()),
|
|
546
|
+
},
|
|
547
|
+
} satisfies Flow;
|
|
548
|
+
```
|
|
549
|
+
|
|
550
|
+
`src/` and `test/` hold `.ts` and `.json` files only, at most 64 of them
|
|
551
|
+
together, each at most 512 KiB. Every one is sent on `check` and `deploy`. The
|
|
552
|
+
files under `src/` are type-checked and linted, and only `src/flow.ts` must
|
|
553
|
+
contain `satisfies Flow`. The files under `test/` are stored as they are; the
|
|
554
|
+
flow's `eslint.config.js` skips them too. `types/` is generated and is never
|
|
555
|
+
sent.
|
|
483
556
|
|
|
484
557
|
| Command | What it does |
|
|
485
558
|
| ----------------------------------------------- | -------------------------------------------------------------------------------------- |
|
|
486
559
|
| `juno flow init <id> [--here]` | write a working copy from the instance |
|
|
487
|
-
| `juno flow gen-types` | regenerate `flow-env.d.ts` and `flow-api.d.ts` from `manifest.json`
|
|
560
|
+
| `juno flow gen-types` | regenerate `types/flow-env.d.ts` and `types/flow-api.d.ts` from `manifest.json` |
|
|
488
561
|
| `juno flow check [--skip-local] [--json]` | local `tsc --noEmit` and `eslint .`, then verify against the instance, writing nothing |
|
|
489
562
|
| `juno flow deploy [--watch] [--force] [--json]` | verify, commit and activate; write back the manifest, the types and `base_version` |
|
|
490
|
-
| `juno flow pull [--force]` |
|
|
563
|
+
| `juno flow pull [--force]` | bring the working copy up to the active version |
|
|
564
|
+
| `juno flow fixture --run <seq> [--force]` | write run `seq` as a test fixture, `test/fixtures/<flow-id>-<seq>.json` |
|
|
565
|
+
|
|
566
|
+
`pull` writes `manifest.json`, `src/**`, `test/**` and both `types/` files, and
|
|
567
|
+
deletes what the flow deleted (see
|
|
568
|
+
[What Juno stores](#what-juno-stores-and-what-pull-writes)).
|
|
491
569
|
|
|
492
570
|
`deploy` writes back what Juno stored: the canonical `manifest.json`, freshly
|
|
493
|
-
generated types, and the new version number. `--watch` redeploys whenever
|
|
494
|
-
`
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
571
|
+
generated types, and the new version number. `--watch` redeploys whenever a file
|
|
572
|
+
under `src/` or `manifest.json` is saved (a deploy sends `test/` too, but saving
|
|
573
|
+
a test does not start one), skips a save that changed nothing, and keeps
|
|
574
|
+
watching after a failure. `--json` on `check` and `deploy` prints the instance's
|
|
575
|
+
JSON answer (or, when verification fails, its diagnostics) on stdout instead,
|
|
576
|
+
for CI; the integration commands take it too.
|
|
577
|
+
|
|
578
|
+
`fixture` turns a recorded run into a scenario a test loads with
|
|
579
|
+
`h.scenario(fixture)` from `@junoflow/testkit`: the event the run received, the
|
|
580
|
+
world it saw as far as Juno recorded it, and, under `expect`, the status, steps
|
|
581
|
+
and target calls it produced. It writes the file the instance builds, prints
|
|
582
|
+
`wrote test/fixtures/porch-light-42.json`, and lists on stderr each thing the
|
|
583
|
+
run did not record, such as a state value reconstructed from history or a
|
|
584
|
+
credential to fill in. It refuses to overwrite an existing fixture without
|
|
585
|
+
`--force` (exit 1), warns when the run ran another version than
|
|
586
|
+
`juno.base_version`, and exits 1 with the instance's reason for a run it cannot
|
|
587
|
+
replay: one still going, one that slept or waited for an event, or one that was
|
|
588
|
+
cancelled.
|
|
498
589
|
|
|
499
590
|
### The flow id and `base_version`
|
|
500
591
|
|
|
@@ -522,11 +613,11 @@ differ, naming the packages.
|
|
|
522
613
|
|
|
523
614
|
### Why there is no `flow verify-types`
|
|
524
615
|
|
|
525
|
-
`flow-env.d.ts` describes the instance as well as the manifest: the states
|
|
526
|
-
flow binds, the integrations and controls it calls. It goes stale whenever
|
|
527
|
-
instance changes, and Juno regenerates it on every check and deploy, so
|
|
528
|
-
local types never ship. `npm run types` refreshes your copy when the
|
|
529
|
-
disagrees with the instance.
|
|
616
|
+
`types/flow-env.d.ts` describes the instance as well as the manifest: the states
|
|
617
|
+
the flow binds, the integrations and controls it calls. It goes stale whenever
|
|
618
|
+
the instance changes, and Juno regenerates it on every check and deploy, so
|
|
619
|
+
stale local types never ship. `npm run types` refreshes your copy when the
|
|
620
|
+
editor disagrees with the instance.
|
|
530
621
|
|
|
531
622
|
## Developing integrations
|
|
532
623
|
|
|
@@ -541,17 +632,18 @@ juno integration init my-integration --url http://juno.local:8080
|
|
|
541
632
|
|
|
542
633
|
### Commands
|
|
543
634
|
|
|
544
|
-
| Command
|
|
545
|
-
|
|
|
546
|
-
| `juno integration init <id> [--name <name>] [--here]`
|
|
547
|
-
| `juno integration gen-types`
|
|
548
|
-
| `juno integration verify-types`
|
|
549
|
-
| `juno integration check [--skip-local] [--id <id>] [--json]`
|
|
550
|
-
| `juno integration deploy [--watch] [--id <id>] [--json]`
|
|
551
|
-
| `juno integration pull [--force] [--id <id>]`
|
|
635
|
+
| Command | What it does |
|
|
636
|
+
| ------------------------------------------------------------------ | ------------------------------------------------------------------------------ |
|
|
637
|
+
| `juno integration init <id> [--name <name>] [--here]` | write the install's project from a Juno, or a starter for a new id |
|
|
638
|
+
| `juno integration gen-types` | POST `manifest.json`, write `types/` |
|
|
639
|
+
| `juno integration verify-types` | check `types/` still matches `manifest.json`; talks to nothing |
|
|
640
|
+
| `juno integration check [--skip-local] [--id <id>] [--json]` | local `verify-types` + `tsc --noEmit` + `eslint`, then validate against a Juno |
|
|
641
|
+
| `juno integration deploy [--watch] [--force] [--id <id>] [--json]` | upload, verify, activate, and write back the returned types and `base_version` |
|
|
642
|
+
| `juno integration pull [--force] [--id <id>]` | write back the manifest, `src/`, `test/`, `types/` and `base_version` |
|
|
552
643
|
|
|
553
644
|
They exit as the [exit-code table](#exit-codes) says: 1 for a failed check or
|
|
554
|
-
deploy, 2 for a usage error, 3 when the instance is unreachable
|
|
645
|
+
deploy, 2 for a usage error, 3 when the instance is unreachable, 4 for a stale
|
|
646
|
+
working copy (see [`base_version`](#base_version)).
|
|
555
647
|
|
|
556
648
|
### Options
|
|
557
649
|
|
|
@@ -561,11 +653,35 @@ deploy, 2 for a usage error, 3 when the instance is unreachable.
|
|
|
561
653
|
| `--id <id>` | address an install under a different id than the manifest declares (`check`, `deploy`, `pull`) |
|
|
562
654
|
| `--name <name>` | display name for a new integration (`init`) |
|
|
563
655
|
| `--watch` | redeploy on every save (`deploy`) |
|
|
564
|
-
| `--force` | overwrite a dirty working tree (`pull`)
|
|
656
|
+
| `--force` | overwrite a dirty working tree (`pull`); replace the active version whatever the base (`deploy`) |
|
|
565
657
|
| `--here` | scaffold into the current directory (`init`) |
|
|
566
658
|
| `--skip-local` | skip the local verify-types/tsc/eslint pass (`check`) |
|
|
567
659
|
| `--json` | print the instance's JSON answer (or the failed verify's diagnostics) on stdout, for CI (`check`, `deploy`) |
|
|
568
660
|
|
|
661
|
+
### `base_version`
|
|
662
|
+
|
|
663
|
+
`package.json`'s `juno.base_version` is the version the working copy was pulled
|
|
664
|
+
from or last deployed. `init` of an installed id, the **Download project** zip,
|
|
665
|
+
`pull` and every successful `deploy` write it. `deploy` and `check` send it, and
|
|
666
|
+
when the install's active version is anything else (someone deployed another
|
|
667
|
+
copy, asked the assistant to change the integration, or rolled it back), Juno
|
|
668
|
+
refuses and the CLI exits **4**:
|
|
669
|
+
|
|
670
|
+
```text
|
|
671
|
+
integration "pushover": active version is v4, but this working copy was pulled from v3 — pull it again, or deploy with --force to replace it
|
|
672
|
+
```
|
|
673
|
+
|
|
674
|
+
Run `npm run pull` to start from the active version, or
|
|
675
|
+
`juno integration deploy --force` to replace it. A working copy without a
|
|
676
|
+
`base_version` sends none; its first deploy or pull records one.
|
|
677
|
+
|
|
678
|
+
The base belongs to the install `manifest.json` names. `--id <other>` deploys
|
|
679
|
+
the same code to a different install, whose versions this copy has never seen,
|
|
680
|
+
so it sends no base, writes none back, and warns
|
|
681
|
+
`no stale-base check: deploying to <other>, not <manifest id>`. It needs no
|
|
682
|
+
`--force`. `pull --id <other>` rewrites `manifest.json` to that install, so
|
|
683
|
+
later deploys are checked against it.
|
|
684
|
+
|
|
569
685
|
### The loop
|
|
570
686
|
|
|
571
687
|
```bash
|
|
@@ -629,5 +745,5 @@ of an id that is already installed writes that install's project, the one the
|
|
|
629
745
|
**Develop locally → Download project** button gives you; `init` of a new id
|
|
630
746
|
writes a starter. Neither is a local template: the CLI writes the files it is
|
|
631
747
|
handed, so a scaffold cannot drift from what the server ejects. To refresh an
|
|
632
|
-
existing checkout use `juno integration pull`, which
|
|
633
|
-
|
|
748
|
+
existing checkout use `juno integration pull`, which touches only the files Juno
|
|
749
|
+
stores; a second download would clobber your working tree.
|