@jitera/connect 1.5.0 → 2.0.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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jitera-connect",
3
- "version": "1.5.0",
3
+ "version": "2.0.0",
4
4
  "description": "Connect this workspace to a Jitera project: read documentation and source, and keep project memory up to date.",
5
5
  "author": {
6
6
  "name": "Jitera"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jitera-connect",
3
- "version": "1.5.0",
3
+ "version": "2.0.0",
4
4
  "description": "Connect this workspace to a Jitera project: read documentation and source, and keep project memory up to date.",
5
5
  "skills": "./skills/"
6
6
  }
package/README.md CHANGED
@@ -60,19 +60,26 @@ CLAUDE.md above a repo leaks into every project underneath it.
60
60
  ## what applies where
61
61
 
62
62
  the api key is global: one per user, per machine, stored by `login --install`.
63
- every repo you open uses it, so init is optional and nothing breaks without it.
64
-
65
- `.jitera.json` configures nothing by itself. it declares what the repo expects,
66
- and sessions check the two against each other. a teammate who has not signed in
67
- yet gets the exact login command for the right environment. a teammate pointed
68
- at a different environment gets a warning instead of quietly reading the wrong
69
- project.
70
-
71
- with a user-level key it does one more thing: it picks the project. the proxy
72
- and the hooks read it and send it as an `X-Jitera-Project` header, so several
73
- repos on one machine can talk to different projects through a single key. older
74
- deployments bind the key itself to one project, and there the marker only makes
75
- a mismatch visible.
63
+ it says who you are, not which project you are in.
64
+
65
+ `.jitera.json` says which project. without it a repo is unbound, and the hooks
66
+ do nothing at all there: no context is gathered, no checkpoint is asked for, and
67
+ no call reaches the server. a repo you have not run `init` in is left alone,
68
+ which is why init is per repo and login is per machine.
69
+
70
+ an unbound session is not silent about it. session start tells the assistant the
71
+ repo is unbound and to suggest `npx @jitera/connect init`, and the status line
72
+ shows the same thing.
73
+
74
+ sessions also check the marker against the plugin. a teammate who has not signed
75
+ in yet gets the exact login command for the right environment. a teammate
76
+ pointed at a different environment gets a warning instead of quietly reading the
77
+ wrong project.
78
+
79
+ the proxy and the hooks send the project it names as an `X-Jitera-Project`
80
+ header, so several repos on one machine can talk to different projects through a
81
+ single key. older deployments bind the key itself to one project; there the
82
+ marker still decides whether the hooks run, and makes a mismatch visible.
76
83
 
77
84
  ## seeing your keys
78
85
 
@@ -3,16 +3,19 @@ memory, documentation, and source. Treat it as the source of truth for this
3
3
  project, not an optional lookup.
4
4
 
5
5
  Before answering a question about this project, and before planning or
6
- implementing anything, call `recall_jitera_memory` first. An empty result is
7
- normal and is not an error.
6
+ implementing anything, call `gather_jitera_context` with the task in the user's
7
+ own words. It recalls memory and searches documentation and source in one pass,
8
+ across every agent in the project. An empty result is normal, not an error.
9
+ Call it again whenever the work reaches something you have not gathered context
10
+ for; it is not a once-per-session lookup.
8
11
 
9
12
  Before writing a spec, design, or plan, search `documents/` with
10
13
  `resource_search` and read any match with `resource_read`. Update the existing
11
14
  document rather than creating a second one.
12
15
 
13
16
  When a decision is made, a constraint is discovered, or the user corrects you,
14
- persist it with `remember_jitera_memory`. Recall the entity first and re-send its
15
- full attribute list — entities are keyed on name plus type, so writing blind
17
+ persist it with `remember_jitera_memory`. Recall the entity first with
18
+ `recall_jitera_memory` and re-send its full attribute list — entities are keyed on name plus type, so writing blind
16
19
  creates duplicates and replaces facts instead of adding them.
17
20
 
18
21
  Do not store anything already recorded in the repository or its git history.
@@ -0,0 +1,12 @@
1
+ An API key is configured, but this repository is not bound to a project.
2
+ No project context is loaded and the MCP tools have nothing to read.
3
+ Do not call them until this repository is bound.
4
+
5
+ If the user asks about project context, documentation, or shared memory, or
6
+ wants this repository bound to one, tell them to run this at the repository root:
7
+
8
+ npx @jitera/connect init
9
+
10
+ That writes a .jitera.json recording which deployment and project this
11
+ repository belongs to, alongside AGENTS.md and CLAUDE.md for the rest of the
12
+ team. Once it exists, project context loads by itself at the start of a session.
@@ -2,10 +2,19 @@ Project context tools are configured for this workspace: project documentation,
2
2
  source, and a shared project memory over MCP.
3
3
 
4
4
  Before your first substantive answer in this session, and before planning or
5
- implementing anything, call `recall_jitera_memory`. An empty result is normal
6
- and is not an error. If the tools are missing from your tool list or a call
7
- fails, say so and continue without stored context instead of guessing.
5
+ implementing anything, call `gather_jitera_context` with the task in the user's
6
+ own words. An empty result is normal and is not an error.
7
+
8
+ If the tools are missing from your tool list or a call fails, say so and
9
+ continue without stored context instead of guessing.
10
+
11
+ Keep using it as the work moves. This is not a once-per-session lookup: call it
12
+ again whenever you reach an area you have not gathered context for yet, an
13
+ unfamiliar name, or a decision about how something should work. Use
14
+ `resource_search` and `resource_read` when you want one specific file rather
15
+ than the whole picture.
8
16
 
9
17
  As decisions are made, constraints are discovered, or you are corrected, persist
