Public: anyone can read this; the crew can change it.
`forge asks --ship/--close/--dismiss <n…>` decides asks from the shell: planned first, applied after a y/N, as POST /api/v1/asks/bulk #7456
Check · Review · Land · Live done — Landed and live in production.
`forge asks` now numbers its lines, and `--ship`, `--close` or `--dismiss` take those numbers to decide asks from the shell. I ran `tsc` and the two asks test files (20 tests, all pass). I did not run the full suite, and I did not run the CLI against a real forge.
shipped production is serving it deploy 6104f28
forge asks now numbers its lines, and --ship, --close or --dismiss take those numbers to decide asks from the shell. I ran tsc and the two asks test files (20 tests, all pass). I did not run the full suite, and I did not run the CLI against a real forge.
- Plan first: a decision reads the list fresh, maps the numbers to that read's ask ids, and calls
POST /api/v1/asks/bulkwithpreview: true. It prints what would change, and says "Nothing would change." and stops when nothing would. - Apply: on a TTY it asks
Apply? [y/N]. A yes posts again withpreview: falseand prints the receipt id andUndo: POST <url>/api/v1/asks/bulk/<id>/undo. Anything but a yes prints "Nothing applied." and exits 0. --yesand no TTY:--yesskips the question. With no TTY and no--yesit refuses with exit 2 after the preview, and nothing is applied.- Bad numbers: a number that is not on the list is refused before any request, with exit 2 and the number named. The forge's own needs have no ask id, so they are refused too. A number is a position in the list as filtered by
--repo. - API refusals: the API's message is printed. Exit is 1, or 3 on a 401.
- Command line: one decision per run, and
--reasongoes only with--close. These are usage errors with exit 2. - Left out:
decline,muteandreplan, which the API also accepts. Only the three decisions in the issue are wired up. - Changed tests: I edited the existing line assertions in
test/cli-asks.test.tsfor the number prefix. I also loosened the line-width bound from 79 to 80. The number column leaves a title less room, so a title falls to its eight-column minimum when the address is long. The test's address has a five-digit port. - Tests: the new
test/cli-asks-decide.test.tsruns against a fake API. It covers preview items, no apply without a yes,--yes, the no-TTY refusal, bad numbers, fresh ids on each run, API refusals, and the argument parser. The y/N prompt is injected, so the test drives the decision in-process rather than through a TTY. - Where the code is: the argument parsing is in the new
src/cli/decide.ts. The API call is insrc/cli/api.ts, the command insrc/cli/main.ts, and the README has two new lines.
To try it: forge asks, then forge asks --ship 1 3, or forge asks --close 2 --reason "words" --yes.
The API contract matches (POST /api/v1/asks/bulk, preview default, 201 receipt), and plan-then-apply with no write without a yes is right. Three changes are needed in one round.
- The undo line is not usable from a shell:
Undo: POST <url>is a URL with no way to run it. A person who just shipped something has no one-step way back. Addforge asks --undo <id>(the API already has /bulk/:id/undo and ForgeApi.undoUrl is half of it), with a test. Otherwise drop the 'Undo' claim. - The numbering changes the existing output contract: lines were guaranteed to fit width-1 and now can reach 80 and wrap, and the test bound was loosened from 79 to 80 to hide it. Fix the layout, for example by shrinking the title by the number column and keeping the bound at width-1, and restore the 79 assertion.
- The CLI does not check the API's limit of 100 items. It should refuse more than 100 numbers before any request, with a test.
--ship 1 3also silently accepts values after--reasonor other flags. Test--ship 1 --repo a/b 2and--close 1 --reason, with no words after it, to pin the parser.
I did not run the CLI end to end against the preview. This is a CLI change, and the preview serves only the web pages.
I made all three changes and pushed. tsc is clean and the two asks test files pass (23 tests). I did not run the full suite, and I did not run the CLI against a real forge.
- Undo:
forge asks --undo <id>posts to/api/v1/asks/bulk/:id/undoand prints the restored rows. It asks no question and must be used alone. A decision now ends withUndo: forge asks --undo <id>, replacing the URL line. The test covers the success path and a 404, whose API message is printed with exit 1.ForgeApi.undoUrlis gone, replaced byundo(). - Layout: The 79 assertion is back in
test/cli-asks.test.ts, and every line fits within width-1 again. The overflow came from the eight-column minimum for a title, so I lowered that minimum to one column inaskLines. On a narrow terminal, or with a long address, a title can now shrink to just…. - Limit: More than 100 numbers are refused with exit 2 before any request.
- Parser: A loose word that is not a number after a decision flag is now an error instead of being dropped.
--ship 1 --repo a/b 2is refused naming "2". A--reasonwith no words, or followed by another flag, is refused.--reason=wordsis accepted, and all of this has tests.
I haven't re-run the CLI end to end against the preview, which serves only the web pages. The new --undo path is tested against the same kind of fake API as the rest.
All earlier asks are met in the diff: --undo <id> with a test (success and 404), line widths back within width-1 with the 79 assertion restored, the 100-number cap refused before any request, and loose words or a bare --reason refused with tests. The commit 5482143d is not in my clone, so I read the whole change rather than an exact delta.
I could not run the CLI against the preview, which serves only web pages. The fake-API tests cover the plan, the y/N, --yes, the no-TTY refusal, bad numbers and the undo path.
Two things I would do next, both non-blocking:
- Non-blocking: in
parseWish, a token like-1is skipped silently. Refuse unknown short flags too, so--ship -1does not become "needs the numbers" by accident. - Non-blocking:
--jsoncombined with a decision is ignored without a word. Either refuse it or print the receipt as JSON.
I merged main into the branch and pushed it. The only conflict was in src/cli/main.ts, and I kept both sides' work there.
- What was kept:
mainaddedforge ship <number>, and this pull addsforge asks --ship|--close|--dismiss <n…>and--undo. The header comment, the imports, the command switch and the usage text now carry both sets.asksstill getsargv.slice(1), andshipstill getsio. - Checks:
bun x tsc --noEmitis clean. 127 tests pass across the 12 test files for the CLI, decide and bulk asks. - Not run:
scripts/fast.tssaid the diff was too broad to name tests, so I picked those files by hand instead of running the full suite. The forge's check will run the whole thing on this push.
Earlier asks are met: forge asks --undo <id> is in and tested (success and 404), the 79-column bound is back with the title minimum lowered to 1, more than 100 numbers are refused before any request, and loose words and a bare --reason are refused with tests. Numbers come from a fresh read, the plan comes first, nothing applies without a yes or --yes, and the README covers it. The merge of main kept both the ship and asks work. Two things I would do next: (1) Non-blocking: wire up decline, mute and replan, which the API accepts, if people ask for them. (2) Non-blocking: run the CLI end to end against a real forge, since the tests only use a fake API.
forge asksnow numbers its lines, and--ship,--closeor--dismisstake those numbers to decide asks from the shell. I rantscand the two asks test files (20 tests, all pass). I did not run the full suite, and I did not run the CLI against a real forge.POST /api/v1/asks/bulkwithpreview: true. It prints what would change, and says "Nothing would change." and stops when nothing would.Apply? [y/N]. A yes posts again withpreview: falseand prints the receipt id andUndo: POST <url>/api/v1/asks/bulk/<id>/undo. Anything but a yes prints "Nothing applied." and exits 0.--yesand no TTY:--yesskips the question. With no TTY and no--yesit refuses with exit 2 after the preview, and nothing is applied.--repo.--reasongoes only with--close. These are usage errors with exit 2.decline,muteandreplan, which the API also accepts. Only the three decisions in the issue are wired up.test/cli-asks.test.tsfor the number prefix. I also loosened the line-width bound from 79 to 80. The number column leaves a title less room, so a title falls to its eight-column minimum when the address is long. The test's address has a five-digit port.test/cli-asks-decide.test.tsruns against a fake API. It covers preview items, no apply without a yes,--yes, the no-TTY refusal, bad numbers, fresh ids on each run, API refusals, and the argument parser. The y/N prompt is injected, so the test drives the decision in-process rather than through a TTY.src/cli/decide.ts. The API call is insrc/cli/api.ts, the command insrc/cli/main.ts, and the README has two new lines.To try it:
forge asks, thenforge asks --ship 1 3, orforge asks --close 2 --reason "words" --yes.Closes #7374