@ornexus/neocortex 4.60.73 → 4.60.75
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/dist/release-source.json +1 -1
- package/dist/sbom.cdx.json +1216 -1210
- package/install.ps1 +1 -1
- package/install.sh +1 -1
- package/package.json +2 -2
- package/packages/client/dist/adapters/adapter-registry.js +1 -108
- package/packages/client/dist/adapters/antigravity-adapter.js +2 -77
- package/packages/client/dist/adapters/claude-code-adapter.js +3 -79
- package/packages/client/dist/adapters/codex-adapter.js +2 -80
- package/packages/client/dist/adapters/cursor-adapter.js +4 -115
- package/packages/client/dist/adapters/gemini-adapter.js +2 -71
- package/packages/client/dist/adapters/grok-adapter.js +2 -42
- package/packages/client/dist/adapters/index.js +1 -22
- package/packages/client/dist/adapters/platform-detector.js +1 -212
- package/packages/client/dist/adapters/target-adapter.js +0 -12
- package/packages/client/dist/adapters/vscode-adapter.js +2 -72
- package/packages/client/dist/agent/refresh-stubs.js +2 -417
- package/packages/client/dist/agent/update-agent-yaml.js +1 -102
- package/packages/client/dist/agent/update-description.js +1 -251
- package/packages/client/dist/cache/crypto-utils.js +1 -78
- package/packages/client/dist/cache/encrypted-cache.d.ts +27 -0
- package/packages/client/dist/cache/encrypted-cache.js +1 -108
- package/packages/client/dist/cache/in-memory-asset-cache.js +1 -73
- package/packages/client/dist/cache/index.js +1 -13
- package/packages/client/dist/cache/protected-pi-boundary.js +1 -44
- package/packages/client/dist/checkpoint/checkpoint-client-reader.js +2 -127
- package/packages/client/dist/checkpoint/index.js +1 -11
- package/packages/client/dist/checkpoint/shared-checkpoint-types.js +1 -32
- package/packages/client/dist/cli.js +5 -358
- package/packages/client/dist/commands/activate.js +8 -394
- package/packages/client/dist/commands/architecture-answers.js +7 -274
- package/packages/client/dist/commands/architecture-memory-terminal.js +4 -253
- package/packages/client/dist/commands/architecture-non-ui-continuation.js +1 -100
- package/packages/client/dist/commands/architecture-root-binding.js +1 -51
- package/packages/client/dist/commands/cache-status.js +2 -112
- package/packages/client/dist/commands/config.js +1 -88
- package/packages/client/dist/commands/doctor.js +2 -635
- package/packages/client/dist/commands/invoke.d.ts +38 -1
- package/packages/client/dist/commands/invoke.js +143 -7200
- package/packages/client/dist/commands/legacy-epic-terminal.js +1 -71
- package/packages/client/dist/commands/legacy-story-branch.js +1 -96
- package/packages/client/dist/commands/legacy-story-pr.js +1 -276
- package/packages/client/dist/commands/mutation-qa-checkpoint.js +5 -285
- package/packages/client/dist/commands/mutation-qa-gate.js +1 -54
- package/packages/client/dist/commands/mutation-qa-git.js +1 -41
- package/packages/client/dist/commands/mutation-qa-policy.js +1 -102
- package/packages/client/dist/commands/mutation-qa-run.js +3 -219
- package/packages/client/dist/commands/mutation-qa-verdict.js +1 -149
- package/packages/client/dist/commands/mutation-qa.js +1 -220
- package/packages/client/dist/commands/native-agent.js +2 -136
- package/packages/client/dist/commands/planning-diagnosis.js +1 -43
- package/packages/client/dist/commands/planning-generation.js +1 -53
- package/packages/client/dist/commands/planning-memory.js +1 -40
- package/packages/client/dist/commands/planning-research.js +1 -42
- package/packages/client/dist/commands/private-session.js +1 -75
- package/packages/client/dist/commands/property-qa.js +1 -139
- package/packages/client/dist/commands/qa-control.js +1 -16
- package/packages/client/dist/commands/qa-scan-browser-launch.js +1 -55
- package/packages/client/dist/commands/qa-scan-browser-route.js +1 -28
- package/packages/client/dist/commands/qa-scan-capture.js +5 -663
- package/packages/client/dist/commands/qa-scan-discovery.js +3 -376
- package/packages/client/dist/commands/qa-scan-review.js +5 -826
- package/packages/client/dist/commands/qa-synthetic-backend-capture.js +1 -266
- package/packages/client/dist/commands/qa-synthetic-backend-review.js +1 -297
- package/packages/client/dist/commands/qa-synthetic-backend.js +2 -340
- package/packages/client/dist/commands/qa-synthetic-broker-port.js +1 -85
- package/packages/client/dist/commands/qa-synthetic-browser.js +1 -39
- package/packages/client/dist/commands/refactor-characterization.js +21 -671
- package/packages/client/dist/commands/refactor-commit.js +13 -399
- package/packages/client/dist/commands/refactor-control.js +3 -142
- package/packages/client/dist/commands/refactor-cpp-assertions.js +3 -93
- package/packages/client/dist/commands/refactor-review.js +5 -283
- package/packages/client/dist/commands/refactor-root.js +7 -588
- package/packages/client/dist/commands/refresh-memory.js +3 -156
- package/packages/client/dist/commands/shared-architecture-non-ui.js +1 -24
- package/packages/client/dist/commands/story-checkpoint.js +1 -171
- package/packages/client/dist/config/host-auth-broker.d.ts +31 -0
- package/packages/client/dist/config/host-auth-broker.js +1 -0
- package/packages/client/dist/config/host-auth-reference.d.ts +32 -0
- package/packages/client/dist/config/host-auth-reference.js +1 -0
- package/packages/client/dist/config/profile-directory.js +1 -13
- package/packages/client/dist/config/resolver-selection.js +1 -278
- package/packages/client/dist/config/secure-config.js +12 -281
- package/packages/client/dist/config.js +2 -223
- package/packages/client/dist/constants.js +1 -25
- package/packages/client/dist/context/context-collector.js +2 -222
- package/packages/client/dist/context/context-sanitizer.js +1 -145
- package/packages/client/dist/continuity/autonomous-governance.js +1 -285
- package/packages/client/dist/continuity/continuity-client-state-store.js +1 -1587
- package/packages/client/dist/continuity/invoke-hooks.js +1 -129
- package/packages/client/dist/continuity/migrations/001-initial-schema.js +2 -12
- package/packages/client/dist/continuity/migrations/002-processing-output-summary-indexes.js +2 -12
- package/packages/client/dist/continuity/migrations/003-headless-execution-attempts.js +2 -12
- package/packages/client/dist/continuity/migrations/004-outbox-delivery-state.js +2 -12
- package/packages/client/dist/continuity/migrations/005-bounded-headless-queue.js +2 -12
- package/packages/client/dist/continuity/migrations/006-native-agent-dispatches.js +2 -10
- package/packages/client/dist/continuity/native-agent-store.js +1 -69
- package/packages/client/dist/continuity/native-agent-types.d.ts +11 -0
- package/packages/client/dist/continuity/native-agent-types.js +1 -90
- package/packages/client/dist/continuity/outbox.js +1 -117
- package/packages/client/dist/continuity/runner-bootstrap-policy.js +1 -172
- package/packages/client/dist/continuity/sqlite-store.js +81 -2612
- package/packages/client/dist/effects/invoke-effect-gateways.js +1 -62
- package/packages/client/dist/errors/error-messages.d.ts +3 -0
- package/packages/client/dist/errors/error-messages.js +2 -228
- package/packages/client/dist/errors/frontmatter-diagnostics.js +1 -125
- package/packages/client/dist/evidence/collector.js +1 -347
- package/packages/client/dist/evidence/index.js +1 -1
- package/packages/client/dist/evidence/types.js +0 -2
- package/packages/client/dist/fs/atomic-state-replace.js +1 -152
- package/packages/client/dist/generated/command-registry.generated.js +1 -4076
- package/packages/client/dist/generated/public-projections.generated.js +1 -149
- package/packages/client/dist/git/direct-yolo-c01-retry.js +4 -138
- package/packages/client/dist/git/direct-yolo-checkpoint.d.ts +11 -1
- package/packages/client/dist/git/direct-yolo-checkpoint.js +4 -1234
- package/packages/client/dist/git/epic-operational-state.js +2 -672
- package/packages/client/dist/git/git-lifecycle-step-ids.js +1 -14
- package/packages/client/dist/git/git-lifecycle-store.d.ts +23 -0
- package/packages/client/dist/git/git-lifecycle-store.js +10 -1981
- package/packages/client/dist/git/legacy-story-branch-checkpoint.js +9 -259
- package/packages/client/dist/git/legacy-story-branch-setup.js +4 -348
- package/packages/client/dist/git/legacy-story-pr.js +70 -3538
- package/packages/client/dist/git/secure-filesystem-boundary.js +5 -182
- package/packages/client/dist/graph-retrieval/pre-command-hook.js +1 -284
- package/packages/client/dist/graph-retrieval/shared-graph-retrieval-contract.js +1 -237
- package/packages/client/dist/i18n/first-run.js +2 -60
- package/packages/client/dist/index.d.ts +2 -0
- package/packages/client/dist/index.js +1 -47
- package/packages/client/dist/invocation/invoke-input.js +1 -24
- package/packages/client/dist/license/host-auth-recovery.d.ts +158 -0
- package/packages/client/dist/license/host-auth-recovery.js +1 -0
- package/packages/client/dist/license/index.js +1 -5
- package/packages/client/dist/license/license-client.d.ts +10 -1
- package/packages/client/dist/license/license-client.js +1 -304
- package/packages/client/dist/machine/fingerprint.js +2 -163
- package/packages/client/dist/machine/index.js +1 -5
- package/packages/client/dist/memory/project-memory-path-scope.js +1 -62
- package/packages/client/dist/memory/project-memory-writer.js +40 -1007
- package/packages/client/dist/memory/shared-project-memory-types.js +2 -253
- package/packages/client/dist/migrations/epic-lifecycle-backfill.js +3 -1060
- package/packages/client/dist/migrations/project-identity-capability.js +1 -50
- package/packages/client/dist/migrations/project-identity.js +7 -493
- package/packages/client/dist/migrations/state-json.js +4 -393
- package/packages/client/dist/policy/architecture-policy.js +2 -184
- package/packages/client/dist/policy/index.js +1 -7
- package/packages/client/dist/policy/shared-policy-types.js +0 -38
- package/packages/client/dist/policy/subagent-approval-policy.js +1 -55
- package/packages/client/dist/private-execution/clean-baseline.js +2 -279
- package/packages/client/dist/private-execution/codex-executor.js +4 -574
- package/packages/client/dist/private-execution/codex-host-runtime.js +1 -137
- package/packages/client/dist/private-execution/codex-lifecycle-guard.js +1 -97
- package/packages/client/dist/private-execution/codex-scoped-permissions.js +1 -128
- package/packages/client/dist/private-execution/delivery.js +13 -410
- package/packages/client/dist/private-execution/diagnosis-root-review.js +2 -294
- package/packages/client/dist/private-execution/frozen-handoff.js +6 -19
- package/packages/client/dist/private-execution/implementation-validation.js +2 -106
- package/packages/client/dist/private-execution/isolated-admission.js +23 -1432
- package/packages/client/dist/private-execution/isolated-session.js +5 -725
- package/packages/client/dist/private-execution/isolated-workspace.js +1 -122
- package/packages/client/dist/private-execution/pact-consumer-runtime.js +3 -409
- package/packages/client/dist/private-execution/pact-test-source.js +1 -258
- package/packages/client/dist/private-execution/pact-toolchain.js +3 -290
- package/packages/client/dist/private-execution/pact-write-set.js +1 -172
- package/packages/client/dist/private-execution/planning-diagnosis-checkpoint.js +5 -406
- package/packages/client/dist/private-execution/planning-generation-checkpoint.js +5 -462
- package/packages/client/dist/private-execution/planning-memory-checkpoint.js +3 -139
- package/packages/client/dist/private-execution/planning-research-checkpoint.js +4 -325
- package/packages/client/dist/private-execution/private-report-store.js +1 -42
- package/packages/client/dist/private-execution/property-test-candidate.js +1 -103
- package/packages/client/dist/private-execution/property-test-choices.js +3 -147
- package/packages/client/dist/private-execution/property-test-plan.js +7 -271
- package/packages/client/dist/private-execution/property-test-review.js +4 -258
- package/packages/client/dist/private-execution/property-test-runtime.js +9 -372
- package/packages/client/dist/private-execution/property-test-source.js +1 -139
- package/packages/client/dist/private-execution/root-checkpoint.js +1 -80
- package/packages/client/dist/private-execution/root-memory-git-evidence.js +3 -135
- package/packages/client/dist/private-execution/root-memory-recovery.js +1 -93
- package/packages/client/dist/private-execution/root-memory-request.js +1 -29
- package/packages/client/dist/private-execution/root-memory-scope.js +1 -178
- package/packages/client/dist/private-execution/root-memory-writer.js +1 -102
- package/packages/client/dist/private-execution/session-lease.js +1 -63
- package/packages/client/dist/private-execution/shared-private-admission-types.js +1 -50
- package/packages/client/dist/private-execution/shared-project-validation.js +1 -66
- package/packages/client/dist/private-execution/shared-root-memory-types.js +1 -61
- package/packages/client/dist/private-execution/ux-source-validation.js +1 -372
- package/packages/client/dist/private-execution/ux-write-set.js +2 -191
- package/packages/client/dist/registry/registry-reconciliation.js +1 -234
- package/packages/client/dist/resilience/circuit-breaker.js +1 -170
- package/packages/client/dist/resilience/degradation-manager.js +1 -164
- package/packages/client/dist/resilience/freshness-indicator.js +1 -100
- package/packages/client/dist/resilience/index.js +1 -8
- package/packages/client/dist/resilience/recovery-detector.js +1 -74
- package/packages/client/dist/resolvers/asset-resolver.js +0 -13
- package/packages/client/dist/resolvers/local-resolver.js +8 -255
- package/packages/client/dist/resolvers/remote-resolver.js +1 -233
- package/packages/client/dist/runner/binary.js +1 -404
- package/packages/client/dist/runner/cli.js +17 -1571
- package/packages/client/dist/runner/epic-background-dispatcher.d.ts +61 -0
- package/packages/client/dist/runner/epic-background-dispatcher.js +1 -0
- package/packages/client/dist/runner/headless/adapters.js +1 -49
- package/packages/client/dist/runner/headless/background-root.d.ts +65 -0
- package/packages/client/dist/runner/headless/background-root.js +1 -0
- package/packages/client/dist/runner/headless/claude-code-adapter.js +1 -79
- package/packages/client/dist/runner/headless/continuous-story-workspace.js +11 -1628
- package/packages/client/dist/runner/headless/epic-git-reconciliation-inventory.js +1 -69
- package/packages/client/dist/runner/headless/epic-merge-candidate-qa.d.ts +1 -1
- package/packages/client/dist/runner/headless/epic-merge-candidate-qa.js +2 -110
- package/packages/client/dist/runner/headless/epic-terminal-git-cli-adapter.d.ts +2 -0
- package/packages/client/dist/runner/headless/epic-terminal-git-cli-adapter.js +10 -1236
- package/packages/client/dist/runner/headless/epic-terminal-git-runner.d.ts +27 -2
- package/packages/client/dist/runner/headless/epic-terminal-git-runner.js +2 -318
- package/packages/client/dist/runner/headless/fake-adapter.js +1 -62
- package/packages/client/dist/runner/headless/managed-environment-cleanup.d.ts +95 -0
- package/packages/client/dist/runner/headless/managed-environment-cleanup.js +1 -0
- package/packages/client/dist/runner/headless/managed-profile.js +1 -132
- package/packages/client/dist/runner/headless/opencode-adapter.js +2 -145
- package/packages/client/dist/runner/headless/prepared-story-bundle.js +1 -43
- package/packages/client/dist/runner/headless/resolver.js +1 -231
- package/packages/client/dist/runner/headless/run-yolo.js +1 -885
- package/packages/client/dist/runner/headless/run-yoloop.d.ts +1 -0
- package/packages/client/dist/runner/headless/run-yoloop.js +2 -2574
- package/packages/client/dist/runner/headless/types.js +2 -574
- package/packages/client/dist/runner/local-console.js +13 -396
- package/packages/client/dist/runner/portal-sync-worker.js +1 -1487
- package/packages/client/dist/runner/project-identity.js +1 -106
- package/packages/client/dist/runner/scheduler.js +7 -995
- package/packages/client/dist/runner-cli.js +2 -18
- package/packages/client/dist/state/invocation-shape.js +1 -13
- package/packages/client/dist/state/project-state-snapshot.d.ts +7 -0
- package/packages/client/dist/state/project-state-snapshot.js +1 -1731
- package/packages/client/dist/state/state-json-repair.js +3 -785
- package/packages/client/dist/state/structural-dag-projection.js +1 -118
- package/packages/client/dist/telemetry/index.js +1 -5
- package/packages/client/dist/telemetry/offline-queue.js +1 -131
- package/packages/client/dist/tier/index.js +1 -5
- package/packages/client/dist/tier/tier-aware-client.js +1 -405
- package/packages/client/dist/types/index.js +1 -38
- package/packages/client/dist/version.js +1 -27
- package/packages/client/dist/yolo/change-evidence-collector.d.ts +21 -1
- package/packages/client/dist/yolo/change-evidence-collector.js +1 -126
- package/packages/client/dist/yolo/invoke-envelope-capability.js +1 -62
- package/packages/client/dist/yolo/spec-envelope-collector.js +5 -184
- package/packages/client/dist/yoloop/discovery-hook.js +2 -300
- package/packages/client/dist/yoloop/index.js +1 -8
- package/packages/client/dist/yoloop/invoke-hooks.js +12 -669
- package/packages/client/dist/yoloop/shared-discover-epics.js +1 -1007
- package/packages/client/dist/yoloop/shared-yoloop-types.js +1 -33
- package/packages/client/dist/yoloop/target-normalization.js +1 -180
- package/packages/client/dist/yoloop/yoloop-client-state-store.js +1 -1920
- package/packages/shared/dist/invocation/explicit-intent-recovery.d.ts +83 -0
- package/packages/shared/dist/invocation/explicit-intent-recovery.js +187 -0
- package/packages/shared/dist/invocation/index.d.ts +7 -0
- package/packages/shared/dist/invocation/index.js +22 -0
- package/packages/shared/dist/yolo/change-evidence.js +1 -1
- package/packages/shared/dist/yoloop/epic-terminal-git.js +144 -2
- package/targets-stubs/antigravity/gemini.md +1 -1
- package/targets-stubs/antigravity/skill/SKILL.md +1 -1
- package/targets-stubs/claude-code/neocortex-root.agent.yaml +1 -1
- package/targets-stubs/claude-code/neocortex-root.md +2 -2
- package/targets-stubs/claude-code/neocortex.agent.yaml +1 -1
- package/targets-stubs/claude-code/neocortex.md +2 -2
- package/targets-stubs/codex/AGENTS.md +24 -21
- package/targets-stubs/codex/README.md +6 -1
- package/targets-stubs/codex/neocortex.toml +7 -2
- package/targets-stubs/cursor/agent.md +2 -2
- package/targets-stubs/gemini-cli/agent.md +2 -2
- package/targets-stubs/opencode/neocortex-root.md +16 -1
- package/targets-stubs/opencode/neocortex.md +6 -0
- package/targets-stubs/vscode/neocortex.agent.md +2 -2
|
@@ -1,300 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
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
|
-
* Epic P120.04 -- Client-side discovery hook (extends P101.07 pattern).
|
|
15
|
-
*
|
|
16
|
-
* Pre-request hook that, when `YOLOOP_AUTO_DISCOVERY=on` and trigger is
|
|
17
|
-
* `*yoloop` resolving to a directory, calls `discoverEpicsFromDir()` (P120.01)
|
|
18
|
-
* + `mergeDiscoveredIntoState()` (P120.02) on the client BEFORE sending the
|
|
19
|
-
* invoke request. Server (P120.05) sees the enriched state in
|
|
20
|
-
* `body.stateSnapshot.epics`, relaxing `EPIC_NOT_FOUND` for filesystem epics.
|
|
21
|
-
*
|
|
22
|
-
* Hook follows P101.07 pattern (lazy dynamic import for tree-shaking via
|
|
23
|
-
* the wrapper in `invoke-hooks.ts`, fail-soft try/catch, mutate stateSnapshot
|
|
24
|
-
* in place).
|
|
25
|
-
*
|
|
26
|
-
* Activation conditions (ALL must hold):
|
|
27
|
-
* 1. `featureFlag === true` -- operator opt-in via `YOLOOP_AUTO_DISCOVERY=on`
|
|
28
|
-
* 2. Args resolve to a yoloop trigger (regex per P101.07)
|
|
29
|
-
* 3. Args target via `@<path>` resolves to a directory
|
|
30
|
-
*
|
|
31
|
-
* Fail-open contract: ANY error in discovery / merge / fs-resolution is
|
|
32
|
-
* caught + logged (warn) + returns `{ applied: false, reason }`. The
|
|
33
|
-
* caller (invoke.ts wrapper) ALSO catches outermost. Hook NEVER blocks
|
|
34
|
-
* the invoke request. Worst case: state is unenriched + server falls back
|
|
35
|
-
* to existing canonical resolver (pre-P120 behavior).
|
|
36
|
-
*
|
|
37
|
-
* Pattern references:
|
|
38
|
-
* - P101.07 (yoloop pre-request hook) -- exact pattern reused
|
|
39
|
-
* - P120.01 (discoverEpicsFromDir) -- consumed via local SSoT-Shadow inline
|
|
40
|
-
* - P120.02 (mergeDiscoveredIntoState) -- consumed via local SSoT-Shadow inline
|
|
41
|
-
* - P120.03 (feature flag) -- gating variable
|
|
42
|
-
* - P107.02 (architecture-policy hook) -- secondary reference for
|
|
43
|
-
* fail-soft + dynamic import + state mutation
|
|
44
|
-
*
|
|
45
|
-
* Pre-request hook order (client-side, before invoke POST):
|
|
46
|
-
* 1. P121.05: maybeAutoResolveYoloopArgs (invoke-hooks.ts) -- rewrite empty args
|
|
47
|
-
* 2. P101.07: yoloop client state collection -- read ~/.neocortex/yoloop-state.json
|
|
48
|
-
* 3. P120.04: maybeRunDiscoveryHook (this hook) -- scan args dir for epics
|
|
49
|
-
* 4. P107.02: architecture-policy reader -- attach state.architecture_policy
|
|
50
|
-
* 5. POST /invoke
|
|
51
|
-
*
|
|
52
|
-
* P121.05 runs FIRST so that subsequent hooks (P101.07, this hook) see the
|
|
53
|
-
* rewritten args. The discovery hook itself sees `*yoloop @docs/epics/`
|
|
54
|
-
* after P121.05 fires and proceeds normally.
|
|
55
|
-
*/
|
|
56
|
-
import { existsSync, readFileSync, renameSync, statSync, writeFileSync, } from 'node:fs';
|
|
57
|
-
import { basename, dirname, resolve, isAbsolute } from 'node:path';
|
|
58
|
-
// P120.04: import from local SSoT-Shadow inline mirror (P117.01 pattern).
|
|
59
|
-
// See `./shared-discover-epics.ts` for sync rules and drift test enforcement
|
|
60
|
-
// in `client/__tests__/discover-shared-sync.test.ts`.
|
|
61
|
-
import { discoverEpicsFromDir, mergeDiscoveredIntoState, buildDefaultDiscoveryFs, } from './shared-discover-epics.js';
|
|
62
|
-
import { extractYoloopTargetPath, isYoloopInvocation, } from './target-normalization.js';
|
|
63
|
-
// =====================================================================
|
|
64
|
-
// Internal helpers
|
|
65
|
-
// =====================================================================
|
|
66
|
-
/**
|
|
67
|
-
* Resolve a `@<path>` token to an absolute path, given a project root.
|
|
68
|
-
* Pure function: zero I/O.
|
|
69
|
-
*/
|
|
70
|
-
function resolveAtPath(token, projectRoot) {
|
|
71
|
-
if (isAbsolute(token))
|
|
72
|
-
return token;
|
|
73
|
-
return resolve(projectRoot, token);
|
|
74
|
-
}
|
|
75
|
-
/**
|
|
76
|
-
* Keep on-disk `.neocortex/state.json` aligned with the enriched snapshot.
|
|
77
|
-
*
|
|
78
|
-
* The server receives `stateSnapshot`, so snapshot mutation is sufficient for
|
|
79
|
-
* the current invoke. Persisting discovered epics removes the next-iteration
|
|
80
|
-
* EPIC_NOT_FOUND failure and matches the operator expectation that filesystem
|
|
81
|
-
* epics are registered once discovered. This writer reads state.json fresh so
|
|
82
|
-
* transient request-only fields (for example `stateSnapshot.yoloop`) are not
|
|
83
|
-
* accidentally stored in the project state.
|
|
84
|
-
*/
|
|
85
|
-
function persistDiscoveredStateJson(projectRoot, discovered, logger) {
|
|
86
|
-
if (discovered.epics.length === 0)
|
|
87
|
-
return;
|
|
88
|
-
const statePath = resolve(projectRoot, '.neocortex', 'state.json');
|
|
89
|
-
if (!existsSync(statePath))
|
|
90
|
-
return;
|
|
91
|
-
try {
|
|
92
|
-
const raw = readFileSync(statePath, 'utf8');
|
|
93
|
-
const diskState = JSON.parse(raw);
|
|
94
|
-
const merge = mergeDiscoveredIntoState(diskState, discovered);
|
|
95
|
-
if (merge.added.length === 0 && merge.storiesAdded === 0)
|
|
96
|
-
return;
|
|
97
|
-
diskState.last_updated = new Date().toISOString();
|
|
98
|
-
const tmpPath = `${statePath}.tmp.${process.pid}.${Date.now()}`;
|
|
99
|
-
writeFileSync(tmpPath, `${JSON.stringify(diskState, null, 2)}\n`, 'utf8');
|
|
100
|
-
renameSync(tmpPath, statePath);
|
|
101
|
-
}
|
|
102
|
-
catch (err) {
|
|
103
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
104
|
-
logger?.warn?.(`[neocortex] discovery hook: failed to persist .neocortex/state.json: ${msg}. Proceeding with request snapshot only.`);
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
function filterDiscoveryToFile(result, absPath) {
|
|
108
|
-
const targetBase = basename(absPath);
|
|
109
|
-
const epics = result.epics.filter((epic) => {
|
|
110
|
-
return epic.path === absPath || epic.filename === targetBase;
|
|
111
|
-
});
|
|
112
|
-
const epicIds = new Set(epics.map((epic) => epic.id));
|
|
113
|
-
return {
|
|
114
|
-
epics: Object.freeze(epics),
|
|
115
|
-
warnings: Object.freeze([
|
|
116
|
-
...result.warnings,
|
|
117
|
-
...(epics.length === 0
|
|
118
|
-
? [`single-file discovery found no matching epic descriptor for ${targetBase}`]
|
|
119
|
-
: []),
|
|
120
|
-
]),
|
|
121
|
-
skipped: Object.freeze([
|
|
122
|
-
...result.skipped,
|
|
123
|
-
...result.epics
|
|
124
|
-
.filter((epic) => !epicIds.has(epic.id))
|
|
125
|
-
.map((epic) => `${epic.filename}: skipped (not requested file)`),
|
|
126
|
-
]),
|
|
127
|
-
};
|
|
128
|
-
}
|
|
129
|
-
// =====================================================================
|
|
130
|
-
// Public API
|
|
131
|
-
// =====================================================================
|
|
132
|
-
/**
|
|
133
|
-
* Run discovery + merge if hook conditions are met.
|
|
134
|
-
*
|
|
135
|
-
* Async because `buildDefaultDiscoveryFs()` lazy-imports `node:fs` /
|
|
136
|
-
* `node:path` (tree-shake friendly per P120.01 design). Returns
|
|
137
|
-
* synchronously-resolvable promise in the no-op cases (flag off, non-yoloop
|
|
138
|
-
* trigger, file not dir, missing dir) -- discovery work only happens on
|
|
139
|
-
* the happy path.
|
|
140
|
-
*
|
|
141
|
-
* **Never throws**. ANY error is caught, logged via `logger.warn`, and
|
|
142
|
-
* returned as `{ applied: false, reason }`. Caller continues normal
|
|
143
|
-
* invoke flow without enrichment.
|
|
144
|
-
*
|
|
145
|
-
* @param ctx hook context (args + projectRoot + stateSnapshot + flag + logger)
|
|
146
|
-
* @returns DiscoveryHookResult with telemetry counters
|
|
147
|
-
*/
|
|
148
|
-
export async function runDiscoveryHook(ctx) {
|
|
149
|
-
// -------------------------------------------------------------------
|
|
150
|
-
// Activation conditions (ordered cheap-to-expensive)
|
|
151
|
-
// -------------------------------------------------------------------
|
|
152
|
-
// 1. Feature flag check (zero I/O, fastest)
|
|
153
|
-
if (!ctx.featureFlag) {
|
|
154
|
-
return {
|
|
155
|
-
applied: false,
|
|
156
|
-
added: Object.freeze([]),
|
|
157
|
-
skipped: Object.freeze([]),
|
|
158
|
-
storiesAdded: 0,
|
|
159
|
-
reason: 'flag off',
|
|
160
|
-
};
|
|
161
|
-
}
|
|
162
|
-
// 2. Yoloop trigger detection (regex over args)
|
|
163
|
-
if (!isYoloopInvocation(ctx.args)) {
|
|
164
|
-
return {
|
|
165
|
-
applied: false,
|
|
166
|
-
added: Object.freeze([]),
|
|
167
|
-
skipped: Object.freeze([]),
|
|
168
|
-
storiesAdded: 0,
|
|
169
|
-
reason: 'not a yoloop trigger',
|
|
170
|
-
};
|
|
171
|
-
}
|
|
172
|
-
// 3. Extract target path arg
|
|
173
|
-
const pathToken = extractYoloopTargetPath(ctx.args, ctx.projectRoot);
|
|
174
|
-
if (!pathToken) {
|
|
175
|
-
return {
|
|
176
|
-
applied: false,
|
|
177
|
-
added: Object.freeze([]),
|
|
178
|
-
skipped: Object.freeze([]),
|
|
179
|
-
storiesAdded: 0,
|
|
180
|
-
reason: 'no path arg',
|
|
181
|
-
};
|
|
182
|
-
}
|
|
183
|
-
// 4. Resolve to absolute path
|
|
184
|
-
let absPath;
|
|
185
|
-
try {
|
|
186
|
-
absPath = resolveAtPath(pathToken, ctx.projectRoot);
|
|
187
|
-
}
|
|
188
|
-
catch (err) {
|
|
189
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
190
|
-
ctx.logger?.warn?.(`[neocortex] discovery hook: path resolution failed: ${msg}. Proceeding without enrichment.`);
|
|
191
|
-
return {
|
|
192
|
-
applied: false,
|
|
193
|
-
added: Object.freeze([]),
|
|
194
|
-
skipped: Object.freeze([]),
|
|
195
|
-
storiesAdded: 0,
|
|
196
|
-
reason: 'path resolution failed',
|
|
197
|
-
};
|
|
198
|
-
}
|
|
199
|
-
// 5. Verify path exists and determine scan mode.
|
|
200
|
-
let isDir = false;
|
|
201
|
-
let isFile = false;
|
|
202
|
-
try {
|
|
203
|
-
if (existsSync(absPath)) {
|
|
204
|
-
const stat = statSync(absPath);
|
|
205
|
-
isDir = stat.isDirectory();
|
|
206
|
-
isFile = stat.isFile();
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
catch {
|
|
210
|
-
// statSync error -> treat as missing (fail-open)
|
|
211
|
-
isDir = false;
|
|
212
|
-
isFile = false;
|
|
213
|
-
}
|
|
214
|
-
if (!isDir && !isFile) {
|
|
215
|
-
return {
|
|
216
|
-
applied: false,
|
|
217
|
-
added: Object.freeze([]),
|
|
218
|
-
skipped: Object.freeze([]),
|
|
219
|
-
storiesAdded: 0,
|
|
220
|
-
reason: 'path not found',
|
|
221
|
-
};
|
|
222
|
-
}
|
|
223
|
-
// -------------------------------------------------------------------
|
|
224
|
-
// Activation: run discovery + merge
|
|
225
|
-
// -------------------------------------------------------------------
|
|
226
|
-
try {
|
|
227
|
-
const fs = await buildDefaultDiscoveryFs();
|
|
228
|
-
const scanDir = isDir ? absPath : dirname(absPath);
|
|
229
|
-
const rawResult = discoverEpicsFromDir(scanDir, fs);
|
|
230
|
-
const result = isFile ? filterDiscoveryToFile(rawResult, absPath) : rawResult;
|
|
231
|
-
// Even if zero epics discovered, we still count this as "applied" for
|
|
232
|
-
// observability (caller knows hook ran). State stays untouched.
|
|
233
|
-
const merge = mergeDiscoveredIntoState(ctx.stateSnapshot, result);
|
|
234
|
-
persistDiscoveredStateJson(ctx.projectRoot, result, ctx.logger);
|
|
235
|
-
// Telemetry: emit info if anything was added
|
|
236
|
-
if (merge.added.length > 0 || merge.storiesAdded > 0) {
|
|
237
|
-
ctx.logger?.info?.(`[neocortex] discovered ${merge.added.length} epic(s), ${merge.storiesAdded} story-ies from ${isDir ? absPath : basename(absPath)}`);
|
|
238
|
-
}
|
|
239
|
-
// Surface non-fatal warnings (e.g., orphan stories, ID collisions)
|
|
240
|
-
for (const w of result.warnings) {
|
|
241
|
-
ctx.logger?.warn?.(`[neocortex] discovery: ${w}`);
|
|
242
|
-
}
|
|
243
|
-
return {
|
|
244
|
-
applied: true,
|
|
245
|
-
added: merge.added,
|
|
246
|
-
skipped: merge.skipped,
|
|
247
|
-
storiesAdded: merge.storiesAdded,
|
|
248
|
-
};
|
|
249
|
-
}
|
|
250
|
-
catch (err) {
|
|
251
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
252
|
-
ctx.logger?.warn?.(`[neocortex] discovery hook failed: ${msg}. Proceeding without enrichment.`);
|
|
253
|
-
return {
|
|
254
|
-
applied: false,
|
|
255
|
-
added: Object.freeze([]),
|
|
256
|
-
skipped: Object.freeze([]),
|
|
257
|
-
storiesAdded: 0,
|
|
258
|
-
reason: `error: ${msg}`,
|
|
259
|
-
};
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
/**
|
|
263
|
-
* Async wrapper with lazy-load semantics + outermost defensive try/catch.
|
|
264
|
-
*
|
|
265
|
-
* Designed to be invoked from `invoke-hooks.ts`. Performs the same
|
|
266
|
-
* `featureFlag` short-circuit as `runDiscoveryHook` to keep the async
|
|
267
|
-
* import truly tree-shakeable when the flag is off. Wraps the inner call
|
|
268
|
-
* in an additional try/catch as defense-in-depth (the hook itself is
|
|
269
|
-
* already fail-open, but module-load errors are caught here).
|
|
270
|
-
*/
|
|
271
|
-
export async function maybeRunDiscoveryHook(ctx) {
|
|
272
|
-
// Defense-in-depth: short-circuit BEFORE doing any work if flag is off.
|
|
273
|
-
// Note: in practice, callers (invoke-hooks.ts) also check the flag
|
|
274
|
-
// before importing this module to maximize tree-shaking. This is a
|
|
275
|
-
// belt-and-suspenders guard.
|
|
276
|
-
if (!ctx.featureFlag) {
|
|
277
|
-
return {
|
|
278
|
-
applied: false,
|
|
279
|
-
added: Object.freeze([]),
|
|
280
|
-
skipped: Object.freeze([]),
|
|
281
|
-
storiesAdded: 0,
|
|
282
|
-
reason: 'flag off',
|
|
283
|
-
};
|
|
284
|
-
}
|
|
285
|
-
try {
|
|
286
|
-
return await runDiscoveryHook(ctx);
|
|
287
|
-
}
|
|
288
|
-
catch (err) {
|
|
289
|
-
// runDiscoveryHook is itself fail-open; this is defense-in-depth.
|
|
290
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
291
|
-
ctx.logger?.warn?.(`[neocortex] discovery hook (outer) failed: ${msg}. Proceeding without enrichment.`);
|
|
292
|
-
return {
|
|
293
|
-
applied: false,
|
|
294
|
-
added: Object.freeze([]),
|
|
295
|
-
skipped: Object.freeze([]),
|
|
296
|
-
storiesAdded: 0,
|
|
297
|
-
reason: `outer error: ${msg}`,
|
|
298
|
-
};
|
|
299
|
-
}
|
|
300
|
-
}
|
|
1
|
+
import{existsSync as f,readFileSync as h,renameSync as m,statSync as y,writeFileSync as j}from"node:fs";import{basename as p,dirname as b,resolve as l,isAbsolute as O}from"node:path";import{discoverEpicsFromDir as w,mergeDiscoveredIntoState as g,buildDefaultDiscoveryFs as k}from"./shared-discover-epics.js";import{extractYoloopTargetPath as z,isYoloopInvocation as S}from"./target-normalization.js";function v(e,o){return O(e)?e:l(o,e)}function $(e,o,t){if(o.epics.length===0)return;const s=l(e,".neocortex","state.json");if(f(s))try{const i=h(s,"utf8"),r=JSON.parse(i),n=g(r,o);if(n.added.length===0&&n.storiesAdded===0)return;r.last_updated=new Date().toISOString();const a=`${s}.tmp.${process.pid}.${Date.now()}`;j(a,`${JSON.stringify(r,null,2)}
|
|
2
|
+
`,"utf8"),m(a,s)}catch(i){const r=i instanceof Error?i.message:String(i);t?.warn?.(`[neocortex] discovery hook: failed to persist .neocortex/state.json: ${r}. Proceeding with request snapshot only.`)}}function A(e,o){const t=p(o),s=e.epics.filter(r=>r.path===o||r.filename===t),i=new Set(s.map(r=>r.id));return{epics:Object.freeze(s),warnings:Object.freeze([...e.warnings,...s.length===0?[`single-file discovery found no matching epic descriptor for ${t}`]:[]]),skipped:Object.freeze([...e.skipped,...e.epics.filter(r=>!i.has(r.id)).map(r=>`${r.filename}: skipped (not requested file)`)])}}async function D(e){if(!e.featureFlag)return{applied:!1,added:Object.freeze([]),skipped:Object.freeze([]),storiesAdded:0,reason:"flag off"};if(!S(e.args))return{applied:!1,added:Object.freeze([]),skipped:Object.freeze([]),storiesAdded:0,reason:"not a yoloop trigger"};const o=z(e.args,e.projectRoot);if(!o)return{applied:!1,added:Object.freeze([]),skipped:Object.freeze([]),storiesAdded:0,reason:"no path arg"};let t;try{t=v(o,e.projectRoot)}catch(r){const n=r instanceof Error?r.message:String(r);return e.logger?.warn?.(`[neocortex] discovery hook: path resolution failed: ${n}. Proceeding without enrichment.`),{applied:!1,added:Object.freeze([]),skipped:Object.freeze([]),storiesAdded:0,reason:"path resolution failed"}}let s=!1,i=!1;try{if(f(t)){const r=y(t);s=r.isDirectory(),i=r.isFile()}}catch{s=!1,i=!1}if(!s&&!i)return{applied:!1,added:Object.freeze([]),skipped:Object.freeze([]),storiesAdded:0,reason:"path not found"};try{const r=await k(),n=s?t:b(t),a=w(n,r),c=i?A(a,t):a,d=g(e.stateSnapshot,c);$(e.projectRoot,c,e.logger),(d.added.length>0||d.storiesAdded>0)&&e.logger?.info?.(`[neocortex] discovered ${d.added.length} epic(s), ${d.storiesAdded} story-ies from ${s?t:p(t)}`);for(const u of c.warnings)e.logger?.warn?.(`[neocortex] discovery: ${u}`);return{applied:!0,added:d.added,skipped:d.skipped,storiesAdded:d.storiesAdded}}catch(r){const n=r instanceof Error?r.message:String(r);return e.logger?.warn?.(`[neocortex] discovery hook failed: ${n}. Proceeding without enrichment.`),{applied:!1,added:Object.freeze([]),skipped:Object.freeze([]),storiesAdded:0,reason:`error: ${n}`}}}async function I(e){if(!e.featureFlag)return{applied:!1,added:Object.freeze([]),skipped:Object.freeze([]),storiesAdded:0,reason:"flag off"};try{return await D(e)}catch(o){const t=o instanceof Error?o.message:String(o);return e.logger?.warn?.(`[neocortex] discovery hook (outer) failed: ${t}. Proceeding without enrichment.`),{applied:!1,added:Object.freeze([]),skipped:Object.freeze([]),storiesAdded:0,reason:`outer error: ${t}`}}}export{I as maybeRunDiscoveryHook,D as runDiscoveryHook};
|
|
@@ -1,8 +1 @@
|
|
|
1
|
-
|
|
2
|
-
* Epic P101.06 -- Client-side yoloop state persistence.
|
|
3
|
-
*
|
|
4
|
-
* Re-exports the YoloopClientStateStore class and wire-format types for
|
|
5
|
-
* consumption by invoke.ts (P101.07 pre/post-request hooks).
|
|
6
|
-
*/
|
|
7
|
-
export { YoloopClientStateStore, createDefaultCounters, createDefaultState, } from './yoloop-client-state-store.js';
|
|
8
|
-
export { isYoloopTrigger, readYoloopForRequest, persistYoloopFromResponse, maybeRunDiscoveryHook, } from './invoke-hooks.js';
|
|
1
|
+
import{YoloopClientStateStore as r,createDefaultCounters as t,createDefaultState as a}from"./yoloop-client-state-store.js";import{isYoloopTrigger as s,readYoloopForRequest as l,persistYoloopFromResponse as i,maybeRunDiscoveryHook as u}from"./invoke-hooks.js";export{r as YoloopClientStateStore,t as createDefaultCounters,a as createDefaultState,s as isYoloopTrigger,u as maybeRunDiscoveryHook,i as persistYoloopFromResponse,l as readYoloopForRequest};
|