@thinkingai/ae-cli 6.0.48-customer.1 → 6.0.48-workbuddy

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.
Files changed (80) hide show
  1. package/README.md +93 -36
  2. package/README.zh.md +93 -36
  3. package/assets/workbuddy-host-page/thinkingai.png +0 -0
  4. package/assets/workbuddy-host-page/workbuddy.png +0 -0
  5. package/bin/ae-cli-workbuddy.js +7 -0
  6. package/dist/auth-HJG2L6DR.js +910 -0
  7. package/dist/{capability-RUSV77CO.js → capability-JHYVQNQ4.js} +47 -34
  8. package/dist/chunk-2BDQB42E.js +15 -0
  9. package/dist/{chunk-GJXRF7Y6.js → chunk-6MXFJVNP.js} +47 -78
  10. package/dist/chunk-6ZIQV5GW.js +26 -0
  11. package/dist/{chunk-KZ6ZHF5J.js → chunk-ARTIHWVD.js} +27 -25
  12. package/dist/{chunk-6QK7SYYY.js → chunk-DU5MZQFQ.js} +29 -37
  13. package/dist/{chunk-BVDST5YT.js → chunk-JFOGWBAT.js} +8 -8
  14. package/dist/{chunk-JYMGHGCE.js → chunk-KSQGGXGA.js} +24 -13
  15. package/dist/{chunk-FR2EDAQM.js → chunk-NXRKDG6E.js} +89 -3
  16. package/dist/{chunk-NSIVXKJH.js → chunk-QSO4SA6C.js} +5 -5
  17. package/dist/{chunk-BE73PUFX.js → chunk-QYJ252CT.js} +2 -2
  18. package/dist/{chunk-B5HMQAOM.js → chunk-UL6SJDYE.js} +1 -1
  19. package/dist/chunk-Y3S2KNNR.js +623 -0
  20. package/dist/{chunk-KEWVSO64.js → chunk-ZCM47ROU.js} +5 -16
  21. package/dist/{community-report-client-6OL6GBQW.js → community-report-client-QE4RC2XG.js} +2 -4
  22. package/dist/{config-XNMACCKX.js → config-XMRP5NDA.js} +8 -9
  23. package/dist/{data-integration-FZQQC3KW.js → data-integration-SGRITHJS.js} +9 -12
  24. package/dist/index.js +53 -80
  25. package/dist/{local-data-upload-client-EFHDLXFG.js → local-data-upload-client-LMVS7YAR.js} +2 -4
  26. package/dist/{memory-HBJQ2GC5.js → memory-5ZC73XBC.js} +4 -6
  27. package/dist/{metadata-PGDJE5RQ.js → metadata-LBX6O24P.js} +7 -9
  28. package/dist/{model-BHLJ2QMT.js → model-CRDIVYN5.js} +4 -6
  29. package/dist/{personal-semantic-preference-E5NZ56DN.js → personal-semantic-preference-7FVUTJZF.js} +6 -8
  30. package/dist/{sync-MUWPRM5I.js → sync-VVNDHU7R.js} +9 -11
  31. package/dist/{te-agent-WQZTMEK4.js → te-agent-4T5TFHD6.js} +393 -90
  32. package/dist/{te-analysis-YWCSSLYL.js → te-analysis-TPYFOIFD.js} +97 -31
  33. package/dist/{te-community-BNE6KREL.js → te-community-PWOTHSEC.js} +9 -32
  34. package/dist/{te-dataops-TXLKM2W6.js → te-dataops-ZJV5QVJU.js} +19 -20
  35. package/dist/{te-engage-VEW4CJHK.js → te-engage-WVHBZAXH.js} +11 -13
  36. package/dist/{te-kb-BUD6N3NI.js → te-kb-PNM2ZKBP.js} +595 -85
  37. package/dist/{te-system-44LZJDTQ.js → te-system-MRCMLAWW.js} +6 -8
  38. package/dist/{te-team-XMP47YXE.js → te-team-Y36TG6AQ.js} +6 -8
  39. package/dist/{update-UODFOZ4P.js → update-UNKCZ5U5.js} +7 -8
  40. package/package.json +15 -10
  41. package/skills/ae-agent/SKILL.md +30 -13
  42. package/skills/ae-agent/references/agent-distribution.md +94 -0
  43. package/skills/ae-agent/references/approval-request.md +4 -0
  44. package/skills/ae-agent/references/command_index.md +9 -2
  45. package/skills/ae-agent/references/create-automation.md +20 -2
  46. package/skills/ae-agent/references/get-agent-context.md +70 -0
  47. package/skills/ae-agent/references/list-automations.md +18 -3
  48. package/skills/ae-agent/references/list-mcp-credentials.md +1 -1
  49. package/skills/ae-agent/references/mcp-token.md +3 -3
  50. package/skills/ae-agent/references/set-mcp-credential.md +0 -1
  51. package/skills/ae-agent/references/update-automation.md +18 -0
  52. package/skills/ae-analysis/SKILL.md +11 -2
  53. package/skills/ae-analysis/references/adhoc_run.md +2 -0
  54. package/skills/ae-analysis/references/ai_models.md +23 -3
  55. package/skills/ae-analysis/references/analysis_gateway_assets.md +2 -2
  56. package/skills/ae-analysis/references/command_index.md +7 -7
  57. package/skills/ae-analysis/references/cross_source_config.md +84 -0
  58. package/skills/ae-analysis/references/dashboard_update.md +1 -1
  59. package/skills/ae-analysis/references/user_tag_create.md +23 -1
  60. package/skills/ae-analysis/references/user_tag_models.md +9 -1
  61. package/skills/ae-analysis/references/user_tag_update.md +14 -2
  62. package/skills/ae-data-integration/SKILL.md +2 -1
  63. package/skills/ae-data-integration/references/dimension-routing.md +36 -0
  64. package/skills/ae-data-integration/references/local-analysis.md +2 -0
  65. package/skills/ae-data-integration/references/source-inspect.md +1 -1
  66. package/skills/ae-data-integration/references/ue-routing.md +17 -1
  67. package/skills/ae-generate-tracking-plan/SKILL.md +16 -5
  68. package/skills/ae-kb/SKILL.md +107 -36
  69. package/skills/ae-kb/references/query-workflow.md +59 -29
  70. package/skills/ae-kb/references/versions.md +46 -0
  71. package/skills/ae-system/SKILL.md +1 -1
  72. package/skills/ae-use-agent/SKILL.md +42 -0
  73. package/skills/ae-use-agent/references/local-agent.md +114 -0
  74. package/dist/auth-QPEVVBKT.js +0 -465
  75. package/dist/auth-UMJAA72O.js +0 -15
  76. package/dist/chunk-533JK3YX.js +0 -72
  77. package/dist/chunk-O6K2ODUE.js +0 -318
  78. package/dist/chunk-RWXIXOZG.js +0 -326
  79. package/dist/client-N7NGZUNI.js +0 -204
  80. package/skills/ae-agent/references/auto-provision-mcp-credentials.md +0 -57
@@ -24,12 +24,20 @@ Top-level `type` is exactly one of `condition`, `metric`, `first_last`, or `sql`
24
24
 
25
25
  ## Metric tag
26
26
 
27
- Required: `event`, `aggregation`. `property`, `time_range`, and `filters` are optional. Filters support only event properties and user properties. A string `field` is an event property; use `{name,type:"user_property"}` for a user property.
27
+ Required: `event`, `aggregation`. `property`, `percentile`, `time_range`, and `filters` are optional. Filters support only event properties and user properties. A string `field` is an event property; use `{name,type:"user_property"}` for a user property.
28
+
29
+ Use `aggregation=percentile` with a numeric event `property` and pass `percentile`. Supported percentile values match the page controls: `5`, `10`, `20`, `25`, `30`, `40`, `60`, `70`, `75`, `80`, `90`, `95`, and `99`. The `percentile` field is required for percentile aggregation and is rejected for every other aggregation.
28
30
 
