@niroai/niro 0.10.1 → 0.11.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/CHANGELOG.md +117 -0
- package/README.md +71 -1
- package/docs/working-on-branches.md +55 -0
- package/package.json +1 -1
- package/src/commands/cleanup.js +689 -0
- package/src/commands/info.js +51 -2
- package/src/commands/release.js +13 -60
- package/src/commands/takeover.js +52 -2
- package/src/commands/watch.js +93 -25
- package/src/index.js +23 -3
- package/src/lib/folderSync.js +6 -0
- package/src/lib/periodicClaim.js +100 -0
- package/src/lib/printError.js +46 -0
- package/src/lib/takeoverRestore.js +156 -0
- package/src/mcp/setup.js +178 -13
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,123 @@
|
|
|
2
2
|
|
|
3
3
|
Notable changes to `@niroai/niro`. Dates are release dates.
|
|
4
4
|
|
|
5
|
+
## 0.11.0 — 2026-09-03
|
|
6
|
+
|
|
7
|
+
### The watcher stops pausing and resuming your uploads over and over
|
|
8
|
+
|
|
9
|
+
The background watcher holds back uploads from a folder whose branch disagrees with the branch its
|
|
10
|
+
private copy is labelled with, so two branches cannot be written into one copy. One developer's log
|
|
11
|
+
carried 306 pauses against 286 resumes. Those counts being nearly equal is the whole story: it was
|
|
12
|
+
toggling, not failing 306 times.
|
|
13
|
+
|
|
14
|
+
Once a minute the watcher asks which branch the copy is on. A request that failed returned nothing,
|
|
15
|
+
which was read as "everything is fine again": it printed "resuming uploads" and cleared the pause, so
|
|
16
|
+
the next check paused and warned all over again. It also let a folder that genuinely should not be
|
|
17
|
+
uploading start writing again on any slow request. Now a question the server could not answer changes
|
|
18
|
+
nothing at all, in either direction. The same six alternating checks went from 3 warnings and 3 resumes
|
|
19
|
+
down to 1 and 0.
|
|
20
|
+
|
|
21
|
+
The message was wrong too. When it paused it looked for another folder on the same *project* and blamed
|
|
22
|
+
it. A project can hold several repositories and each folder can have its own, so it regularly named a
|
|
23
|
+
folder that was writing nowhere near yours and told you to discard it. It now matches on the repository
|
|
24
|
+
actually being written to, so it either names the folder that really shares your copy or tells you
|
|
25
|
+
plainly that you switched branch in that folder yourself.
|
|
26
|
+
|
|
27
|
+
**The pause itself is unchanged, deliberately.** While a folder's branch and its copy's label disagree,
|
|
28
|
+
your assistant's questions are not sent to that copy anyway, so uploading into it would only fill it
|
|
29
|
+
with the wrong branch's files. Run `niro new-temp-project` in that folder to put it back in step.
|
|
30
|
+
|
|
31
|
+
### Servlet apps declare their endpoints in a file that was never sent
|
|
32
|
+
|
|
33
|
+
A Java web app written before Spring Boot lists its whole HTTP surface in `WEB-INF/web.xml` rather than
|
|
34
|
+
in annotations. That file was missing from the set the CLI offers, so such a project indexed as a
|
|
35
|
+
servlet application with no endpoints at all. Measured on one repository: 11 real endpoints, 0 detected,
|
|
36
|
+
against an otherwise complete and healthy index.
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
### Stale pointers clean themselves up
|
|
40
|
+
|
|
41
|
+
Delete a project, or let an unused private copy expire, and your machine is never told. The folder
|
|
42
|
+
carries on naming something that is gone. That is what makes `niro new-temp-project` in another
|
|
43
|
+
worktree say the slot is taken, naming a copy that no longer exists.
|
|
44
|
+
|
|
45
|
+
That command never shipped: it went in under this same Unreleased section and has been renamed since,
|
|
46
|
+
so `niro doctor sync-registry` is its first public name. It also only helped if you remembered to run
|
|
47
|
+
it. Now the background watcher runs it every six hours by itself, and it covers two more cases:
|
|
48
|
+
|
|
49
|
+
- **Ordinary registrations**, not just private copies. A folder registered against a deleted project
|
|
50
|
+
used to sit there for ever: the daemon retried it on every start and nothing could clear it. One
|
|
51
|
+
developer asked whether they should edit `~/.niro/projects.json` by hand. They were right that there
|
|
52
|
+
was no supported way.
|
|
53
|
+
- **`.niro-project` files** naming something the server does not recognise. Nothing has ever surfaced
|
|
54
|
+
these, and they are not inert: that file is read before your git remote, so a stale one keeps
|
|
55
|
+
answering. They are REPORTED, never deleted — the file can hold a project's name rather than its id,
|
|
56
|
+
and a renamed project is indistinguishable from a deleted one from the client, so the right repair
|
|
57
|
+
(update it, or remove it) is yours to choose.
|
|
58
|
+
|
|
59
|
+
**What it refuses to do matters more than what it does.** A deleted project is not enough to
|
|
60
|
+
unregister a folder, because a project can be deleted while its repos are moved to another one and
|
|
61
|
+
that folder is still syncing fine, so the repo is checked too. On the machine this was built on that
|
|
62
|
+
took the count from 18 folders to 1. And a `.niro-project` may hold an *alias* rather than an id, which
|
|
63
|
+
the direct lookup reports as "not found" for a project that is perfectly alive; the account's project
|
|
64
|
+
list is now the authority. Both of those were caught by dry runs against real data after the unit tests
|
|
65
|
+
were green.
|
|
66
|
+
|
|
67
|
+
The watcher remembers when it last swept, so restarting it does not re-run the job, and a `niro watch`
|
|
68
|
+
left in a terminal cannot sweep at the same moment as the background one. It stays silent when there
|
|
69
|
+
was nothing to do.
|
|
70
|
+
|
|
71
|
+
### When you run out of private copies, it says where they are
|
|
72
|
+
|
|
73
|
+
The server already tells you which branches are holding your copies. It cannot tell you where those
|
|
74
|
+
branches are checked out, because that is a fact about your machine. The CLI now adds the folder next
|
|
75
|
+
to each branch, so you can go straight to one and discard it.
|
|
76
|
+
|
|
77
|
+
### Multi-line error messages are no longer cut off
|
|
78
|
+
|
|
79
|
+
Errors printed only their first line, so any message built over several lines lost the rest. Two were
|
|
80
|
+
affected: "Multiple projects match this repo — pass --project:" showed no projects, and the
|
|
81
|
+
working-copy-limit refusal showed no folders. The text was always correct and simply never reached the
|
|
82
|
+
screen. Found by running the real CLI against a real backend until it refused; no unit test could have
|
|
83
|
+
caught it, because both features assert on the message and the message was right.
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
### `niro doctor sync-registry` tidies up copies the server deleted for you
|
|
87
|
+
|
|
88
|
+
A temporary project can go without this machine ever being told: somebody deletes it in the web
|
|
89
|
+
app, or the sweeper reaps it after two weeks. The folder keeps a registration pointing at an id
|
|
90
|
+
that resolves to nothing. That is not harmless, because it is exactly what makes
|
|
91
|
+
`niro new-temp-project` in a second worktree refuse with "already held by another folder".
|
|
92
|
+
|
|
93
|
+
`niro discard-temp-project` already repaired one folder in that state. What nothing did was find
|
|
94
|
+
them. On the machine this was built on, 13 of 14 registered copies had gone and every one of the
|
|
95
|
+
14 folders was still pointing at a dead id.
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
niro doctor sync-registry # check and repair
|
|
99
|
+
niro doctor sync-registry --dry-run # list, change nothing
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
It asks the server once per copy and moves the folders whose copy has gone back onto their
|
|
103
|
+
original project. Three things it will not do. It never treats an unreachable server as an
|
|
104
|
+
answer: only a definitive "Project not found" counts, so a 500, a timeout, or a project you are
|
|
105
|
+
simply not allowed to see leaves every entry exactly as it was. It never unregisters a folder,
|
|
106
|
+
because the watch daemon still needs somewhere to sync it. And it never guesses: a copy that no
|
|
107
|
+
folder recorded a source project for is reported and left alone.
|
|
108
|
+
|
|
109
|
+
`--json` for scripts, `--dry-run` to look first, `-y` to skip the prompt. At a terminal, `--json`
|
|
110
|
+
asks for one of the last two rather than writing without a prompt it cannot show.
|
|
111
|
+
|
|
112
|
+
Two guards came out of review and apply to `niro discard-temp-project` as well, because both commands
|
|
113
|
+
now share one repair routine. A folder re-registered by another process while the command runs is
|
|
114
|
+
left alone and reported, instead of being overwritten by a stale snapshot. And within a copy that
|
|
115
|
+
covers several folders, the one holding the record of the original project is always written last, so
|
|
116
|
+
a run interrupted half way through can still be finished by running it again.
|
|
117
|
+
|
|
118
|
+
Folders that had no local registration before the copy was made are now listed separately from the
|
|
119
|
+
ones that keep syncing. They go back to not having one, which is where they started, but calling that
|
|
120
|
+
"repaired" and stopping there implied the daemon was still watching them.
|
|
121
|
+
|
|
5
122
|
## 0.10.0 — 2026-08-28
|
|
6
123
|
|
|
7
124
|
One command to get started, and a way to check what Niro is worth.
|
package/README.md
CHANGED
|
@@ -67,6 +67,13 @@ niro build
|
|
|
67
67
|
```
|
|
68
68
|
Rebuild the index by hand and watch it finish.
|
|
69
69
|
|
|
70
|
+
```bash
|
|
71
|
+
niro doctor
|
|
72
|
+
```
|
|
73
|
+
Check this machine against the server and repair what is safe to repair. Today that is
|
|
74
|
+
`niro doctor sync-registry`, which fixes folders and `.niro-project` files left pointing at projects
|
|
75
|
+
that have gone or been renamed. The background watcher runs it for you every six hours.
|
|
76
|
+
|
|
70
77
|
---
|
|
71
78
|
|
|
72
79
|
## Working on a branch
|
|
@@ -85,10 +92,72 @@ niro discard-temp-project
|
|
|
85
92
|
```
|
|
86
93
|
Run when the branch is merged. Forgotten copies are cleaned up after two weeks.
|
|
87
94
|
|
|
95
|
+
If a copy is deleted for you, or a project is renamed, your machine is not told and the folder keeps
|
|
96
|
+
pointing at something that is gone. `niro doctor sync-registry` sorts that out, and the background
|
|
97
|
+
watcher runs it every six hours — see [When a project is deleted](#when-a-project-is-deleted).
|
|
98
|
+
|
|
88
99
|
Full guide: [docs/working-on-branches.md](https://unpkg.com/@niroai/niro/docs/working-on-branches.md)
|
|
89
100
|
|
|
90
101
|
---
|
|
91
102
|
|
|
103
|
+
## When a project is deleted
|
|
104
|
+
|
|
105
|
+
Delete a project, or let an unused private copy expire, and your machine is not told. The folder
|
|
106
|
+
carries on pointing at something that is no longer there.
|
|
107
|
+
|
|
108
|
+
That is not just untidy. It is what makes `niro new-temp-project` in another folder say the slot is
|
|
109
|
+
already taken, naming a copy that no longer exists. And a `.niro-project` file left naming a deleted
|
|
110
|
+
project keeps answering, because it is read before your git remote.
|
|
111
|
+
|
|
112
|
+
The background watcher checks every six hours and sorts this out for you. `niro
|
|
113
|
+
doctor sync-registry` does the same thing on demand.
|
|
114
|
+
|
|
115
|
+
What it does depends on what went missing:
|
|
116
|
+
|
|
117
|
+
| What is gone | What happens to your folder |
|
|
118
|
+
|---|---|
|
|
119
|
+
| A private copy of a project | Goes back to the original project and carries on syncing |
|
|
120
|
+
| The project itself | Left alone if the repo still exists; unregistered only when both are gone |
|
|
121
|
+
| Neither, just a stale `.niro-project` | Repaired if your git remote says which project it should name; removed if it names nothing and is not shared; otherwise you are told |
|
|
122
|
+
|
|
123
|
+
It never deletes anything on the server, and it never touches a `.niro-project` file. Everything it
|
|
124
|
+
acts on has already gone. It only acts on what it can check, too: a folder git cannot read, or a
|
|
125
|
+
project it could not reach, is left exactly as it is and reported. A bad connection can never cost
|
|
126
|
+
you a working folder.
|
|
127
|
+
|
|
128
|
+
**How it decides what to do with a stale `.niro-project`.** That file can hold a project's name
|
|
129
|
+
rather than its id, so a renamed project looks exactly like a deleted one. Niro uses a second signal:
|
|
130
|
+
your folder's git remote. If the remote points at exactly one project, the pin is rewritten to that
|
|
131
|
+
project's id, which cannot be broken by a future rename. If the remote points at nothing either, the
|
|
132
|
+
pin identifies nothing and is removed.
|
|
133
|
+
|
|
134
|
+
**Unless the file is committed.** A `.niro-project` in git is shared with everyone who clones the
|
|
135
|
+
repo, and what looks like a dead project to you may be a colleague's. Niro never changes a committed
|
|
136
|
+
one for you. It tells you, and you decide.
|
|
137
|
+
|
|
138
|
+
`niro info` also mentions it when you are standing in an affected folder, so you do not have to go
|
|
139
|
+
looking.
|
|
140
|
+
|
|
141
|
+
## When you run out of private copies
|
|
142
|
+
|
|
143
|
+
You get a limited number of private copies of each project. If you hit that limit, Niro tells you
|
|
144
|
+
which branches are holding them, and the CLI adds where each one is checked out:
|
|
145
|
+
|
|
146
|
+
```
|
|
147
|
+
You already have 5 working copies of this project, which is the limit (5).
|
|
148
|
+
They are for: feature/a, feature/b, feature/c, feature/d, feature/e.
|
|
149
|
+
|
|
150
|
+
You have 5 working copies of this project on this machine:
|
|
151
|
+
feature/a /home/you/work/service
|
|
152
|
+
feature/b /home/you/work/service-wt2
|
|
153
|
+
...
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Run `niro discard-temp-project` in one you have finished with, then try again. Copies nobody has
|
|
157
|
+
touched for a while are also cleared automatically.
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
92
161
|
## Measure what Niro changes
|
|
93
162
|
|
|
94
163
|
```bash
|
|
@@ -181,7 +250,8 @@ Watch this folder in the foreground instead, for one session.
|
|
|
181
250
|
## Reference
|
|
182
251
|
|
|
183
252
|
Add `--help` to any command for its flags. Add `--json` to `whoami`, `info`, `status`,
|
|
184
|
-
`projects`, `build`, `ab report
|
|
253
|
+
`projects`, `build`, `ab report`, `edit --list-env` and `doctor sync-registry` for machine-readable
|
|
254
|
+
output.
|
|
185
255
|
|
|
186
256
|
| File | What it holds |
|
|
187
257
|
|---|---|
|
|
@@ -63,6 +63,61 @@ Run this in the repo folder:
|
|
|
63
63
|
It deletes your private copy. Your local files are never touched.
|
|
64
64
|
If you forget, Niro deletes unused copies by itself after two weeks.
|
|
65
65
|
|
|
66
|
+
## Tidying up copies that were deleted for you
|
|
67
|
+
|
|
68
|
+
When a copy goes after two weeks, or somebody deletes it in the web app,
|
|
69
|
+
your machine is not told. The folder is left pointing at a copy that is
|
|
70
|
+
no longer there. Nothing breaks, but "niro new-temp-project" in another
|
|
71
|
+
worktree of the same repo will say the slot is already taken.
|
|
72
|
+
|
|
73
|
+
Run this from anywhere to sort it out:
|
|
74
|
+
|
|
75
|
+
niro doctor sync-registry
|
|
76
|
+
|
|
77
|
+
You will rarely need to type it. The background watcher runs the same
|
|
78
|
+
check every six hours by itself.
|
|
79
|
+
|
|
80
|
+
It sorts out three things, and treats them differently:
|
|
81
|
+
|
|
82
|
+
- A folder pointing at a private copy that has gone goes back to the
|
|
83
|
+
original project, and carries on syncing.
|
|
84
|
+
- A folder pointing at a project that has gone is only unregistered when
|
|
85
|
+
the repo has gone too. A project can be deleted while its repos are
|
|
86
|
+
moved somewhere else, and that folder is still syncing perfectly well.
|
|
87
|
+
- A ".niro-project" file naming something the server does not know is
|
|
88
|
+
repaired where possible. That file can hold a project's NAME rather
|
|
89
|
+
than its id, so a renamed project looks exactly like a deleted one.
|
|
90
|
+
Niro checks your folder's git remote instead: if that points at one
|
|
91
|
+
project, the file is rewritten to that project's id, which a future
|
|
92
|
+
rename cannot break. If the remote points at nothing either, the file
|
|
93
|
+
names nothing and is removed.
|
|
94
|
+
|
|
95
|
+
Not if the file is committed to git, though. Then it is shared with
|
|
96
|
+
everyone who clones the repo, and a project that means nothing to you
|
|
97
|
+
may be a colleague's. Niro tells you and leaves the choice to you.
|
|
98
|
+
"niro info" mentions it too, when you are standing in that folder.
|
|
99
|
+
|
|
100
|
+
Copies that are still there are left alone, and so is anything it could
|
|
101
|
+
not check, so a dropped connection never costs you a working folder. Add
|
|
102
|
+
"--dry-run" to see the list without changing anything.
|
|
103
|
+
|
|
104
|
+
## When you run out of private copies
|
|
105
|
+
|
|
106
|
+
You get a limited number of private copies of each project. When you hit
|
|
107
|
+
the limit, Niro says which branches are holding them, and the CLI adds
|
|
108
|
+
where each one is checked out on this machine:
|
|
109
|
+
|
|
110
|
+
You already have 5 working copies of this project, which is
|
|
111
|
+
the limit (5). They are for: feature/a, feature/b, ...
|
|
112
|
+
|
|
113
|
+
You have 5 working copies of this project on this machine:
|
|
114
|
+
feature/a /home/you/work/service
|
|
115
|
+
feature/b /home/you/work/service-wt2
|
|
116
|
+
|
|
117
|
+
Run "niro discard-temp-project" in one you have finished with, then try
|
|
118
|
+
again. Copies nobody has touched for a while are cleared automatically,
|
|
119
|
+
so this usually sorts itself out.
|
|
120
|
+
|
|
66
121
|
## A feature that spans several repos
|
|
67
122
|
|
|
68
123
|
Run "niro new-temp-project" in each repo folder you branch.
|