@ornexus/neocortex 4.59.1
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/LICENSE +56 -0
- package/LICENSE-COMMERCIAL.md +70 -0
- package/README.md +58 -0
- package/dist/sbom.cdx.json +7067 -0
- package/docs/install/coderabbit-manual-setup.md +86 -0
- package/docs/install/installer-diagnostics.md +107 -0
- package/docs/install/linux-global-install.md +97 -0
- package/install.js +572 -0
- package/install.ps1 +2214 -0
- package/install.sh +2013 -0
- package/package.json +118 -0
- package/packages/client/dist/adapters/adapter-registry.d.ts +61 -0
- package/packages/client/dist/adapters/adapter-registry.js +1 -0
- package/packages/client/dist/adapters/antigravity-adapter.d.ts +18 -0
- package/packages/client/dist/adapters/antigravity-adapter.js +2 -0
- package/packages/client/dist/adapters/claude-code-adapter.d.ts +19 -0
- package/packages/client/dist/adapters/claude-code-adapter.js +3 -0
- package/packages/client/dist/adapters/codex-adapter.d.ts +19 -0
- package/packages/client/dist/adapters/codex-adapter.js +2 -0
- package/packages/client/dist/adapters/cursor-adapter.d.ts +19 -0
- package/packages/client/dist/adapters/cursor-adapter.js +4 -0
- package/packages/client/dist/adapters/gemini-adapter.d.ts +18 -0
- package/packages/client/dist/adapters/gemini-adapter.js +2 -0
- package/packages/client/dist/adapters/index.d.ts +19 -0
- package/packages/client/dist/adapters/index.js +1 -0
- package/packages/client/dist/adapters/platform-detector.d.ts +48 -0
- package/packages/client/dist/adapters/platform-detector.js +1 -0
- package/packages/client/dist/adapters/target-adapter.d.ts +70 -0
- package/packages/client/dist/adapters/target-adapter.js +0 -0
- package/packages/client/dist/adapters/vscode-adapter.d.ts +19 -0
- package/packages/client/dist/adapters/vscode-adapter.js +2 -0
- package/packages/client/dist/agent/refresh-stubs.d.ts +80 -0
- package/packages/client/dist/agent/refresh-stubs.js +2 -0
- package/packages/client/dist/agent/update-agent-yaml.d.ts +26 -0
- package/packages/client/dist/agent/update-agent-yaml.js +1 -0
- package/packages/client/dist/agent/update-description.d.ts +45 -0
- package/packages/client/dist/agent/update-description.js +1 -0
- package/packages/client/dist/cache/crypto-utils.d.ts +30 -0
- package/packages/client/dist/cache/crypto-utils.js +1 -0
- package/packages/client/dist/cache/encrypted-cache.d.ts +30 -0
- package/packages/client/dist/cache/encrypted-cache.js +1 -0
- package/packages/client/dist/cache/in-memory-asset-cache.d.ts +62 -0
- package/packages/client/dist/cache/in-memory-asset-cache.js +1 -0
- package/packages/client/dist/cache/index.d.ts +13 -0
- package/packages/client/dist/cache/index.js +1 -0
- package/packages/client/dist/cache/protected-pi-boundary.d.ts +19 -0
- package/packages/client/dist/cache/protected-pi-boundary.js +1 -0
- package/packages/client/dist/checkpoint/checkpoint-client-reader.d.ts +45 -0
- package/packages/client/dist/checkpoint/checkpoint-client-reader.js +2 -0
- package/packages/client/dist/checkpoint/index.d.ts +12 -0
- package/packages/client/dist/checkpoint/index.js +1 -0
- package/packages/client/dist/checkpoint/shared-checkpoint-types.d.ts +85 -0
- package/packages/client/dist/checkpoint/shared-checkpoint-types.js +1 -0
- package/packages/client/dist/cli.d.ts +14 -0
- package/packages/client/dist/cli.js +48 -0
- package/packages/client/dist/commands/activate.d.ts +55 -0
- package/packages/client/dist/commands/activate.js +8 -0
- package/packages/client/dist/commands/cache-status.d.ts +39 -0
- package/packages/client/dist/commands/cache-status.js +2 -0
- package/packages/client/dist/commands/invoke.d.ts +229 -0
- package/packages/client/dist/commands/invoke.js +63 -0
- package/packages/client/dist/commands/refresh-memory.d.ts +11 -0
- package/packages/client/dist/commands/refresh-memory.js +1 -0
- package/packages/client/dist/config/resolver-selection.d.ts +40 -0
- package/packages/client/dist/config/resolver-selection.js +1 -0
- package/packages/client/dist/config/secure-config.d.ts +78 -0
- package/packages/client/dist/config/secure-config.js +12 -0
- package/packages/client/dist/constants.d.ts +25 -0
- package/packages/client/dist/constants.js +1 -0
- package/packages/client/dist/context/context-collector.d.ts +28 -0
- package/packages/client/dist/context/context-collector.js +2 -0
- package/packages/client/dist/context/context-sanitizer.d.ts +28 -0
- package/packages/client/dist/context/context-sanitizer.js +1 -0
- package/packages/client/dist/continuity/continuity-client-state-store.d.ts +183 -0
- package/packages/client/dist/continuity/continuity-client-state-store.js +1 -0
- package/packages/client/dist/continuity/invoke-hooks.d.ts +18 -0
- package/packages/client/dist/continuity/invoke-hooks.js +1 -0
- package/packages/client/dist/continuity/migrations/001-initial-schema.d.ts +11 -0
- package/packages/client/dist/continuity/migrations/001-initial-schema.js +263 -0
- package/packages/client/dist/continuity/sqlite-store.d.ts +409 -0
- package/packages/client/dist/continuity/sqlite-store.js +226 -0
- package/packages/client/dist/errors/error-messages.d.ts +40 -0
- package/packages/client/dist/errors/error-messages.js +2 -0
- package/packages/client/dist/graph-retrieval/pre-command-hook.d.ts +31 -0
- package/packages/client/dist/graph-retrieval/pre-command-hook.js +1 -0
- package/packages/client/dist/graph-retrieval/shared-graph-retrieval-contract.d.ts +77 -0
- package/packages/client/dist/graph-retrieval/shared-graph-retrieval-contract.js +1 -0
- package/packages/client/dist/i18n/first-run.d.ts +23 -0
- package/packages/client/dist/i18n/first-run.js +2 -0
- package/packages/client/dist/index.d.ts +56 -0
- package/packages/client/dist/index.js +1 -0
- package/packages/client/dist/license/index.d.ts +5 -0
- package/packages/client/dist/license/index.js +1 -0
- package/packages/client/dist/license/license-client.d.ts +79 -0
- package/packages/client/dist/license/license-client.js +1 -0
- package/packages/client/dist/machine/fingerprint.d.ts +34 -0
- package/packages/client/dist/machine/fingerprint.js +2 -0
- package/packages/client/dist/machine/index.d.ts +5 -0
- package/packages/client/dist/machine/index.js +1 -0
- package/packages/client/dist/memory/project-memory-writer.d.ts +74 -0
- package/packages/client/dist/memory/project-memory-writer.js +36 -0
- package/packages/client/dist/memory/shared-project-memory-types.d.ts +370 -0
- package/packages/client/dist/memory/shared-project-memory-types.js +2 -0
- package/packages/client/dist/policy/architecture-policy.d.ts +40 -0
- package/packages/client/dist/policy/architecture-policy.js +2 -0
- package/packages/client/dist/policy/index.d.ts +8 -0
- package/packages/client/dist/policy/index.js +1 -0
- package/packages/client/dist/policy/shared-policy-types.d.ts +89 -0
- package/packages/client/dist/policy/shared-policy-types.js +0 -0
- package/packages/client/dist/resilience/circuit-breaker.d.ts +70 -0
- package/packages/client/dist/resilience/circuit-breaker.js +1 -0
- package/packages/client/dist/resilience/degradation-manager.d.ts +67 -0
- package/packages/client/dist/resilience/degradation-manager.js +1 -0
- package/packages/client/dist/resilience/freshness-indicator.d.ts +59 -0
- package/packages/client/dist/resilience/freshness-indicator.js +1 -0
- package/packages/client/dist/resilience/index.d.ts +8 -0
- package/packages/client/dist/resilience/index.js +1 -0
- package/packages/client/dist/resilience/recovery-detector.d.ts +59 -0
- package/packages/client/dist/resilience/recovery-detector.js +1 -0
- package/packages/client/dist/resolvers/asset-resolver.d.ts +79 -0
- package/packages/client/dist/resolvers/asset-resolver.js +0 -0
- package/packages/client/dist/resolvers/local-resolver.d.ts +26 -0
- package/packages/client/dist/resolvers/local-resolver.js +8 -0
- package/packages/client/dist/resolvers/remote-resolver.d.ts +91 -0
- package/packages/client/dist/resolvers/remote-resolver.js +1 -0
- package/packages/client/dist/runner/cli.d.ts +121 -0
- package/packages/client/dist/runner/cli.js +20 -0
- package/packages/client/dist/runner/scheduler.d.ts +116 -0
- package/packages/client/dist/runner/scheduler.js +6 -0
- package/packages/client/dist/runner-cli.d.ts +9 -0
- package/packages/client/dist/runner-cli.js +3 -0
- package/packages/client/dist/state/project-state-snapshot.d.ts +15 -0
- package/packages/client/dist/state/project-state-snapshot.js +1 -0
- package/packages/client/dist/state/state-json-repair.d.ts +17 -0
- package/packages/client/dist/state/state-json-repair.js +3 -0
- package/packages/client/dist/telemetry/index.d.ts +5 -0
- package/packages/client/dist/telemetry/index.js +1 -0
- package/packages/client/dist/telemetry/offline-queue.d.ts +57 -0
- package/packages/client/dist/telemetry/offline-queue.js +1 -0
- package/packages/client/dist/tier/index.d.ts +5 -0
- package/packages/client/dist/tier/index.js +1 -0
- package/packages/client/dist/tier/tier-aware-client.d.ts +105 -0
- package/packages/client/dist/tier/tier-aware-client.js +1 -0
- package/packages/client/dist/types/index.d.ts +140 -0
- package/packages/client/dist/types/index.js +1 -0
- package/packages/client/dist/yoloop/discovery-hook.d.ts +85 -0
- package/packages/client/dist/yoloop/discovery-hook.js +2 -0
- package/packages/client/dist/yoloop/index.d.ts +10 -0
- package/packages/client/dist/yoloop/index.js +1 -0
- package/packages/client/dist/yoloop/invoke-hooks.d.ts +125 -0
- package/packages/client/dist/yoloop/invoke-hooks.js +5 -0
- package/packages/client/dist/yoloop/shared-discover-epics.d.ts +289 -0
- package/packages/client/dist/yoloop/shared-discover-epics.js +1 -0
- package/packages/client/dist/yoloop/shared-yoloop-types.d.ts +172 -0
- package/packages/client/dist/yoloop/shared-yoloop-types.js +1 -0
- package/packages/client/dist/yoloop/yoloop-client-state-store.d.ts +124 -0
- package/packages/client/dist/yoloop/yoloop-client-state-store.js +1 -0
- package/postinstall.js +754 -0
- package/targets-stubs/antigravity/README.md +36 -0
- package/targets-stubs/antigravity/gemini.md +29 -0
- package/targets-stubs/antigravity/install-antigravity.sh +153 -0
- package/targets-stubs/antigravity/mcp-config.json +30 -0
- package/targets-stubs/antigravity/skill/SKILL.md +159 -0
- package/targets-stubs/claude-code/.mcp.json +32 -0
- package/targets-stubs/claude-code/README.md +20 -0
- package/targets-stubs/claude-code/neocortex-root.agent.yaml +42 -0
- package/targets-stubs/claude-code/neocortex-root.md +310 -0
- package/targets-stubs/claude-code/neocortex.agent.yaml +42 -0
- package/targets-stubs/claude-code/neocortex.md +378 -0
- package/targets-stubs/codex/AGENTS.md +244 -0
- package/targets-stubs/codex/README.md +47 -0
- package/targets-stubs/codex/config-mcp.toml +22 -0
- package/targets-stubs/codex/install-codex.sh +63 -0
- package/targets-stubs/codex/neocortex.toml +29 -0
- package/targets-stubs/cursor/README.md +33 -0
- package/targets-stubs/cursor/agent.md +204 -0
- package/targets-stubs/cursor/install-cursor.sh +50 -0
- package/targets-stubs/cursor/mcp.json +30 -0
- package/targets-stubs/gemini-cli/README.md +34 -0
- package/targets-stubs/gemini-cli/agent.md +234 -0
- package/targets-stubs/gemini-cli/agents/neocortex.md +54 -0
- package/targets-stubs/gemini-cli/gemini.md +46 -0
- package/targets-stubs/gemini-cli/install-gemini.sh +70 -0
- package/targets-stubs/gemini-cli/settings-mcp.json +30 -0
- package/targets-stubs/kimi/mcp.json +33 -0
- package/targets-stubs/kimi/neocortex.md +54 -0
- package/targets-stubs/lib/mcp-merge.js +189 -0
- package/targets-stubs/openclaw/README.md +12 -0
- package/targets-stubs/openclaw/SKILL.md +88 -0
- package/targets-stubs/opencode/neocortex-root.md +261 -0
- package/targets-stubs/opencode/neocortex.md +59 -0
- package/targets-stubs/opencode/opencode-mcp.json +35 -0
- package/targets-stubs/vscode/README.md +34 -0
- package/targets-stubs/vscode/copilot-instructions.md +47 -0
- package/targets-stubs/vscode/install-vscode.sh +72 -0
- package/targets-stubs/vscode/mcp.json +36 -0
- package/targets-stubs/vscode/neocortex.agent.md +245 -0
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license FSL-1.1
|
|
3
|
+
* Copyright (c) 2026 OrNexus AI
|
|
4
|
+
*
|
|
5
|
+
* Central, localized error message helpers for CLI output. Turns
|
|
6
|
+
* server error codes and low-level exceptions into friendly, actionable
|
|
7
|
+
* messages with "What happened" + "What to do" + support email.
|
|
8
|
+
*
|
|
9
|
+
* Story P76.06.
|
|
10
|
+
*/
|
|
11
|
+
export type ErrorMessageLocale = 'pt-BR' | 'en';
|
|
12
|
+
export interface HumanizedError {
|
|
13
|
+
/** Short one-line summary. */
|
|
14
|
+
readonly summary: string;
|
|
15
|
+
/** What happened (friendly explanation). */
|
|
16
|
+
readonly whatHappened: string;
|
|
17
|
+
/** Actionable next step(s). */
|
|
18
|
+
readonly whatToDo: string;
|
|
19
|
+
/** Optional CLI command snippet the user should run. */
|
|
20
|
+
readonly command?: string;
|
|
21
|
+
/** URL the user can visit for more context. */
|
|
22
|
+
readonly url?: string;
|
|
23
|
+
}
|
|
24
|
+
/** Detect the best locale from LC_ALL / LANG. Falls back to 'en'. */
|
|
25
|
+
export declare function detectErrorLocale(env?: NodeJS.ProcessEnv): ErrorMessageLocale;
|
|
26
|
+
/**
|
|
27
|
+
* Look up a humanized message for an error code.
|
|
28
|
+
* Returns null if the code is unknown -- caller should fall back to the
|
|
29
|
+
* raw server message.
|
|
30
|
+
*/
|
|
31
|
+
export declare function humanizeError(code: string, locale?: ErrorMessageLocale): HumanizedError | null;
|
|
32
|
+
/**
|
|
33
|
+
* Format a humanized error for stderr. Always ends with the support email.
|
|
34
|
+
*/
|
|
35
|
+
export declare function formatHumanizedError(humanized: HumanizedError, locale?: ErrorMessageLocale): string;
|
|
36
|
+
/**
|
|
37
|
+
* Infer an error code from a low-level error object (e.g., Node.js error
|
|
38
|
+
* thrown by fetch / dns / pg). Returns null if we cannot classify it.
|
|
39
|
+
*/
|
|
40
|
+
export declare function inferErrorCodeFromException(err: unknown): string | null;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const t="support@neocortex.sh",u={AUTH_EXPIRED:{en:{summary:"Your session has expired.",whatHappened:"The token we use to authenticate your CLI has expired. This is normal and happens every few hours.",whatToDo:"Re-activate with the license key that was emailed to you.",command:"neocortex activate YOUR-LICENSE-KEY",url:"https://neocortex.sh/portal"},"pt-BR":{summary:"Sua sess\xE3o expirou.",whatHappened:"O token de autentica\xE7\xE3o do CLI expirou. Isso \xE9 normal e acontece a cada poucas horas.",whatToDo:"Reative o CLI com a license key que voc\xEA recebeu por email.",command:"neocortex activate SUA-LICENSE-KEY",url:"https://neocortex.sh/portal"}},UPGRADE_REQUIRED:{en:{summary:"Your CLI version is outdated.",whatHappened:"The server requires a newer CLI version. Older versions are not allowed for security and compatibility reasons.",whatToDo:"Install the latest CLI globally with npm.",command:"npm install -g @ornexus/neocortex@latest"},"pt-BR":{summary:"Sua vers\xE3o do CLI est\xE1 desatualizada.",whatHappened:"O servidor exige uma vers\xE3o mais recente do CLI. Vers\xF5es antigas n\xE3o s\xE3o permitidas por motivos de seguran\xE7a e compatibilidade.",whatToDo:"Instale a vers\xE3o mais recente globalmente via npm.",command:"npm install -g @ornexus/neocortex@latest"}},RATE_LIMITED:{en:{summary:"You sent too many requests in a short window.",whatHappened:"You hit the rate limit for your plan. This protects the service from abuse and keeps it fast for everyone.",whatToDo:"Wait a few seconds and try again. If you hit this often, upgrading your plan raises the limit.",url:"https://neocortex.sh/portal/plans"},"pt-BR":{summary:"Voc\xEA fez muitas requisi\xE7\xF5es em pouco tempo.",whatHappened:"O limite de taxa do seu plano foi atingido. Isso protege o servi\xE7o contra abuso e mant\xE9m a velocidade para todos.",whatToDo:"Espere alguns segundos e tente novamente. Se isso acontece com frequ\xEAncia, fazer upgrade do seu plano aumenta o limite.",url:"https://neocortex.sh/portal/plans"}},TRIGGER_NOT_ALLOWED:{en:{summary:"This command is not available on your current plan.",whatHappened:"You tried to use a trigger that requires a paid plan (Pro or Enterprise).",whatToDo:"See the full comparison and upgrade in the portal.",url:"https://neocortex.sh/portal/plans"},"pt-BR":{summary:"Este comando n\xE3o est\xE1 dispon\xEDvel no seu plano atual.",whatHappened:"Voc\xEA tentou usar um trigger que requer um plano pago (Pro ou Enterprise).",whatToDo:"Veja a compara\xE7\xE3o completa e fa\xE7a upgrade no portal.",url:"https://neocortex.sh/portal/plans"}},QUOTA_EXCEEDED:{en:{summary:"Daily quota reached.",whatHappened:"You have used all invocations allowed by your plan today. Quotas reset at midnight UTC.",whatToDo:"Wait for the daily reset, or upgrade your plan for a higher quota.",url:"https://neocortex.sh/portal/plans"},"pt-BR":{summary:"Quota di\xE1ria atingida.",whatHappened:"Voc\xEA usou todas as invoca\xE7\xF5es permitidas pelo seu plano hoje. As quotas s\xE3o resetadas \xE0 meia-noite UTC.",whatToDo:"Aguarde o reset di\xE1rio ou fa\xE7a upgrade do plano para uma quota maior.",url:"https://neocortex.sh/portal/plans"}},SERVER_ERROR:{en:{summary:"Server error.",whatHappened:"Something went wrong on our side. We have logged the error and will investigate.",whatToDo:`Try again in a minute. If the problem persists, please contact ${t} with the details.`},"pt-BR":{summary:"Erro do servidor.",whatHappened:"Algo deu errado no nosso lado. O erro foi registrado e vamos investigar.",whatToDo:`Tente novamente em um minuto. Se o problema persistir, entre em contato: ${t}.`}},ECONNREFUSED:{en:{summary:"Cannot reach the Neocortex server.",whatHappened:"We could not open a connection to the server. This is usually a network problem on your side.",whatToDo:"Check your internet connection, any VPN or corporate proxy, and try again."},"pt-BR":{summary:"N\xE3o foi poss\xEDvel alcan\xE7ar o servidor Neocortex.",whatHappened:"N\xE3o conseguimos abrir uma conex\xE3o com o servidor. Isso geralmente \xE9 um problema de rede do seu lado.",whatToDo:"Verifique sua conex\xE3o, qualquer VPN ou proxy corporativo, e tente novamente."}},MACHINE_LIMIT_EXCEEDED:{en:{summary:"Machine limit reached.",whatHappened:"Your plan allows a limited number of active machines, and this one would exceed it.",whatToDo:"Deactivate a machine you no longer use from the portal, then re-run activate here.",url:"https://neocortex.sh/portal/machines"},"pt-BR":{summary:"Limite de m\xE1quinas atingido.",whatHappened:"Seu plano permite um n\xFAmero limitado de m\xE1quinas ativas, e esta ultrapassaria o limite.",whatToDo:"Desative uma m\xE1quina que voc\xEA n\xE3o usa mais no portal e rode activate aqui de novo.",url:"https://neocortex.sh/portal/machines"}},NOT_CONFIGURED:{en:{summary:"Neocortex is not configured on this machine.",whatHappened:"No license key was found. You need to run `neocortex activate` once before using the CLI.",whatToDo:"Get a license key from the portal and activate.",command:"neocortex activate YOUR-LICENSE-KEY",url:"https://neocortex.sh/portal"},"pt-BR":{summary:"Neocortex n\xE3o est\xE1 configurado nesta m\xE1quina.",whatHappened:"Nenhuma license key encontrada. Voc\xEA precisa rodar `neocortex activate` uma vez antes de usar o CLI.",whatToDo:"Pegue uma license key no portal e ative.",command:"neocortex activate SUA-LICENSE-KEY",url:"https://neocortex.sh/portal"}}};function r(o=process.env){return(o.LC_ALL??o.LANG??"").toLowerCase().startsWith("pt")?"pt-BR":"en"}function p(o,a=r()){const e=u[o];return e?e[a]??e.en??null:null}function c(o,a=r()){const e=[];e.push(""),e.push(`[Neocortex] ${o.summary}`),e.push("");const n=a==="pt-BR"?"O que aconteceu":"What happened",s=a==="pt-BR"?"O que fazer":"What to do",i=a==="pt-BR"?`Precisa de ajuda? ${t}`:`Need help? ${t}`;return e.push(`${n}: ${o.whatHappened}`),e.push(`${s}: ${o.whatToDo}`),o.command&&(e.push(""),e.push(` ${o.command}`)),o.url&&(e.push(""),e.push(` ${o.url}`)),e.push(""),e.push(i),e.push(""),e.join(`
|
|
2
|
+
`)}function l(o){if(!o||typeof o!="object")return null;const a=o;return typeof a.code=="string"&&(a.code==="ECONNREFUSED"||a.code==="ENOTFOUND"||a.code==="ETIMEDOUT"||a.code==="ECONNRESET")||typeof a.message=="string"&&(/connect/i.test(a.message)&&/refus/i.test(a.message)||/fetch failed/i.test(a.message))?"ECONNREFUSED":null}export{r as detectErrorLocale,c as formatHumanizedError,p as humanizeError,l as inferErrorCodeFromException};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* P158.06 -- optional pre-command deterministic graph retrieval enrichment.
|
|
3
|
+
*
|
|
4
|
+
* The client collects a tiny, public, redacted context envelope for selected
|
|
5
|
+
* commands only. It never constructs workflow prompts or decides orchestration;
|
|
6
|
+
* the server validates and decides whether to consume this auxiliary metadata.
|
|
7
|
+
*/
|
|
8
|
+
import { type GraphRetrievalMetadata } from './shared-graph-retrieval-contract.js';
|
|
9
|
+
declare const CONTRACT_VERSION = "client-pre-command-v1";
|
|
10
|
+
export interface GraphRetrievalHookContext {
|
|
11
|
+
readonly args: string;
|
|
12
|
+
readonly projectRoot: string;
|
|
13
|
+
readonly featureFlag: boolean;
|
|
14
|
+
readonly nowIso?: string;
|
|
15
|
+
readonly logger?: {
|
|
16
|
+
readonly warn?: (msg: string) => void;
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
export type GraphRetrievalCommand = 'yolo' | 'implement' | 'diagnose' | 'review' | 'create-epic' | 'arch-plan';
|
|
20
|
+
export type GraphRetrievalEnrichmentMetadata = GraphRetrievalMetadata & {
|
|
21
|
+
readonly contractVersion: typeof CONTRACT_VERSION;
|
|
22
|
+
readonly command: GraphRetrievalCommand;
|
|
23
|
+
};
|
|
24
|
+
export interface GraphRetrievalHookResult {
|
|
25
|
+
readonly applied: boolean;
|
|
26
|
+
readonly reason: 'flag_off' | 'command_not_allowlisted' | 'no_items' | 'applied' | 'hook_error';
|
|
27
|
+
readonly metadata?: GraphRetrievalEnrichmentMetadata;
|
|
28
|
+
readonly warning?: string;
|
|
29
|
+
}
|
|
30
|
+
export declare function runGraphRetrievalHook(ctx: GraphRetrievalHookContext): Promise<GraphRetrievalHookResult>;
|
|
31
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{createHash as g}from"node:crypto";import{existsSync as f,readFileSync as i,statSync as y}from"node:fs";import{join as d}from"node:path";import{DEFAULT_GRAPH_RETRIEVAL_BUDGETS as l,createGraphRetrievalMetadata as p,normalizeGraphRetrievalPath as C}from"./shared-graph-retrieval-contract.js";const b=new Set(["*yolo","yolo","*implement","implement","*diagnose","diagnose","*review","review","*create-epic","create-epic","*arch-plan","arch-plan"]),a="client-pre-command-v1",_="1970-01-01T00:00:00.000Z",T={yolo:{maxItems:6,maxTotalCost:50,maxSnippetChars:320},implement:{maxItems:8,maxTotalCost:55,maxSnippetChars:320},diagnose:{maxItems:10,maxTotalCost:60,maxSnippetChars:360},review:{maxItems:8,maxTotalCost:55,maxSnippetChars:320},"create-epic":{maxItems:8,maxTotalCost:60,maxSnippetChars:320},"arch-plan":{maxItems:10,maxTotalCost:65,maxSnippetChars:360}};function E(t){const e=t.trim().split(/\s+/,1)[0]?.toLowerCase();return!e||!b.has(e)?null:e.replace(/^\*/,"")}function x(t){return T[t]}function m(t){return g("sha256").update(t).digest("hex")}function I(t,e){const r=C(e);if(r.startsWith("..")||r.includes("/.env")||r.includes("credentials"))return null;const o=d(t,r);if(!f(o))return null;const n=y(o);if(!n.isFile()||n.size>96*1024)return null;const s=i(o,"utf8");return{kind:"repo-path",path:r,contentHash:m(s).slice(0,16),mtimeMs:Math.floor(n.mtimeMs)}}function u(t){let e=t;const r=e;return e=e.replace(/[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}/gi,"[REDACTED_EMAIL]"),e=e.replace(/\b(api[-_ ]?key|license[-_ ]?key|token|password|secret)\b\s*[:=]\s*[^\s`'"\])}]+/gi,"$1=[REDACTED_SECRET]"),e=e.replace(/\b(?:sk|pk|ghp|github_pat|pat)_[A-Za-z0-9_\-]{16,}\b/g,"[REDACTED_TOKEN]"),e=e.replace(/\b[A-Za-z0-9+/]{32,}={0,2}\b/g,"[REDACTED_TOKEN]"),e=e.replace(/<!--\s*(?:server|private|proprietary)[\s\S]*?-->/gi,"[REDACTED_PRIVATE_PROMPT]"),{text:e,redacted:e!==r}}function A(t,e=l.maxSnippetChars){const r=t.split(/\r?\n/).map(n=>n.trim()).filter(n=>n.length>0&&!n.startsWith("---")&&!n.startsWith("<!--")).slice(0,8).join(" "),o=u(r);return{summary:o.text.slice(0,e),redacted:o.redacted}}function S(t,e){const r=I(t,e.path);if(!r)return null;const o=i(d(t,r.path),"utf8"),n=A(o);return{nodeType:e.nodeType,stableId:e.stableId,source:r,confidence:n.redacted?Math.min(e.confidence,.72):e.confidence,reasonCode:e.reasonCode,budgetCost:e.budgetCost,summary:n.summary,warnings:n.redacted?["redacted_sensitive_content"]:void 0,score:e.score}}function D(t){return t.match(/@?(docs\/stories\/[A-Za-z0-9._-]+\.story\.md)\b/)?.[1]??null}function v(t,e,r){const o=[{path:"NEOCORTEX.md",nodeType:"CanonicalMemory",stableId:"canonical-memory",reasonCode:"canonical_memory_seed",confidence:.92,budgetCost:4,score:100},{path:"docs/arquitetura-software/deterministic-graph-retrieval.md",nodeType:"Doc",stableId:"deterministic-graph-retrieval",reasonCode:"architecture_reference",confidence:.9,budgetCost:4,score:84},{path:"package.json",nodeType:"Package",stableId:"root-package",reasonCode:"package_surface_match",confidence:.78,budgetCost:2,score:72}],n=D(e);if(n){const s=n.split("/").pop()?.replace(/\.story\.md$/,"")??n;o.push({path:n,nodeType:"Story",stableId:s,reasonCode:"story_scope_match",confidence:.96,budgetCost:3,score:96})}return(t==="yolo"||t==="implement"||t==="diagnose")&&o.push({path:".neocortex/tech-debt-registry.json",nodeType:"Debt",stableId:"tech-debt-registry",reasonCode:"debt_area_match",confidence:.74,budgetCost:3,score:76}),o.map(s=>S(r,s)).filter(s=>s!==null)}function R(t){let e=[...t.items],r=t;for(;Buffer.byteLength(JSON.stringify(r),"utf8")>l.maxPayloadBytes&&e.length>0;){const o=e.pop(),n=p({retrievalId:t.retrievalId,query:t.query,items:e,generatedAt:t.generatedAt,warnings:t.warnings,budgets:t.budget});r={...n,skipped:o?[...n.skipped,{stableId:o.stableId,source:o.source,reasonCode:"budget_exceeded"}]:n.skipped,contractVersion:a,command:t.command}}return r}async function L(t){const e=E(t.args);if(!e)return{applied:!1,reason:"command_not_allowlisted"};try{const r=v(e,t.args,t.projectRoot);if(r.length===0)return{applied:!1,reason:"no_items"};const o=u(t.args.trim().slice(0,240)).text,n=m(`${a}:${e}:${o}:${r.map(c=>`${c.source.path}:${c.source.contentHash??""}`).sort().join("|")}`).slice(0,24),s=x(e),h=p({retrievalId:n,query:o,items:r,generatedAt:t.nowIso??_,budgets:s});return{applied:!0,reason:"applied",metadata:R({...h,contractVersion:a,command:e})}}catch(r){const o=r instanceof Error?r.message:String(r);return t.logger?.warn?.(`[neocortex] graph retrieval hook failed: ${o}. Proceeding without enrichment.`),{applied:!1,reason:"hook_error",warning:o}}}export{L as runGraphRetrievalHook};
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* P158.06 client-side SSoT shadow for graph retrieval metadata.
|
|
3
|
+
*
|
|
4
|
+
* Mirrored from @neocortex/shared/graph-retrieval-contract for globally
|
|
5
|
+
* installed clients, where importing shared source/dist subpaths can break
|
|
6
|
+
* before the monorepo build has materialized dist files.
|
|
7
|
+
*/
|
|
8
|
+
export declare const GRAPH_RETRIEVAL_SCHEMA_VERSION: 1;
|
|
9
|
+
export declare const GRAPH_RETRIEVAL_CLIENT_CONTRACT_VERSION: "client-pre-command-v1";
|
|
10
|
+
export type GraphRetrievalCommand = 'yolo' | 'implement' | 'diagnose' | 'review' | 'create-epic' | 'arch-plan';
|
|
11
|
+
export type GraphRetrievalNodeType = 'CanonicalMemory' | 'PlatformMemory' | 'Doc' | 'Epic' | 'Story' | 'Command' | 'State' | 'Debt' | 'Package' | 'Api' | 'Route' | 'DbSchema' | 'Flag' | 'BusinessRule' | 'Guardrail' | 'Risk';
|
|
12
|
+
export type GraphRetrievalEdgeType = 'references' | 'derived_from' | 'updates' | 'governs' | 'implements' | 'depends_on' | 'conflicts_with' | 'supersedes' | 'documents' | 'affects' | 'retrieved_for';
|
|
13
|
+
export type GraphRetrievalReasonCode = 'canonical_memory_seed' | 'platform_memory_reference' | 'architecture_reference' | 'story_scope_match' | 'epic_scope_match' | 'command_surface_match' | 'state_status_match' | 'debt_area_match' | 'package_surface_match' | 'api_surface_match' | 'route_surface_match' | 'db_schema_surface_match' | 'flag_surface_match' | 'business_rule_match' | 'guardrail_match' | 'risk_match' | 'dependency_match' | 'conflict_warning' | 'stale_source_warning' | 'budget_exceeded' | 'redacted_sensitive_content' | 'invalid_source_rejected';
|
|
14
|
+
export interface GraphRetrievalBudgets {
|
|
15
|
+
readonly maxItems: number;
|
|
16
|
+
readonly maxEdges: number;
|
|
17
|
+
readonly maxPayloadBytes: number;
|
|
18
|
+
readonly maxSnippetChars: number;
|
|
19
|
+
readonly maxLabelChars: number;
|
|
20
|
+
readonly maxTotalCost: number;
|
|
21
|
+
}
|
|
22
|
+
export declare const DEFAULT_GRAPH_RETRIEVAL_BUDGETS: GraphRetrievalBudgets;
|
|
23
|
+
export interface GraphRetrievalSource {
|
|
24
|
+
readonly kind: 'repo-path' | 'state' | 'command' | 'generated-summary';
|
|
25
|
+
readonly path: string;
|
|
26
|
+
readonly contentHash?: string;
|
|
27
|
+
readonly mtimeMs?: number;
|
|
28
|
+
}
|
|
29
|
+
export interface GraphRetrievalEdge {
|
|
30
|
+
readonly type: GraphRetrievalEdgeType;
|
|
31
|
+
readonly targetNodeType: GraphRetrievalNodeType;
|
|
32
|
+
readonly targetStableId: string;
|
|
33
|
+
readonly source: GraphRetrievalSource;
|
|
34
|
+
readonly confidence: number;
|
|
35
|
+
readonly reasonCode: GraphRetrievalReasonCode;
|
|
36
|
+
}
|
|
37
|
+
export interface GraphRetrievalItem {
|
|
38
|
+
readonly nodeType: GraphRetrievalNodeType;
|
|
39
|
+
readonly stableId: string;
|
|
40
|
+
readonly source: GraphRetrievalSource;
|
|
41
|
+
readonly confidence: number;
|
|
42
|
+
readonly reasonCode: GraphRetrievalReasonCode;
|
|
43
|
+
readonly budgetCost: number;
|
|
44
|
+
readonly summary: string;
|
|
45
|
+
readonly edges?: readonly GraphRetrievalEdge[];
|
|
46
|
+
readonly warnings?: readonly GraphRetrievalReasonCode[];
|
|
47
|
+
readonly score?: number;
|
|
48
|
+
}
|
|
49
|
+
export interface GraphRetrievalSkippedItem {
|
|
50
|
+
readonly stableId: string;
|
|
51
|
+
readonly reasonCode: 'budget_exceeded' | 'redacted_sensitive_content' | 'invalid_source_rejected';
|
|
52
|
+
readonly source?: GraphRetrievalSource;
|
|
53
|
+
}
|
|
54
|
+
export interface GraphRetrievalMetadata {
|
|
55
|
+
readonly schemaVersion: typeof GRAPH_RETRIEVAL_SCHEMA_VERSION;
|
|
56
|
+
readonly contractVersion?: typeof GRAPH_RETRIEVAL_CLIENT_CONTRACT_VERSION;
|
|
57
|
+
readonly command?: GraphRetrievalCommand;
|
|
58
|
+
readonly retrievalId: string;
|
|
59
|
+
readonly query: string;
|
|
60
|
+
readonly budget: GraphRetrievalBudgets & {
|
|
61
|
+
readonly totalCost: number;
|
|
62
|
+
};
|
|
63
|
+
readonly items: readonly GraphRetrievalItem[];
|
|
64
|
+
readonly skipped: readonly GraphRetrievalSkippedItem[];
|
|
65
|
+
readonly warnings: readonly GraphRetrievalReasonCode[];
|
|
66
|
+
readonly generatedAt: string;
|
|
67
|
+
}
|
|
68
|
+
export declare function normalizeGraphRetrievalPath(path: string): string;
|
|
69
|
+
export declare function compareGraphRetrievalItems(a: GraphRetrievalItem, b: GraphRetrievalItem): number;
|
|
70
|
+
export declare function createGraphRetrievalMetadata(params: {
|
|
71
|
+
readonly retrievalId: string;
|
|
72
|
+
readonly query: string;
|
|
73
|
+
readonly items: readonly GraphRetrievalItem[];
|
|
74
|
+
readonly generatedAt: string;
|
|
75
|
+
readonly budgets?: Partial<GraphRetrievalBudgets>;
|
|
76
|
+
readonly warnings?: readonly GraphRetrievalReasonCode[];
|
|
77
|
+
}): GraphRetrievalMetadata;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const R=1,m="client-pre-command-v1",p={maxItems:24,maxEdges:64,maxPayloadBytes:12288,maxSnippetChars:480,maxLabelChars:160,maxTotalCost:100},u={CanonicalMemory:0,Guardrail:1,Debt:2,State:3,Story:4,Epic:5,Command:6,Doc:7,Package:8,Api:9,Route:10,DbSchema:11,Flag:12,BusinessRule:13,Risk:14,PlatformMemory:15};function i(e){return e.replace(/\\/g,"/").replace(/\/+/g,"/").replace(/^\.\//,"")}function d(e){return[e.nodeType,`${e.source.kind}:${i(e.source.path).toLowerCase()}`,e.stableId.toLowerCase()].join("|")}function l(e){return e.score??0}function f(e,o){const n=l(o)-l(e);if(n!==0)return n;const r=o.confidence-e.confidence;if(r!==0)return r;const a=e.budgetCost-o.budgetCost;if(a!==0)return a;const s=u[e.nodeType]-u[o.nodeType];if(s!==0)return s;const t=i(e.source.path).localeCompare(i(o.source.path),"en-US");return t!==0?t:e.stableId.localeCompare(o.stableId,"en-US")}function C(e){const o={...p,...e.budgets},n=new Map;for(const t of e.items){const c=n.get(d(t));(!c||f(t,c)<0)&&n.set(d(t),t)}const r=[],a=[];let s=0;for(const t of[...n.values()].sort(f)){const c=s+Math.max(1,t.budgetCost);if(r.length>=o.maxItems||c>o.maxTotalCost){a.push({stableId:t.stableId,source:t.source,reasonCode:"budget_exceeded"});continue}r.push(t),s=c}return{schemaVersion:1,retrievalId:e.retrievalId,query:e.query,budget:{...o,totalCost:s},items:r,skipped:a,warnings:e.warnings??[],generatedAt:e.generatedAt}}export{p as DEFAULT_GRAPH_RETRIEVAL_BUDGETS,m as GRAPH_RETRIEVAL_CLIENT_CONTRACT_VERSION,R as GRAPH_RETRIEVAL_SCHEMA_VERSION,f as compareGraphRetrievalItems,C as createGraphRetrievalMetadata,i as normalizeGraphRetrievalPath};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license FSL-1.1
|
|
3
|
+
* Copyright (c) 2026 OrNexus AI
|
|
4
|
+
*
|
|
5
|
+
* First-run messages -- localized welcome strings shown on the user's
|
|
6
|
+
* first `neocortex-client invoke` call. Writes to stderr so it never
|
|
7
|
+
* contaminates instruction output. See P76.02.
|
|
8
|
+
*/
|
|
9
|
+
export type FirstRunLocale = 'pt-BR' | 'en';
|
|
10
|
+
export interface FirstRunMessage {
|
|
11
|
+
readonly banner: string;
|
|
12
|
+
readonly intro: string;
|
|
13
|
+
readonly commands: readonly {
|
|
14
|
+
label: string;
|
|
15
|
+
description: string;
|
|
16
|
+
}[];
|
|
17
|
+
readonly tip: string;
|
|
18
|
+
}
|
|
19
|
+
export declare const FIRST_RUN_MESSAGES: Record<FirstRunLocale, FirstRunMessage>;
|
|
20
|
+
/** Detect the best locale from process.env.LANG / LC_ALL. Falls back to en. */
|
|
21
|
+
export declare function detectFirstRunLocale(env?: NodeJS.ProcessEnv): FirstRunLocale;
|
|
22
|
+
/** Render the first-run message as a plain-text block suitable for stderr. */
|
|
23
|
+
export declare function renderFirstRunMessage(locale: FirstRunLocale): string;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const i={en:{banner:"\u2500\u2500 Welcome to Neocortex \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500",intro:"Looks like this is your first time here. Here are a few commands to get started:",commands:[{label:"@neocortex *menu",description:"See all available commands"},{label:"@neocortex *arch-plan",description:"Plan a new project architecture"},{label:"@neocortex *yolo",description:"Quick implementation mode"},{label:"@neocortex *status",description:"Check your project status"}],tip:"Tip: run `@neocortex *menu` for the full, tier-aware command list."},"pt-BR":{banner:"\u2500\u2500 Bem-vindo ao Neocortex \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500",intro:"Parece que esta \xE9 a sua primeira vez por aqui. Alguns comandos para come\xE7ar:",commands:[{label:"@neocortex *menu",description:"Ver todos os comandos dispon\xEDveis"},{label:"@neocortex *arch-plan",description:"Planejar a arquitetura de um novo projeto"},{label:"@neocortex *yolo",description:"Modo de implementa\xE7\xE3o r\xE1pida"},{label:"@neocortex *status",description:"Ver o status do seu projeto"}],tip:"Dica: execute `@neocortex *menu` para a lista completa (j\xE1 filtrada pelo seu tier)."}};function c(t=process.env){return(t.LC_ALL??t.LANG??"").toLowerCase().startsWith("pt")?"pt-BR":"en"}function p(t){const o=i[t],n=62,s=o.commands.reduce((r,a)=>Math.max(r,a.label.length),0),e=[];e.push(o.banner),e.push(""),e.push(o.intro),e.push("");for(const r of o.commands){const a=r.label.padEnd(s+2);e.push(` ${a}${r.description}`)}return e.push(""),e.push(o.tip),e.push("".padEnd(n,"\u2500")),e.push(""),e.join(`
|
|
2
|
+
`)}export{i as FIRST_RUN_MESSAGES,c as detectFirstRunLocale,p as renderFirstRunMessage};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license FSL-1.1
|
|
3
|
+
* Copyright (c) 2026 OrNexus AI
|
|
4
|
+
*
|
|
5
|
+
* This file is part of Neocortex CLI, licensed under the
|
|
6
|
+
* Functional Source License, Version 1.1 (FSL-1.1).
|
|
7
|
+
*
|
|
8
|
+
* Change Date: February 20, 2029
|
|
9
|
+
* Change License: MIT
|
|
10
|
+
*
|
|
11
|
+
* See the LICENSE file in the project root for full license text.
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* @neocortex/client - Thin Client Abstraction Layer
|
|
15
|
+
*
|
|
16
|
+
* Strategy pattern for transparent asset resolution from either
|
|
17
|
+
* local filesystem (development) or remote server (production).
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```typescript
|
|
21
|
+
* import { createResolver, collectContext } from '@neocortex/client';
|
|
22
|
+
*
|
|
23
|
+
* // Auto-detect resolver based on environment
|
|
24
|
+
* const resolver = await createResolver();
|
|
25
|
+
*
|
|
26
|
+
* // Collect pipeline context
|
|
27
|
+
* const context = await collectContext({
|
|
28
|
+
* projectRoot: process.cwd(),
|
|
29
|
+
* storyFilePath: 'docs/stories/1.1.story.md',
|
|
30
|
+
* storyId: '1.1',
|
|
31
|
+
* stepId: 'step-c-06-implement-tasks',
|
|
32
|
+
* });
|
|
33
|
+
*
|
|
34
|
+
* // Resolve a step (works the same whether local or remote)
|
|
35
|
+
* const step = await resolver.resolveStep('step-c-01-setup-branch', context);
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
export type { AssembledPrompt, CacheProvider, CodebaseMetadata, CreateResolverOptions, LocalResolverOptions, PipelineContext, RemoteResolverOptions, SkillContent, StandardContent, StepContent, StepRegistry, StepRegistryEntry, StoryMetadata, } from './types/index.js';
|
|
39
|
+
export { ResolverMode, NoOpCache } from './types/index.js';
|
|
40
|
+
export type { AssetResolver } from './resolvers/asset-resolver.js';
|
|
41
|
+
export { LocalResolver } from './resolvers/local-resolver.js';
|
|
42
|
+
export { RemoteResolver, RemoteResolverError } from './resolvers/remote-resolver.js';
|
|
43
|
+
export { EncryptedCache, type EncryptedCacheOptions } from './cache/index.js';
|
|
44
|
+
export { createResolver, selectResolver, type ResolverSelectionResult, } from './config/resolver-selection.js';
|
|
45
|
+
export { collectContext, type CollectContextOptions, } from './context/context-collector.js';
|
|
46
|
+
export { sanitizeValue, sanitizeRecord, sanitizeObject, } from './context/context-sanitizer.js';
|
|
47
|
+
export { getMachineFingerprint } from './machine/index.js';
|
|
48
|
+
export { LicenseClient, type LicenseClientOptions } from './license/index.js';
|
|
49
|
+
export type { InjectionMethod, PlatformInstructions, TargetAdapter, TargetCapabilities, TargetConfig, DetectionContext, DetectionResult, FileExistsCheck, TargetId, } from './adapters/index.js';
|
|
50
|
+
export { ClaudeCodeAdapter, CursorAdapter, VSCodeAdapter, GeminiAdapter, CodexAdapter, AntigravityAdapter, AdapterRegistry, UnknownTargetError, createDefaultRegistry, detectPlatform, isValidTargetId, } from './adapters/index.js';
|
|
51
|
+
export { ClientCircuitBreaker, type CircuitState, type CircuitBreakerConfig, type CircuitBreakerState, DegradationManager, DegradationLevel, type DegradationContext, type DegradationDecision, FreshnessIndicator, type FreshnessInfo, RecoveryDetector, type RecoveryActions, type RecoveryResult, } from './resilience/index.js';
|
|
52
|
+
export { OfflineTelemetryQueue, type TelemetryEvent, type QueueConfig, type QueueStats, type FlushResult, } from './telemetry/index.js';
|
|
53
|
+
export { getCacheStatus, formatCacheStatus, type CacheStatusInfo, type CacheStatusOptions, } from './commands/cache-status.js';
|
|
54
|
+
export { invoke, invokeCliHandler, collectStateSnapshot, type InvokeOptions, type InvokeResult, } from './commands/invoke.js';
|
|
55
|
+
export { TierAwareClient, type TierAwareClientOptions, type PreFlightResult, type QuotaSnapshot, } from './tier/index.js';
|
|
56
|
+
export { buildProjectMemoryContent, createNodeProjectMemoryFs, writeProjectMemory, writeProjectMemoryTargetFiles, type WriteProjectMemoryFileResult, type ProjectMemoryWriterFs, type WriteProjectMemoryOptions, type WriteProjectMemoryResult, type WriteProjectMemoryTargetFilesResult, } from './memory/project-memory-writer.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{ResolverMode as t,NoOpCache as o}from"./types/index.js";import{LocalResolver as i}from"./resolvers/local-resolver.js";import{RemoteResolver as c,RemoteResolverError as l}from"./resolvers/remote-resolver.js";import{EncryptedCache as m}from"./cache/index.js";import{createResolver as s,selectResolver as f}from"./config/resolver-selection.js";import{collectContext as C}from"./context/context-collector.js";import{sanitizeValue as R,sanitizeRecord as v,sanitizeObject as u}from"./context/context-sanitizer.js";import{getMachineFingerprint as A}from"./machine/index.js";import{LicenseClient as M}from"./license/index.js";import{ClaudeCodeAdapter as P,CursorAdapter as S,VSCodeAdapter as T,GeminiAdapter as k,CodexAdapter as w,AntigravityAdapter as D,AdapterRegistry as F,UnknownTargetError as z,createDefaultRegistry as E,detectPlatform as L,isValidTargetId as O}from"./adapters/index.js";import{ClientCircuitBreaker as b,DegradationManager as I,DegradationLevel as N,FreshnessIndicator as B,RecoveryDetector as G}from"./resilience/index.js";import{OfflineTelemetryQueue as Q}from"./telemetry/index.js";import{getCacheStatus as q,formatCacheStatus as J}from"./commands/cache-status.js";import{invoke as W,invokeCliHandler as X,collectStateSnapshot as Y}from"./commands/invoke.js";import{TierAwareClient as _}from"./tier/index.js";import{buildProjectMemoryContent as ee,createNodeProjectMemoryFs as re,writeProjectMemory as te,writeProjectMemoryTargetFiles as oe}from"./memory/project-memory-writer.js";export{F as AdapterRegistry,D as AntigravityAdapter,P as ClaudeCodeAdapter,b as ClientCircuitBreaker,w as CodexAdapter,S as CursorAdapter,N as DegradationLevel,I as DegradationManager,m as EncryptedCache,B as FreshnessIndicator,k as GeminiAdapter,M as LicenseClient,i as LocalResolver,o as NoOpCache,Q as OfflineTelemetryQueue,G as RecoveryDetector,c as RemoteResolver,l as RemoteResolverError,t as ResolverMode,_ as TierAwareClient,z as UnknownTargetError,T as VSCodeAdapter,ee as buildProjectMemoryContent,C as collectContext,Y as collectStateSnapshot,E as createDefaultRegistry,re as createNodeProjectMemoryFs,s as createResolver,L as detectPlatform,J as formatCacheStatus,q as getCacheStatus,A as getMachineFingerprint,W as invoke,X as invokeCliHandler,O as isValidTargetId,u as sanitizeObject,v as sanitizeRecord,R as sanitizeValue,f as selectResolver,te as writeProjectMemory,oe as writeProjectMemoryTargetFiles};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{LicenseClient as n}from"./license-client.js";export{n as LicenseClient};
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license FSL-1.1
|
|
3
|
+
* Copyright (c) 2026 OrNexus AI
|
|
4
|
+
*
|
|
5
|
+
* This file is part of Neocortex CLI, licensed under the
|
|
6
|
+
* Functional Source License, Version 1.1 (FSL-1.1).
|
|
7
|
+
*
|
|
8
|
+
* Change Date: February 20, 2029
|
|
9
|
+
* Change License: MIT
|
|
10
|
+
*
|
|
11
|
+
* See the LICENSE file in the project root for full license text.
|
|
12
|
+
*/
|
|
13
|
+
import type { CacheProvider } from '../types/index.js';
|
|
14
|
+
export interface LicenseClientOptions {
|
|
15
|
+
readonly serverUrl: string;
|
|
16
|
+
readonly licenseKey: string;
|
|
17
|
+
readonly cacheProvider?: CacheProvider;
|
|
18
|
+
readonly clientVersion?: string;
|
|
19
|
+
}
|
|
20
|
+
interface ActivationResult {
|
|
21
|
+
readonly token: string;
|
|
22
|
+
readonly expiresIn: number;
|
|
23
|
+
readonly refreshToken?: string;
|
|
24
|
+
}
|
|
25
|
+
export declare class LicenseClient {
|
|
26
|
+
private readonly serverUrl;
|
|
27
|
+
private readonly licenseKey;
|
|
28
|
+
private readonly cache;
|
|
29
|
+
private readonly clientVersion;
|
|
30
|
+
private readonly machineId;
|
|
31
|
+
private token;
|
|
32
|
+
private refreshToken;
|
|
33
|
+
constructor(options: LicenseClientOptions);
|
|
34
|
+
/**
|
|
35
|
+
* Get a valid JWT token. Checks memory, cache, refresh token, then activation.
|
|
36
|
+
* NEVER throws - returns null on failure.
|
|
37
|
+
*
|
|
38
|
+
* Flow:
|
|
39
|
+
* 1. in-memory JWT valid? -> return
|
|
40
|
+
* 2. in-memory JWT needs-refresh? -> refresh(refresh_token) -> return
|
|
41
|
+
* 3. cached JWT valid? -> return
|
|
42
|
+
* 4. cached JWT needs-refresh? -> refresh(refresh_token) -> return
|
|
43
|
+
* 5. cached refresh_token exists? -> refresh(refresh_token) -> return (Story 31.02)
|
|
44
|
+
* 6. activate() -> return
|
|
45
|
+
*/
|
|
46
|
+
getToken(): Promise<string | null>;
|
|
47
|
+
/**
|
|
48
|
+
* Activate the license by calling POST /api/v1/license/activate.
|
|
49
|
+
* Stores token and refresh_token in memory and cache on success.
|
|
50
|
+
* NEVER throws - returns null on failure.
|
|
51
|
+
*/
|
|
52
|
+
activate(): Promise<ActivationResult | null>;
|
|
53
|
+
/**
|
|
54
|
+
* Refresh using refresh_token by calling POST /api/v1/license/refresh.
|
|
55
|
+
* Sends refresh_token in body (no Authorization header needed).
|
|
56
|
+
* Handles token rotation: stores the new refresh_token from response.
|
|
57
|
+
* NEVER throws - returns null on failure.
|
|
58
|
+
*
|
|
59
|
+
* Story 31.02: Signature changed from refresh(currentToken) to refresh().
|
|
60
|
+
* The refresh_token in the body is the credential, not the JWT.
|
|
61
|
+
*
|
|
62
|
+
* @param _currentToken - Deprecated. Kept for backward compat but ignored.
|
|
63
|
+
*/
|
|
64
|
+
refresh(_currentToken?: string): Promise<ActivationResult | null>;
|
|
65
|
+
/**
|
|
66
|
+
* Force-refresh the token.
|
|
67
|
+
* Used when tier_changed is detected or a 401 response indicates the token is expired.
|
|
68
|
+
* Falls back to re-activation if refresh fails.
|
|
69
|
+
* NEVER throws - returns new token or null on failure.
|
|
70
|
+
*
|
|
71
|
+
* Story 18.8: Updated to prefer refresh over re-activate (preserves updated tier).
|
|
72
|
+
* Story 31.02: Uses refresh_token flow instead of JWT-based refresh.
|
|
73
|
+
*/
|
|
74
|
+
forceRefresh(): Promise<string | null>;
|
|
75
|
+
private checkTokenValidity;
|
|
76
|
+
private loadFromCache;
|
|
77
|
+
private loadRefreshTokenFromCache;
|
|
78
|
+
}
|
|
79
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{decodeJwt as c}from"jose";import{NoOpCache as o}from"../types/index.js";import{getMachineFingerprint as a}from"../machine/fingerprint.js";const i="neocortex:jwt:token",s="neocortex:jwt:refresh_token",l=300,h=10080*60*1e3,f="0.1.0";class T{serverUrl;licenseKey;cache;clientVersion;machineId;token=null;refreshToken=null;constructor(e){this.serverUrl=e.serverUrl.replace(/\/+$/,""),this.licenseKey=e.licenseKey,this.cache=e.cacheProvider??new o,this.clientVersion=e.clientVersion??f,this.machineId=a()}async getToken(){try{if(this.token){const r=this.checkTokenValidity(this.token);if(r==="valid")return this.token;if(r==="needs-refresh")return(await this.refresh())?.token??this.token;this.token=null}const e=await this.loadFromCache();if(e){this.token=e;const r=this.checkTokenValidity(e);if(r==="valid")return e;if(r==="needs-refresh")return(await this.refresh())?.token??e;this.token=null}if(this.refreshToken||(this.refreshToken=await this.loadRefreshTokenFromCache()),this.refreshToken){const r=await this.refresh();if(r?.token)return r.token}return(await this.activate())?.token??null}catch{return null}}async activate(){try{const e=await fetch(`${this.serverUrl}/api/v1/license/activate`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({license_key:this.licenseKey,machine_id:this.machineId,client_version:this.clientVersion})});if(!e.ok)return null;const t=await e.json();return this.token=t.token,this.refreshToken=t.refresh_token??null,this.cache.set(i,t.token,t.expires_in*1e3).catch(()=>{}),t.refresh_token&&this.cache.set(s,t.refresh_token,h).catch(()=>{}),{token:t.token,expiresIn:t.expires_in,refreshToken:t.refresh_token}}catch{return null}}async refresh(e){try{const t=this.refreshToken??await this.loadRefreshTokenFromCache();if(!t)return null;const r=await fetch(`${this.serverUrl}/api/v1/license/refresh`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refresh_token:t})});if(!r.ok)return this.refreshToken=null,this.cache.set(s,"",1).catch(()=>{}),null;const n=await r.json();return this.token=n.token,this.refreshToken=n.refresh_token??null,this.cache.set(i,n.token,n.expires_in*1e3).catch(()=>{}),n.refresh_token&&this.cache.set(s,n.refresh_token,h).catch(()=>{}),{token:n.token,expiresIn:n.expires_in,refreshToken:n.refresh_token}}catch{return null}}async forceRefresh(){try{const e=await this.refresh();return e?.token?e.token:(this.token=null,this.refreshToken=null,await this.cache.clear().catch(()=>{}),(await this.activate())?.token??null)}catch{return null}}checkTokenValidity(e){try{const t=c(e);if(!t.exp)return"expired";const r=Math.floor(Date.now()/1e3);return t.exp<=r?"expired":t.exp-r<=l?"needs-refresh":"valid"}catch{return"expired"}}async loadFromCache(){try{return await this.cache.get(i)}catch{return null}}async loadRefreshTokenFromCache(){try{const e=await this.cache.get(s);return e&&e.length>0?e:null}catch{return null}}}export{T as LicenseClient};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license FSL-1.1
|
|
3
|
+
* Copyright (c) 2026 OrNexus AI
|
|
4
|
+
*
|
|
5
|
+
* This file is part of Neocortex CLI, licensed under the
|
|
6
|
+
* Functional Source License, Version 1.1 (FSL-1.1).
|
|
7
|
+
*
|
|
8
|
+
* Change Date: February 20, 2029
|
|
9
|
+
* Change License: MIT
|
|
10
|
+
*
|
|
11
|
+
* See the LICENSE file in the project root for full license text.
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* Generate a hardware-based fingerprint (not persisted).
|
|
15
|
+
* This is the original computation used as fallback and for seeding.
|
|
16
|
+
*
|
|
17
|
+
* @returns 64-character hex string (SHA-256 digest)
|
|
18
|
+
*/
|
|
19
|
+
export declare function computeHardwareFingerprint(): string;
|
|
20
|
+
/**
|
|
21
|
+
* Generate a stable machine fingerprint as a SHA-256 hex digest.
|
|
22
|
+
*
|
|
23
|
+
* Story P26.01: On first call, generates from hardware and persists to
|
|
24
|
+
* ~/.neocortex/.machine-id. On subsequent calls, reads from disk.
|
|
25
|
+
* This ensures the fingerprint remains stable even if hardware attributes
|
|
26
|
+
* change (e.g., USB NIC added/removed, hostname change).
|
|
27
|
+
*
|
|
28
|
+
* Backward compat: if config.json has machineId, uses that to seed .machine-id.
|
|
29
|
+
*
|
|
30
|
+
* Fail-open: if disk operations fail, falls back to hardware-generated fingerprint.
|
|
31
|
+
*
|
|
32
|
+
* @returns 64-character hex string (SHA-256 digest)
|
|
33
|
+
*/
|
|
34
|
+
export declare function getMachineFingerprint(): string;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{createHash as p}from"node:crypto";import{existsSync as s,readFileSync as a,writeFileSync as h,mkdirSync as d,chmodSync as g}from"node:fs";import{join as o}from"node:path";import{arch as y,cpus as F,homedir as I,hostname as M,networkInterfaces as S,platform as w}from"node:os";const $="00:00:00:00:00:00",i=o(I(),".neocortex"),c=o(i,".machine-id");function E(){const t=S(),n=[];for(const e of Object.values(t))if(e)for(const r of e)!r.internal&&r.mac!==$&&n.push(r.mac);return[...new Set(n)].sort()}function x(){const t=M(),n=w(),e=y(),r=F(),u=r.length>0?r[0].model:"",m=E(),l=`${t}|${n}|${e}|${u}|${m.join(",")}`;return p("sha256").update(l).digest("hex")}function C(t){try{process.platform!=="win32"&&g(t,384)}catch{}}function O(){try{if(!s(c))return null;const t=a(c,"utf-8").trim();return/^[a-f0-9]{64}$/.test(t)?t:null}catch{return null}}function f(t){try{d(i,{recursive:!0}),h(c,t+`
|
|
2
|
+
`,"utf-8"),C(c)}catch{}}function _(){try{const t=o(i,"config.json");if(!s(t))return null;const n=a(t,"utf-8"),r=JSON.parse(n.replace(/^\uFEFF/,"")).machineId;return typeof r=="string"&&/^[a-f0-9]{64}$/.test(r)?r:null}catch{return null}}function N(){const t=O();if(t)return t;const n=_();if(n)return f(n),n;const e=x();return f(e),e}export{x as computeHardwareFingerprint,N as getMachineFingerprint};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{getMachineFingerprint as i}from"./fingerprint.js";export{i as getMachineFingerprint};
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Project memory writer for platform-specific always-loaded files.
|
|
3
|
+
*
|
|
4
|
+
* The writer owns only the NEOCORTEX-MEMORY block. Everything outside that
|
|
5
|
+
* block is preserved byte-for-byte so users can keep local instructions.
|
|
6
|
+
*/
|
|
7
|
+
import { type ArchitectureReference, type BootstrapArchitectureMemory, type ProjectMemoryTarget, type ProjectMemoryTargetId } from './shared-project-memory-types.js';
|
|
8
|
+
export interface ProjectMemoryWriterFs {
|
|
9
|
+
readFile(path: string): string | undefined;
|
|
10
|
+
writeFileAtomic(path: string, content: string): {
|
|
11
|
+
backupPath?: string;
|
|
12
|
+
};
|
|
13
|
+
join(...parts: string[]): string;
|
|
14
|
+
}
|
|
15
|
+
export interface WriteProjectMemoryOptions {
|
|
16
|
+
readonly projectRoot: string;
|
|
17
|
+
readonly targetId: ProjectMemoryTargetId;
|
|
18
|
+
readonly memoryNotes?: readonly string[];
|
|
19
|
+
readonly architectureReferences?: readonly ArchitectureReference[];
|
|
20
|
+
readonly bootstrapArchitecture?: BootstrapArchitectureMemory;
|
|
21
|
+
readonly fs?: ProjectMemoryWriterFs;
|
|
22
|
+
readonly symlinkCapability?: ProjectMemorySymlinkCapability;
|
|
23
|
+
readonly dryRun?: boolean;
|
|
24
|
+
}
|
|
25
|
+
export interface ProjectMemorySymlinkCapability {
|
|
26
|
+
readonly os: NodeJS.Platform | string;
|
|
27
|
+
readonly supported: boolean;
|
|
28
|
+
readonly permission: 'ok' | 'denied' | 'unknown';
|
|
29
|
+
readonly filesystem: 'supports-symlink' | 'no-symlink-support' | 'unknown';
|
|
30
|
+
readonly targetPolicy: ProjectMemoryTarget['linkRequirement']['policy'];
|
|
31
|
+
readonly targetPolicyAllowsSymlink: boolean;
|
|
32
|
+
readonly requiresWrapperPreservation: boolean;
|
|
33
|
+
readonly reason?: string;
|
|
34
|
+
}
|
|
35
|
+
export interface WriteProjectMemoryResult {
|
|
36
|
+
readonly filePath: string;
|
|
37
|
+
readonly changed: boolean;
|
|
38
|
+
readonly content: string;
|
|
39
|
+
readonly safeDiff?: string;
|
|
40
|
+
readonly backupPath?: string;
|
|
41
|
+
readonly reasonCodes?: readonly string[];
|
|
42
|
+
}
|
|
43
|
+
export interface WriteProjectMemoryFileResult extends WriteProjectMemoryResult {
|
|
44
|
+
readonly relativeFile: string;
|
|
45
|
+
readonly mode: 'canonical' | 'semantic-symlink' | 'managed-wrapper' | 'compatibility-materialized-fallback';
|
|
46
|
+
readonly canonicalSource: string;
|
|
47
|
+
readonly symlinkCapability?: ProjectMemorySymlinkCapability;
|
|
48
|
+
readonly fallbackReason?: string;
|
|
49
|
+
readonly remediationDebt?: string;
|
|
50
|
+
}
|
|
51
|
+
export interface WriteProjectMemoryTargetFilesResult {
|
|
52
|
+
readonly targetId: ProjectMemoryTargetId;
|
|
53
|
+
readonly canonicalFilePath: string;
|
|
54
|
+
readonly files: readonly WriteProjectMemoryFileResult[];
|
|
55
|
+
readonly changed: boolean;
|
|
56
|
+
}
|
|
57
|
+
export declare function createNodeProjectMemoryFs(): ProjectMemoryWriterFs;
|
|
58
|
+
export declare const PROJECT_MEMORY_LAYER_CATEGORIES: readonly ["skills-agents", "frontend", "backend", "api", "db", "schemas", "envs", "devops", "cyber-security", "testing-qa", "observability", "product-business", "docs-architecture", "platform-memory", "command-behavior", "generic"];
|
|
59
|
+
export type ProjectMemoryLayerCategory = typeof PROJECT_MEMORY_LAYER_CATEGORIES[number];
|
|
60
|
+
export type ProjectMemoryChangeKind = 'feature' | 'rule' | 'flag' | 'route' | 'api' | 'db-schema' | 'architecture' | 'debt' | 'decision' | 'generic';
|
|
61
|
+
export interface ClassifiedProjectMemoryUpdate {
|
|
62
|
+
readonly kind: ProjectMemoryChangeKind;
|
|
63
|
+
readonly layer: ProjectMemoryLayerCategory;
|
|
64
|
+
readonly sectionTitle: string;
|
|
65
|
+
readonly summary: string;
|
|
66
|
+
readonly reasonCode: string;
|
|
67
|
+
}
|
|
68
|
+
export declare function classifyProjectMemoryUpdate(value: string): ClassifiedProjectMemoryUpdate;
|
|
69
|
+
export declare function createSafeProjectMemoryDiff(before: string | undefined, after: string): string;
|
|
70
|
+
export declare function bootstrapArchitectureMemory(projectRoot: string): BootstrapArchitectureMemory;
|
|
71
|
+
export declare function buildProjectMemoryContent(target: ProjectMemoryTarget, existingContent: string | undefined, memoryNotes?: readonly string[], architectureReferences?: readonly ArchitectureReference[], bootstrapArchitecture?: BootstrapArchitectureMemory): string;
|
|
72
|
+
export declare function writeProjectMemory(options: WriteProjectMemoryOptions): WriteProjectMemoryResult;
|
|
73
|
+
export declare function writeCanonicalProjectMemory(options: Omit<WriteProjectMemoryOptions, 'targetId'>): WriteProjectMemoryResult;
|
|
74
|
+
export declare function writeProjectMemoryTargetFiles(options: WriteProjectMemoryOptions): WriteProjectMemoryTargetFilesResult;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import{existsSync as y,lstatSync as C,mkdirSync as $,copyFileSync as v,readdirSync as W,readFileSync as k,readlinkSync as F,renameSync as z,rmSync as T,statSync as de,symlinkSync as N,unlinkSync as G,writeFileSync as j}from"node:fs";import{platform as A}from"node:os";import{dirname as x,join as p,relative as ue}from"node:path";import{CANONICAL_PROJECT_MEMORY_SOURCE as b,getProjectMemoryTarget as I,renderArchitectureReferenceTable as le}from"./shared-project-memory-types.js";function me(){return{readFile(e){try{return k(e,"utf8")}catch{return}},writeFileAtomic(e,t){$(x(e),{recursive:!0});const r=`${e}.tmp-${process.pid}-${Date.now()}`,n=y(e)?`${e}.bak-${Date.now()}`:void 0;try{return j(r,t,"utf8"),n!==void 0&&v(e,n),z(r,e),{backupPath:n}}catch(o){if(T(r,{force:!0}),n!==void 0&&y(n))try{v(n,e)}catch{}throw o}},join(...e){return p(...e)}}}function O(e){return`<!-- ${e.ownedBlockName}-START -->`}function _(e){return`<!-- ${e.ownedBlockName}-END -->`}function g(e){const t=new Set,r=[];for(const n of e){const o=n.trim().replace(/\s+/g," ");o.length===0||t.has(o.toLowerCase())||(t.add(o.toLowerCase()),r.push(o))}return r}function fe(e){const t=new Set,r=[];for(const n of e)t.has(n.path)||(t.add(n.path),r.push(n));return r}function pe(e){switch(e.templateKind){case"neocortex-md":return"# NEOCORTEX.md Project Memory";case"claude-md":return"# CLAUDE.md Project Memory";case"agents-md":return"# AGENTS.md Project Instructions";case"gemini-md":return"# GEMINI.md Project Memory";case"copilot-instructions":return"# GitHub Copilot Repository Instructions";case"cursor-rule":return`---
|
|
2
|
+
description: Neocortex project memory
|
|
3
|
+
alwaysApply: true
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Cursor Project Memory`}}const ye=["Keep always-loaded memory compact: laws, active context, and references only.","Preserve human-authored instructions outside this owned block.","Prefer repository SSoT docs over duplicating architecture details here."],be=["Consult `docs/architecture/` before changes that affect architecture, contracts, data, security, performance, UX, or infrastructure.","Reference architecture documents by repository path, such as `docs/architecture/architecture.md`, before changing related implementation.","Summarize decisions and trade-offs in NEOCORTEX.md; do not paste complete architecture documents into memory.","Update memory for durable cross-layer changes across skills/agents, frontend, backend, API, DB, schemas, envs, DevOps, cyber security, testing/QA, observability, product, docs, and platform contracts.","Prioritize compact summaries of durable decisions, public contracts, operational risks, debts, command behavior, and repository paths; skip transient logs, raw payloads, secrets, private prompts, long documents, and duplicated canonical sources.","Keep platform memory files symlink-backed or include-backed to NEOCORTEX.md when supported."],We=["skills-agents","frontend","backend","api","db","schemas","envs","devops","cyber-security","testing-qa","observability","product-business","docs-architecture","platform-memory","command-behavior","generic"],he=360,X={feature:"Features",rule:"Rules/Policies",flag:"Flags",route:"Routes",api:"APIs/Contracts","db-schema":"DB/Schema",architecture:"Architecture",debt:"Debts",decision:"Decisions",generic:"General Updates"},ge=/\b(private|proprietary|server[- ]only|system)\s+prompt\b|\b(api[-_ ]?key|license[-_ ]?key|password|authorization|bearer|token|secret)\s*[:=]|\b(ghp_[A-Za-z0-9_]+|sk-[A-Za-z0-9_-]+|xox[baprs]-[A-Za-z0-9-]+)\b|\b(customer|cliente)\s+(payload|record|email|phone)\b|\b(customer|cliente)\s+(data|dados)\s+(payload|record|email|phone)\b|\b(customer|cliente)\s+(data|dados)\s*[:=]|\braw\s+payload\b/i;function ke(e){const t=e.toLowerCase();return/\b(project memory|canonical memory|memory heuristic|neocortex\.md|\*update-memory)\b/.test(t)?"decision":/\b(feature|capability|funcionalidade|release)\b/.test(t)?"feature":/\b(rule|policy|guardrail|regra|lei|must|never)\b/.test(t)?"rule":/\b(flag|feature[- ]?flag|toggle|env var|environment variable)\b/.test(t)?"flag":/\b(api|contract|schema contract|graphql|rest|rpc|webhook)\b/.test(t)?"api":/\b(db|database|schema|migration|table|column|prisma|sql)\b/.test(t)?"db-schema":/\b(decision|decisão|decisao|accepted|rejected|trade[- ]?off)\b/.test(t)?"decision":/\b(route|endpoint route|url path|pathname)\b|\/(api|admin|portal|v\d+)\//.test(t)?"route":/\b(architecture|arquitetura|adr|topology|infra|boundary)\b/.test(t)?"architecture":/\b(debt|follow[- ]?up|todo|tech[- ]?debt|dívida|divida)\b/.test(t)?"debt":"generic"}function we(e){const t=e.toLowerCase();return/\b(neocortex\.md|project memory|canonical memory|memory wrapper|symlink|owned block|memory heuristic)\b/.test(t)?"platform-memory":/\b(command|cli|\*update-memory|\*create-epic|\*arch-plan|workflow behavior)\b/.test(t)?"command-behavior":/\b(skill|agent|subagent|orchestrator|opencode|codex|claude|gemini|cursor)\b/.test(t)?"skills-agents":/\b(frontend|ui|ux|react|component|design[- ]?system|css|accessibility|a11y)\b/.test(t)?"frontend":/\b(backend|server|service|worker|job|queue)\b/.test(t)?"backend":/\b(api|endpoint|rest|graphql|rpc|webhook|contract)\b/.test(t)?"api":/\b(db|database|table|column|migration|sql|prisma)\b/.test(t)?"db":/\b(schema|schemas|zod|json schema|protobuf|openapi)\b/.test(t)?"schemas":/\b(env|environment|\.env\.example|config|configuration|feature[- ]?flag)\b/.test(t)?"envs":/\b(devops|deploy|deployment|ci|cd|docker|container|kubernetes|infra|terraform|rollback)\b/.test(t)?"devops":/\b(security|cyber|auth|authorization|permission|compliance|vulnerability|secret|token redaction)\b/.test(t)?"cyber-security":/\b(test|testing|qa|e2e|unit|integration|snapshot|property[- ]?based|flaky)\b/.test(t)?"testing-qa":/\b(observability|metric|metrics|log|logging|trace|tracing|alert|monitoring|slo)\b/.test(t)?"observability":/\b(product|business|user journey|onboarding|pricing|tenant|customer-facing)\b/.test(t)?"product-business":/\b(docs|documentation|architecture|arquitetura|adr|runbook|decision record)\b/.test(t)?"docs-architecture":"generic"}function K(e){const t=e.trim().replace(/\s+/g," ");if(Buffer.byteLength(t,"utf8")<=he)return t;const r=t.match(/(?:^|\s)([\w.-]+(?:\/[\w.@-]+)+(?:\.[A-Za-z0-9]+)?)/)?.[1],n=t.slice(0,220).replace(/\s+\S*$/,"").trim();return r?`${n}\u2026 See ${r} for details.`:`${n}\u2026 Details omitted from always-loaded memory; keep source content in repository docs.`}function Ee(e){f(e);const t=ke(e),r=we(e);return{kind:t,layer:r,sectionTitle:X[t],summary:K(e),reasonCode:`memory_update_${t.replace("-","_")}`}}function H(e){const t=new Set,r=[];for(const n of e){const o=Ee(n),i=`${o.kind}:${o.summary.toLowerCase()}`;t.has(i)||(t.add(i),r.push(o))}return r}function f(e){if(ge.test(e))throw new Error("Project memory input violates IP boundary guardrails.")}function Y(e,t){const r=(e??"").split(`
|
|
7
|
+
`),n=t.split(`
|
|
8
|
+
`),o=[],i=Math.max(r.length,n.length);for(let d=0;d<i;d++){const a=r[d],u=n[d];if(a!==u&&(a!==void 0&&o.push(`- ${a}`),u!==void 0&&o.push(`+ ${u}`),o.length>=80)){o.push("\u2026 diff truncated; inspect repository diff for full context.");break}}const s=o.join(`
|
|
9
|
+
`);return f(s),s}function L(e){f(e.path),f(e.title),f(e.purpose),f(e.suggestedUsage)}function Ce(e,t,r){e.forEach(f),t.forEach(L),r?.universalLaws?.forEach(f),r?.businessContext?.forEach(f),r?.activeContext?.forEach(f),r?.repositoryMap?.forEach(f),r?.environmentPractices?.forEach(f),r?.platformMemoryContract?.forEach(f),r?.maintenanceRules?.forEach(f),r?.heuristics?.forEach(f),r?.importantReferences?.forEach(L),r?.architectureReferences?.forEach(L)}function J(e){return[pe(e),"","This file contains compact, always-loaded project memory. Keep detailed architecture in referenced docs.",""].join(`
|
|
10
|
+
`)}function Z(e,t,r,n){Ce(t,r,n);const o=g([...ye,...n?.universalLaws??[]]),i=g([...n?.activeContext??[],...t.map(K)]),s=H(t),d=g(n?.businessContext??["Product/business context was not explicitly documented during bootstrap; treat conclusions as repository-inferred until a human updates this section."]),a=g(n?.repositoryMap??["Source, tests, package/build files, docs, CI, and runtime manifests are the permitted bootstrap sources for repository orientation."]),u=g(n?.environmentPractices??["Use `.env.example` for configuration shape only; do not read real environment files or credential-bearing files into always-loaded memory."]),c=g(n?.platformMemoryContract??["Semantic platform memory file must resolve to NEOCORTEX.md through a symlink; do not replace it with an unrelated wrapper or copied frontmatter.","Platform wrapper/frontmatter must be preserved via split/include/managed block while the semantic memory payload remains symlink-backed by NEOCORTEX.md."]),l=g(n?.maintenanceRules??["Keep NEOCORTEX.md deterministic, compact, objective, and direct; store only summaries, indexes, and links to detailed docs.","Do not copy protected prompt bodies, proprietary wrappers, server-side internals, customer data, license keys, or long document bodies into always-loaded memory."]),h=fe([...n?.importantReferences??[],...n?.architectureReferences??[],...r]),R=g([...be,...n?.heuristics??[]]),w=o.map(m=>`- ${m}`),S=i.length>0?i.map(m=>`- ${m}`):["- No active project notes recorded."],ie=h.length>0?le(h):"No architecture references discovered.",ae=s.length>0?Object.entries(X).flatMap(([m,ce])=>{const U=s.filter(E=>E.kind===m);return U.length>0?[`### ${ce}`,...U.map(E=>`- [${E.reasonCode}] ${E.summary} (layer: ${E.layer})`)]:[]}):["- No durable change feedback recorded."];return[O(e),"## Universal Project Laws",...w,"","## Business/Product Context",...d.map(m=>`- ${m}`),"","## Active Context",...S,"","## Durable Change Feedback",...ae,"","## Architecture References",ie,"","## Repository Map",...a.map(m=>`- ${m}`),"","## Environment/Container/Production/Security/Dev Practices",...u.map(m=>`- ${m}`),"","## Platform Memory Contract",...c.map(m=>`- ${m}`),`- NEOCORTEX.md is the canonical project memory source for every platform target; run \`${e.bidirectionalReference.feedbackTrigger}\` when durable context discovered in a platform wrapper should be fed back into canonical memory.`,"","## Maintenance Rules",...l.map(m=>`- ${m}`),"","## Architecture Heuristics",...R.map(m=>`- ${m}`),_(e)].join(`
|
|
11
|
+
`)}const Q=["docs/architecture","docs/arquitetura-software"],Pe=["README.md","readme.md","architecture.md","docs/architecture.md"],Re=["package.json","pnpm-lock.yaml","package-lock.json","yarn.lock","tsconfig.json","vite.config.ts","turbo.json"],Se=["Dockerfile","docker-compose.yml","compose.yml",".env.example","fly.toml"],$e=["AGENTS.md","CLAUDE.md","GEMINI.md",".opencode/AGENTS.md",".cursor/rules/neocortex.mdc"];function V(e,t,r=24e3){const n=p(e,t);try{if(!y(n)||C(n).isDirectory())return;const o=k(n,"utf8");return o.length<=r?o:o.slice(0,r)}catch{return}}function D(e,t){$(x(e),{recursive:!0});const r=`${e}.tmp-${process.pid}-${Date.now()}`,n=y(e)?`${e}.bak-${Date.now()}`:void 0;try{return j(r,t,"utf8"),n!==void 0&&v(e,n),z(r,e),n}catch(o){if(T(r,{force:!0}),n!==void 0&&y(n))try{v(n,e)}catch{}throw o}}function q(e){return Array.from(new Set(H(e).map(t=>t.reasonCode)))}function P(e,t){try{return y(p(e,t))}catch{return!1}}function ve(e,t){try{return W(p(e,t),{withFileTypes:!0}).filter(r=>!r.name.startsWith(".")&&!r.name.toLowerCase().includes("secret")).sort((r,n)=>r.name.localeCompare(n.name)).slice(0,8).map(r=>`${t}/${r.name}${r.isDirectory()?"/":""}`)}catch{return[]}}function ee(e,t,r=16){try{const n=W(p(e,t),{withFileTypes:!0}).filter(i=>!i.name.startsWith(".")&&!i.name.startsWith("_")).sort((i,s)=>i.name.localeCompare(s.name)),o=[];for(const i of n){const s=`${t}/${i.name}`;if(i.isDirectory()?o.push(...ee(e,s,r-o.length)):/\.(md|markdown)$/i.test(i.name)&&o.push(s),o.length>=r)break}return o}catch{return[]}}function Te(e,t){const r=t.match(/^#\s+(.+?)\s*$/m)?.[1]?.trim();return r?r.replace(/[`*_#]/g,""):e.split("/").pop()?.replace(/\.(md|markdown)$/i,"").replace(/[-_]+/g," ")??e}function xe(e,t){const r=/\b(stale|deprecated|outdated|incerto|uncertain)\b/i.test(`${e}
|
|
12
|
+
${t.slice(0,2e3)}`),n=t.replace(/^---[\s\S]*?---\s*/,"").split(/\n{2,}/).map(i=>i.replace(/^#+\s+.+$/gm,"").replace(/[`*_>#]/g,"").replace(/\s+/g," ").trim()).find(i=>i.length>0&&!i.startsWith("|"));return`${r?"[stale/uncertain evidence] ":""}${(n??"Architecture reference for this project.").slice(0,180)}`}function Oe(e){const t=e.toLowerCase();return/deploy|infra|docker|production|runbook/.test(t)?"Use before changing deployment, runtime, containers, or production operations.":/security|auth|compliance/.test(t)?"Use before changing auth, compliance, or security-sensitive behavior.":/api|contract|state|schema/.test(t)?"Use before changing contracts, APIs, schemas, or persisted state.":"Use before implementation in this area; verify freshness when marked stale or uncertain."}function te(e){const t=Re.filter(c=>P(e,c)),r=Se.filter(c=>P(e,c)),n=$e.filter(c=>P(e,c)),o=["packages","src","apps","tests","__tests__"].filter(c=>P(e,c)),s=[...Q.flatMap(c=>ee(e,c)),...Pe.filter(c=>P(e,c))].slice(0,24).flatMap(c=>{const l=V(e,c,48e3);return l?[{path:c,title:Te(c,l),purpose:xe(c,l),suggestedUsage:Oe(c),source:Q.some(h=>c.startsWith(`${h}/`))?"architecture-root":"fallback-file"}]:[]}),d=V(e,"package.json"),a=d?.match(/"name"\s*:\s*"([^"]+)"/)?.[1],u=[...d?.matchAll(/"(test|build|lint|typecheck|dev)"\s*:/g)??[]].map(c=>c[1]);return{universalLaws:["Bootstrap canonical memory before creating or repairing platform memory wrappers when NEOCORTEX.md is absent.","Use only permitted repository sources for bootstrap: package/build files, architecture docs, README/deploy docs, .env.example, runtime manifests, CI, source/test layout, and platform memory wrappers."],businessContext:[a?`Repository package name: ${a}.`:"Repository product name was not declared in package metadata.","Business/product conclusions are bootstrap-inferred and must be refined from canonical docs or human input."],activeContext:[`Bootstrap scanned ${t.length} package/build files, ${s.length} architecture/readme docs, ${r.length} runtime/config templates, and ${n.length} platform memory wrappers.`,u.length>0?`Detected quality scripts: ${u.sort().join(", ")}.`:"No standard quality scripts were detected in package metadata."],repositoryMap:[t.length>0?`Package/build files: ${t.join(", ")}.`:"No package/build files detected in permitted bootstrap set.",o.length>0?`Source/test roots: ${o.flatMap(c=>ve(e,c)).slice(0,16).join(", ")}.`:"Source/test roots were not detected in standard locations.",n.length>0?`Platform memory/wrappers: ${n.join(", ")}.`:"No platform memory wrappers detected before bootstrap."],environmentPractices:[r.length>0?`Runtime/config templates: ${r.join(", ")}.`:"No Docker/compose/.env.example/runtime manifest detected in permitted bootstrap set.","Read `.env.example` only for configuration shape; never ingest real .env files, credentials, customer data, or license keys into memory.","Run repository quality scripts before commit and keep CI/deploy evidence referenced by path or URL rather than copied verbatim."],platformMemoryContract:["Semantic platform memory file must resolve to NEOCORTEX.md through a symlink; do not replace it with an unrelated wrapper or copied frontmatter.","Preserve wrappers/frontmatter via split/include/managed block while the semantic memory payload remains symlink-backed by NEOCORTEX.md."],maintenanceRules:["Generated memory must be deterministic, objective, direct, compact, and inside the target always-loaded context budget.","Cite long architecture docs by path with usage guidance; mark stale or uncertain docs when repository evidence indicates that status.","Do not copy protected prompt bodies, proprietary wrappers, server internals, secrets, customer data, license keys, or complete long documents."],architectureReferences:s,heuristics:["Before processing a story, consult the cited Architecture References whose path or suggested usage intersects the change.","When a referenced doc is marked stale/uncertain, validate against current package/runtime/source evidence before relying on it."]}}function B(e,t,r){const n=O(t),o=_(t),i=e.indexOf(n),s=e.indexOf(o);if(i>=0&&s>=i){const a=s+o.length;return`${e.slice(0,i)}${r}${e.slice(a)}`}const d=e.endsWith(`
|
|
13
|
+
`)?`
|
|
14
|
+
`:`
|
|
15
|
+
|
|
16
|
+
`;return`${e}${d}${r}
|
|
17
|
+
`}function Me(e){return e.endsWith(".mdc")?`---
|
|
18
|
+
description: Neocortex project memory
|
|
19
|
+
alwaysApply: true
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
`:e.endsWith(".toml")?`[agent]
|
|
23
|
+
name = "neocortex"
|
|
24
|
+
description = "Neocortex project memory wrapper"
|
|
25
|
+
|
|
26
|
+
`:e.endsWith(".agent.md")?`---
|
|
27
|
+
name: neocortex
|
|
28
|
+
description: Neocortex project memory wrapper
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
`:""}function re(e,t){const r=x(p(e,t)),n=p(e,b),o=ue(r,n);return o.length>0?o:b}function M(e,t){return!!(e.targetId==="canonical"||e.requiresWrapperPreservation||e.linkRequirement.requiresWrapperPreservation||e.linkRequirement.wrapperAllowed||t==="AGENTS.md"||t.includes("/agents/")||t.includes("/skills/")||t.endsWith(".toml")||t.endsWith(".mdc")||t.endsWith(".agent.md")||t.endsWith(".instructions.md"))}function Ne(e){return e.linkRequirement.symlinkBacked&&e.linkRequirement.semanticFileRequired}function ne(e,t,r,n){if(n!==void 0)return n;const o=Ne(t);if(!o)return{os:A(),supported:!1,permission:"unknown",filesystem:"unknown",targetPolicy:t.linkRequirement.policy,targetPolicyAllowsSymlink:o,requiresWrapperPreservation:M(t,r),reason:`target policy ${t.linkRequirement.policy} does not allow semantic symlink orchestration`};const i=p(e,".neocortex","tmp"),s=p(i,`symlink-capability-source-${process.pid}-${Date.now()}`),d=p(i,`symlink-capability-link-${process.pid}-${Date.now()}`);try{$(i,{recursive:!0}),j(s,"probe","utf8"),N(s,d);const a=C(d).isSymbolicLink()&&de(d).isFile();return{os:A(),supported:a,permission:a?"ok":"unknown",filesystem:a?"supports-symlink":"no-symlink-support",targetPolicy:t.linkRequirement.policy,targetPolicyAllowsSymlink:o,requiresWrapperPreservation:M(t,r),reason:a?void 0:"filesystem probe did not create a resolvable symbolic link"}}catch(a){const u=a instanceof Error?a.message:String(a),c=/EPERM|EACCES|operation not permitted|permission/i.test(u);return{os:A(),supported:!1,permission:c?"denied":"unknown",filesystem:"no-symlink-support",targetPolicy:t.linkRequirement.policy,targetPolicyAllowsSymlink:o,requiresWrapperPreservation:M(t,r),reason:u}}finally{T(d,{force:!0}),T(s,{force:!0})}}function je(e,t,r,n){const o=re(n,t),i=r??`${Me(t)}# ${e.platformName} Neocortex Memory Wrapper
|
|
32
|
+
|
|
33
|
+
`,s=[O(e),"## Canonical Project Memory Source","",`This platform wrapper preserves host-specific frontmatter/instructions while resolving project memory to \`${o}\`.`,"",`- Canonical source: \`${b}\``,`- Symlink-backed/source-of-truth file: \`${o}\``,`- Feedback loop: read \`${o}\` for shared context and run \`${e.bidirectionalReference.feedbackTrigger}\` when durable platform findings should update \`${b}\`.`,"- Human-authored content outside this managed block is preserved byte-for-byte.",_(e)].join(`
|
|
34
|
+
`);return B(i,e,s)}function oe(e,t,r,n,o,i=!1){const s=p(e,t),a=`${["[NEOCORTEX COMPATIBILITY REMEDIATION]","Materialized project memory fallback because semantic symlink orchestration failed.","This is not product mode; repair host permissions/filesystem support and restore the symlink to NEOCORTEX.md.","WARNING: materialized fallback is remediation debt, not a silent mode; run *update-memory for durable context and repair this file back to canonical NEOCORTEX.md resolution.",`Fallback reason: ${o}`,""].join(`
|
|
35
|
+
`)}${r}`,c=(y(s)?k(s,"utf8"):void 0)!==a;return c&&!i&&(y(s)&&C(s).isSymbolicLink()&&G(s),D(s,a)),{filePath:s,relativeFile:t,changed:c,content:a,mode:"compatibility-materialized-fallback",canonicalSource:b,symlinkCapability:n,fallbackReason:o,remediationDebt:`Repair ${t} so it is a symlink to ${b}; fallback is compatibility remediation only.`}}function Ae(e,t,r,n,o,i=!1){const s=p(e,t),d=re(e,t);$(x(s),{recursive:!0});const a=ne(e,r,t,o);if(!a.supported)return oe(e,t,n,a,a.reason??"symlink capability detection reported unsupported host",i);if(i){let c=!0;try{c=!(y(s)&&C(s).isSymbolicLink()&&F(s)===d)}catch{c=!0}return{filePath:s,relativeFile:t,changed:c,content:n,mode:"semantic-symlink",canonicalSource:b,symlinkCapability:a}}let u=!1;try{return y(s)?C(s).isSymbolicLink()&&F(s)===d?u=!1:(G(s),N(d,s),u=!0):(N(d,s),u=!0),{filePath:s,relativeFile:t,changed:u,content:k(s,"utf8"),mode:"semantic-symlink",canonicalSource:b,symlinkCapability:a}}catch(c){const l=c instanceof Error?c.message:String(c);return oe(e,t,n,{...a,supported:!1,permission:/EPERM|EACCES|operation not permitted|permission/i.test(l)?"denied":a.permission,filesystem:"no-symlink-support",reason:l},l,i)}}function Ie(e,t,r,n,o){const i=a=>a.split(`
|
|
36
|
+
`).length<=e.budget.maxLines&&Buffer.byteLength(a,"utf8")<=e.budget.maxBytes;if(i(t))return t;const s=Z(e,r.slice(0,8),n.slice(0,12),o),d=B(t.includes(O(e))?t:J(e),e,s);return i(d)?d:d.slice(0,e.budget.maxBytes)}function se(e,t,r=[],n=[],o){const i=t??J(e),s=Z(e,r,n,o),d=B(i,e,s);return Ie(e,d,r,n,o)}function _e(e){const t=I(e.targetId),r=e.fs??me(),n=r.join(e.projectRoot,t.primaryFile);if(t.targetId!=="canonical"&&e.fs===void 0){const a=Le(e).files.find(u=>u.relativeFile===t.primaryFile);if(a===void 0)throw new Error(`Primary project memory file was not written for ${t.targetId}.`);return{filePath:a.filePath,changed:a.changed,content:a.content}}const o=r.readFile(n),i=e.bootstrapArchitecture??(e.fs===void 0&&t.targetId==="canonical"&&o===void 0?te(e.projectRoot):void 0),s=se(t,o,e.memoryNotes,e.architectureReferences,i);if(o===s)return{filePath:n,changed:!1,content:s};const d=e.dryRun?void 0:r.writeFileAtomic(n,s);return{filePath:n,changed:!0,content:s,safeDiff:Y(o,s),backupPath:d?.backupPath,reasonCodes:q(e.memoryNotes??[])}}function Fe(e){return _e({...e,targetId:"canonical"})}function Le(e){if(e.fs!==void 0)throw new Error("writeProjectMemoryTargetFiles requires the node filesystem to manage symlinks safely.");const t=I(e.targetId),r=I("canonical"),n=p(e.projectRoot,b),o=y(n)?k(n,"utf8"):void 0,i=e.bootstrapArchitecture??(o===void 0?te(e.projectRoot):void 0),s=se(r,o,e.memoryNotes,e.architectureReferences,i),d=!y(n)||k(n,"utf8")!==s;let a;if(d&&!e.dryRun&&(a=D(n,s)),t.targetId==="canonical")return{targetId:t.targetId,canonicalFilePath:n,changed:d,files:[{filePath:n,relativeFile:b,changed:d,content:s,mode:"canonical",canonicalSource:b,safeDiff:Y(o,s),backupPath:a,reasonCodes:q(e.memoryNotes??[])}]};const c=Array.from(new Set([t.primaryFile,...t.secondaryFiles])).map(l=>{if(!M(t,l))return Ae(e.projectRoot,l,t,s,e.symlinkCapability,e.dryRun);const h=p(e.projectRoot,l),R=y(h)?k(h,"utf8"):void 0,w=je(t,l,R,e.projectRoot),S=R!==w;return S&&!e.dryRun&&D(h,w),{filePath:h,relativeFile:l,changed:S,content:w,mode:"managed-wrapper",canonicalSource:b,symlinkCapability:ne(e.projectRoot,t,l,e.symlinkCapability),reasonCodes:q(e.memoryNotes??[])}});return{targetId:t.targetId,canonicalFilePath:n,files:c,changed:d||c.some(l=>l.changed)}}export{We as PROJECT_MEMORY_LAYER_CATEGORIES,te as bootstrapArchitectureMemory,se as buildProjectMemoryContent,Ee as classifyProjectMemoryUpdate,me as createNodeProjectMemoryFs,Y as createSafeProjectMemoryDiff,Fe as writeCanonicalProjectMemory,_e as writeProjectMemory,Le as writeProjectMemoryTargetFiles};
|