29
31
  ```json
30
32
  {"type":"metric","metric":{"event":"pay","aggregation":"sum","property":"amount","time_range":{"mode":"previous","unit":"day","value":30},"filters":{"relation":"and","items":[{"field":"channel","operator":"eq","values":["app"]},{"field":{"name":"country","type":"user_property"},"operator":"eq","values":["US"]}]}}}
31
33
  ```
32
34
 
35
+ Percentile example:
36
+
37
+ ```json
38
+ {"type":"metric","metric":{"event":"pay","aggregation":"percentile","property":"amount","percentile":90}}
39
+ ```
40
+
33
41
  ## First/last tag
34
42
 
35
43
  Required: `event`, `occurrence=first|last`, and exactly one value source: `calculation` or `property`. `time_range` and `filters` are optional. Filters support only event properties and user properties. A string `field` is an event property; use `{name,type:"user_property"}` for a user property. Supplying neither or both value sources is rejected before execution. Use the semantic time mappings in [`audience_models.md`](audience_models.md) for dynamic ranges such as today, this month, or a fixed start date through today.
@@ -2,11 +2,11 @@
2
2
 
3
3
  Update a user tag. Discover the exact `tag_name` first.
4
4
 
5
- Do not use it for ID-file value replacement or to create a missing tag. Supplying `--definition-request` automatically starts recomputation after the definition is updated; do not call `user-tag refresh` afterward. Updating only `--display-name` or `--remark` does not recompute. `--auto-refresh-cron` changes an existing enabled auto-refresh schedule and does not enable auto refresh. A successful update means the definition was saved, not that the new result is complete. Record the current `refresh_time` before updating, then poll `user-tag get` until `progress=100` and `refresh_time` advances before using `users_num` or querying members.
5
+ Do not use it for ID-file value replacement or to create a missing tag. Supplying `--definition-request` automatically starts recomputation after the definition is updated; do not call `user-tag refresh` afterward. Updating only `--display-name` or `--remark` does not recompute. A schedule-only update changes periodic refresh without starting immediate recomputation. `--auto-refresh-cron` or `--auto-refresh-schedule` can enable periodic refresh directly, including on a previously disabled tag. A successful update means the definition was saved, not that the new result is complete. Record the current `refresh_time` before updating, then poll `user-tag get` until `progress=100` and `refresh_time` advances before using `users_num` or querying members.
6
6
 
7
7
  The response distinguishes both paths. A definition update returns `computation.triggered_automatically=true`, `result_freshness.is_stale=true`, and normally `next_action=poll_get` with an exact capability/input pair. A display-name/remark-only update returns `computation.status=not_triggered`, `result_freshness.status=fresh`, and `next_action=none`.
8
8
 
9
- Flags: `--project-id`, `--tag-name` required. Optional: `--display-name`, `--definition-request`, `--authenticated-only`, `--remark`, `--zone-offset`, `--auto-refresh-cron`. The tag type comes from `definition_request.type` when the definition changes.
9
+ Flags: `--project-id`, `--tag-name` required. Optional: `--display-name`, `--definition-request`, `--authenticated-only`, `--remark`, `--zone-offset`, `--enable-auto-refresh`, `--auto-refresh-schedule`, `--auto-refresh-cron`. The tag type comes from `definition_request.type` when the definition changes.
10
10
 
11
11
  `display_name` is at most 80 characters and `remark` is at most 400 characters. The CLI rejects violations before dispatch. `tag_name` is an existing exact identifier and cannot be renamed by update.
12
12
 
@@ -17,3 +17,15 @@ ae-cli analysis user-tag update --project-id <project_id> --tag-name user_level
17
17
 
18
18
  ae-cli analysis user-tag update --project-id <project_id> --tag-name user_level --auto-refresh-cron '0 30 2 * * ? *'
19
19
  ```
20
+
21
+ Omitting scheduling flags preserves the existing enable state and schedule, including during a definition update. Omitting `--zone-offset` preserves the saved tag timezone. `--enable-auto-refresh true` can reuse an existing saved plan; if none exists, provide a new schedule. `--enable-auto-refresh false` disables periodic refresh. Do not combine false with a schedule or pass both schedule forms. Structured schedule fields and timezone rules are described in [user_tag_create.md](user_tag_create.md).
22
+
23
+ ```bash
24
+ # Enable daily refresh in one update
25
+ ae-cli analysis user-tag update --project-id <project_id> --tag-name user_level --auto-refresh-schedule '{"frequency":"daily","time":"02:30"}'
26
+
27
+ # Disable periodic refresh
28
+ ae-cli analysis user-tag update --project-id <project_id> --tag-name user_level --enable-auto-refresh false
29
+ ```
30
+
31
+ Read `user-tag get` after updating to verify `enable_auto_refresh` (1=enabled, 0=disabled), `scheduler_ui_config`, and `cluster_zone_offset`. Schedule-only updates return `computation.status=not_triggered` and `next_action=none`.
@@ -36,6 +36,7 @@ Use this skill when the user wants to bring a **local data file** (CSV/TSV/TXT/J
36
36
  | Generate / upload a project-level tracking plan (source material is PRD / chat / template / code; deliverable is a real platform tracking plan) | ae-generate-tracking-plan |
37
37
  | Upload documents / URLs to a knowledge base | ae-kb |
38
38
  | Reports / dashboards / queries / governance on data already in AE | ae-analysis |
39
+ | Dimension / dictionary data (a stable-entity lookup — city / product / device) to load as a dimension table bound to a property | ae-metadata |
39
40
 
40
41
  This skill also produces a tracking-plan draft (`source_type: data`) as a governance prerequisite; that draft is an input to ae-generate-tracking-plan, not a substitute for its five-phase platform plan.
41
42
 
@@ -43,7 +44,7 @@ This skill also produces a tracking-plan draft (`source_type: data`) as a govern
43
44
 
44
45
  Walk the four submodules in order. Each submodule is its own reference; follow it and come back here for the next step.
45
46
 
46
- 1. **Source — business identification.** Read [references/source-inspect.md](references/source-inspect.md). Profile every file fully, infer its business meaning using business-doc / user-prompt priors, then pick a branch via [references/ue-routing.md](references/ue-routing.md).
47
+ 1. **Source — business identification.** Read [references/source-inspect.md](references/source-inspect.md). Profile every file fully, infer its business meaning using business-doc / user-prompt priors, then pick a branch via [references/ue-routing.md](references/ue-routing.md): UE ingestion, dimension routing ([references/dimension-routing.md](references/dimension-routing.md)), or local analysis.
47
48
  2. **Reuse check.** If the profile is `ue_eligible`, read [references/reuse.md](references/reuse.md) and match the recommended mapping against the handoff index. `reuse` searches the current directory's `.ae-cli/data-integration/` upward, then `~/.ae-cli/data-integration/`, so a package written elsewhere is still found. A match proposes a frozen package; after one explicit confirmation, run the returned `transform.mjs` command and jump to Sink (step 5). No match → continue.
48
49
  3. **Tracking plan.** Read [references/tracking-plan.md](references/tracking-plan.md). The plan is generated from the mapping (`plan --mapping`), so confirm the recommended mapping's key system fields with the user first — `mode`, `#account_id`/`#distinct_id`, `#time` + timezone, `#event_name`, `#ip`/`#uuid` (see [references/transform.md](references/transform.md) steps 1–5) — then generate the event/property plan and get a single explicit confirmation from the user before touching data. The plan is a separate, required deliverable from the transform mapping: a user who supplies a column→field mapping directly has **not** completed this step, so build the plan from the confirmed mapping anyway. `user_set` still requires a plan (no events; every property becomes a user property). This step runs for **every** file: a second or later file merges its new events and properties into the existing project plan (tracking-plan.md step 4) — an existing plan is never a reason to skip it.
49
50
  4. **Transform.** Read [references/transform.md](references/transform.md). Map columns to AE system fields and properties, convert, and quarantine dirty rows per [references/ue-mapping.md](references/ue-mapping.md).
