## 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.