10
- them with `remember_jitera_memory`. Recall the entity first and re-send its full
11
- attribute list, so you update it rather than creating a duplicate.
18
+ them with `remember_jitera_memory`. Recall the entity first with
19
+ `recall_jitera_memory` and re-send its full attribute list, so you update it
20
+ rather than creating a duplicate.
@@ -13,5 +13,10 @@ catch {
13
13
  const dir = input.workspace?.project_dir ?? input.workspace?.current_dir ?? input.cwd;
14
14
  const marker = dir ? readProjectMarker(dir) : undefined;
15
15
  const status = readSessionStatus(input.session_id);
16
- process.stdout.write(`${renderStatusLine({ status, markerEnvironment: marker?.environment })}\n`);
16
+ process.stdout.write(`${renderStatusLine({
17
+ status,
18
+ markerEnvironment: marker?.environment,
19
+ // No directory to inspect is not the same as an unbound repository.
20
+ bound: dir ? marker !== undefined : undefined,
21
+ })}\n`);
17
22
  //# sourceMappingURL=statusline.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"statusline.js","sourceRoot":"","sources":["../../src/bin/statusline.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEvC,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAQpD,IAAI,KAAK,GAAgB,EAAE,CAAC;AAC5B,IAAI,CAAC;IACH,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,EAAE,MAAM,CAAC,CAAgB,CAAC;AAC7D,CAAC;AAAC,MAAM,CAAC;IACP,KAAK,GAAG,EAAE,CAAC;AACb,CAAC;AAED,MAAM,GAAG,GAAG,KAAK,CAAC,SAAS,EAAE,WAAW,IAAI,KAAK,CAAC,SAAS,EAAE,WAAW,IAAI,KAAK,CAAC,GAAG,CAAC;AACtF,MAAM,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AACxD,MAAM,MAAM,GAAG,iBAAiB,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;AAEnD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,gBAAgB,CAAC,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,IAAI,CAAC,CAAC"}
1
+ {"version":3,"file":"statusline.js","sourceRoot":"","sources":["../../src/bin/statusline.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEvC,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAQpD,IAAI,KAAK,GAAgB,EAAE,CAAC;AAC5B,IAAI,CAAC;IACH,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,EAAE,MAAM,CAAC,CAAgB,CAAC;AAC7D,CAAC;AAAC,MAAM,CAAC;IACP,KAAK,GAAG,EAAE,CAAC;AACb,CAAC;AAED,MAAM,GAAG,GAAG,KAAK,CAAC,SAAS,EAAE,WAAW,IAAI,KAAK,CAAC,SAAS,EAAE,WAAW,IAAI,KAAK,CAAC,GAAG,CAAC;AACtF,MAAM,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AACxD,MAAM,MAAM,GAAG,iBAAiB,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;AAEnD,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,GAAG,gBAAgB,CAAC;IAClB,MAAM;IACN,iBAAiB,EAAE,MAAM,EAAE,WAAW;IACtC,oEAAoE;IACpE,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS;CAC9C,CAAC,IAAI,CACP,CAAC"}
package/dist/hook-io.d.ts CHANGED
@@ -9,6 +9,7 @@ export interface SessionStartInput extends HookInputBase {
9
9
  readonly source?: "startup" | "resume" | "clear" | "compact" | "fork";
10
10
  }
11
11
  export interface UserPromptSubmitInput extends HookInputBase {
12
+ readonly prompt?: string;
12
13
  readonly prompt_text?: string;
13
14
  }
14
15
  export interface StopInput extends HookInputBase {
@@ -18,5 +19,6 @@ export interface StopInput extends HookInputBase {
18
19
  }
19
20
  export type HookInput = SessionStartInput & UserPromptSubmitInput & StopInput;
20
21
  export declare function readHookInput(fd?: number): HookInput;
22
+ export declare function promptText(input: UserPromptSubmitInput): string;
21
23
  export declare function emitContext(event: HookEventName, additionalContext: string): void;
22
24
  //# sourceMappingURL=hook-io.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"hook-io.d.ts","sourceRoot":"","sources":["../src/hook-io.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,aAAa,GACrB,cAAc,GACd,kBAAkB,GAClB,MAAM,GACN,YAAY,GACZ,YAAY,CAAC;AAEjB,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,eAAe,CAAC,EAAE,aAAa,CAAC;IACzC,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,iBAAkB,SAAQ,aAAa;IACtD,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,GAAG,QAAQ,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;CACvE;AAED,MAAM,WAAW,qBAAsB,SAAQ,aAAa;IAC1D,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,WAAW,SAAU,SAAQ,aAAa;IAC9C,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,sBAAsB,CAAC,EAAE,MAAM,CAAC;CAC1C;AAED,MAAM,MAAM,SAAS,GAAG,iBAAiB,GAAG,qBAAqB,GAAG,SAAS,CAAC;AAE9E,wBAAgB,aAAa,CAAC,EAAE,GAAE,MAAU,GAAG,SAAS,CAMvD;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAIjF"}
1
+ {"version":3,"file":"hook-io.d.ts","sourceRoot":"","sources":["../src/hook-io.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,aAAa,GACrB,cAAc,GACd,kBAAkB,GAClB,MAAM,GACN,YAAY,GACZ,YAAY,CAAC;AAEjB,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,eAAe,CAAC,EAAE,aAAa,CAAC;IACzC,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,iBAAkB,SAAQ,aAAa;IACtD,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,GAAG,QAAQ,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;CACvE;AAED,MAAM,WAAW,qBAAsB,SAAQ,aAAa;IAI1D,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,WAAW,SAAU,SAAQ,aAAa;IAC9C,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,sBAAsB,CAAC,EAAE,MAAM,CAAC;CAC1C;AAED,MAAM,MAAM,SAAS,GAAG,iBAAiB,GAAG,qBAAqB,GAAG,SAAS,CAAC;AAE9E,wBAAgB,aAAa,CAAC,EAAE,GAAE,MAAU,GAAG,SAAS,CAMvD;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,qBAAqB,GAAG,MAAM,CAE/D;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAIjF"}
package/dist/hook-io.js CHANGED
@@ -7,6 +7,9 @@ export function readHookInput(fd = 0) {
7
7
  return {};
8
8
  }
9
9
  }
10
+ export function promptText(input) {
11
+ return (input.prompt ?? input.prompt_text ?? "").trim();
12
+ }
10
13
  export function emitContext(event, additionalContext) {
11
14
  process.stdout.write(JSON.stringify({ hookSpecificOutput: { hookEventName: event, additionalContext } }));
12
15
  }
@@ -1 +1 @@
1
- {"version":3,"file":"hook-io.js","sourceRoot":"","sources":["../src/hook-io.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAgCvC,MAAM,UAAU,aAAa,CAAC,EAAE,GAAW,CAAC;IAC1C,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,EAAE,EAAE,MAAM,CAAC,CAAc,CAAC;IAC3D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,KAAoB,EAAE,iBAAyB;IACzE,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,IAAI,CAAC,SAAS,CAAC,EAAE,kBAAkB,EAAE,EAAE,aAAa,EAAE,KAAK,EAAE,iBAAiB,EAAE,EAAE,CAAC,CACpF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"hook-io.js","sourceRoot":"","sources":["../src/hook-io.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAoCvC,MAAM,UAAU,aAAa,CAAC,EAAE,GAAW,CAAC;IAC1C,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,EAAE,EAAE,MAAM,CAAC,CAAc,CAAC;IAC3D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,KAA4B;IACrD,OAAO,CAAC,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;AAC1D,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,KAAoB,EAAE,iBAAyB;IACzE,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,IAAI,CAAC,SAAS,CAAC,EAAE,kBAAkB,EAAE,EAAE,aAAa,EAAE,KAAK,EAAE,iBAAiB,EAAE,EAAE,CAAC,CACpF,CAAC;AACJ,CAAC"}
@@ -12,7 +12,16 @@ const input = readHookInput();
12
12
  // teach the model to call tools that are not there.
13
13
  const apiKey = (process.env["CLAUDE_PLUGIN_OPTION_JITERA_API_KEY"] ?? "").trim();
14
14
  const configuredEnvironment = (process.env["CLAUDE_PLUGIN_OPTION_ENVIRONMENT"] ?? "").trim();
15
- const file = apiKey ? "session-start.md" : "session-start-unconfigured.md";
15
+ // A committed .jitera.json binds the repository to a deployment and project.
16
+ // Read it first: which directive applies depends on whether this repo is bound.
17
+ const marker = readProjectMarker(input.cwd ?? process.cwd());
18
+ // Three states, because "connected" and "bound to a project" are different
19
+ // things: without a binding the tools would have no project to read.
20
+ const file = !apiKey
21
+ ? "session-start-unconfigured.md"
22
+ : marker
23
+ ? "session-start.md"
24
+ : "session-start-unbound.md";
16
25
  let directive;
17
26
  try {
18
27
  directive = readFileSync(join(CONTENT_ROOT, file), "utf8").trim();
@@ -20,10 +29,6 @@ try {
20
29
  catch {
21
30
  process.exit(0);
22
31
  }
23
- // A committed .jitera.json binds the repository to a deployment, so teammates
24
- // who have not connected yet get the exact command, and a mismatched plugin
25
- // configuration is called out instead of silently reading the wrong project.
26
- const marker = readProjectMarker(input.cwd ?? process.cwd());
27
32
  writeSessionStatus(input.session_id, {
28
33
  configured: Boolean(apiKey),
29
34
  environment: configuredEnvironment || "studio",
@@ -42,5 +47,14 @@ if (marker?.environment) {
42
47
  `Project context may come from the wrong deployment. Suggest rebinding with:\n\n ${login}`;
43
48
  }
44
49
  }
50
+ // `init` writes a marker with no project when nobody was signed in to pick one.
51
+ // A project-scoped key still works, but a user-level key cannot infer a project
52
+ // and every call quietly fails, so name the gap rather than let it dead-end.
53
+ if (apiKey && marker && !marker.project) {
54
+ directive +=
55
+ `\n\nNote: this repository's .jitera.json records no project. A user-level ` +
56
+ `API key cannot infer one, so project context may not load. Suggest finishing ` +
57
+ `the binding with:\n\n npx @jitera/connect init --project=<uuid>`;
58
+ }
45
59
  emitContext("SessionStart", directive);
46
60
  //# sourceMappingURL=session-start.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"session-start.js","sourceRoot":"","sources":["../../src/hooks/session-start.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAE1D,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;AAE1F,MAAM,KAAK,GAAG,aAAa,EAAE,CAAC;AAE9B,gFAAgF;AAChF,+EAA+E;AAC/E,oDAAoD;AACpD,MAAM,MAAM,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,qCAAqC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;AACjF,MAAM,qBAAqB,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,kCAAkC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;AAC7F,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,+BAA+B,CAAC;AAE3E,IAAI,SAAiB,CAAC;AACtB,IAAI,CAAC;IACH,SAAS,GAAG,YAAY,CAAC,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;AACpE,CAAC;AAAC,MAAM,CAAC;IACP,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,8EAA8E;AAC9E,4EAA4E;AAC5E,6EAA6E;AAC7E,MAAM,MAAM,GAAG,iBAAiB,CAAC,KAAK,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;AAE7D,kBAAkB,CAAC,KAAK,CAAC,UAAU,EAAE;IACnC,UAAU,EAAE,OAAO,CAAC,MAAM,CAAC;IAC3B,WAAW,EAAE,qBAAqB,IAAI,QAAQ;CAC/C,CAAC,CAAC;AAEH,IAAI,MAAM,EAAE,WAAW,EAAE,CAAC;IACxB,MAAM,KAAK,GAAG,mCAAmC,MAAM,CAAC,WAAW,YAAY,CAAC;IAChF,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,SAAS;YACP,8DAA8D;gBAC9D,iBAAiB,MAAM,CAAC,WAAW,8CAA8C,KAAK,EAAE,CAAC;IAC7F,CAAC;SAAM,IAAI,qBAAqB,IAAI,qBAAqB,KAAK,MAAM,CAAC,WAAW,EAAE,CAAC;QACjF,SAAS;YACP,gEAAgE;gBAChE,IAAI,MAAM,CAAC,WAAW,wCAAwC,qBAAqB,KAAK;gBACxF,sFAAsF,KAAK,EAAE,CAAC;IAClG,CAAC;AACH,CAAC;AAED,WAAW,CAAC,cAAc,EAAE,SAAS,CAAC,CAAC"}
1
+ {"version":3,"file":"session-start.js","sourceRoot":"","sources":["../../src/hooks/session-start.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAE1D,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;AAE1F,MAAM,KAAK,GAAG,aAAa,EAAE,CAAC;AAE9B,gFAAgF;AAChF,+EAA+E;AAC/E,oDAAoD;AACpD,MAAM,MAAM,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,qCAAqC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;AACjF,MAAM,qBAAqB,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,kCAAkC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;AAC7F,6EAA6E;AAC7E,gFAAgF;AAChF,MAAM,MAAM,GAAG,iBAAiB,CAAC,KAAK,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;AAE7D,2EAA2E;AAC3E,qEAAqE;AACrE,MAAM,IAAI,GAAG,CAAC,MAAM;IAClB,CAAC,CAAC,+BAA+B;IACjC,CAAC,CAAC,MAAM;QACN,CAAC,CAAC,kBAAkB;QACpB,CAAC,CAAC,0BAA0B,CAAC;AAEjC,IAAI,SAAiB,CAAC;AACtB,IAAI,CAAC;IACH,SAAS,GAAG,YAAY,CAAC,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;AACpE,CAAC;AAAC,MAAM,CAAC;IACP,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,kBAAkB,CAAC,KAAK,CAAC,UAAU,EAAE;IACnC,UAAU,EAAE,OAAO,CAAC,MAAM,CAAC;IAC3B,WAAW,EAAE,qBAAqB,IAAI,QAAQ;CAC/C,CAAC,CAAC;AAEH,IAAI,MAAM,EAAE,WAAW,EAAE,CAAC;IACxB,MAAM,KAAK,GAAG,mCAAmC,MAAM,CAAC,WAAW,YAAY,CAAC;IAChF,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,SAAS;YACP,8DAA8D;gBAC9D,iBAAiB,MAAM,CAAC,WAAW,8CAA8C,KAAK,EAAE,CAAC;IAC7F,CAAC;SAAM,IAAI,qBAAqB,IAAI,qBAAqB,KAAK,MAAM,CAAC,WAAW,EAAE,CAAC;QACjF,SAAS;YACP,gEAAgE;gBAChE,IAAI,MAAM,CAAC,WAAW,wCAAwC,qBAAqB,KAAK;gBACxF,sFAAsF,KAAK,EAAE,CAAC;IAClG,CAAC;AACH,CAAC;AAED,gFAAgF;AAChF,gFAAgF;AAChF,6EAA6E;AAC7E,IAAI,MAAM,IAAI,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;IACxC,SAAS;QACP,4EAA4E;YAC5E,+EAA+E;YAC/E,oEAAoE,CAAC;AACzE,CAAC;AAED,WAAW,CAAC,cAAc,EAAE,SAAS,CAAC,CAAC"}
@@ -3,13 +3,19 @@ import { readFileSync } from "node:fs";
3
3
  import { join, dirname } from "node:path";
4
4
  import { fileURLToPath } from "node:url";
5
5
  import { emitContext, readHookInput } from "../hook-io.js";
6
+ import { readProjectMarker } from "../project-marker.js";
6
7
  const CONTENT_ROOT = join(dirname(fileURLToPath(import.meta.url)), "..", "..", "content");
7
8
  const CHECKPOINT_EVERY_TURNS = 5;
8
- const turn = readHookInput().turn_number;
9
+ const input = readHookInput();
10
+ const turn = input.turn_number;
9
11
  if (!Number.isInteger(turn) || turn < 1)
10
12
  process.exit(0);
11
13
  if (turn % CHECKPOINT_EVERY_TURNS !== 0)
12
14
  process.exit(0);
15
+ // The checkpoint asks the model to write to project memory, which needs a
16
+ // project. Unbound repositories get nothing, same as the other hooks.
17
+ if (!readProjectMarker(input.cwd ?? process.cwd()))
18
+ process.exit(0);
13
19
  let directive;
14
20
  try {
15
21
  directive = readFileSync(join(CONTENT_ROOT, "checkpoint.md"), "utf8").trim();
@@ -1 +1 @@
1
- {"version":3,"file":"stop.js","sourceRoot":"","sources":["../../src/hooks/stop.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAE3D,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;AAC1F,MAAM,sBAAsB,GAAG,CAAC,CAAC;AAEjC,MAAM,IAAI,GAAG,aAAa,EAAE,CAAC,WAAW,CAAC;AACzC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,IAAK,IAAe,GAAG,CAAC;IAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACrE,IAAK,IAAe,GAAG,sBAAsB,KAAK,CAAC;IAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAErE,IAAI,SAAiB,CAAC;AACtB,IAAI,CAAC;IACH,SAAS,GAAG,YAAY,CAAC,IAAI,CAAC,YAAY,EAAE,eAAe,CAAC,EAAE,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;AAC/E,CAAC;AAAC,MAAM,CAAC;IACP,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,WAAW,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC"}
1
+ {"version":3,"file":"stop.js","sourceRoot":"","sources":["../../src/hooks/stop.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAEzD,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;AAC1F,MAAM,sBAAsB,GAAG,CAAC,CAAC;AAEjC,MAAM,KAAK,GAAG,aAAa,EAAE,CAAC;AAC9B,MAAM,IAAI,GAAG,KAAK,CAAC,WAAW,CAAC;AAC/B,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,IAAK,IAAe,GAAG,CAAC;IAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACrE,IAAK,IAAe,GAAG,sBAAsB,KAAK,CAAC;IAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAErE,0EAA0E;AAC1E,sEAAsE;AACtE,IAAI,CAAC,iBAAiB,CAAC,KAAK,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAEpE,IAAI,SAAiB,CAAC;AACtB,IAAI,CAAC;IACH,SAAS,GAAG,YAAY,CAAC,IAAI,CAAC,YAAY,EAAE,eAAe,CAAC,EAAE,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;AAC/E,CAAC;AAAC,MAAM,CAAC;IACP,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,WAAW,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC"}
@@ -1,18 +1,36 @@
1
1
  #!/usr/bin/env node
2
2
  import { callTool, McpCallError } from "../mcp-client.js";
3
3
  import { discoverDeployment } from "../discovery.js";
4
- import { emitContext, readHookInput } from "../hook-io.js";
4
+ import { emitContext, promptText, readHookInput } from "../hook-io.js";
5
5
  import { readProjectMarker } from "../project-marker.js";
6
6
  import { claimOnce } from "../session-marker.js";
7
7
  import { writeSessionStatus } from "../session-status.js";
8
8
  const MAX_CONTEXT_CHARS = 6000;
9
+ // The composite tool searches memory, documents and source concurrently, so it
10
+ // is slower than a bare recall. This hook blocks the user's prompt, so the
11
+ // ceiling stays close to the old one rather than tracking the server's own
12
+ // per-section timeout.
13
+ const GATHER_TIMEOUT_MS = 10000;
9
14
  const RECALL_TIMEOUT_MS = 8000;
15
+ // Keywords are extracted from the task, so a pasted stack trace or diff adds
16
+ // upload on a path that blocks the prompt without adding signal.
17
+ const MAX_TASK_CHARS = 2000;
10
18
  const input = readHookInput();
11
- if (!claimOnce(input.session_id, "recall"))
12
- process.exit(0);
13
19
  const apiKey = process.env["CLAUDE_PLUGIN_OPTION_JITERA_API_KEY"] ?? "";
14
20
  if (!apiKey)
15
21
  process.exit(0);
22
+ // Without .jitera.json this repository is not bound to a project, so there is
23
+ // no project whose context could be gathered. Bail before discovery rather
24
+ // than spend a network round trip guessing at a project nobody chose; session
25
+ // start is where the user is told how to bind it.
26
+ const marker = readProjectMarker(input.cwd ?? process.cwd());
27
+ if (!marker)
28
+ process.exit(0);
29
+ // Claimed only once there is something to claim it for: burning the session's
30
+ // single gather on an unbound repo would mean running init mid-session never
31
+ // took effect.
32
+ if (!claimOnce(input.session_id, "recall"))
33
+ process.exit(0);
16
34
  let url;
17
35
  const override = process.env["JITERA_MCP_URL"];
18
36
  if (override) {
@@ -31,24 +49,60 @@ else {
31
49
  process.exit(0);
32
50
  }
33
51
  }
34
- let memory;
35
- const startedAt = Date.now();
36
- try {
37
- memory = await callTool({
38
- url,
39
- apiKey,
40
- projectUuid: readProjectMarker(input.cwd ?? process.cwd())?.project,
41
- name: "recall_jitera_memory",
42
- args: {},
43
- timeoutMs: RECALL_TIMEOUT_MS,
44
- });
52
+ const transport = { url, apiKey, projectUuid: marker.project };
53
+ const task = promptText(input).slice(0, MAX_TASK_CHARS);
54
+ // The blind recall serves two purposes: it is what deployments predating the
55
+ // composite tool answer, and it is the right call when there is no prompt text
56
+ // to gather for. It stays query-less on purpose — a server without the widening
57
+ // ladder can return less for a query than for no query.
58
+ const recall = () => callTool({
59
+ ...transport,
60
+ name: "recall_jitera_memory",
61
+ args: {},
62
+ timeoutMs: RECALL_TIMEOUT_MS,
63
+ });
64
+ // The fallback exists for deployments that predate the composite tool, so it
65
+ // is worth a second round trip only when the tool is genuinely absent. Falling
66
+ // back on a timeout would stack RECALL_TIMEOUT_MS on top of GATHER_TIMEOUT_MS
67
+ // while the user's prompt is blocked.
68
+ function toolIsMissing(error) {
69
+ if (!(error instanceof McpCallError))
70
+ return false;
71
+ const detail = error.detail;
72
+ if (detail?.code === -32601 || detail?.code === -32602)
73
+ return true;
74
+ return /unknown tool|tool not found|method not found/i.test(error.message);
45
75
  }
46
- catch (error) {
76
+ function giveUp(error) {
47
77
  const message = error instanceof McpCallError ? error.message : String(error);
48
78
  writeSessionStatus(input.session_id, { recallError: message });
49
- process.stderr.write(`jitera-connect: could not load project memory: ${message}\n`);
79
+ process.stderr.write(`jitera-connect: could not load project context: ${message}\n`);
50
80
  process.exit(0);
51
81
  }
82
+ let memory;
83
+ const startedAt = Date.now();
84
+ try {
85
+ // Gathering for an empty task makes the server ask for one, and that answer
86
+ // would be injected as though it were project context.
87
+ memory = task
88
+ ? await callTool({
89
+ ...transport,
90
+ name: "gather_jitera_context",
91
+ args: { task, budget: MAX_CONTEXT_CHARS },
92
+ timeoutMs: GATHER_TIMEOUT_MS,
93
+ })
94
+ : await recall();
95
+ }
96
+ catch (gatherError) {
97
+ if (!task || !toolIsMissing(gatherError))
98
+ giveUp(gatherError);
99
+ try {
100
+ memory = await recall();
101
+ }
102
+ catch (error) {
103
+ giveUp(error);
104
+ }
105
+ }
52
106
  writeSessionStatus(input.session_id, {
53
107
  recallMs: Date.now() - startedAt,
54
108
  recallChars: memory.length,
@@ -57,9 +111,10 @@ writeSessionStatus(input.session_id, {
57
111
  if (!memory)
58
112
  process.exit(0);
59
113
  const body = memory.length > MAX_CONTEXT_CHARS
60
- ? `${memory.slice(0, MAX_CONTEXT_CHARS)}\n\n[truncated, call recall_jitera_memory for the rest]`
114
+ ? `${memory.slice(0, MAX_CONTEXT_CHARS)}\n\n[truncated, call gather_jitera_context for the rest]`
61
115
  : memory;
62
- emitContext("UserPromptSubmit", `Stored project memory for this workspace, loaded at session start:\n\n${body}\n\n` +
63
- `Treat this as current. Call recall_jitera_memory again if you need a narrower or fuller view, ` +
64
- `and persist new decisions with remember_jitera_memory.`);
116
+ emitContext("UserPromptSubmit", `Project context for this workspace, gathered at session start:\n\n${body}\n\n` +
117
+ `Treat this as current. It was gathered for the first prompt of this session, so call ` +
118
+ `gather_jitera_context yourself when the task moves on to a different area, and persist ` +
119
+ `new decisions with remember_jitera_memory.`);
65
120
  //# sourceMappingURL=user-prompt-submit.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"user-prompt-submit.js","sourceRoot":"","sources":["../../src/hooks/user-prompt-submit.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"user-prompt-submit.js","sourceRoot":"","sources":["../../src/hooks/user-prompt-submit.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"project-marker.d.ts","sourceRoot":"","sources":["../src/project-marker.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,eAAe,iBAAiB,CAAC;AAM9C,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1C,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACvC;AAED,MAAM,WAAW,kBAAmB,SAAQ,aAAa;IACvD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,kBAAkB,GAAG,SAAS,CAyBlF;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;CAC3B;AAED,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,aAAa,EACrB,MAAM,UAAQ,GACb,iBAAiB,CAuBnB"}
1
+ {"version":3,"file":"project-marker.d.ts","sourceRoot":"","sources":["../src/project-marker.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,eAAe,iBAAiB,CAAC;AAM9C,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1C,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACvC;AAED,MAAM,WAAW,kBAAmB,SAAQ,aAAa;IACvD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,kBAAkB,GAAG,SAAS,CAsClF;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;CAC3B;AAED,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,aAAa,EACrB,MAAM,UAAQ,GACb,iBAAiB,CAuBnB"}
@@ -16,8 +16,15 @@ export function readProjectMarker(startDir) {
16
16
  catch {
17
17
  return undefined;
18
18
  }
19
- const environment = parsed["environment"];
20
- const project = parsed["project"];
19
+ // `null` parses cleanly and then throws on property access, and a array
20
+ // or a bare scalar is not a marker either. Malformed reads as unbound,
21
+ // the same as unparseable, because hooks must never break a session.
22
+ if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
23
+ return undefined;
24
+ }
25
+ const fields = parsed;
26
+ const environment = fields["environment"];
27
+ const project = fields["project"];
21
28
  return {
22
29
  path,
23
30
  ...(typeof environment === "string" && SAFE_ENVIRONMENT.test(environment)
@@ -26,6 +33,11 @@ export function readProjectMarker(startDir) {
26
33
  ...(typeof project === "string" ? { project } : {}),
27
34
  };
28
35
  }
36
+ // Never look past the repository root. `init` writes the marker there, so
37
+ // a stray .jitera.json in a parent directory (or $HOME) would otherwise
38
+ // bind every repository beneath it to a project nobody chose for them.
39
+ if (existsSync(join(dir, ".git")))
40
+ return undefined;
29
41
  const parent = dirname(dir);
30
42
  if (parent === dir)
31
43
  return undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"project-marker.js","sourceRoot":"","sources":["../src/project-marker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAClE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAE1C,MAAM,CAAC,MAAM,eAAe,GAAG,cAAc,CAAC;AAE9C,8EAA8E;AAC9E,2CAA2C;AAC3C,MAAM,gBAAgB,GAAG,sBAAsB,CAAC;AAWhD,MAAM,UAAU,iBAAiB,CAAC,QAAgB;IAChD,IAAI,GAAG,GAAG,QAAQ,CAAC;IACnB,SAAS,CAAC;QACR,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,eAAe,CAAC,CAAC;QACxC,IAAI,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YACrB,IAAI,MAA+B,CAAC;YACpC,IAAI,CAAC;gBACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAA4B,CAAC;YAC7E,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,SAAS,CAAC;YACnB,CAAC;YACD,MAAM,WAAW,GAAG,MAAM,CAAC,aAAa,CAAC,CAAC;YAC1C,MAAM,OAAO,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC;YAClC,OAAO;gBACL,IAAI;gBACJ,GAAG,CAAC,OAAO,WAAW,KAAK,QAAQ,IAAI,gBAAgB,CAAC,IAAI,CAAC,WAAW,CAAC;oBACvE,CAAC,CAAC,EAAE,WAAW,EAAE;oBACjB,CAAC,CAAC,EAAE,CAAC;gBACP,GAAG,CAAC,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aACpD,CAAC;QACJ,CAAC;QACD,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;QAC5B,IAAI,MAAM,KAAK,GAAG;YAAE,OAAO,SAAS,CAAC;QACrC,GAAG,GAAG,MAAM,CAAC;IACf,CAAC;AACH,CAAC;AAOD,MAAM,UAAU,kBAAkB,CAChC,IAAY,EACZ,MAAqB,EACrB,MAAM,GAAG,KAAK;IAEd,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC;IAEzC,IAAI,QAAQ,GAA4B,EAAE,CAAC;IAC3C,IAAI,MAA0B,CAAC;IAC/B,IAAI,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACrB,MAAM,GAAG,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACpC,IAAI,CAAC;YACH,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAA4B,CAAC;QAC3D,CAAC;QAAC,MAAM,CAAC;YACP,QAAQ,GAAG,EAAE,CAAC;QAChB,CAAC;IACH,CAAC;IAED,MAAM,IAAI,GAAG;QACX,GAAG,QAAQ;QACX,GAAG,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAClE,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACvD,CAAC;IACF,MAAM,UAAU,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC,IAAI,CAAC;IAC7D,MAAM,OAAO,GAAG,MAAM,KAAK,UAAU,CAAC;IACtC,IAAI,OAAO,IAAI,CAAC,MAAM;QAAE,aAAa,CAAC,IAAI,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC;IAChE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;AAC3B,CAAC"}
1
+ {"version":3,"file":"project-marker.js","sourceRoot":"","sources":["../src/project-marker.ts"],"names":[],"mappings":"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"}
@@ -2,6 +2,7 @@ import type { SessionStatus } from "./session-status.ts";
2
2
  export interface StatusLineInput {
3
3
  readonly status?: SessionStatus | undefined;
4
4
  readonly markerEnvironment?: string | undefined;
5
+ readonly bound?: boolean | undefined;
5
6
  }
6
- export declare function renderStatusLine({ status, markerEnvironment }: StatusLineInput): string;
7
+ export declare function renderStatusLine({ status, markerEnvironment, bound, }: StatusLineInput): string;
7
8
  //# sourceMappingURL=statusline.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"statusline.d.ts","sourceRoot":"","sources":["../src/statusline.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAOzD,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,MAAM,CAAC,EAAE,aAAa,GAAG,SAAS,CAAC;IAC5C,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACjD;AAUD,wBAAgB,gBAAgB,CAAC,EAAE,MAAM,EAAE,iBAAiB,EAAE,EAAE,eAAe,GAAG,MAAM,CAmBvF"}
1
+ {"version":3,"file":"statusline.d.ts","sourceRoot":"","sources":["../src/statusline.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAOzD,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,MAAM,CAAC,EAAE,aAAa,GAAG,SAAS,CAAC;IAC5C,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAGhD,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CACtC;AAUD,wBAAgB,gBAAgB,CAAC,EAC/B,MAAM,EACN,iBAAiB,EACjB,KAAK,GACN,EAAE,eAAe,GAAG,MAAM,CAwB1B"}
@@ -8,11 +8,16 @@ function compactChars(chars) {
8
8
  function compactMs(ms) {
9
9
  return ms >= 1000 ? `${(ms / 1000).toFixed(1)}s` : `${ms}ms`;
10
10
  }
11
- export function renderStatusLine({ status, markerEnvironment }) {
11
+ export function renderStatusLine({ status, markerEnvironment, bound, }) {
12
12
  if (!status)
13
13
  return `${DIM}○${RESET} jitera`;
14
14
  if (!status.configured)
15
15
  return `${DIM}○${RESET} jitera · not connected`;
16
+ // Connected, but this repository is not bound to a project, so the hooks
17
+ // deliberately do nothing here. Carry the command that fixes it.
18
+ if (bound === false) {
19
+ return `${YELLOW}○${RESET} jitera · not initialised · npx @jitera/connect init`;
20
+ }
16
21
  const dot = status.recallError ? `${YELLOW}●${RESET}` : `${GREEN}●${RESET}`;
17
22
  const parts = [`${dot} jitera`];
18
23
  if (status.environment)
@@ -1 +1 @@
1
- {"version":3,"file":"statusline.js","sourceRoot":"","sources":["../src/statusline.ts"],"names":[],"mappings":"AAEA,MAAM,KAAK,GAAG,OAAO,CAAC;AACtB,MAAM,MAAM,GAAG,OAAO,CAAC;AACvB,MAAM,GAAG,GAAG,MAAM,CAAC;AACnB,MAAM,KAAK,GAAG,MAAM,CAAC;AAOrB,SAAS,YAAY,CAAC,KAAa;IACjC,OAAO,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,KAAK,IAAI,CAAC;AACxE,CAAC;AAED,SAAS,SAAS,CAAC,EAAU;IAC3B,OAAO,EAAE,IAAI,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,IAAI,CAAC;AAC/D,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,EAAE,MAAM,EAAE,iBAAiB,EAAmB;IAC7E,IAAI,CAAC,MAAM;QAAE,OAAO,GAAG,GAAG,IAAI,KAAK,SAAS,CAAC;IAC7C,IAAI,CAAC,MAAM,CAAC,UAAU;QAAE,OAAO,GAAG,GAAG,IAAI,KAAK,yBAAyB,CAAC;IAExE,MAAM,GAAG,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,IAAI,KAAK,EAAE,CAAC;IAC5E,MAAM,KAAK,GAAG,CAAC,GAAG,GAAG,SAAS,CAAC,CAAC;IAChC,IAAI,MAAM,CAAC,WAAW;QAAE,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;IAEvD,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC;QACvB,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IAC9B,CAAC;SAAM,IAAI,OAAO,MAAM,CAAC,QAAQ,KAAK,QAAQ,IAAI,OAAO,MAAM,CAAC,WAAW,KAAK,QAAQ,EAAE,CAAC;QACzF,KAAK,CAAC,IAAI,CAAC,UAAU,YAAY,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IACzF,CAAC;IAED,IAAI,iBAAiB,IAAI,MAAM,CAAC,WAAW,IAAI,iBAAiB,KAAK,MAAM,CAAC,WAAW,EAAE,CAAC;QACxF,KAAK,CAAC,IAAI,CAAC,GAAG,MAAM,cAAc,iBAAiB,GAAG,KAAK,EAAE,CAAC,CAAC;IACjE,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC3B,CAAC"}
1
+ {"version":3,"file":"statusline.js","sourceRoot":"","sources":["../src/statusline.ts"],"names":[],"mappings":"AAEA,MAAM,KAAK,GAAG,OAAO,CAAC;AACtB,MAAM,MAAM,GAAG,OAAO,CAAC;AACvB,MAAM,GAAG,GAAG,MAAM,CAAC;AACnB,MAAM,KAAK,GAAG,MAAM,CAAC;AAUrB,SAAS,YAAY,CAAC,KAAa;IACjC,OAAO,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,KAAK,IAAI,CAAC;AACxE,CAAC;AAED,SAAS,SAAS,CAAC,EAAU;IAC3B,OAAO,EAAE,IAAI,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,IAAI,CAAC;AAC/D,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,EAC/B,MAAM,EACN,iBAAiB,EACjB,KAAK,GACW;IAChB,IAAI,CAAC,MAAM;QAAE,OAAO,GAAG,GAAG,IAAI,KAAK,SAAS,CAAC;IAC7C,IAAI,CAAC,MAAM,CAAC,UAAU;QAAE,OAAO,GAAG,GAAG,IAAI,KAAK,yBAAyB,CAAC;IACxE,yEAAyE;IACzE,iEAAiE;IACjE,IAAI,KAAK,KAAK,KAAK,EAAE,CAAC;QACpB,OAAO,GAAG,MAAM,IAAI,KAAK,sDAAsD,CAAC;IAClF,CAAC;IAED,MAAM,GAAG,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,IAAI,KAAK,EAAE,CAAC;IAC5E,MAAM,KAAK,GAAG,CAAC,GAAG,GAAG,SAAS,CAAC,CAAC;IAChC,IAAI,MAAM,CAAC,WAAW;QAAE,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;IAEvD,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC;QACvB,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IAC9B,CAAC;SAAM,IAAI,OAAO,MAAM,CAAC,QAAQ,KAAK,QAAQ,IAAI,OAAO,MAAM,CAAC,WAAW,KAAK,QAAQ,EAAE,CAAC;QACzF,KAAK,CAAC,IAAI,CAAC,UAAU,YAAY,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IACzF,CAAC;IAED,IAAI,iBAAiB,IAAI,MAAM,CAAC,WAAW,IAAI,iBAAiB,KAAK,MAAM,CAAC,WAAW,EAAE,CAAC;QACxF,KAAK,CAAC,IAAI,CAAC,GAAG,MAAM,cAAc,iBAAiB,GAAG,KAAK,EAAE,CAAC,CAAC;IACjE,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC3B,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jitera/connect",
3
- "version": "1.5.0",
3
+ "version": "2.0.0",
4
4
  "type": "module",
5
5
  "description": "Connect AI coding assistants to Jitera projects: documentation, source, and shared project memory",
6
6
  "license": "Apache-2.0",
@@ -17,6 +17,24 @@ Three virtual domains:
17
17
  | `sources/` | Project source code | no |
18
18
  | `uploads/` | Uploaded files | no |
19
19
 
20
+ ## Start with the whole picture
21
+
22
+ ```
23
+ gather_jitera_context(task="how do refunds get issued", budget=6000)
24
+ ```
25
+
26
+ Recalls project memory and searches documentation and source in one call,
27
+ running the widening fallbacks itself: memory falls back to every stored entity
28
+ when keywords match nothing, and search falls back to fuzzy matching when exact
29
+ matching is dry. It also lists the project's agents, so a recalled fact can be
30
+ attributed. Use it before planning or answering, then narrow with the tools
31
+ below.
32
+
33
+ It is not a once-per-session lookup. Call it again whenever the work reaches
34
+ something you have not gathered context for yet: a subsystem you have not
35
+ touched, a name you do not recognise, or a decision about how something should
36
+ work. Checking costs one call; guessing costs the rest of the session.
37
+
20
38
  ## Searching
21
39
 
22
40
  ```
@@ -27,6 +45,10 @@ resource_search(pattern="documents/**/*.md", content="refund", limit=30, offset=
27
45
  domain prefix to search every domain: `resource_search(pattern="**/checkout*.*")`
28
46
  - `content` — a grep-style match inside files, supporting boolean expressions:
29
47
  `content="(api OR rest) AND controller"`
48
+ - `mode` — how `content` is matched. `default` is a case-insensitive substring;
49
+ `regex` treats `content` as a case-insensitive regular expression; `full-text`
50
+ matches fuzzily by trigram similarity, for when you are unsure of the exact
51
+ wording. `pattern` is always a glob, whatever the mode
30
52
  - Results are grouped by domain. Open a match with `resource_read`
31
53
 
32
54
  Search before reading. Do not guess paths.
@@ -31,17 +31,29 @@ failed.
31
31
 
32
32
  ### When the first recall comes back thin
33
33
 
34
- `recall_jitera_memory` filters entities by keywords extracted from `query`. Work
35
- down this ladder, stopping as soon as you have what you need:
34
+ `gather_jitera_context` runs this ladder for you and says when it widened, so
35
+ prefer it for a first look. Reach for `recall_jitera_memory` directly when you
36
+ want memory alone, and work down the ladder yourself:
36
37
 
37
38
  1. `recall_jitera_memory(query="<specific terms from the task>")`
38
39
  2. `recall_jitera_memory(query="<the subsystem or domain>")`
39
40
  3. `recall_jitera_memory()` with no query — returns every stored entity
40
41
 
42
+ Keywords are combined with OR, so *more* terms match more entities. There is no
43
+ narrower rung below step 1 — when it comes back empty, widen rather than
44
+ refine.
45
+
41
46
  Do not conclude that memory is empty until step 3 returns nothing. Results
42
47
  containing `[[id]]` references mean related entities exist, and a broader query
43
48
  will surface them.
44
49
 
50
+ ### Whose memory you are reading
51
+
52
+ Each agent in a project writes to its own partition. A project-level key reads
53
+ across all of them, so a recalled fact may have been written by any agent;
54
+ `list_jitera_agents` names them. A key pinned to one agent sees only that
55
+ agent's own partition.
56
+
45
57
  ## Remember when knowledge is created
46
58
 
47
59
  Persist with `remember_jitera_memory(name, type, attrs)` when:
@@ -4,16 +4,22 @@
4
4
  This repository is connected to a {{BRAND}} project. Documentation, source, and a
5
5
  shared project memory are available through the `jitera` MCP server.
6
6
 
7
- Before planning or implementing anything, call `recall_jitera_memory`. An empty
8
- result is normal and is not an error.
7
+ Before planning or implementing anything, and before answering a question about
8
+ this project, call `gather_jitera_context` with the task in your own words. It
9
+ recalls project memory and searches documentation and source in one pass. An
10
+ empty result is normal and is not an error.
11
+
12
+ Keep using it as the work moves. It is not a once-per-session lookup: call it
13
+ again whenever you reach an area you have not gathered context for yet.
9
14
 
10
15
  Before writing a spec or design, search `documents/` with `resource_search` and
11
16
  read any match with `resource_read`. Update the existing document rather than
12
17
  creating a second one.
13
18
 
14
19
  When a decision is made, a constraint is discovered, or you are corrected,
15
- persist it with `remember_jitera_memory`. Recall the entity first and re-send its
16
- full attribute list, because entities are keyed on name plus type.
20
+ persist it with `remember_jitera_memory`. Recall the entity first with
21
+ `recall_jitera_memory` and re-send its full attribute list, because entities are
22
+ keyed on name plus type.
17
23
 
18
24
  `documents/` is readable and writable. `sources/` and `uploads/` are read-only.
19
25