@@ -0,0 +1,36 @@
1
+ # Dimension routing
2
+
3
+ Use this reference after [ue-routing.md](ue-routing.md) has classified the file as dimension data — a stable-entity lookup with no row-level identity or event time. It covers the handoff to ae-metadata; this skill does not ingest dimension data itself.
4
+
5
+ ## What dimension data is
6
+
7
+ Judge by content, never by file extension — CSV / TSV / TXT / JSON / JSONL / XLS / XLSX can all be dimension data. The classification signals live in [ue-routing.md](ue-routing.md): no row-level identity, no row-level event time, finite entity enumeration, and a join key shared with event data.
8
+
9
+ Dimension data is not the only file that fails UE prerequisites. Aggregates, pivot tables, and cumulative snapshots also lack identity/time, but those are local-analysis material, not dictionaries. The tell is the entity shape and the join key: a dimension table maps one entity code to its attributes (`city_code` → name / level), while an aggregate summarizes many rows into one measure.
10
+
11
+ Low confidence is a proposal, never a silent decision — ask the user instead of routing automatically.
12
+
13
+ ## Handoff to ae-metadata
14
+
15
+ Extract the dimension sheet / file to CSV, then hand the following commands to ae-metadata. The sequence lists entry points only; full flags live in ae-metadata's references.
16
+
17
+ Bind prerequisite (confirm before creating the table):
18
+
19
+ - The table binds to an existing property (`property_name` + `property_scope` = user or event). That property usually appears once event/user data is uploaded first (e.g. events carrying `city_code`), so dimension binding is a second-phase action after data lands.
20
+ - If the target property does not exist yet, create it first via ae-analysis metadata or a tracking plan. Never invent a property name.
21
+
22
+ Entry command sequence:
23
+
24
+ ```bash
25
+ # 1. Extract the dimension sheet/file to CSV (metadata upload accepts CSV only,
26
+ # purpose data_table.csv)
27
+ ae-cli analysis input-file upload --project-id <id> --purpose data_table.csv --file <dim.csv>
28
+ # 2. Create + bind in one step (or split into csv-write + bind-existing)
29
+ ae-cli metadata property create-and-bind-csv-dimension-table --project-id <id> \
30
+ --property-name <p> --property-scope user|event --input-file-id ifile_xxx
31
+ # 3. Later dictionary changes (add/update/delete):
32
+ ae-cli metadata data-table csv-write --operation incremental_update|replace_update \
33
+ --data-table-id <id> --input-file-id ifile_xxx
34
+ ```
35
+
36
+ Binding model: AE attaches a dimension table to a user/event property, turning it into a dict property whose values join through the table's key column to expand `--dict-columns`. See ae-metadata's dimension-table reference for the full flags.
@@ -1,5 +1,7 @@
1
1
  # Local analysis
2
2
 
3
+ Dimension / dictionary data (a stable-entity lookup with a join key) is not local-analysis material — it routes to ae-metadata as a dimension table. See [ue-routing.md](ue-routing.md) and [dimension-routing.md](dimension-routing.md).
4
+
3
5
  Keep the source on the local machine. Generated scripts and reports belong under `.ae-cli/data-integration/runs/<run-id>/` with restrictive permissions.
4
6
  Set the directory to `0700` and generated scripts/reports to `0600`.
5
7
 
@@ -63,7 +63,7 @@ Summarize both — report the shape of the distribution and the names of the val
63
63
  - **Excel date cells** — a cell whose number format is a date or date+time is read as the wall-clock timestamp shown in Excel, not as the Excel serial number stored behind it, so the column infers as `datetime` and can serve as the time field. Inspect lists every such column in a warning. Treat that warning as a question to the user, not as a note: the same column profiled as `number` before this behavior existed, so if any part of this file was already sent to AE, the property may have been received as a number and its type is now locked — it cannot be changed to datetime, and the column has to be re-sent under a new property name. Ask whether the column was uploaded before, and only map it once the user answers. Elapsed-duration formats (`[h]:mm:ss` and the equivalent built-ins) are durations rather than points in time and stay `number`.
64
64
  - **Excel formula cells** — a spreadsheet stores a formula and, next to it, the result Excel last computed. That cached result is the value: it is read normally, including a result of `0` or `""`, which are real values and not blanks. This tool never evaluates a formula and never guesses a result, so a cell holding a formula the file never computed has nothing to upload; it is read as missing and counted, as is an Excel error value (`#N/A`, `#DIV/0!`, …). Inspect reports the counts per column in a warning and `convert` repeats them in `manifest.output.unreadable_cells`. Report them: the rows are kept and the record count is unchanged, so this is the only explanation for a column that is empty in AE while the spreadsheet looks full. When a column that matters reads as missing this way, ask the user to recalculate and re-export in Excel, or to export values instead of formulas, before uploading. This covers XLSX; a legacy `.xls` workbook goes through a different parser and is not counted here.
