@remnic/core 9.69.11 → 9.69.13
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/access-admin-ops-surface.d.ts +11 -11
- package/dist/access-admin-ops-surface.js +4 -4
- package/dist/access-authorization-probe.d.ts +11 -11
- package/dist/access-authorization-probe.js +5 -5
- package/dist/access-boundary.d.ts +11 -11
- package/dist/access-boundary.js +4 -4
- package/dist/access-cli.js +28 -28
- package/dist/access-coding-context-resolution.d.ts +1 -1
- package/dist/access-extraction-force-flush.d.ts +11 -11
- package/dist/access-extraction-force-flush.js +4 -4
- package/dist/access-health-types.d.ts +1 -1
- package/dist/access-http-lcm-compaction.d.ts +11 -11
- package/dist/access-http-lifecycle-flush.d.ts +11 -11
- package/dist/access-http-offline-stream.d.ts +11 -11
- package/dist/access-http-query.d.ts +2 -2
- package/dist/access-http-query.js +4 -4
- package/dist/access-http.d.ts +12 -12
- package/dist/access-http.js +15 -15
- package/dist/access-identity-continuity-surface.d.ts +9 -9
- package/dist/access-identity-continuity-surface.js +4 -4
- package/dist/access-lcm-surface.d.ts +11 -11
- package/dist/access-lcm-surface.js +4 -4
- package/dist/access-mcp.d.ts +11 -11
- package/dist/access-mcp.js +11 -11
- package/dist/access-memory-search-fanout.d.ts +2 -2
- package/dist/{access-namespace-preflight-Cy0yPsaE.d.ts → access-namespace-preflight-Rzuo1nGR.d.ts} +1 -1
- package/dist/access-namespace-preflight.d.ts +3 -3
- package/dist/access-namespace-preflight.js +4 -4
- package/dist/access-observe-write-surface.d.ts +11 -11
- package/dist/access-observe-write-surface.js +4 -4
- package/dist/access-offline-manifest.d.ts +9 -9
- package/dist/access-operations-batch.js +5 -5
- package/dist/access-operations.d.ts +17 -17
- package/dist/access-operations.js +10 -10
- package/dist/access-recall-concurrency.d.ts +11 -11
- package/dist/access-recall-concurrency.js +4 -4
- package/dist/access-recall-response.d.ts +11 -11
- package/dist/access-recall-response.js +4 -4
- package/dist/access-recall-surface.d.ts +11 -11
- package/dist/access-recall-surface.js +4 -4
- package/dist/access-schema.d.ts +91 -91
- package/dist/{access-service-Cqfk3dD1.d.ts → access-service-Bb2Fykzc.d.ts} +71 -71
- package/dist/access-service-helpers.d.ts +11 -11
- package/dist/access-service.d.ts +11 -11
- package/dist/access-service.js +4 -4
- package/dist/access-surface-catalog.d.ts +11 -11
- package/dist/access-surface-catalog.js +6 -6
- package/dist/access-wearables-meetings-surface.d.ts +3 -3
- package/dist/action-confidence.d.ts +1 -1
- package/dist/active-memory-bridge.d.ts +1 -1
- package/dist/active-recall.d.ts +1 -1
- package/dist/active-recall.js +4 -4
- package/dist/ambient-provenance.d.ts +1 -1
- package/dist/artifact-search.d.ts +1 -1
- package/dist/behavior-learner.d.ts +1 -1
- package/dist/behavior-signals.d.ts +1 -1
- package/dist/bootstrap.d.ts +9 -9
- package/dist/briefing-window.d.ts +2 -2
- package/dist/briefing.d.ts +2 -2
- package/dist/buffer-surprise-report.d.ts +1 -1
- package/dist/buffer-turn-helpers.d.ts +1 -1
- package/dist/buffer.d.ts +2 -2
- package/dist/buffer.js +4 -4
- package/dist/bulk-import/index.d.ts +3 -3
- package/dist/calibration.d.ts +1 -1
- package/dist/capabilities.d.ts +1 -1
- package/dist/{catalog-9X8WpZNO.d.ts → catalog-DjTLVOYp.d.ts} +1 -1
- package/dist/causal-behavior.d.ts +1 -1
- package/dist/causal-consolidation.d.ts +1 -1
- package/dist/causal-trajectory-graph.d.ts +1 -1
- package/dist/{chunk-TEZ2HTC7.js → chunk-33JKYLPX.js} +2 -2
- package/dist/{chunk-MNH2GM4O.js → chunk-3BS2OGDT.js} +6 -19
- package/dist/{chunk-MNH2GM4O.js.map → chunk-3BS2OGDT.js.map} +1 -1
- package/dist/{chunk-5PTS43CH.js → chunk-4LG4CPOC.js} +2 -2
- package/dist/{chunk-Z33VUMKY.js → chunk-5H2G5X4R.js} +2 -2
- package/dist/{chunk-XFPHV65N.js → chunk-5JQV4T5Q.js} +2 -2
- package/dist/{chunk-OASGWNYL.js → chunk-63I7LMLG.js} +2 -2
- package/dist/{chunk-J3NGQ5SC.js → chunk-7GSSHAXC.js} +2 -2
- package/dist/{chunk-X4FIZAVQ.js → chunk-7JV4JST3.js} +854 -42
- package/dist/chunk-7JV4JST3.js.map +1 -0
- package/dist/{chunk-VHAKBUBD.js → chunk-B64IVEOH.js} +2 -2
- package/dist/{chunk-R7FXPG4T.js → chunk-C25N5HWX.js} +2 -2
- package/dist/{chunk-DH3V7RCQ.js → chunk-F2ERDKY2.js} +7 -7
- package/dist/{chunk-LJNLLNEM.js → chunk-HODFGQGT.js} +2 -2
- package/dist/{chunk-B75VCEX5.js → chunk-K2IJH4D3.js} +2 -2
- package/dist/{chunk-227WJVPY.js → chunk-KLSPKMIO.js} +2 -2
- package/dist/{chunk-5P2KNFJZ.js → chunk-MSDIETFC.js} +3 -3
- package/dist/{chunk-HFRGCNFY.js → chunk-OAKATRAN.js} +2 -2
- package/dist/chunk-OGUKSLYZ.js +560 -0
- package/dist/chunk-OGUKSLYZ.js.map +1 -0
- package/dist/{chunk-M6L7HI7R.js → chunk-P6FHFTZ7.js} +16 -1
- package/dist/chunk-P6FHFTZ7.js.map +1 -0
- package/dist/{chunk-LWBSEYW3.js → chunk-PAWIY5OQ.js} +5 -5
- package/dist/{chunk-3ITTF7YH.js → chunk-QVI63XSO.js} +90 -383
- package/dist/chunk-QVI63XSO.js.map +1 -0
- package/dist/{chunk-6TOWUN2R.js → chunk-RE3H6Y2X.js} +2 -2
- package/dist/{chunk-V3HUBF7T.js → chunk-S35IIP5P.js} +2 -2
- package/dist/{chunk-3YKOFCKP.js → chunk-SXHBZXHK.js} +2 -2
- package/dist/{chunk-7NCUHD5U.js → chunk-VAMZYOOV.js} +2 -2
- package/dist/{chunk-PGCZLHRB.js → chunk-W272SWN7.js} +3 -3
- package/dist/{chunk-5HO3QBAD.js → chunk-W6GEMUZM.js} +2 -2
- package/dist/{chunk-UCNQV43K.js → chunk-XQYTSZW3.js} +2 -2
- package/dist/{chunk-GR4C3FHT.js → chunk-ZKZCJRRO.js} +2 -2
- package/dist/{cli-Dk-lM_tI.d.ts → cli-DXXy60A4.d.ts} +5 -5
- package/dist/cli.d.ts +13 -13
- package/dist/cli.js +21 -21
- package/dist/coding/export-okf-codegraph.d.ts +1 -1
- package/dist/coding/pre-action-gate.d.ts +1 -1
- package/dist/compounding/engine.d.ts +2 -2
- package/dist/compounding/preference-consolidator.d.ts +1 -1
- package/dist/compression-optimizer.d.ts +1 -1
- package/dist/config.d.ts +1 -1
- package/dist/config.js +4 -4
- package/dist/connectors/codex-materialize-runner.d.ts +1 -1
- package/dist/connectors/codex-materialize.d.ts +1 -1
- package/dist/connectors/index.d.ts +1 -1
- package/dist/consolidation-provenance-check.d.ts +2 -2
- package/dist/consolidation-undo.d.ts +2 -2
- package/dist/contradiction/index.d.ts +3 -3
- package/dist/converge-config.d.ts +1 -1
- package/dist/convergence-refresh.d.ts +2 -2
- package/dist/conversation-index/backend.d.ts +1 -1
- package/dist/conversation-index/chunker.d.ts +1 -1
- package/dist/conversation-index/faiss-adapter.d.ts +1 -1
- package/dist/conversation-index/indexer.d.ts +1 -1
- package/dist/conversation-index/search.d.ts +1 -1
- package/dist/corpus-watermark.d.ts +1 -1
- package/dist/cross-lingual-recall.d.ts +1 -1
- package/dist/day-summary.d.ts +1 -1
- package/dist/deep-recall-http-glue.d.ts +11 -11
- package/dist/deep-recall-mcp-tools.d.ts +11 -11
- package/dist/deep-recall-policy-llm.d.ts +1 -1
- package/dist/deep-recall-seeds.d.ts +1 -1
- package/dist/delinearize.d.ts +1 -1
- package/dist/dependency-propagation-config.d.ts +1 -1
- package/dist/{dependency-propagation-delivery-BZGUecZf.d.ts → dependency-propagation-delivery-37JdQv_3.d.ts} +1 -1
- package/dist/direct-answer-wiring.d.ts +1 -1
- package/dist/direct-answer.d.ts +1 -1
- package/dist/embedding-fallback.d.ts +1 -1
- package/dist/enrichment/index.d.ts +1 -1
- package/dist/entity-origin-fields.d.ts +1 -1
- package/dist/entity-retrieval.d.ts +2 -2
- package/dist/entity-schema.d.ts +1 -1
- package/dist/episodic-context.d.ts +1 -1
- package/dist/eval-trajectory-contracts.d.ts +1 -1
- package/dist/eval-trajectory-store.d.ts +1 -1
- package/dist/eval-trajectory.d.ts +1 -1
- package/dist/explicit-capture.d.ts +9 -9
- package/dist/external-wiki-access.d.ts +11 -11
- package/dist/external-wiki-access.js +5 -5
- package/dist/external-wiki-collection-registration.d.ts +1 -1
- package/dist/external-wiki-collection.d.ts +1 -1
- package/dist/external-wiki-mcp-tools.d.ts +11 -11
- package/dist/extraction-error-classification.d.ts +1 -1
- package/dist/extraction-faithfulness.d.ts +1 -1
- package/dist/extraction-judge-telemetry.d.ts +1 -1
- package/dist/extraction-judge-training.d.ts +1 -1
- package/dist/extraction-judge.d.ts +1 -1
- package/dist/extraction-liveness.d.ts +1 -1
- package/dist/extraction-normalization.d.ts +1 -1
- package/dist/extraction-prompt.d.ts +1 -1
- package/dist/extraction-source-grounding-rules.d.ts +1 -1
- package/dist/extraction-source-grounding.d.ts +1 -1
- package/dist/extraction.d.ts +1 -1
- package/dist/extraction.js +5 -5
- package/dist/fallback-llm.d.ts +1 -1
- package/dist/graph-dashboard-diff.d.ts +1 -1
- package/dist/graph-dashboard-key.d.ts +1 -1
- package/dist/graph-dashboard-parser.d.ts +1 -1
- package/dist/graph-edge-reinforcement.d.ts +1 -1
- package/dist/graph-path-reconstruction.d.ts +1 -1
- package/dist/graph-path-scoring.d.ts +1 -1
- package/dist/graph-snapshot.d.ts +1 -1
- package/dist/graph.d.ts +1 -1
- package/dist/importance.d.ts +1 -1
- package/dist/importers/index.d.ts +1 -1
- package/dist/in-flight-reads.d.ts +1 -1
- package/dist/{index-B4iTvT-w.d.ts → index-DquhYqsc.d.ts} +2 -2
- package/dist/index.d.ts +876 -738
- package/dist/index.js +59 -37
- package/dist/intent.d.ts +1 -1
- package/dist/lcm/engine.d.ts +1 -1
- package/dist/lcm/index.d.ts +1 -1
- package/dist/lcm/tools.d.ts +1 -1
- package/dist/lifecycle.d.ts +1 -1
- package/dist/live-connectors-runner.d.ts +1 -1
- package/dist/local-llm.d.ts +1 -1
- package/dist/local-model-endpoint.d.ts +1 -1
- package/dist/location/index.d.ts +3 -3
- package/dist/location/index.js +5 -5
- package/dist/maintenance/memory-governance.d.ts +1 -1
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.d.ts +2 -2
- package/dist/maintenance/rebuild-memory-projection.d.ts +2 -2
- package/dist/{maintenance-BBpNqEeJ.d.ts → maintenance-CizZOycr.d.ts} +3 -3
- package/dist/mcp-memory-inspector-app.d.ts +11 -11
- package/dist/memory-action-policy.d.ts +1 -1
- package/dist/memory-cache.d.ts +1 -1
- package/dist/memory-controller.d.ts +1 -1
- package/dist/memory-lifecycle-ledger-utils.d.ts +1 -1
- package/dist/memory-projection-store.d.ts +1 -1
- package/dist/memory-provenance.d.ts +1 -1
- package/dist/memory-snapshot.d.ts +1 -1
- package/dist/memory-subject-cli.d.ts +11 -11
- package/dist/memory-subject.d.ts +11 -11
- package/dist/memory-worth-outcomes.d.ts +2 -2
- package/dist/models-json.d.ts +1 -1
- package/dist/namespaces/migrate.d.ts +3 -3
- package/dist/namespaces/principal.d.ts +1 -1
- package/dist/namespaces/search.d.ts +1 -1
- package/dist/namespaces/storage.d.ts +3 -3
- package/dist/native-knowledge.d.ts +1 -1
- package/dist/offline-sync-impression-drain.d.ts +1 -1
- package/dist/operator-doctor-corpus.d.ts +1 -1
- package/dist/operator-doctor-replica.d.ts +1 -1
- package/dist/operator-toolkit.d.ts +3 -3
- package/dist/operator-toolkit.js +5 -5
- package/dist/orchestration/compression-guideline-coordinator.d.ts +2 -2
- package/dist/orchestration/maintenance.d.ts +4 -4
- package/dist/orchestration/maintenance.js +6 -6
- package/dist/{orchestrator-DglY1H0w.d.ts → orchestrator-DqLcuNMP.d.ts} +8 -8
- package/dist/orchestrator.d.ts +9 -9
- package/dist/orchestrator.js +28 -28
- package/dist/patterns-cli.d.ts +1 -1
- package/dist/{pipeline-C7qRsy6g.d.ts → pipeline-DbJpmcRu.d.ts} +1 -1
- package/dist/policy-runtime.d.ts +1 -1
- package/dist/proactive-contention.d.ts +1 -1
- package/dist/provenance.d.ts +1 -1
- package/dist/{public-http-CPpCsi35.d.ts → public-http-NQ3UUp6W.d.ts} +1 -1
- package/dist/{qmd-YRLTa3AE.d.ts → qmd-DA_7fbSz.d.ts} +1 -1
- package/dist/qmd-preflight.d.ts +2 -2
- package/dist/qmd-recall-cache.d.ts +1 -1
- package/dist/qmd.d.ts +2 -2
- package/dist/recall-concurrency-config.d.ts +1 -1
- package/dist/recall-disclosure-escalation.d.ts +1 -1
- package/dist/recall-explain-renderer.d.ts +1 -1
- package/dist/recall-memory-map.d.ts +1 -1
- package/dist/recall-navigate-access.d.ts +1 -1
- package/dist/recall-navigate-disclosure.d.ts +1 -1
- package/dist/recall-navigate.d.ts +1 -1
- package/dist/recall-planner-llm.d.ts +1 -1
- package/dist/recall-state.d.ts +1 -1
- package/dist/recall-tag-filter.d.ts +1 -1
- package/dist/recall-timings.d.ts +1 -1
- package/dist/recall-xray-cli.d.ts +1 -1
- package/dist/recall-xray-renderer.d.ts +1 -1
- package/dist/recall-xray.d.ts +1 -1
- package/dist/reconcile/cursor.d.ts +1 -1
- package/dist/reconcile/manifest.d.ts +1 -1
- package/dist/reconcile/plan.d.ts +1 -1
- package/dist/replay/normalizers/chatgpt.d.ts +1 -1
- package/dist/replay/normalizers/claude.d.ts +1 -1
- package/dist/replay/normalizers/openclaw.d.ts +1 -1
- package/dist/replay/normalizers/shared.d.ts +1 -1
- package/dist/replay/runner.d.ts +1 -1
- package/dist/replay/types.d.ts +1 -1
- package/dist/replica-divergence.d.ts +1 -1
- package/dist/replica-peers-config.d.ts +1 -1
- package/dist/resolve-auth-token.d.ts +1 -1
- package/dist/resume-bundles.js +5 -5
- package/dist/retrieval-agents.d.ts +2 -2
- package/dist/retrieval-tiers.d.ts +1 -1
- package/dist/routing/engine.d.ts +1 -1
- package/dist/routing/store.d.ts +1 -1
- package/dist/salvage-envelope.d.ts +1 -1
- package/dist/schemas.d.ts +176 -176
- package/dist/{scope-profiles-BVvqVzJX.d.ts → scope-profiles-BpiWKZzx.d.ts} +1 -1
- package/dist/search/embed-helper.d.ts +1 -1
- package/dist/search/factory.d.ts +1 -1
- package/dist/search/index.d.ts +1 -1
- package/dist/search/lancedb-backend.d.ts +1 -1
- package/dist/search/meilisearch-backend.d.ts +1 -1
- package/dist/search/noop-backend.d.ts +1 -1
- package/dist/search/orama-backend.d.ts +1 -1
- package/dist/search/port.d.ts +1 -1
- package/dist/search/remote-backend.d.ts +1 -1
- package/dist/{semantic-consolidation-BzCI6Kuu.d.ts → semantic-consolidation-NJpaZpkY.d.ts} +1 -1
- package/dist/semantic-consolidation.d.ts +2 -2
- package/dist/semantic-rule-verifier.d.ts +1 -1
- package/dist/{service-DQ3Gscy5.d.ts → service-DdlZjX1D.d.ts} +2 -2
- package/dist/session-observer-bands.d.ts +1 -1
- package/dist/session-observer-state.d.ts +1 -1
- package/dist/shared-context/manager.d.ts +7 -7
- package/dist/signal.d.ts +1 -1
- package/dist/source-agent-qualifier.d.ts +1 -1
- package/dist/source-agent-qualifier.js +4 -4
- package/dist/standup/build.js +2 -2
- package/dist/{storage-DmTbQdD0.d.ts → storage-C7BWrpU9.d.ts} +1 -1
- package/dist/storage.d.ts +2 -2
- package/dist/subject-config.d.ts +1 -1
- package/dist/summarizer.d.ts +1 -1
- package/dist/summary-snapshot.d.ts +1 -1
- package/dist/support-passport/index.d.ts +14 -14
- package/dist/support-passport/index.js +7 -7
- package/dist/temporal-supersession.d.ts +2 -2
- package/dist/temporal-timeline-recall.d.ts +1 -1
- package/dist/temporal-validity.d.ts +1 -1
- package/dist/threading.d.ts +1 -1
- package/dist/tier-migration.d.ts +2 -2
- package/dist/tier-routing.d.ts +1 -1
- package/dist/topics.d.ts +1 -1
- package/dist/transcript.d.ts +1 -1
- package/dist/transfer/export-okf.d.ts +1 -1
- package/dist/transfer/types.d.ts +78 -78
- package/dist/trust-score-stage.d.ts +1 -1
- package/dist/trust-score.d.ts +1 -1
- package/dist/{types-CLRTESSD.d.ts → types-Cy1l6fzp.d.ts} +48 -1
- package/dist/types.d.ts +1 -1
- package/dist/utility-runtime.d.ts +1 -1
- package/dist/who-knows-cli.d.ts +11 -11
- package/dist/who-knows.d.ts +11 -11
- package/dist/write-envelope.d.ts +1 -1
- package/package.json +2 -2
- package/src/activity/config.test.ts +94 -1
- package/src/activity/config.ts +256 -3
- package/src/activity/digest.ts +21 -0
- package/src/activity/index.ts +2 -0
- package/src/activity/runner.ts +2 -17
- package/src/activity/timeline/publish-cli.test.ts +169 -0
- package/src/activity/timeline/publish-cli.ts +144 -0
- package/src/activity/timeline/query.ts +51 -15
- package/src/activity/types.ts +45 -0
- package/src/activity/vault-insert.ts +14 -33
- package/src/activity/vault-path.ts +100 -22
- package/src/activity/vault-publish.test.ts +51 -0
- package/src/activity/vault-publish.ts +157 -17
- package/src/activity/vault-publisher.test.ts +881 -0
- package/src/activity/vault-publisher.ts +597 -0
- package/src/activity/vault-region.test.ts +5 -0
- package/src/activity/vault-region.ts +7 -2
- package/src/cli/timeline-publish-commands.ts +34 -0
- package/src/cli.ts +2 -2
- package/src/config.test.ts +24 -1
- package/dist/chunk-3ITTF7YH.js.map +0 -1
- package/dist/chunk-KJUWWN3T.js +0 -237
- package/dist/chunk-KJUWWN3T.js.map +0 -1
- package/dist/chunk-M6L7HI7R.js.map +0 -1
- package/dist/chunk-X4FIZAVQ.js.map +0 -1
- /package/dist/{chunk-TEZ2HTC7.js.map → chunk-33JKYLPX.js.map} +0 -0
- /package/dist/{chunk-5PTS43CH.js.map → chunk-4LG4CPOC.js.map} +0 -0
- /package/dist/{chunk-Z33VUMKY.js.map → chunk-5H2G5X4R.js.map} +0 -0
- /package/dist/{chunk-XFPHV65N.js.map → chunk-5JQV4T5Q.js.map} +0 -0
- /package/dist/{chunk-OASGWNYL.js.map → chunk-63I7LMLG.js.map} +0 -0
- /package/dist/{chunk-J3NGQ5SC.js.map → chunk-7GSSHAXC.js.map} +0 -0
- /package/dist/{chunk-VHAKBUBD.js.map → chunk-B64IVEOH.js.map} +0 -0
- /package/dist/{chunk-R7FXPG4T.js.map → chunk-C25N5HWX.js.map} +0 -0
- /package/dist/{chunk-DH3V7RCQ.js.map → chunk-F2ERDKY2.js.map} +0 -0
- /package/dist/{chunk-LJNLLNEM.js.map → chunk-HODFGQGT.js.map} +0 -0
- /package/dist/{chunk-B75VCEX5.js.map → chunk-K2IJH4D3.js.map} +0 -0
- /package/dist/{chunk-227WJVPY.js.map → chunk-KLSPKMIO.js.map} +0 -0
- /package/dist/{chunk-5P2KNFJZ.js.map → chunk-MSDIETFC.js.map} +0 -0
- /package/dist/{chunk-HFRGCNFY.js.map → chunk-OAKATRAN.js.map} +0 -0
- /package/dist/{chunk-LWBSEYW3.js.map → chunk-PAWIY5OQ.js.map} +0 -0
- /package/dist/{chunk-6TOWUN2R.js.map → chunk-RE3H6Y2X.js.map} +0 -0
- /package/dist/{chunk-V3HUBF7T.js.map → chunk-S35IIP5P.js.map} +0 -0
- /package/dist/{chunk-3YKOFCKP.js.map → chunk-SXHBZXHK.js.map} +0 -0
- /package/dist/{chunk-7NCUHD5U.js.map → chunk-VAMZYOOV.js.map} +0 -0
- /package/dist/{chunk-PGCZLHRB.js.map → chunk-W272SWN7.js.map} +0 -0
- /package/dist/{chunk-5HO3QBAD.js.map → chunk-W6GEMUZM.js.map} +0 -0
- /package/dist/{chunk-UCNQV43K.js.map → chunk-XQYTSZW3.js.map} +0 -0
- /package/dist/{chunk-GR4C3FHT.js.map → chunk-ZKZCJRRO.js.map} +0 -0
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import test from "node:test";
|
|
3
|
+
import { mkdirSync, mkdtempSync, readFileSync, writeFileSync } from "node:fs";
|
|
4
|
+
import { tmpdir } from "node:os";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
|
|
7
|
+
import { parseConfig } from "../../config.js";
|
|
8
|
+
import type { PluginConfig } from "../../types.js";
|
|
9
|
+
import { runTimelineCliCommand } from "./query.js";
|
|
10
|
+
|
|
11
|
+
const DATE = "2026-08-21";
|
|
12
|
+
const RECAP = "- 09:00-10:00 code review (60m)";
|
|
13
|
+
|
|
14
|
+
interface Capture {
|
|
15
|
+
out: string;
|
|
16
|
+
err: string;
|
|
17
|
+
io: { stdout: { write(chunk: string): unknown }; stderr: { write(chunk: string): unknown } };
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function capture(): Capture {
|
|
21
|
+
const sink: Capture = {
|
|
22
|
+
out: "",
|
|
23
|
+
err: "",
|
|
24
|
+
io: {
|
|
25
|
+
stdout: {
|
|
26
|
+
write(chunk: string) {
|
|
27
|
+
sink.out += chunk;
|
|
28
|
+
return true;
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
stderr: {
|
|
32
|
+
write(chunk: string) {
|
|
33
|
+
sink.err += chunk;
|
|
34
|
+
return true;
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
return sink;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function makeFixture(): { config: PluginConfig; notePath: string; note: string } {
|
|
43
|
+
const root = mkdtempSync(path.join(tmpdir(), "remnic-publish-cli-"));
|
|
44
|
+
const memoryDir = path.join(root, "memory");
|
|
45
|
+
const vaultPath = path.join(root, "vault");
|
|
46
|
+
mkdirSync(path.join(memoryDir, "journal"), { recursive: true });
|
|
47
|
+
mkdirSync(vaultPath, { recursive: true });
|
|
48
|
+
writeFileSync(path.join(memoryDir, "journal", `${DATE}.md`), `${RECAP}\n`, "utf8");
|
|
49
|
+
|
|
50
|
+
const note = [
|
|
51
|
+
"# Daily",
|
|
52
|
+
"",
|
|
53
|
+
"human text that must survive",
|
|
54
|
+
"",
|
|
55
|
+
"<!-- remnic:Timeline:start -->",
|
|
56
|
+
"stale",
|
|
57
|
+
"<!-- remnic:Timeline:end -->",
|
|
58
|
+
"",
|
|
59
|
+
].join("\n");
|
|
60
|
+
const notePath = path.join(vaultPath, `${DATE}.md`);
|
|
61
|
+
writeFileSync(notePath, note, "utf8");
|
|
62
|
+
|
|
63
|
+
const config = parseConfig({
|
|
64
|
+
memoryDir,
|
|
65
|
+
activity: {
|
|
66
|
+
timezone: "UTC",
|
|
67
|
+
timeline: { vault: { enabled: true, vaultPath, dailyNotePath: "{yyyy}-{MM}-{dd}.md" } },
|
|
68
|
+
},
|
|
69
|
+
});
|
|
70
|
+
return { config, notePath, note };
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
test("the shared timeline runner dispatches publish and writes the managed region", async () => {
|
|
74
|
+
const { config, notePath } = makeFixture();
|
|
75
|
+
const sink = capture();
|
|
76
|
+
|
|
77
|
+
const code = await runTimelineCliCommand(
|
|
78
|
+
// qa stays disabled: publish is not a qa surface and must not be gated by it.
|
|
79
|
+
{ cards: null, qa: { enabled: false, maxRangeDays: 31 }, timelineEnabled: true, config },
|
|
80
|
+
["publish", "--date", DATE],
|
|
81
|
+
sink.io,
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
assert.equal(code, 0, sink.err);
|
|
85
|
+
assert.doesNotMatch(sink.err, /unknown command publish/);
|
|
86
|
+
assert.match(sink.out, /updated=1/);
|
|
87
|
+
const after = readFileSync(notePath, "utf8");
|
|
88
|
+
assert.ok(after.includes(RECAP), "the recap is published into the managed region");
|
|
89
|
+
assert.ok(after.includes("human text that must survive"));
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
test("the shared timeline runner reports publish as a valid command", async () => {
|
|
93
|
+
const sink = capture();
|
|
94
|
+
const code = await runTimelineCliCommand(
|
|
95
|
+
{ cards: null, qa: { enabled: true, maxRangeDays: 31 }, timelineEnabled: true },
|
|
96
|
+
["bogus"],
|
|
97
|
+
sink.io,
|
|
98
|
+
);
|
|
99
|
+
assert.equal(code, 1);
|
|
100
|
+
assert.match(sink.err, /valid: range, search, publish/);
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
test("publish without a config refuses instead of throwing", async () => {
|
|
104
|
+
const sink = capture();
|
|
105
|
+
const code = await runTimelineCliCommand(
|
|
106
|
+
{ cards: null, qa: { enabled: true, maxRangeDays: 31 }, timelineEnabled: true },
|
|
107
|
+
["publish"],
|
|
108
|
+
sink.io,
|
|
109
|
+
);
|
|
110
|
+
assert.equal(code, 1);
|
|
111
|
+
assert.match(sink.err, /requires the Remnic config/);
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
test("--what with only separators is rejected with a validation error", async () => {
|
|
115
|
+
const { config, notePath, note } = makeFixture();
|
|
116
|
+
const sink = capture();
|
|
117
|
+
|
|
118
|
+
const code = await runTimelineCliCommand(
|
|
119
|
+
{ cards: null, qa: { enabled: false, maxRangeDays: 31 }, timelineEnabled: true, config },
|
|
120
|
+
["publish", "--date", DATE, "--what", ",,"],
|
|
121
|
+
sink.io,
|
|
122
|
+
);
|
|
123
|
+
|
|
124
|
+
assert.equal(code, 1);
|
|
125
|
+
assert.match(sink.err, /--what must name at least one artifact/);
|
|
126
|
+
assert.equal(readFileSync(notePath, "utf8"), note, "nothing is published");
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
test("publish rejects query-only flags instead of silently publishing today's note", async () => {
|
|
130
|
+
const { config, notePath, note } = makeFixture();
|
|
131
|
+
const sink = capture();
|
|
132
|
+
|
|
133
|
+
const code = await runTimelineCliCommand(
|
|
134
|
+
{ cards: null, qa: { enabled: false, maxRangeDays: 31 }, timelineEnabled: true, config },
|
|
135
|
+
["publish", "--from", "2026-08-01"],
|
|
136
|
+
sink.io,
|
|
137
|
+
);
|
|
138
|
+
|
|
139
|
+
assert.equal(code, 1);
|
|
140
|
+
assert.match(sink.err, /unknown flag --from \(valid: --date, --dry-run, --week, --what\)/);
|
|
141
|
+
assert.equal(readFileSync(notePath, "utf8"), note, "no note is touched by unsupported syntax");
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
test("range and search reject publish-only flags instead of ignoring them", async () => {
|
|
145
|
+
const { config } = makeFixture();
|
|
146
|
+
const deps = {
|
|
147
|
+
cards: null,
|
|
148
|
+
qa: { enabled: true, maxRangeDays: 31 },
|
|
149
|
+
timelineEnabled: true,
|
|
150
|
+
config,
|
|
151
|
+
} as const;
|
|
152
|
+
|
|
153
|
+
const rangeSink = capture();
|
|
154
|
+
const rangeCode = await runTimelineCliCommand(
|
|
155
|
+
deps,
|
|
156
|
+
["range", "--date", DATE, "--from", `${DATE}T00:00:00.000Z`, "--to", `${DATE}T00:00:00.000Z`],
|
|
157
|
+
rangeSink.io,
|
|
158
|
+
);
|
|
159
|
+
assert.equal(rangeCode, 1);
|
|
160
|
+
assert.match(
|
|
161
|
+
rangeSink.err,
|
|
162
|
+
/unknown flag --date \(valid: --categories, --format, --from, --include-distractions, --to\)/,
|
|
163
|
+
);
|
|
164
|
+
|
|
165
|
+
const searchSink = capture();
|
|
166
|
+
const searchCode = await runTimelineCliCommand(deps, ["search", "--query", "x", "--dry-run"], searchSink.io);
|
|
167
|
+
assert.equal(searchCode, 1);
|
|
168
|
+
assert.match(searchSink.err, /unknown flag --dry-run \(valid: --from, --limit, --query, --to\)/);
|
|
169
|
+
});
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared `timeline publish` implementation (issue #1985).
|
|
3
|
+
*
|
|
4
|
+
* Both CLI trees dispatch this one function: the host command group in
|
|
5
|
+
* `cli/timeline-publish-commands.ts` and the standalone binary's shared
|
|
6
|
+
* runner in `timeline/query.ts`. A documented command that exists on only
|
|
7
|
+
* one tree is a defect — the shipped `@remnic/cli` binary must publish too.
|
|
8
|
+
*/
|
|
9
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
10
|
+
|
|
11
|
+
import type { PluginConfig } from "../../types.js";
|
|
12
|
+
import { activityDateInTimezone, isValidActivityDate } from "../digest.js";
|
|
13
|
+
import { journalPath } from "../journal.js";
|
|
14
|
+
import { publishVaultNote, type VaultSectionPublish } from "../vault-publisher.js";
|
|
15
|
+
|
|
16
|
+
export interface TimelinePublishIo {
|
|
17
|
+
stdout: { write(chunk: string): unknown };
|
|
18
|
+
stderr: { write(chunk: string): unknown };
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface TimelinePublishOptions {
|
|
22
|
+
date?: unknown;
|
|
23
|
+
week?: unknown;
|
|
24
|
+
what?: unknown;
|
|
25
|
+
dryRun?: unknown;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const AVAILABLE_KINDS = ["timeline"] as const;
|
|
29
|
+
const KNOWN_KINDS = ["timeline", "standup", "weekly", "locations"] as const;
|
|
30
|
+
const UNLANDED_REASONS: Record<string, string> = {
|
|
31
|
+
standup: "the standup renderer lands with timeline phase 3",
|
|
32
|
+
weekly: "the weekly review renderer lands with timeline phase 4",
|
|
33
|
+
locations: "the location day renderer is not wired to publishing yet",
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export function runTimelinePublishCli(
|
|
37
|
+
config: PluginConfig,
|
|
38
|
+
options: TimelinePublishOptions,
|
|
39
|
+
io: TimelinePublishIo,
|
|
40
|
+
): number {
|
|
41
|
+
const vault = config.activity?.timeline?.vault;
|
|
42
|
+
|
|
43
|
+
if (options.week !== undefined) {
|
|
44
|
+
io.stderr.write("--week is not available yet: the weekly review renderer lands with timeline phase 4.\n");
|
|
45
|
+
return 1;
|
|
46
|
+
}
|
|
47
|
+
if (!vault || vault.enabled !== true) {
|
|
48
|
+
io.stderr.write(
|
|
49
|
+
"Vault publishing is disabled: set activity.timeline.vault.enabled=true and configure vaultPath first.\n",
|
|
50
|
+
);
|
|
51
|
+
return 1;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Timeline artifacts are grouped on the configured activity timezone's
|
|
55
|
+
// calendar day, so "today" must be derived there — the host-local day
|
|
56
|
+
// drifts by one near either timezone's midnight.
|
|
57
|
+
const date =
|
|
58
|
+
typeof options.date === "string" && options.date.length > 0
|
|
59
|
+
? options.date
|
|
60
|
+
: activityDateInTimezone(new Date(), config.activity?.timezone ?? "UTC");
|
|
61
|
+
if (!isValidActivityDate(date)) {
|
|
62
|
+
io.stderr.write(`Invalid --date "${date}"; expected YYYY-MM-DD.\n`);
|
|
63
|
+
return 1;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const requested = parseKinds(typeof options.what === "string" && options.what.length > 0 ? options.what : "timeline");
|
|
67
|
+
if (typeof requested !== "string") {
|
|
68
|
+
io.stderr.write(requested.error);
|
|
69
|
+
return 1;
|
|
70
|
+
}
|
|
71
|
+
const kinds = requested.split(",");
|
|
72
|
+
const sections: VaultSectionPublish[] = [];
|
|
73
|
+
let notePathTemplate = vault.dailyNotePath;
|
|
74
|
+
|
|
75
|
+
for (const kind of kinds) {
|
|
76
|
+
if ((AVAILABLE_KINDS as readonly string[]).indexOf(kind) === -1) {
|
|
77
|
+
io.stderr.write(`--what ${kind} is not available yet: ${UNLANDED_REASONS[kind] ?? "unknown kind"}.\n`);
|
|
78
|
+
return 1;
|
|
79
|
+
}
|
|
80
|
+
const target = vault.publish[kind as "timeline"];
|
|
81
|
+
if (target.enabled !== true) {
|
|
82
|
+
io.stderr.write(`--what ${kind} is disabled: enable activity.timeline.vault.publish.${kind}.enabled.\n`);
|
|
83
|
+
return 1;
|
|
84
|
+
}
|
|
85
|
+
// Honor the target's configured note file; config parsing already
|
|
86
|
+
// rejects target="weekly" with an empty weeklyNotePath.
|
|
87
|
+
notePathTemplate = target.target === "weekly" ? vault.weeklyNotePath : vault.dailyNotePath;
|
|
88
|
+
const source = journalPath(config.memoryDir, date);
|
|
89
|
+
if (!existsSync(source)) {
|
|
90
|
+
io.stderr.write(
|
|
91
|
+
`No timeline artifact for ${date}: run the journal recap generation first (${kind} target reads the persisted day recap).\n`,
|
|
92
|
+
);
|
|
93
|
+
return 1;
|
|
94
|
+
}
|
|
95
|
+
sections.push({ name: target.section, content: readFileSync(source, "utf8").trimEnd() });
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const status = publishVaultNote({
|
|
99
|
+
vaultPath: vault.vaultPath,
|
|
100
|
+
notePathTemplate,
|
|
101
|
+
date,
|
|
102
|
+
sections,
|
|
103
|
+
strategy: vault.sectionStrategy,
|
|
104
|
+
insertUnderHeading: vault.insertUnderHeading.length > 0 ? vault.insertUnderHeading : undefined,
|
|
105
|
+
createMissingNotes: vault.createMissingNotes,
|
|
106
|
+
noteTemplate: vault.noteTemplate.length > 0 ? vault.noteTemplate : undefined,
|
|
107
|
+
propertiesMode: vault.properties.mode,
|
|
108
|
+
propertiesPrefix: vault.properties.prefix,
|
|
109
|
+
dryRun: options.dryRun === true,
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
for (const row of status.results) {
|
|
113
|
+
const label = row.outcome === "updated" && options.dryRun === true ? "would update" : row.outcome;
|
|
114
|
+
io.stdout.write(`${label} ${row.path}${row.reason ? ` (${row.reason})` : ""}\n`);
|
|
115
|
+
}
|
|
116
|
+
io.stdout.write(
|
|
117
|
+
`updated=${status.counts.updated} unchanged=${status.counts.unchanged} skipped=${status.counts.skipped} error=${status.counts.error}\n`,
|
|
118
|
+
);
|
|
119
|
+
return status.hasError ? 1 : 0;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* `--what` is normalized to a comma-joined kind list. An empty normalized
|
|
124
|
+
* list (`--what ','`) is rejected here rather than reaching the publisher,
|
|
125
|
+
* which throws a RangeError on a zero-length section list.
|
|
126
|
+
*/
|
|
127
|
+
function parseKinds(raw: string): string | { error: string } {
|
|
128
|
+
const kinds = raw
|
|
129
|
+
.split(",")
|
|
130
|
+
.map((part) => part.trim())
|
|
131
|
+
.filter((part) => part.length > 0);
|
|
132
|
+
for (const kind of kinds) {
|
|
133
|
+
if ((KNOWN_KINDS as readonly string[]).indexOf(kind) === -1) {
|
|
134
|
+
return { error: `Unknown --what kind "${kind}"; valid kinds are ${KNOWN_KINDS.join(", ")}.\n` };
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
if (new Set(kinds).size !== kinds.length) {
|
|
138
|
+
return { error: "--what must not repeat a kind.\n" };
|
|
139
|
+
}
|
|
140
|
+
if (kinds.length === 0) {
|
|
141
|
+
return { error: `--what must name at least one artifact; valid kinds are ${KNOWN_KINDS.join(", ")}.\n` };
|
|
142
|
+
}
|
|
143
|
+
return kinds.join(",");
|
|
144
|
+
}
|
|
@@ -9,7 +9,9 @@
|
|
|
9
9
|
* MCP/HTTP and recall injection are later PRs.
|
|
10
10
|
*/
|
|
11
11
|
import { parseFlexibleIsoTimestamp } from "../../utils/iso-timestamp.js";
|
|
12
|
+
import type { PluginConfig } from "../../types.js";
|
|
12
13
|
import type { ActivityTimelineQaConfig } from "../types.js";
|
|
14
|
+
import { runTimelinePublishCli } from "./publish-cli.js";
|
|
13
15
|
import type { TimelineCard } from "./types.js";
|
|
14
16
|
|
|
15
17
|
const RANGE_FORMATS = ["cards", "compact"] as const;
|
|
@@ -70,6 +72,8 @@ export interface TimelineCliDeps {
|
|
|
70
72
|
cards: readonly TimelineQueryCard[] | null;
|
|
71
73
|
qa: ActivityTimelineQaConfig;
|
|
72
74
|
timelineEnabled?: boolean;
|
|
75
|
+
/** Required for `publish`; range/search never read it. */
|
|
76
|
+
config?: PluginConfig;
|
|
73
77
|
}
|
|
74
78
|
|
|
75
79
|
const USAGE = `Usage: timeline <command> [options]
|
|
@@ -77,17 +81,25 @@ const USAGE = `Usage: timeline <command> [options]
|
|
|
77
81
|
Commands:
|
|
78
82
|
range --from <ISO> --to <ISO> [--format cards|compact] [--categories id,id] [--include-distractions]
|
|
79
83
|
search --query <text> [--from <ISO>] [--to <ISO>] [--limit N]
|
|
84
|
+
publish [--date YYYY-MM-DD] [--what timeline] [--dry-run]
|
|
80
85
|
`;
|
|
81
86
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
"--
|
|
88
|
-
"--
|
|
87
|
+
// Per-subcommand flag allow-lists (issue #1985 review): a shared union table
|
|
88
|
+
// let `timeline publish --from …` parse and then silently discard `--from`,
|
|
89
|
+
// publishing today's note on a query-only flag — and `range --date` likewise.
|
|
90
|
+
// Every subcommand validates its own syntax before dispatch.
|
|
91
|
+
const PUBLISH_FLAGS = {
|
|
92
|
+
value: { "--date": true, "--week": true, "--what": true } as Record<string, true>,
|
|
93
|
+
boolean: { "--dry-run": true } as Record<string, true>,
|
|
94
|
+
};
|
|
95
|
+
const RANGE_FLAGS = {
|
|
96
|
+
value: { "--from": true, "--to": true, "--format": true, "--categories": true } as Record<string, true>,
|
|
97
|
+
boolean: { "--include-distractions": true } as Record<string, true>,
|
|
98
|
+
};
|
|
99
|
+
const SEARCH_FLAGS = {
|
|
100
|
+
value: { "--query": true, "--from": true, "--to": true, "--limit": true } as Record<string, true>,
|
|
101
|
+
boolean: {} as Record<string, true>,
|
|
89
102
|
};
|
|
90
|
-
const BOOLEAN_FLAGS: Record<string, true> = { "--include-distractions": true };
|
|
91
103
|
|
|
92
104
|
function parseInstant(value: string, label: string): number {
|
|
93
105
|
const ms = parseFlexibleIsoTimestamp(value);
|
|
@@ -214,16 +226,19 @@ export function queryTimelineSearch(
|
|
|
214
226
|
return { ok: true, results: ranked };
|
|
215
227
|
}
|
|
216
228
|
|
|
217
|
-
function parseFlags(
|
|
229
|
+
function parseFlags(
|
|
230
|
+
args: string[],
|
|
231
|
+
spec: { value: Record<string, true>; boolean: Record<string, true> },
|
|
232
|
+
): { flags: Map<string, string | true>; positional: string[] } {
|
|
218
233
|
const flags = new Map<string, string | true>();
|
|
219
234
|
const positional: string[] = [];
|
|
220
|
-
for (let i = 0; i < args.length; i
|
|
235
|
+
for (let i = 0; i < args.length; i += 1) {
|
|
221
236
|
const arg = args[i]!;
|
|
222
237
|
if (!arg.startsWith("--")) {
|
|
223
238
|
positional.push(arg);
|
|
224
239
|
continue;
|
|
225
240
|
}
|
|
226
|
-
if (
|
|
241
|
+
if (spec.value[arg] === true) {
|
|
227
242
|
const value = args[i + 1];
|
|
228
243
|
if (value === undefined || value.startsWith("--")) {
|
|
229
244
|
throw new TypeError(`flag ${arg} requires a value`);
|
|
@@ -232,11 +247,11 @@ function parseFlags(args: string[]): { flags: Map<string, string | true>; positi
|
|
|
232
247
|
i += 1;
|
|
233
248
|
continue;
|
|
234
249
|
}
|
|
235
|
-
if (
|
|
250
|
+
if (spec.boolean[arg] === true) {
|
|
236
251
|
flags.set(arg, true);
|
|
237
252
|
continue;
|
|
238
253
|
}
|
|
239
|
-
const known = [...Object.keys(
|
|
254
|
+
const known = [...Object.keys(spec.value), ...Object.keys(spec.boolean)].sort().join(", ");
|
|
240
255
|
throw new TypeError(`unknown flag ${arg} (valid: ${known})`);
|
|
241
256
|
}
|
|
242
257
|
return { flags, positional };
|
|
@@ -259,11 +274,32 @@ export async function runTimelineCliCommand(
|
|
|
259
274
|
io.stdout.write(USAGE);
|
|
260
275
|
return command === undefined ? 1 : 0;
|
|
261
276
|
}
|
|
277
|
+
// `publish` writes into the user's vault and is not a qa/query surface,
|
|
278
|
+
// so it dispatches before the qa gate. Flags are validated against the
|
|
279
|
+
// publish-only set: `--from`/`--format` are query syntax and must be
|
|
280
|
+
// rejected here, not silently dropped while today's note is published.
|
|
281
|
+
if (command === "publish") {
|
|
282
|
+
if (deps.config === undefined) {
|
|
283
|
+
io.stderr.write("timeline publish requires the Remnic config — run `remnic doctor`\n");
|
|
284
|
+
return 1;
|
|
285
|
+
}
|
|
286
|
+
const publishFlags = parseFlags(rest, PUBLISH_FLAGS).flags;
|
|
287
|
+
return runTimelinePublishCli(
|
|
288
|
+
deps.config,
|
|
289
|
+
{
|
|
290
|
+
date: flagString(publishFlags, "--date"),
|
|
291
|
+
week: flagString(publishFlags, "--week"),
|
|
292
|
+
what: flagString(publishFlags, "--what"),
|
|
293
|
+
dryRun: publishFlags.get("--dry-run") === true,
|
|
294
|
+
},
|
|
295
|
+
io,
|
|
296
|
+
);
|
|
297
|
+
}
|
|
262
298
|
if (deps.timelineEnabled === false || !deps.qa.enabled) {
|
|
263
299
|
io.stderr.write("timeline qa disabled — set activity.timeline.qa.enabled=true\n");
|
|
264
300
|
return 1;
|
|
265
301
|
}
|
|
266
|
-
const { flags } = parseFlags(rest);
|
|
302
|
+
const { flags } = parseFlags(rest, command === "range" ? RANGE_FLAGS : SEARCH_FLAGS);
|
|
267
303
|
if (command === "range") {
|
|
268
304
|
const from = flagString(flags, "--from");
|
|
269
305
|
const to = flagString(flags, "--to");
|
|
@@ -305,7 +341,7 @@ export async function runTimelineCliCommand(
|
|
|
305
341
|
io.stdout.write(`${JSON.stringify(result)}\n`);
|
|
306
342
|
return result.ok ? 0 : 1;
|
|
307
343
|
}
|
|
308
|
-
throw new TypeError(`unknown command ${command} (valid: range, search)`);
|
|
344
|
+
throw new TypeError(`unknown command ${command} (valid: range, search, publish)`);
|
|
309
345
|
} catch (err) {
|
|
310
346
|
io.stderr.write(`${err instanceof Error ? err.message : String(err)}\n`);
|
|
311
347
|
return 1;
|
package/src/activity/types.ts
CHANGED
|
@@ -105,6 +105,50 @@ export interface ActivityTimelineJournalConfig {
|
|
|
105
105
|
heading?: string;
|
|
106
106
|
}
|
|
107
107
|
|
|
108
|
+
/** Section ownership strategy for vault publishing (issue #1985). */
|
|
109
|
+
export type VaultSectionStrategy = "markers" | "heading";
|
|
110
|
+
|
|
111
|
+
/** Where section stats are written (issue #1985). `off` writes none. */
|
|
112
|
+
export type VaultPropertiesMode = "off" | "frontmatter" | "dataview-inline";
|
|
113
|
+
|
|
114
|
+
export interface ActivityTimelineVaultTargetConfig {
|
|
115
|
+
enabled: boolean;
|
|
116
|
+
target: "daily" | "weekly";
|
|
117
|
+
section: string;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Opt-in markdown-vault publisher settings (issue #1985). Default off:
|
|
122
|
+
* `enabled: false` means no vault reads or writes ever occur.
|
|
123
|
+
*/
|
|
124
|
+
export interface ActivityTimelineVaultConfig {
|
|
125
|
+
enabled: boolean;
|
|
126
|
+
/** Vault root; absolute or `~` path. Required and non-empty when enabled. */
|
|
127
|
+
vaultPath: string;
|
|
128
|
+
/** Vault-relative daily-note path template; date tokens. */
|
|
129
|
+
dailyNotePath: string;
|
|
130
|
+
/** Empty means weekly-note publishing is disabled. */
|
|
131
|
+
weeklyNotePath: string;
|
|
132
|
+
createMissingNotes: boolean;
|
|
133
|
+
/** Vault-relative template file, used only when creating a missing note. */
|
|
134
|
+
noteTemplate: string;
|
|
135
|
+
sectionStrategy: VaultSectionStrategy;
|
|
136
|
+
publish: {
|
|
137
|
+
timeline: ActivityTimelineVaultTargetConfig;
|
|
138
|
+
/** Standup target lights up when phase 3 lands. */
|
|
139
|
+
standup: ActivityTimelineVaultTargetConfig;
|
|
140
|
+
/** Weekly target lights up when phase 4 lands. */
|
|
141
|
+
weekly: ActivityTimelineVaultTargetConfig;
|
|
142
|
+
/** Locations target lights up with the location day renderer. */
|
|
143
|
+
locations: ActivityTimelineVaultTargetConfig;
|
|
144
|
+
};
|
|
145
|
+
/** Markers strategy: heading under which missing marker pairs are inserted; empty = never insert. */
|
|
146
|
+
insertUnderHeading: string;
|
|
147
|
+
wikilinks: { places: boolean; placesFolder: string };
|
|
148
|
+
properties: { mode: VaultPropertiesMode; prefix: string };
|
|
149
|
+
autoPublish: boolean;
|
|
150
|
+
}
|
|
151
|
+
|
|
108
152
|
/** Opt-in timeline Q&A range/search settings (issue #1983 PR1). Default off. */
|
|
109
153
|
export interface ActivityTimelineQaConfig {
|
|
110
154
|
enabled: boolean;
|
|
@@ -117,6 +161,7 @@ export interface ActivityTimelineConfig {
|
|
|
117
161
|
enabled: boolean;
|
|
118
162
|
journal: ActivityTimelineJournalConfig;
|
|
119
163
|
qa: ActivityTimelineQaConfig;
|
|
164
|
+
vault: ActivityTimelineVaultConfig;
|
|
120
165
|
}
|
|
121
166
|
|
|
122
167
|
/** Opt-in activity synchronization + trust-gated extraction settings. */
|
|
@@ -2,10 +2,13 @@
|
|
|
2
2
|
* Managed-region marker insertion (issue #1985).
|
|
3
3
|
*
|
|
4
4
|
* Inserts a `<!-- remnic:<name>:start/end -->` pair under a unique ATX
|
|
5
|
-
* heading when the region is absent.
|
|
6
|
-
*
|
|
7
|
-
*
|
|
5
|
+
* heading when the region is absent. Code blocks — fenced or indented —
|
|
6
|
+
* are invisible to
|
|
7
|
+
* the heading scan, so a live region is never inserted into a `## …`
|
|
8
|
+
* example. This helper never replaces (see `vault-publish.ts`), never
|
|
9
|
+
* creates files, and never invents a heading. Pure string-in/string-out.
|
|
8
10
|
*/
|
|
11
|
+
import { fileLines, parseAtxHeading } from "./vault-publish.js";
|
|
9
12
|
|
|
10
13
|
export type InsertVaultRegionResult =
|
|
11
14
|
| { ok: true; text: string; inserted: true }
|
|
@@ -26,13 +29,17 @@ export function insertMarkersUnderHeading(
|
|
|
26
29
|
|
|
27
30
|
const startMarker = `<!-- remnic:${opts.name}:start -->`;
|
|
28
31
|
const endMarker = `<!-- remnic:${opts.name}:end -->`;
|
|
29
|
-
if (fileText.includes(startMarker) && fileText.includes(endMarker)) {
|
|
30
|
-
return { ok: true, text: fileText, inserted: false };
|
|
31
|
-
}
|
|
32
|
-
|
|
33
32
|
const rows = fileLines(fileText);
|
|
33
|
+
// A fenced example pair is sample text, not a live region (issue #1985):
|
|
34
|
+
// only markers outside a code block count as "already present".
|
|
35
|
+
const present =
|
|
36
|
+
rows.some((row) => !row.fenced && row.line.includes(startMarker)) &&
|
|
37
|
+
rows.some((row) => !row.fenced && row.line.includes(endMarker));
|
|
38
|
+
if (present) return { ok: true, text: fileText, inserted: false };
|
|
39
|
+
|
|
34
40
|
const hits: Array<{ row: (typeof rows)[number]; level: number }> = [];
|
|
35
41
|
for (const row of rows) {
|
|
42
|
+
if (row.fenced) continue;
|
|
36
43
|
const heading = parseAtxHeading(row.line);
|
|
37
44
|
if (heading && heading.text === opts.heading) {
|
|
38
45
|
hits.push({ row, level: heading.level });
|
|
@@ -58,29 +65,3 @@ export function insertMarkersUnderHeading(
|
|
|
58
65
|
return { ok: true, text, inserted: true };
|
|
59
66
|
}
|
|
60
67
|
|
|
61
|
-
type FileLine = { line: string; start: number; next: number; number: number };
|
|
62
|
-
|
|
63
|
-
function fileLines(fileText: string): FileLine[] {
|
|
64
|
-
const rows: FileLine[] = [];
|
|
65
|
-
let start = 0;
|
|
66
|
-
let number = 1;
|
|
67
|
-
while (start < fileText.length) {
|
|
68
|
-
let i = start;
|
|
69
|
-
while (i < fileText.length && fileText[i] !== "\n" && fileText[i] !== "\r") i++;
|
|
70
|
-
let next = i;
|
|
71
|
-
if (fileText[i] === "\r" && fileText[i + 1] === "\n") next = i + 2;
|
|
72
|
-
else if (fileText[i] === "\n" || fileText[i] === "\r") next = i + 1;
|
|
73
|
-
else next = fileText.length;
|
|
74
|
-
rows.push({ line: fileText.slice(start, i), start, next, number });
|
|
75
|
-
number += 1;
|
|
76
|
-
start = next;
|
|
77
|
-
}
|
|
78
|
-
return rows;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
function parseAtxHeading(line: string): { level: number; text: string } | null {
|
|
82
|
-
let level = 0;
|
|
83
|
-
while (level < line.length && level < 6 && line[level] === "#") level++;
|
|
84
|
-
if (level === 0 || line[level] !== " ") return null;
|
|
85
|
-
return { level, text: line.slice(level + 1) };
|
|
86
|
-
}
|