@allocator-one/harness-cli 1.16.0 → 1.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -927,6 +927,121 @@ refusal exits 1 with the server's message and what it means
927
927
  answers a capability that doesn't exist, ships disabled, or is switched off
928
928
  with the same 404.
929
929
 
930
+ ## Code index
931
+
932
+ ```sh
933
+ harness code sync # sync this worktree’s overlay
934
+ harness code sync --path ../app # use that worktree’s host/org config
935
+ harness code status --json # active version and local freshness
936
+ harness code status --skipped # include the base’s skipped-files report
937
+ ```
938
+
939
+ The repository must be shared through the organization’s Harness GitHub
940
+ connection and code indexing must be enabled for that org. The server builds
941
+ commit bases from GitHub. The CLI polls a fetching base with backoff, opens an
942
+ overlay sync, uploads only blobs that sync requests, and activates it. It never
943
+ uploads a base or follows source symlinks. A successful sync reports the server’s
944
+ state; `queued` means indexing has been requested, not that queries are ready.
945
+ Safe source reads require macOS 11 or later, or Linux with `/proc/self/fd`;
946
+ code sync refuses when these kernel facilities are unavailable.
947
+
948
+ Sync needs both `harness:read` and `harness:write`; ordinary `code status`
949
+ needs `harness:read`, and base-status requests also need `harness:write`. `--skipped` on sync or status asks the server for its base
950
+ exclusions (path and reason). Local binary, oversized, ignored and secret-shaped
951
+ files are excluded before upload. Built-in secret rules cannot be removed by
952
+ an ignore-file negation. Deny and secret-path matches use ASCII case-insensitive
953
+ checks; path identities are preserved. Served content expressions must exactly
954
+ match the reviewed sources bundled with this client, or be literal-only markers
955
+ matched as substrings. Other expressions stop sync with an upgrade message before
956
+ source scanning. Source content is never included in diagnostics.
957
+
958
+ `.harnesscodeignore` uses the code-index policy dialect, not Git's ignore
959
+ grammar: each line is trimmed; `#` and `!` lines are skipped; and a backslash
960
+ is literal. The CLI reports warnings for skipped `!` lines and backslashes.
961
+ Patterns are case-sensitive, limited to 256 bytes and eight `*` characters,
962
+ and an ignore file has at most 1,000 patterns and 64 KiB. The server's indexed
963
+ extensions are exact, so `.TS` is distinct from `.ts`.
964
+
965
+ The working copy's `.harnesscodeignore` governs its view. The CLI compares it with
966
+ the committed ignore file: newly ignored base paths become delete entries, and
967
+ newly included files are read from the worktree through the usual policy checks.
968
+ It never reads unchanged source content from the base. If ignore changes exceed
969
+ 20,000 overlay paths, commit the ignore file so the server-built base honors it.
970
+
971
+ View/session state is isolated by server, organization, repository and worktree
972
+ under the user’s cache directory. `HARNESS_CODE_STATE_DIR` overrides the directory
973
+ and must be absolute. It stores control metadata and hashes, not source bytes or
974
+ tokens. Retrying the same interrupted overlay reuses its client ID. An uncertain
975
+ activation retains its opened sync ID and timestamp; the CLI reads that sync and
976
+ records its original pending version once it is no longer receiving. A missing sync
977
+ is treated as a replaced, never-activated sync only within 60 minutes; an older
978
+ missing sync fails closed. The server keeps a client ID unique per view and
979
+ manifest across states, so the CLI never uses one for a different manifest. A stale
980
+ policy is fetched again and the overlay rescanned. Syncs of the same local view are serialized: a
981
+ second sync is refused while one is running, because opening a sync can replace older
982
+ unactivated syncs on the server. If the process is forcibly interrupted, its error
983
+ message names the lock directory; remove it only after confirming no sync is running.
984
+ The server refuses overlays above 20,000 paths; sync against a newer base commit. A failed index is reported as `failed` with exit
985
+ code 1, while a worktree with no sync is `not_synced`.
986
+
987
+ ### Query the active view
988
+
989
+ ```sh
990
+ harness code search 'process' --kind function --limit 20
991
+ harness code explain 'OPAQUE_ID_FROM_SEARCH' --budget-tokens 4000
992
+ harness code affected --symbol 'OPAQUE_ID' --file src/app.ts --depth 3
993
+ harness code context --symbol 'OPAQUE_ID' --budget-tokens 2000 --json
994
+ harness code context 'name' --path ../app
995
+ ```
996
+
997
+ Queries need `harness:read` and an existing view from `code sync`. They read its
998
+ active version, even while a later version is pending. The output includes base
999
+ commit, overlay digest, active version and pending progress. Querying neither
1000
+ scans nor uploads local source. No code-index MCP tools are registered.
1001
+
1002
+ Human output cites `path:line@sha256`, indexed snippets, version and base/overlay
1003
+ origin. Search citations may lack snippet text: use `context` to retrieve it.
1004
+ Context items that exceed the budget remain citations explicitly lacking text.
1005
+ JSON preserves server `data` and `meta`, adding a `guidance` array. Resolved,
1006
+ possible, name-only and unresolved references remain separate. A snippet budget
1007
+ covers the server's indexed text, not command formatting or metadata.
1008
+
1009
+ Contract 1.3 `meta.truncation` is always displayed: the returned count, the total
1010
+ if the server supplies it, limits and next command or narrowing hint. The CLI
1011
+ never invents a total or silently pages beyond the request. A `not_tracked`
1012
+ coverage answer gives a local `rg` hint instead of asserting there are no callers.
1013
+ Results cite the indexed snapshot; inspect the current file before editing it.
1014
+
1015
+ IDs are opaque. Swift IDs include declaration positions and can stop resolving
1016
+ when an edit moves a declaration; qualified names can include argument labels.
1017
+ Do not parse or reconstruct either. `not_found` asks you to search again, rather
1018
+ than blindly retrying an old symbol. `--include-ambiguous` and `--include-types`
1019
+ explicitly expand the affected walk; without them, possible/type impact is
1020
+ reported separately. Limits are bounded (search 1–100; depth 1–6; at most 200
1021
+ seeds; snippet budget 100–16,000, or 100–32,000 for context).
1022
+
1023
+ ### Agent Skill
1024
+
1025
+ The portable source of truth ships as `skills/harness-code/SKILL.md` in both npm
1026
+ packages. Copy it into your consumer repo's skill tree, following that repo's
1027
+ adapters and metadata conventions. For an agent that discovers `.agents/skills`:
1028
+
1029
+ ```sh
1030
+ mkdir -p .agents/skills
1031
+ cp -R "$(npm root -g)/@allocator-one/harness-cli/skills/harness-code" .agents/skills/
1032
+ ```
1033
+
1034
+ A short `AGENTS.md`/`CLAUDE.md` snippet:
1035
+
1036
+ > For symbol relationships, callers, impact and cited context, use the
1037
+ > harness-code skill and `harness code search/explain/affected/context`. Start
1038
+ > with `code status`; use `rg` for literal text and `not_tracked` coverage.
1039
+ > Report truncation and indexed hashes/versions; search again after missing IDs.
1040
+
1041
+ Allocator-one adoption and a paired agent tool-use comparison against a grep-only
1042
+ baseline are delivered in the consumer follow-up to CLI-70, before publication.
1043
+
1044
+
930
1045
  ## Uploads