65
65
  - **Merged cells, hidden rows, and hidden columns** — a sheet maintained by hand merges a label down the rows it covers (`区域` spanning one region's block). Excel keeps that value on the block's first row only and stores every row below it as an empty cell, so a column that looks full on screen arrives mostly missing, and the AE property built from it would be empty for most events. The same worksheet may also hide a row inside a data block or hide a whole column. None of this travels with a row, so inspect scans the worksheet structure separately and reports it under `xlsx_structure`: `merged_ranges` with `merged_range_samples` (references such as `A3:A5`, never cell text), `merged_covered_cells` per column, `hidden_rows` with `hidden_row_samples` (source row numbers as Excel numbers them), and `hidden_columns` by header name. The default read is unchanged, so the report is a question for the user, and each answer is a flag: `--fill-merged-cells` copies each block's value into the cells its own range covers — bounded to the range, never overwriting a value that is there and never inventing one when the block's own cell is empty, so it is not a forward fill; `--exclude-hidden-rows` leaves hidden rows out. Neither is on by default: those cells really are empty in the file, and a row hidden inside a data block may still be real data — unlike a hidden *worksheet* (below), which is excluded by default. Hidden columns have no flag at all; when the user confirms one is not data, list it in the mapping's `exclude_columns`. Both flags are carried into the recommended mapping as `fill_merged_cells` / `exclude_hidden_rows`, which is what makes `convert` read the rows inspect profiled — `convert` has no read flags of its own — and `convert` repeats the findings in `manifest.output.xlsx_structure`, the only record of a layout the converted rows no longer show. This covers XLSX; a legacy `.xls` workbook is not scanned, so ask the user about merged labels and hidden rows there instead of trusting silence.
66
- - **Hidden worksheets** — a worksheet hidden in the workbook is left out of the `--data-set` candidates and out of `--merge-sheets`, because a sheet the file does not show is usually scratch space, a lookup table, or a superseded draft rather than rows anyone meant to upload. Inspect lists each one under `excluded_sheets` (with `reason: hidden`); report those names to the user, since they are the only explanation for a row count lower than the workbook appears to hold. Their headers are also left out of `header_consistency`, so a stale hidden draft cannot make a mergeable workbook look ragged. A hidden sheet stays readable when the user names it in `--data-set` — the command then warns on stderr that the selected sheet is hidden. Only pass a hidden sheet after the user says that is what they want. When *every* worksheet is hidden there is no candidate left, and inspect fails with `LOCAL_DATA_ALL_DATA_SETS_HIDDEN` whose hint lists the hidden sheets; treat that as a question about which sheet holds the real data, not as an unreadable file. This detection covers XLSX only: a legacy `.xls` workbook's sheet list is unfiltered, so a hidden sheet there still appears as a candidate and is still merged — for `.xls`, ask the user to confirm the sheet list instead of trusting it.
66
+ - **Hidden worksheets** — a worksheet hidden in the workbook is left out of the `--data-set` candidates and out of `--merge-sheets`, because a sheet the file does not show is usually scratch space or a superseded draft rather than rows anyone meant to upload, but a hidden sheet can also be a dimension / dictionary table that is meant to be loaded, and that goes through dimension routing instead of being dismissed as scratch. Inspect lists each one under `excluded_sheets` (with `reason: hidden`); report those names to the user, since they are the only explanation for a row count lower than the workbook appears to hold. Their headers are also left out of `header_consistency`, so a stale hidden draft cannot make a mergeable workbook look ragged. A hidden sheet stays readable when the user names it in `--data-set` — the command then warns on stderr that the selected sheet is hidden. Only pass a hidden sheet after the user says that is what they want. When *every* worksheet is hidden there is no candidate left, and inspect fails with `LOCAL_DATA_ALL_DATA_SETS_HIDDEN` whose hint lists the hidden sheets; treat that as a question about which sheet holds the real data, not as an unreadable file. This detection covers XLSX only: a legacy `.xls` workbook's sheet list is unfiltered, so a hidden sheet there still appears as a candidate and is still merged — for `.xls`, ask the user to confirm the sheet list instead of trusting it.
67
67
  - **Excel sheets** — `--merge-sheets` streams every visible worksheet in file order instead of a single selected sheet; otherwise ask which sheet/`--data-set` to use. Inspect also reports `header_consistency` (`all_same` or `different`) across a workbook's sheets, with `header_details` listing each sheet's header row when they differ; prefer `--merge-sheets` only when headers match. Matching headers establish a shared structure, not disjoint rows: a detail sheet and a summary sheet, or `1月` and `1月修订版`, usually carry identical headers and would be merged and reported twice over. Before merging, confirm with the user that the sources are mutually exclusive partitions (one month per sheet, no overlap) rather than overlapping, revised, or derived views of the same rows, and show each sheet's row count and time coverage range in that confirmation so an overlap is visible. The same rule applies to repeated `--input-file`.
68
68
  - **Multi-file type conflicts** — when the same column has different inferred types across files, present each conflict and resolve with `--type-resolutions` on `convert` (see [transform](transform.md)).
69
69
 
@@ -20,7 +20,7 @@ Classification order:
20
20
  5. Rows that mix track and user-profile facts in one file use `mixed` with a `record_type_field`; require explicit review.
21
21
  6. Low-confidence output is a proposal, never silent approval.
22
22
 
23
- Aggregated metrics, pivot tables, cross-tabs, model outputs, free-form documents, and records without real identity/time should normally use local analysis.
23
+ Aggregated metrics, pivot tables, cross-tabs, model outputs, and free-form documents should normally use local analysis. Records without real identity/time are checked against dimension routing next and fall to local analysis only if they are not a stable-entity lookup.
24
24
 
25
25
  ### Time coverage is not native granularity
26
26
 
@@ -44,6 +44,22 @@ point, and do not proceed until they answer:
44
44
  An unanswered question, a cumulative snapshot, or overlapping periods route to local analysis
45
45
  instead.
46
46
 
47
+ ## Route to dimension table
48
+
49
+ A dimension / dictionary table describes stable entities (city, product, device): a lookup that maps an entity code to its attributes. It has no row-level identity or event time, so it fails the UE prerequisites above, but it is not local-analysis material either — it belongs in AE as a dimension table bound to a property.
50
+
51
+ Classification order (UE first, dimension second, local analysis last):
52
+
53
+ 1. Satisfy the UE must-holds above → UE ingestion wins; never route an identity/time-bearing file here.
54
+ 2. Fail the UE prerequisites **and** match most of these dimension signals → dimension routing:
55
+ - No row-level identity: no `account_id` / `distinct_id` column. A `code` / `id` / `no` key is an entity code, not a user identity.
56
+ - No row-level event time: no `#time` column. If time exists, it is an effective / expiry interval, not an event occurrence.
57
+ - Finite enumeration: few rows, each describing one entity's attributes (code → name / level), not facts accumulating over time.
58
+ - A join key: a column shared with event data (`city_code`, `sku_id`, `device_id`) whose values are descriptive attributes, not measures.
59
+ 3. Otherwise → local analysis.
60
+
61
+ See [references/dimension-routing.md](references/dimension-routing.md) for the handoff.
62
+
47
63
  ## Route to local analysis
48
64
 
49
65
  Choose local analysis when:
@@ -111,7 +111,7 @@ If **not** in a sandbox environment, ask exactly:
111
111
  ```text
112
112
  Choose your source material (up to 2):
113
113
 
114
- 1 - Product document (local path, image file, or folder) — Extract events and properties from product docs; supports md/pdf/docx/URL/images (png/jpg/jpeg/webp)
114
+ 1 - Product document (local path, image file, or folder) — Extract events and properties from product docs; supports md/pdf/docx/xlsx/pptx/URL/images (png/jpg/jpeg/webp)
115
115
  2 - Detailed description (conversational) — Describe app business flow, core features, user behaviors, monetization model, etc.
116
116
  3 - Codebase (local project path; hidden in sandbox) — Analyze source code to extract events and properties
117
117
  4 - Pre-built template (built-in industry and game genre templates) — Select a built-in template
@@ -126,7 +126,7 @@ If in a sandbox environment, ask exactly:
126
126
  ```text
127
127
  Choose your source material (up to 2):
128
128
 
129
- 1 - Product document (sandbox workspace path, uploaded attachment, URL, image file, or folder) — Extract events and properties from product docs; supports md/pdf/docx/URL/images (png/jpg/jpeg/webp). You can attach/upload relevant files here.
129
+ 1 - Product document (sandbox workspace path, uploaded attachment, URL, image file, or folder) — Extract events and properties from product docs; supports md/pdf/docx/xlsx/pptx/URL/images (png/jpg/jpeg/webp). You can attach/upload relevant files here.
130
130
  2 - Detailed description (conversational) — Describe app business flow, core features, user behaviors, monetization model, etc.
131
131
  3 - Pre-built template (built-in industry and game genre templates) — Select a built-in template
132
132
  4 - Modify existing tracking plan (sandbox workspace path) — Import an existing tracking plan xlsx as baseline for modification; can be combined with Product doc / Description, but NOT with Pre-built template
@@ -142,7 +142,7 @@ User can multi-select (max 2). Interpret numbers by the **visible list shown to
142
142
 
143
143
  Canonical source material options (non-sandbox numbering):
144
144
 
145
- 1. **Product document** ****(****local path, sandbox workspace path, uploaded attachment, URL, image file, or folder) — Extract events and properties from product docs; supports md/pdf/docx/URL/images (png/jpg/jpeg/webp)
145
+ 1. **Product document** ****(****local path, sandbox workspace path, uploaded attachment, URL, image file, or folder) — Extract events and properties from product docs; supports md/pdf/docx/xlsx/pptx/URL/images (png/jpg/jpeg/webp)
146
146
  2. **Detailed description** (conversational) — Describe app business flow, core features, user behaviors, monetization model, etc.
147
147
  3. **Codebase** (local project path; hidden in sandbox) — Analyze source code to extract events and properties
148
148
  4. **Pre-built template** (built-in industry and game genre templates) — Select a built-in template (run `AE_LANG=<user_lang> ae-cli tracking plan list-templates --json` to see available templates)
@@ -674,9 +674,20 @@ Earlier sources take precedence — same-name events keep the earlier version, l
674
674
  - ⚠️ **No model-invented translations for template labels**: When replacing or explaining a localized template-owned label, use the exact value from `src/tracking/i18n` resources. If no corresponding resource exists, preserve the template text and ask the user before changing semantics.
675
675
  - ⚠️ **event_tag is not free-form model translation**: Do not manually map `业务事件`/`系统事件` to another language. Preserve template tags, or rely on `src/tracking/i18n` and autotrack generation for system labels when the CLI owns them.
676
676
  - **codebase**: Scan project source directory, extract events/properties from business logic; **same-name events merge prop_names without overwriting existing fields**; new items `source: "codebase"`
677
- - **prd**: Read all user-provided product documents (md / pdf / docx / URL / images), extract events and properties from each file; **same-name events merge prop_names without overwriting existing fields**; image files analyzed via multimodal interpretation of UI elements and interaction flows; all new items `source: "prd"`
677
+ - **prd**: Read all user-provided product documents (md / pdf / docx / xlsx / pptx / URL / images), extract events and properties from each file; **same-name events merge prop_names without overwriting existing fields**; image files analyzed via multimodal interpretation of UI elements and interaction flows; all new items `source: "prd"`
678
+ - **Read each format with the table below.** Preferred tool first; when it is missing, fall back rather than fail the read.
679
+ | Format | Read via |
680
+ |---|---|
681
+ | md | read directly |
682
+ | docx | `pandoc -t markdown <file>`; fallback `markitdown <file>` (`pip install markitdown` if missing); last resort `unzip -p <file> word/document.xml` and read the text |
683
+ | pdf (text) | extract text (native Read or a PDF text extractor) |
684
+ | pdf (scanned) | render pages to images, then read with vision |
685
+ | xlsx | read rows/columns with a structure-preserving reader (`openpyxl` / `pandas`, `pip install` if missing); a tracking table's row/column layout carries meaning — do NOT rely on a flattened markdown dump |
686
+ | pptx | `markitdown <file>` (`pip install markitdown` if missing) |
687
+ | png/jpg/jpeg/webp | multimodal interpretation, analyze UI elements and interaction flows |
688
+ - **xlsx is a third source-material path, distinct from the two existing xlsx flows.** A human-readable tracking table (event / property / type rows) is read row-by-row here. An **AE-format tracking-plan xlsx** goes through `import-template`; a **CSV/Excel data sample** goes through the data path (`ae-cli data-integration inspect`). Never route one into another's flow.
678
689
  - **prd path is a folder**: Recursively scan all files in the directory:
679
- - md/pdf/docx → read text content, extract events/properties
690
+ - md/pdf/docx/xlsx/pptx → read per the table above, extract events/properties
680
691
  - png/jpg/jpeg/webp → multimodal interpretation, analyze UI elements and interaction flows
681
692
  - subdirectories → recurse
682
693
  - other files → skip
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: ae-kb
3
3
  version: 1.0.0
4
- description: 'AE/TE knowledge base CLI manual for creating, importing read-only compiled snapshots, querying, LLM-powered ask, listing accessible knowledge bases and their sources, deterministic index/grep/read retrieval, checking status, uploading, compiling, schema generation, URL sources, source deletion, and knowledge base deletion. Use when the user asks to manage TE/AE/ThinkingEngine knowledge bases, import a compiled Markdown ZIP snapshot, upload documents or URLs to a knowledge base, query knowledge, ask knowledge bases with an LLM, list accessible knowledge bases or source metadata, inspect knowledge base indexes, search knowledge base pages, read a specific knowledge base page, check knowledge base status, generate schemas, compile knowledge, remove sources, or delete a knowledge base. To choose which knowledge base is worth searching, use the ae-kb-discovery skill first; this skill runs the retrieval once a target is chosen. Must use ae-cli kb commands and must not guess knowledge base names, scopes, page paths, source IDs, source display names, JSON payload shapes, or URL formats.'
4
+ description: 'AE/TE knowledge base CLI manual for creating, importing read-only compiled snapshots, querying, LLM-powered ask, listing accessible knowledge bases and their sources, deterministic index/grep/read retrieval, checking status, ZIP source upload and directory management, raw child-file reading, revision-checked child updates and deletion, compiling, schema generation, URL sources, source deletion, and knowledge base deletion. Use when the user asks to manage TE/AE/ThinkingEngine knowledge bases, import a compiled Markdown ZIP snapshot, upload documents or URLs to a knowledge base, query knowledge, ask knowledge bases with an LLM, list accessible knowledge bases or source metadata, inspect knowledge base indexes, search knowledge base pages, read a specific knowledge base page, check knowledge base status, generate schemas, compile knowledge, remove sources, or delete a knowledge base. To choose which knowledge base is worth searching, use the ae-kb-discovery skill first; this skill runs the retrieval once a target is chosen. Must use ae-cli kb commands and must not guess knowledge base names, scopes, page paths, source IDs, source display names, JSON payload shapes, or URL formats.'
5
5
  ---
6
6
 
7
7
  # ae-kb
@@ -35,12 +35,12 @@ ae-cli kb +<command> [options]
35
35
  | `+list` | read | List accessible knowledge bases filtered by buildStatus (default: compiled). |
36
36
  | `+list-sources` | read | List source metadata for one knowledge base so exact source identifiers can be discovered safely. |
37
37
  | `+index` | read | List accessible knowledge bases and their `index.md` navigation maps. |
38
- | `+grep` | read | Keyword-search knowledge base pages and return matched lines with context. |
38
+ | `+grep` | read | Keyword-search knowledge base pages; returns a page-level results array (hitCount / pageKind / sections previews). |
39
39
  | `+read` | read | Read a full knowledge base page, a line window, or (with `--outline`) only the page heading tree. |
40
40
  | `+new` | write | Create a new personal or company knowledge base. |
41
- | `+import` | write | Import a compiled Markdown ZIP as a personal read-only snapshot. |
42
- | `+import-status` | read | Query one snapshot import task by `--request-id` without polling. |
43
- | `+add` | write | Upload local files, a non-recursive directory, or HTTP(S) pages converted to markdown. |
41
+ | `+import` | write | Import a compiled Markdown ZIP as a personal or company read-only snapshot; `--scope` defaults to `personal`. |
42
+ | `+import-status` | read | Query one snapshot import task by `--request-id` without polling; output includes the persisted `scope`. |
43
+ | `+add` | write | Upload local files (including ZIP directory sources), a non-recursive directory, or HTTP(S) pages converted to markdown. |
44
44
  | `+url` | write | Upload a URL source directly with optional display name and parsing instruction. |
45
45
  | `+schema` | write | Generate the compile schema for a knowledge base. |
46
46
  | `+compile` | write | Compile a knowledge base in incremental or full mode. |
@@ -48,6 +48,67 @@ ae-cli kb +<command> [options]
48
48
  | `+rm-source` | high-risk-write | Delete one source from a knowledge base by stable ID; exact display name is legacy compatibility only. |
49
49
  | `+remove` | write | Delete an entire knowledge base. |
50
50
 
51
+ ## Published Version History
52
+
53
+ Use the nine version commands described in [`references/versions.md`](references/versions.md) to inspect immutable published history, compare source changes, and explicitly roll back an earlier version as a new publication. These commands manage history; `+index/+grep/+read/+ask` continue to use current published content.
54
+
55
+ | Command | Risk | Purpose |
56
+ | --- | --- | --- |
57
+ | `+versions` | read | List published versions and latestVersionId. |
58
+ | `+version-show` | read | Show one version summary. |
59
+ | `+version-sources` | read | Discover historical source IDs. |
60
+ | `+version-diff` | read | Compare two versions. |
61
+ | `+version-tree` | read | List a historical ZIP/URL source directory. |
62
+ | `+version-read` | read | Preview a historical directory child file. |
63
+ | `+version-download` | read | Save one ordinary historical file source; no directory download. |
64
+ | `+rollback` | high-risk-write | Restore an earlier version and create a new version. |
65
+ | `+rollback-status` | read | Query a persisted rollback Operation without polling. |
66
+
67
+ ## ZIP Directory Sources
68
+
69
+ Use `+add --files '["./sources.zip"]'` to upload one ZIP as one editable parent source, preserving its internal hierarchy. Archive validation and limits are enforced by the server. This is different from `+import`, which creates a read-only compiled snapshot. Passing a local directory to `+add` still uploads only its immediate supported files; it does not recursively package that directory.
70
+
71
+ Discover the exact parent ID with `+list-sources`. ZIP rows include `fileCount`, `sizeBytes`, `contentRevision`, and `updateStatus`.
72
+
73
+ | Command | Risk | Purpose |
74
+ | --- | --- | --- |
75
+ | `+source-ls` | read | List one directory page with revision, current children and deleted paths relative to the successful baseline. |
76
+ | `+source-read` | read | Read a child source file as UTF-8/base64, or save original bytes. |
77
+ | `+source-put` | write | Add one local file or explicitly replace the exact ZIP-relative path. |
78
+ | `+source-rm` | high-risk-write | Delete one child file or recursively delete a child directory. |
79
+
80
+ ```bash
81
+ ae-cli kb +source-ls --name handbook --id <source-id> --path "" --limit 100
82
+ ae-cli kb +source-ls --name handbook --id <source-id> --path "guides" --cursor <nextCursor>
83
+ ae-cli kb +source-read --name handbook --id <source-id> --path "guides/intro.md"
84
+ ae-cli kb +source-read --name handbook --id <source-id> --path "images/chart.png" --output ./chart.png
85
+ ae-cli kb +source-read --name handbook --id <source-id> --path "images/chart.png" --encoding base64
86
+ ae-cli kb +source-put --name handbook --id <source-id> --path "guides/new.md" --file ./new.md --action add --expected-revision 7 --dry-run
87
+ ae-cli kb +source-put --name handbook --id <source-id> --path "guides/new.md" --file ./new.md --action add --expected-revision 7
88
+ ae-cli kb +source-put --name handbook --id <source-id> --path "guides/new.md" --file ./revised.md --action replace --expected-revision 8
89
+ ae-cli kb +source-rm --name handbook --id <source-id> --path "guides/new.md" --expected-revision 9
90
+ ae-cli kb +source-rm --name handbook --id <source-id> --path "guides/obsolete" --recursive --expected-revision 10
91
+ ae-cli kb +compile --name handbook --mode incremental
92
+ ```
93
+
94
+ - Copy the source ID, paths and revision from current discovery. Names resolve personal then company, following the existing External API; no scope override is available on these commands.
95
+ - `--path` is relative to the ZIP root, not a local filesystem or `raw/zip/...` path. Root listing uses an empty path. Nonempty paths cannot be absolute or contain empty, dot, parent or backslash segments.
96
+ - Listing returns one page; continue using `nextCursor` and the same path. On a revision change, restart discovery before writing.
97
+ - `+source-read` reads source bytes; `+read` reads compiled Wiki pages. Default UTF-8 output fails on invalid UTF-8. Base64 preserves binary data. `--output` creates a new local file and refuses to overwrite an existing file.
98
+ - `+source-put` accepts one file up to 50 MB. Default `--action add` rejects an existing path; `--action replace` explicitly authorizes overwriting an existing child. There is no silent upsert. Dry-run shows metadata and redacts file content.
99
+ - `--expected-revision` is mandatory for writes. A 409 conflict is returned with its server error code; the command never refreshes and retries the write automatically.
100
+ - `+source-rm` keeps the parent source. Nonempty directory removal requires `--recursive`; deletion follows the CLI confirmation gate. Use `--yes` only when automated deletion of the exact target is already authorized. `+rm-source --id` deletes the entire parent.
101
+ - A mutation marks the parent changed but does not start compilation or regenerate Schema. Run incremental compilation explicitly; wait for successful publication before the next test stage.
102
+ - `+status` is the existing aggregate status query; it is not a per-run event or ZIP Diff reader. Do not interpret its compilation submission response as successful publication.
103
+ - No Gateway equivalent is registered in the current KB implementation. These commands reuse the typed External source APIs.
104
+
105
+ Transition status: transitional
106
+ Owning module: te-claude External Knowledge Base Sources API
107
+ Current transport: authenticated External REST via `kbApi` and multipart `kbUpload`.
108
+ Gateway target: TBD (ZIP source directory and raw-file capabilities)
109
+ Review after: 2026-12-06
110
+ Exit condition: migrate when equivalent typed Gateway file, directory and revision-aware mutation capabilities exist; retain CLI file handling and explicit mutation semantics.
111
+
51
112
  ## Common Workflows
52
113
 
53
114
  ### Create a Knowledge Base
@@ -107,6 +168,7 @@ Use `+add` when sources are local files, local directories, or pages that should
107
168
  ```bash
108
169
  ae-cli kb +add \
109
170
  --name engineering-handbook \
171
+ --scope company \
110
172
  --files '["./README.md","./docs","https://example.com/guide"]'
111
173
  ```
112
174
 
@@ -125,6 +187,7 @@ Use `+url` when adding one URL source and optionally passing a display name or p
125
187
  ```bash
126
188
  ae-cli kb +url \
127
189
  --name engineering-handbook \
190
+ --scope company \
128
191
  --url https://example.com/guide \
129
192
  --display-name guide \
130
193
  --parse-instruction "Keep headings and code blocks"
@@ -137,16 +200,20 @@ ae-cli kb +url \
137
200
  Generate the schema first when the knowledge base needs a compile schema.
138
201
 
139
202
  ```bash
140
- ae-cli kb +schema --name engineering-handbook
203
+ ae-cli kb +schema --name engineering-handbook --scope company
141
204
  ```
142
205
 
143
- Use `--force` only when `+status` reports `schema_generating` and the user explicitly wants to replace the current generation attempt. The replacement may consume additional tokens. Use `--model` only when the user provides the model display name.
206
+ Use `--force` only when `+status` reports `schema_generating` and the user explicitly wants to replace the current generation attempt. The replacement may consume additional tokens.
207
+
208
+ Schema and Compile accept the same optional model reference. Prefer the model record `id` returned by `ae-cli agent +list-models` (`Model.id`). Historical `modelId` and the unambiguous `modelId::scope` form remain compatible. A model `displayName` is presentation text, not a stable reference.
144
209
 
145
210
  To add one-time guidance for this generation without changing stored knowledge base metadata, pass `--custom-instructions`. The server trims the value, treats whitespace-only input as absent, and accepts up to 10,000 Unicode characters. Do not include secrets or credentials.
146
211
 
147
212
  ```bash
148
213
  ae-cli kb +schema \
149
214
  --name engineering-handbook \
215
+ --scope company \
216
+ --model <model-ref> \
150
217
  --custom-instructions "Prioritize troubleshooting workflows and preserve command examples"
151
218
  ```
152
219
 
@@ -155,7 +222,7 @@ Use `--dry-run` to inspect the request body before sending it. While generation
155
222
  Compile after sources and schema are ready:
156
223
 
157
224
  ```bash
158
- ae-cli kb +compile --name engineering-handbook --mode incremental
225
+ ae-cli kb +compile --name engineering-handbook --scope company --mode incremental --model <model-ref>
159
226
  ```
160
227
 
161
228
  Valid compile modes are `incremental` and `full`; default is `incremental`.
@@ -165,14 +232,14 @@ Valid compile modes are `incremental` and `full`; default is `incremental`.
165
232
  Use `+status` to inspect the current status of a knowledge base.
166
233
 
167
234
  ```bash
168
- ae-cli kb +status --name engineering-handbook
235
+ ae-cli kb +status --name engineering-handbook --scope company
169
236
  ```
170
237
 
171
238
  ### Ask Knowledge (LLM)
172
239
 
173
240
  Use `+ask` when the question requires synthesizing across multiple pages or multi-hop reasoning — a server-side agent runs the full retrieval loop and returns a synthesized answer with its source paths. Prefer `+index` -> `+grep` -> `+read` when deterministic retrieval is enough.
174
241
 
175
- The `+ask` command uses asynchronous submit/poll: by default, it automatically polls for completion (every 5s, up to 10 minutes) and prints the final answer. The output JSON is isomorphic to the previous synchronous response, so consumers require no changes.
242
+ The `+ask` command uses asynchronous submit/poll: by default, it automatically polls for completion (every 5s, up to 10 minutes) and prints the final answer with its execution ID, sources, model usage, tool call count, and model ID.
176
243
 
177
244
  ```bash
178
245
  # Default: submit and poll for completion
@@ -180,7 +247,6 @@ ae-cli kb +ask \
180
247
  --question "How do we troubleshoot payment alerts?" \
181
248
  --sources '[{"scope":"company","name":"engineering-handbook"}]' \
182
249
  --model-id claude-sonnet-4-6 \
183
- --max-turns 50 \
184
250
  --locale zh
185
251
 
186
252
  # Submit only, return executionId immediately (for batch processing)
@@ -193,10 +259,9 @@ ae-cli kb +ask-status --execution-id <id>
193
259
  - `--question`, alias `-q`: required natural-language question (1-2000 characters).
194
260
  - `--sources`: optional JSON array of knowledge base refs. Omit to search all accessible knowledge bases.
195
261
  - `--model-id`: optional LLM model ID. Omit to use the platform default.
196
- - `--max-turns`: optional agent turn limit (1-100, server default 50).
197
262
  - `--locale`: optional locale: `zh`, `en`, `ja`, or `ko`.
198
263
  - `--no-wait`: optional boolean flag. Return immediately after submission with `{executionId, status}`, without polling.
199
- - **Failure handling**: If execution fails, the command exits non-zero and prints an error message on stderr prefixed with the typed error code, e.g. `[timeout] ...` / `[model_error] ...` / `[invalid_sources] ...` (followed by the executionId). Treat the bracketed code as the machine-readable failure type.
264
+ - **Failure handling**: If execution fails, the command exits non-zero and prints the unified JSON error envelope on stderr: `{"ok":false,"error":{"type":"api","code":"<server-code>","message":"..."}}`. Stable server codes are `model_unavailable`, `sandbox_unavailable`, `agent_skill_unavailable`, `dispatch_auth_unavailable`, `provider_failed`, `retrieval_error`, `timeout`, and `process_restart`.
200
265
 
201
266
  ### List Accessible Knowledge Bases
202
267
 
@@ -225,7 +290,7 @@ ae-cli kb +index \
225
290
  --sources '[{"scope":"company","name":"engineering-handbook"}]'
226
291
  ```
227
292
 
228
- Then use `+grep` to locate likely pages and line numbers:
293
+ Then use `+grep` to locate likely pages:
229
294
 
230
295
  ```bash
231
296
  ae-cli kb +grep \
@@ -235,7 +300,7 @@ ae-cli kb +grep \
235
300
  --top-k 10
236
301
  ```
237
302
 
238
- Each grep hit carries `path`, `line`, `breadcrumb`, a context snippet, and the section range of the matched line (`sectionStartLine` / `sectionEndLine`). `line` is the hit anchor; `sectionStartLine` / `sectionEndLine` are the enclosing heading-section boundaries. Choose the smallest reliable `--offset` / `--limit` window that preserves the needed evidence; use the section range when the answer needs whole-section context.
303
+ The response is a page-level `results` array: each entry is one page with its full `hitCount`, a `pageKind` (`content` or `catalog`), up to 4 `sections` previews (breadcrumb, `sectionStartLine`/`sectionEndLine`, text preview), and `moreSections`. Use `hitCount` and the previews to decide which pages to read; `pageKind: "catalog"` marks a module directory page — treat its entries as detail-page navigation, not as an answer source. Read the section range with `--offset sectionStartLine` / `--limit sectionEndLine - sectionStartLine + 1`; when `moreSections > 0` and the answer is not in the previews, re-grep that single page to see all its hits.
239
304
 
240
305
  Use `+read --outline` when the current target page has no reliable grep range and headings are needed to choose a section:
241
306
 
@@ -246,14 +311,15 @@ ae-cli kb +read \
246
311
  --outline
247
312
  ```
248
313
 
249
- Then use `+read` to open the selected window, using the hit anchor, a section boundary from same-page or linked-page grep, or two adjacent outline headings:
314
+ Then use `+read` to open the selected window, using a page-group section boundary or two adjacent outline headings:
250
315
 
251
316
  ```bash
252
317
  ae-cli kb +read \
253
318
  --source '{"scope":"company","name":"engineering-handbook"}' \
254
319
  --path "wiki/sandbox.md" \
255
320
  --offset 42 \
256
- --limit 60
321
+ --limit 60 \
322
+ --expand block
257
323
  ```
258
324
 
259
325
  ### List Sources
@@ -261,7 +327,7 @@ ae-cli kb +read \
261
327
  List sources first to discover the stable identifier for the intended source:
262
328
 
263
329
  ```bash
264
- ae-cli kb +list-sources --name engineering-handbook
330
+ ae-cli kb +list-sources --name engineering-handbook --scope company
265
331
  ```
266
332
 
267
333
  Copy the exact `id` from the response into `+rm-source`. Do not guess a source ID from a local filename, URL, display name, or an older upload response.
@@ -280,6 +346,7 @@ Use `+rm-source --id` with the exact ID returned by the current `+list-sources`
280
346
  ```bash
281
347
  ae-cli kb +rm-source \
282
348
  --name engineering-handbook \
349
+ --scope company \
283
350
  --id cm-source-id
284
351
  ```
285
352
 
@@ -298,7 +365,7 @@ If the user only gives a loose source name, do not guess a source ID. Run `+list
298
365
  Use `+remove` for deleting the entire knowledge base. Confirm the target name with the user if there is any ambiguity.
299
366
 
300
367
  ```bash
301
- ae-cli kb +remove --name engineering-handbook
368
+ ae-cli kb +remove --name engineering-handbook --scope company
302
369
  ```
303
370
 
304
371
  ## Command Reference
@@ -306,17 +373,16 @@ ae-cli kb +remove --name engineering-handbook
306
373
  ### `+ask`
307
374
 
308
375
  ```bash
309
- ae-cli kb +ask --question "<question>" [--sources '[{"scope":"company","name":"kb-name"}]'] [--model-id claude-sonnet-4-6] [--max-turns 50] [--locale zh|en|ja|ko] [--no-wait]
376
+ ae-cli kb +ask --question "<question>" [--sources '[{"scope":"company","name":"kb-name"}]'] [--model-id claude-sonnet-4-6] [--locale zh|en|ja|ko] [--no-wait]
310
377
  ```
311
378
 
312
379
  - `--question`, alias `-q`: required natural-language question (1-2000 characters).
313
380
  - `--sources`: optional JSON array of knowledge base refs. Omit to search all accessible knowledge bases.
314
381
  - `--model-id`: optional LLM model ID. Omit to use the platform default.
315
- - `--max-turns`: optional agent turn limit (1-100, server default 50).
316
382
  - `--locale`: optional locale: `zh`, `en`, `ja`, or `ko`.
317
383
  - `--no-wait`: optional. Return immediately with `{executionId, status}` instead of polling.
318
384
  - When to use: multi-page synthesis or multi-hop questions. For simple factual lookups, prefer `+index` / `+grep` / `+read`.
319
- - Output: By default, polls and returns `{executionId, answer, sources, modelUsage, toolCallCount, maxTurns, modelId}` (same fields as the previous synchronous response, plus `executionId`). With `--no-wait`, returns `{executionId, status}` immediately. On failure, exits non-zero with a stderr message prefixed by the typed error code (`[timeout]`, `[model_error]`, `[invalid_sources]`, `[process_restart]`).
385
+ - Output: By default, polls and returns `{executionId, answer, sources, modelUsage, toolCallCount, modelId}`. With `--no-wait`, returns `{executionId, status}` immediately. On failure, exits non-zero with the unified stderr envelope containing `error.type="api"`, the server `error.code` (`model_unavailable`, `sandbox_unavailable`, `agent_skill_unavailable`, `dispatch_auth_unavailable`, `provider_failed`, `retrieval_error`, `timeout`, or `process_restart`), and `error.message`.
320
386
 
321
387
  ### `+ask-status`
322
388
 
@@ -325,7 +391,7 @@ ae-cli kb +ask-status --execution-id <id>
325
391
  ```
326
392
 
327
393
  - `--execution-id`: required. The execution ID returned by `+ask` submission.
328
- - Output: Returns the current execution state: `{executionId, status, elapsedMs?, answer?, sources?, modelUsage?, toolCallCount?, error?}`. Does not poll; returns a single snapshot.
394
+ - Output: Returns one successful CLI envelope snapshot. For a failed execution, the stable server code remains at `data.error.code`: `{"ok":true,"data":{"executionId":"...","status":"failed","error":{"code":"retrieval_error","message":"..."}}}`. Does not poll.
329
395
 
330
396
  ### `+list`
331
397
 
@@ -357,18 +423,19 @@ ae-cli kb +grep --query "<keywords>" --sources '[{"scope":"company","name":"kb-n
357
423
  - `--paths`: required JSON array of wiki pages or subdirectories **copied** from `+index`. A single page is still an array, e.g. `["wiki/sandbox.md"]`. Distinct from `+read --path` (one string).
358
424
  - `--top-k`: optional max number of hits, 1-50, default 10.
359
425
  - `--locale`: optional locale: `zh`, `en`, `ja`, or `ko`.
360
- - Each hit includes `sectionStartLine` / `sectionEndLine`: the line range of the section (bounded by the nearest headings) containing the matched line. Use it as the `+read` window.
426
+ - Each page entry in results carries `hitCount` (full match count), `pageKind`, and `sections` previews with `sectionStartLine` / `sectionEndLine` use the section range as the `+read` window.
361
427
 
362
428
  ### `+read`
363
429
 
364
430
  ```bash
365
- ae-cli kb +read --source '{"scope":"company","name":"kb-name"}' --path "index.md" [--offset 1] [--limit 200] [--outline] [--locale zh|en|ja|ko]
431
+ ae-cli kb +read --source '{"scope":"company","name":"kb-name"}' --path "index.md" [--offset 1] [--limit 200] [--expand block|none] [--outline] [--locale zh|en|ja|ko]
366
432
  ```
367
433
 
368
434
  - `--source`: required JSON object pointing to exactly one knowledge base.
369
435
  - `--path`: required page path relative to the knowledge base root, such as `index.md` or `wiki/concepts/data-model.md`.
370
- - `--offset`: optional 1-based start line.
371
- - `--limit`: optional max line count, 1-10000.
436
+ - `--offset`: optional 1-based integer start line.
437
+ - `--limit`: optional max line count, 1-2000.
438
+ - `--expand`: optional Markdown block expansion mode. `block` lets the server include a complete Markdown block outside the requested line window; `none` keeps the exact offset/limit window. Omit it to use the server default, `block`.
372
439
  - `--outline`: optional. Return only the whole-page heading tree (`{level, heading, line}`) with empty content, independent of `--offset` / `--limit`. Use it on long pages to choose which section to read.
373
440
  - `--locale`: optional locale: `zh`, `en`, `ja`, or `ko`.
374
441
 
@@ -381,7 +448,7 @@ ae-cli kb +new --name "<name>" [--scope personal|company] [--description "..."]
381
448
  ### `+add`
382
449
 
383
450
  ```bash
384
- ae-cli kb +add --name "<name>" --files '["./a.md","./docs","https://example.com/page"]'
451
+ ae-cli kb +add --name "<name>" --files '["./a.md","./docs","https://example.com/page"]' [--scope personal|company]
385
452
  ```
386
453
 
387
454
  ### `+import`
@@ -411,46 +478,50 @@ ae-cli kb +import-status --request-id <requestId>
411
478
  ### `+url`
412
479
 
413
480
  ```bash
414
- ae-cli kb +url --name "<name>" --url "https://example.com/page" [--display-name "..."] [--parse-instruction "..."]
481
+ ae-cli kb +url --name "<name>" --url "https://example.com/page" [--scope personal|company] [--display-name "..."] [--parse-instruction "..."]
415
482
  ```
416
483
 
417
484
  ### `+schema`
418
485
 
419
486
  ```bash
420
- ae-cli kb +schema --name "<name>" [--force] [--model "<model displayName>"] [--custom-instructions "<one-time guidance>"]
487
+ ae-cli kb +schema --name "<name>" [--scope personal|company] [--force] [--model <model-ref>] [--custom-instructions "<one-time guidance>"]
421
488
  ```
422
489
 
423
490
  - `--custom-instructions`: Optional per-run schema-generation guidance. It is not persisted; whitespace-only input is omitted. The server allows at most 10,000 Unicode characters and rejects disallowed control characters. Do not include secrets or credentials.
424
491
  - `--force`: Replace the current attempt only when schema generation is already running and the user explicitly requests the replacement. The selected model and custom instructions apply to the new attempt, which may consume additional tokens.
425
492
  - `--dry-run`: Shows the same `customInstructions` request field that execution will send.
493
+ - `--model`: Optional stable model reference. Prefer `Model.id` from `ae-cli agent +list-models`; historical `modelId` and `modelId::scope` remain compatible.
494
+ - `--scope`: Optional exact knowledge-base scope. Omit it to retain the legacy personal-to-company lookup order.
426
495
  - Errors: `KB_SCHEMA_CUSTOM_INSTRUCTIONS_INVALID` means the field failed validation. `KB_SCHEMA_GENERATION_IN_PROGRESS` means generation is active and a request without `--force` supplied a new model or effective custom instructions.
427
496
 
428
497
  ### `+compile`
429
498
 
430
499
  ```bash
431
- ae-cli kb +compile --name "<name>" [--mode incremental|full]
500
+ ae-cli kb +compile --name "<name>" [--scope personal|company] [--mode incremental|full] [--model <model-ref>]
432
501
  ```
433
502
 
434
503
  ### `+status`
435
504
 
436
505
  ```bash
437
- ae-cli kb +status --name "<name>"
506
+ ae-cli kb +status --name "<name>" [--scope personal|company]
438
507
  ```
439
508
 
440
509
  ### `+list-sources`
441
510
 
442
511
  ```bash
443
- ae-cli kb +list-sources --name "<name>"
512
+ ae-cli kb +list-sources --name "<name>" [--scope personal|company]
444
513
  ```
445
514
 
446
515
  - `--name`: required knowledge base name.
447
- - Output: Safe source metadata including the stable `id` needed by `+rm-source`; raw paths, hashes, credentials, and source content are not returned.
516
+ - Output: `items` contains effective sources with stable `id`. `pendingDeletions` contains soft-deleted sources still included in the current successful version. `deletionMaintenance` is separate and may report already-published deletions awaiting cleanup. Paths, hashes, credentials, and source content are not returned.
517
+ - Check `deletionProjection.state` and its `baseline` before interpreting deletion lists. `ready` with `pendingDeletions: []` means no pending deletion at that baseline. `changing`, `review_required`, or `unavailable` with `pendingDeletions: null` means undetermined; display the `reasonCode`, never turn null into an empty list. Legacy libraries without a verifiable complete publication manifest return unavailable until a real version is published.
518
+ - A rollback creates a new current version. An older deletion receipt cannot override membership in that version. A later source deletion needs publication again.
448
519
  - Copy the exact `id` from the current response before deleting a source; never guess it.
449
520
 
450
521
  ### `+rm-source`
451
522
 
452
523
  ```bash
453
- ae-cli kb +rm-source --name "<name>" --id "<source-id>"
524
+ ae-cli kb +rm-source --name "<name>" --id "<source-id>" [--scope personal|company]
454
525
  ```
455
526
 
456
527
  - `--id`: preferred stable source identifier copied from `+list-sources`.
@@ -460,5 +531,5 @@ ae-cli kb +rm-source --name "<name>" --id "<source-id>"
460
531
  ### `+remove`
461
532
 
462
533
  ```bash
463
- ae-cli kb +remove --name "<name>"
534
+ ae-cli kb +remove --name "<name>" [--scope personal|company]
464
535
  ```