Reindex command, implicit note shorthand, add→addfile rename
- Add `kb reindex` command with confirmation prompt and --yes flag - Add implicit note shorthand: `kb "my note"` submits a note directly - Rename `add` to `addfile`, remove --note/--title/--type flags - Add client-side file extension validation before upload - Add `kb examples` command for common usage patterns - Update README, SKILL.md, and main specs - Archive completed changes and sync delta specs BREAKING: `kb add` renamed to `kb addfile`, `kb add --note` replaced by `kb "text"` Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-03-29
|
||||
@@ -0,0 +1,23 @@
|
||||
## Context
|
||||
|
||||
The engine's `POST /api/v1/reindex` re-embeds all chunks synchronously and returns `{"chunks_reindexed": N, "model": "..."}`. The client has an established confirmation pattern in `remove.go` using `--yes`/`-y` flag.
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:**
|
||||
- Add `kb reindex` with confirmation prompt matching `kb remove` pattern
|
||||
- Display human-readable and JSON output
|
||||
|
||||
**Non-Goals:**
|
||||
- Progress reporting during reindex (engine returns synchronously)
|
||||
- Model selection from the client (model is engine-side config)
|
||||
|
||||
## Decisions
|
||||
|
||||
### 1. Confirmation prompt before reindex
|
||||
|
||||
Reindex drops and rebuilds the vector table — destructive if interrupted. Use the same `[y/N]` prompt pattern as `kb remove`, skippable with `--yes`/`-y`.
|
||||
|
||||
### 2. Warn that it may take a while
|
||||
|
||||
The prompt should mention that reindex re-embeds all chunks, so the user knows it's not instant.
|
||||
@@ -0,0 +1,22 @@
|
||||
## Why
|
||||
|
||||
The engine exposes `POST /api/v1/reindex` but there's no client command for it. Users switching embedding models must use curl directly. Adding `kb reindex` with a confirmation prompt keeps it consistent with other destructive commands like `kb remove`.
|
||||
|
||||
## What Changes
|
||||
|
||||
- Add `kb reindex` command to the Go client with confirmation prompt (skip with `--yes`/`-y`)
|
||||
- Display reindex results (chunks reindexed, model used)
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
|
||||
(none)
|
||||
|
||||
### Modified Capabilities
|
||||
|
||||
- `go-client`: Add reindex command requirement
|
||||
|
||||
## Impact
|
||||
|
||||
- New file: `client/cmd/reindex.go`
|
||||
@@ -0,0 +1,25 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Reindex command
|
||||
|
||||
The client SHALL provide a `kb reindex` command that triggers re-embedding of all chunks on the engine. The command SHALL prompt for confirmation before proceeding.
|
||||
|
||||
#### Scenario: Reindex with confirmation
|
||||
- **WHEN** the user runs `kb reindex`
|
||||
- **THEN** the client SHALL display a warning that all chunks will be re-embedded and prompt `Reindex all chunks? This will re-embed everything. [y/N]`. If confirmed, it SHALL POST to `/api/v1/reindex` and display the result.
|
||||
|
||||
#### Scenario: Reindex with skip confirmation
|
||||
- **WHEN** the user runs `kb reindex --yes`
|
||||
- **THEN** the client SHALL skip the confirmation prompt and POST to `/api/v1/reindex` immediately
|
||||
|
||||
#### Scenario: Reindex cancelled
|
||||
- **WHEN** the user runs `kb reindex` and responds with anything other than `y` or `yes`
|
||||
- **THEN** the client SHALL print `Cancelled.` and exit with code 0
|
||||
|
||||
#### Scenario: Reindex human output
|
||||
- **WHEN** the reindex completes successfully with default format
|
||||
- **THEN** the client SHALL print `Reindexed N chunks (model: <model_name>)`
|
||||
|
||||
#### Scenario: Reindex JSON output
|
||||
- **WHEN** the user runs `kb reindex --yes --format json`
|
||||
- **THEN** the client SHALL output the raw JSON response from the engine
|
||||
@@ -0,0 +1,5 @@
|
||||
## 1. Implementation
|
||||
|
||||
- [x] 1.1 Create `client/cmd/reindex.go` with `kb reindex` command, `--yes`/`-y` flag, confirmation prompt matching `remove.go` pattern
|
||||
- [x] 1.2 POST to `/api/v1/reindex`, handle human output (`Reindexed N chunks (model: ...)`) and JSON output
|
||||
- [x] 1.3 Verify build compiles and command appears in `kb --help`
|
||||
@@ -0,0 +1,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-03-29
|
||||
@@ -0,0 +1,43 @@
|
||||
## Context
|
||||
|
||||
The `add` command currently handles both file uploads and notes via a `--note` string flag. This creates confusing flag parsing and a muddled help screen. The engine already auto-detects file type from extension (`detector.py`) and rejects unsupported ones, so the client's `--type` flag is redundant.
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:**
|
||||
- `kb "my note"` as the sole note entry path (replaces `kb add --note`)
|
||||
- `kb addfile <path>` as a file-only upload command (replaces `kb add`)
|
||||
- Client-side extension validation before uploading
|
||||
- Clean, unambiguous help text for both paths
|
||||
|
||||
**Non-Goals:**
|
||||
- Engine changes — type detection stays server-side
|
||||
- Backward compatibility shim for `kb add` — clean break
|
||||
- Client-side MIME type detection — extension check is sufficient
|
||||
|
||||
## Decisions
|
||||
|
||||
### Rename add → addfile, strip note/type flags
|
||||
|
||||
Rename the cobra command from `add` to `addfile`. Remove `--note`, `--title`, and `--type` flags. Keep `--tags`, `--recursive`. The command becomes purely about file uploads.
|
||||
|
||||
**Why not keep `add` as an alias?** Clean break is simpler. The old form was confusing — better to force a quick migration than maintain two paths.
|
||||
|
||||
### Extension validation on single file uploads
|
||||
|
||||
The `supportedExts` map already gates recursive walks. Apply the same check to single file uploads — reject with a clear error listing supported extensions. This gives instant feedback instead of a round-trip to the engine.
|
||||
|
||||
### Root command RunE for note shorthand
|
||||
|
||||
Use cobra's `Args: cobra.ArbitraryArgs` and `RunE` on the root command. When args are present and no subcommand matched, join all args into a single note string and submit. `--tags` flag on root for tagging notes. No `--title` — keep it minimal.
|
||||
|
||||
**Why join all args?** `kb remember to update dns` (unquoted) should work the same as `kb "remember to update dns"`.
|
||||
|
||||
### Reuse note submission logic via shared helper
|
||||
|
||||
Extract `submitNote` from the current `runAdd` so both the root command and any future callers use the same POST + duplicate-handling + output logic.
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
- **Breaking change** → Anyone with `kb add` in scripts needs to update to `kb addfile`. Acceptable for a personal tool.
|
||||
- **No `--type` override** → If a user ever needs to force a type, they'd have to go through the engine API directly. Low risk since the engine's auto-detection covers all supported formats.
|
||||
@@ -0,0 +1,34 @@
|
||||
## Why
|
||||
|
||||
Adding a note requires `kb add --note "my note"` — too much ceremony for what should be instant. The `--note` flag taking a string value also creates confusing flag parsing (e.g. `kb add --note --tags foo` parses `--tags` as the note value). Meanwhile, `kb add` tries to do two things (files and notes) which muddies its help text and UX.
|
||||
|
||||
Splitting these into distinct paths makes the CLI clearer:
|
||||
- **Notes**: `kb "my note"` — zero-friction, no subcommand needed
|
||||
- **Files**: `kb addfile report.pdf` — explicit, file-only command
|
||||
|
||||
## What Changes
|
||||
|
||||
- **Add `kb "text"` shorthand**: bare string arguments without a subcommand are treated as notes, submitted via `POST /api/v1/jobs`
|
||||
- **Rename `add` → `addfile`**: the command becomes file-only, no more `--note`/`--title` flags
|
||||
- **Drop `--type` flag**: the engine already auto-detects type from file extension (`detector.py`); the client doesn't need to override this
|
||||
- **Add client-side extension validation**: reject unsupported file extensions with a clear error before uploading, using the same extension set as recursive directory walks
|
||||
- **Update README**: document the new shorthand and renamed command
|
||||
- **BREAKING**: `kb add` no longer exists; `kb add --note` no longer exists
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
|
||||
_(none)_
|
||||
|
||||
### Modified Capabilities
|
||||
|
||||
- `go-client`: Rename `add` to `addfile`, remove `--note`/`--title`/`--type` flags, add extension validation for single file uploads, add implicit note shorthand on root command
|
||||
|
||||
## Impact
|
||||
|
||||
- `client/cmd/add.go` → renamed/refactored to `addfile` command, stripped of note logic, added extension check
|
||||
- `client/cmd/root.go` — bare args handling + `--tags` flag for note shorthand
|
||||
- `README.md` — updated usage examples
|
||||
- No engine changes — engine already detects type from extension and rejects unsupported files
|
||||
- Breaking change for any scripts using `kb add` or `kb add --note`
|
||||
@@ -0,0 +1,95 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Implicit note shorthand
|
||||
|
||||
The client SHALL treat bare string arguments (with no subcommand) as an implicit note. `kb "my note"` SHALL behave identically to submitting a note via `POST /api/v1/jobs`. All persistent flags (`--format`, `--engine`, `--api-key`) and the root `--tags` flag SHALL work with the shorthand form.
|
||||
|
||||
#### Scenario: Quick note via bare argument
|
||||
- **WHEN** the user runs `kb "remember to update DNS"`
|
||||
- **THEN** the client SHALL submit the text as a note via `POST /api/v1/jobs` and print `Queued: note`
|
||||
|
||||
#### Scenario: Bare argument with tags
|
||||
- **WHEN** the user runs `kb "server room is building 3" --tags ops`
|
||||
- **THEN** the client SHALL submit the note with the specified tags
|
||||
|
||||
#### Scenario: Bare argument with JSON output
|
||||
- **WHEN** the user runs `kb "my note" --format json`
|
||||
- **THEN** the client SHALL output the raw JSON response from the engine
|
||||
|
||||
#### Scenario: Bare argument duplicate detection
|
||||
- **WHEN** the user runs `kb "my note"` and the engine returns HTTP 409
|
||||
- **THEN** the client SHALL handle the duplicate response identically to the previous `kb add --note` behaviour
|
||||
|
||||
#### Scenario: Multiple unquoted words
|
||||
- **WHEN** the user runs `kb remember to update dns` (without quotes)
|
||||
- **THEN** the client SHALL join all arguments into a single note string and submit it
|
||||
|
||||
#### Scenario: No interference with subcommands
|
||||
- **WHEN** the user runs `kb search "query"` or any other existing subcommand
|
||||
- **THEN** the client SHALL route to the subcommand as before — the implicit note shorthand SHALL NOT interfere
|
||||
|
||||
#### Scenario: No arguments
|
||||
- **WHEN** the user runs `kb` with no arguments
|
||||
- **THEN** the client SHALL display the help text
|
||||
|
||||
---
|
||||
|
||||
## MODIFIED Requirements
|
||||
|
||||
### Requirement: Add command (file and note ingestion)
|
||||
|
||||
The client SHALL provide a `kb addfile` command that uploads files to the engine for async ingestion. The command SHALL validate file extensions before uploading and reject unsupported types. The client SHALL handle duplicate rejection (HTTP 409) and display the existing document information. The command SHALL NOT handle notes — notes are submitted via the implicit note shorthand (`kb "text"`).
|
||||
|
||||
#### Scenario: Add a single file
|
||||
- **WHEN** the user runs `kb addfile report.pdf`
|
||||
- **THEN** the client SHALL validate the file extension, upload the file via `POST /api/v1/jobs` (multipart), print "Queued: report.pdf", and exit
|
||||
|
||||
#### Scenario: Add a file with tags
|
||||
- **WHEN** the user runs `kb addfile manual.pdf --tags car,maintenance`
|
||||
- **THEN** the client SHALL include the tags in the multipart upload metadata
|
||||
|
||||
#### Scenario: Add a directory recursively
|
||||
- **WHEN** the user runs `kb addfile ~/documents/ --recursive`
|
||||
- **THEN** the client SHALL discover all supported files in the directory tree, upload each one sequentially, and print "Queued: N files"
|
||||
|
||||
#### Scenario: Unsupported file extension
|
||||
- **WHEN** the user runs `kb addfile photo.jpg`
|
||||
- **THEN** the client SHALL print an error listing supported extensions and exit with a non-zero code without making any API call
|
||||
|
||||
#### Scenario: Duplicate file rejected (already ingested)
|
||||
- **WHEN** the user runs `kb addfile report.pdf` and the engine returns HTTP 409 with `{"error": "duplicate", "document_id": 42, "title": "report.pdf"}`
|
||||
- **THEN** the client SHALL print "Already imported: report.pdf (doc ID: 42)" and exit with code 0
|
||||
|
||||
#### Scenario: Duplicate file rejected (in-flight job)
|
||||
- **WHEN** the user runs `kb addfile report.pdf` and the engine returns HTTP 409 with `{"error": "duplicate", "job_id": 7, "title": "report.pdf"}`
|
||||
- **THEN** the client SHALL print "Already queued: report.pdf (job ID: 7)" and exit with code 0
|
||||
|
||||
#### Scenario: Duplicate file in recursive add
|
||||
- **WHEN** the user runs `kb addfile ~/documents/ --recursive` and some files are rejected as duplicates
|
||||
- **THEN** the client SHALL print the duplicate message for each rejected file, continue uploading remaining files, and include a summary (e.g., "Queued: 5 files, 2 duplicates skipped")
|
||||
|
||||
#### Scenario: Duplicate with JSON output
|
||||
- **WHEN** the user runs `kb addfile report.pdf --format json` and the engine returns HTTP 409
|
||||
- **THEN** the client SHALL output the raw JSON response from the engine including the document_id and title
|
||||
|
||||
#### Scenario: Add with JSON output
|
||||
- **WHEN** the user runs `kb addfile report.pdf --format json`
|
||||
- **THEN** the client SHALL output the JSON response from the engine including the job_id
|
||||
|
||||
#### Scenario: File not found
|
||||
- **WHEN** the user runs `kb addfile nonexistent.pdf`
|
||||
- **THEN** the client SHALL print an error and exit with a non-zero code without making any API call
|
||||
|
||||
#### Scenario: Upload failure
|
||||
- **WHEN** the upload fails (network error, engine returns 4xx/5xx other than 409)
|
||||
- **THEN** the client SHALL print the error and exit with a non-zero code
|
||||
|
||||
## REMOVED Requirements
|
||||
|
||||
### Requirement: Note ingestion via add command
|
||||
**Reason**: Notes are now submitted via the implicit note shorthand (`kb "text"`). The `--note` and `--title` flags on the add command are removed.
|
||||
**Migration**: Use `kb "my note"` or `kb "my note" --tags ops` instead of `kb add --note "my note" --tags ops`.
|
||||
|
||||
### Requirement: Document type override via add command
|
||||
**Reason**: The engine auto-detects document type from file extension (`detector.py`). The client `--type` flag is redundant.
|
||||
**Migration**: Remove `--type` from scripts. The engine handles type detection automatically.
|
||||
@@ -0,0 +1,19 @@
|
||||
## 1. Refactor note submission
|
||||
|
||||
- [x] 1.1 Extract note submission logic from `runAdd` into a shared `submitNote` helper (multipart POST, duplicate detection, output formatting)
|
||||
|
||||
## 2. Root command shorthand
|
||||
|
||||
- [x] 2.1 Add `Args: cobra.ArbitraryArgs` and `RunE` to the root command — join args into a note string, call `submitNote`; show help when no args
|
||||
- [x] 2.2 Add `--tags` flag on the root command for note tagging
|
||||
|
||||
## 3. Rename add → addfile
|
||||
|
||||
- [x] 3.1 Rename command from `add` to `addfile` (`Use: "addfile <path>"`)
|
||||
- [x] 3.2 Remove `--note`, `--title`, and `--type` flags from the command
|
||||
- [x] 3.3 Add extension validation for single file uploads — reject unsupported extensions with a clear error listing supported types
|
||||
|
||||
## 4. Documentation and verification
|
||||
|
||||
- [x] 4.1 Update README.md usage section: show `kb "text"` shorthand, rename `add` references to `addfile`
|
||||
- [x] 4.2 Verify build compiles, `kb --help` and `kb addfile --help` show expected output
|
||||
Reference in New Issue
Block a user