931
1046
 
932
1047
  `harness upload <path>` uploads a file and prints a markdown reference to
@@ -11,14 +11,34 @@ var CLI_PACKAGE = pkg.name;
11
11
  // src/invocation.ts
12
12
  import { basename } from "path";
13
13
  var OPERATOR_PACKAGE = "@allocator-one/operator";
14
- function invokedName(argv1 = process.argv[1], packageName = CLI_PACKAGE) {
14
+ var INFRAONE_PACKAGE = "@allocator-one/infraone";
15
+ var PACKAGES = {
16
+ harness: "@allocator-one/harness-cli",
17
+ operator: OPERATOR_PACKAGE,
18
+ infraone: INFRAONE_PACKAGE
19
+ };
20
+ var operatorMount = false;
21
+ function mountOperatorUnderInfraone() {
22
+ operatorMount = true;
23
+ }
24
+ function operatorMounted() {
25
+ return operatorMount;
26
+ }
27
+ function invokedName(argv1 = process.argv[1], packageName = CLI_PACKAGE, infraoneBinary = typeof __INFRAONE_BINARY__ !== "undefined" && __INFRAONE_BINARY__ === true) {
28
+ if (operatorMount) return "operator";
29
+ if (infraoneBinary) return "infraone";
15
30
  const typed = basename(argv1 ?? "").replace(/\.[cm]?js$/i, "").toLowerCase();
16
- if (typed === "operator" || typed === "harness") return typed;
17
- return packageName === OPERATOR_PACKAGE ? "operator" : "harness";
31
+ if (typed === "operator" || typed === "harness" || typed === "infraone") return typed;
32
+ if (packageName === OPERATOR_PACKAGE) return "operator";
33
+ return packageName === INFRAONE_PACKAGE ? "infraone" : "harness";
18
34
  }
19
35
  function named(text, name = invokedName()) {
20
36
  if (name === "harness") return text;
21
- return text.replace(/^harness: /gm, `${name}: `).replace(/(?<![\w@/.-])harness (?=[a-z])(?!disagree)/g, `${name} `).replaceAll("@allocator-one/harness-cli", OPERATOR_PACKAGE);
37
+ if (name === "operator" && operatorMount) return mountedNamed(text);
38
+ return text.replace(/^harness: /gm, `${name}: `).replace(/(?<![\w@/.-])harness (?=[a-z])(?!disagree)/g, `${name} `).replaceAll(PACKAGES.harness, PACKAGES[name]);
39
+ }
40
+ function mountedNamed(text) {
41
+ return text.replace(/^(?:harness|operator): /gm, "infraone: ").replace(/(?<![\w@/.-])(?<!infraone )(?:harness|operator) (?=[a-z[<])(?!disagree)/g, "infraone operator ").replaceAll(PACKAGES.harness, INFRAONE_PACKAGE).replaceAll(OPERATOR_PACKAGE, INFRAONE_PACKAGE);
22
42
  }
23
43
  var OPERATOR_COMMANDS = [
24
44
  "run",
@@ -67,6 +87,8 @@ export {
67
87
  CLI_VERSION,
68
88
  CLI_PACKAGE,
69
89
  OPERATOR_PACKAGE,
90
+ mountOperatorUnderInfraone,
91
+ operatorMounted,
70
92
  invokedName,
71
93
  named,
72
94
  layoutOperatorHelp