textus 0.55.1 → 0.56.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +175 -2768
- data/README.md +17 -18
- data/lib/textus/artifact.rb +8 -0
- data/lib/textus/errors.rb +2 -39
- data/lib/textus/human.rb +7 -0
- data/lib/textus/infra/adapters/concurrency_adapter.rb +15 -0
- data/lib/textus/infra/clock.rb +7 -0
- data/lib/textus/infra/database.rb +127 -0
- data/lib/textus/infra/file_system.rb +54 -0
- data/lib/textus/infra/locks.rb +50 -0
- data/lib/textus/infra/port/clock.rb +18 -0
- data/lib/textus/infra/port/publisher.rb +71 -0
- data/lib/textus/infra/port/sentinel.rb +25 -0
- data/lib/textus/infra/port/sentinel_store.rb +93 -0
- data/lib/textus/infra/store/audit_log.rb +42 -0
- data/lib/textus/infra/store/base.rb +25 -0
- data/lib/textus/infra/store/cursor_store.rb +27 -0
- data/lib/textus/infra/store/entry_index.rb +31 -0
- data/lib/textus/infra/store/envelope/meta.rb +63 -0
- data/lib/textus/infra/store/file_store.rb +23 -0
- data/lib/textus/infra/store/index/builder.rb +28 -0
- data/lib/textus/infra/store/index/lookup.rb +23 -0
- data/lib/textus/infra/store/link_store.rb +43 -0
- data/lib/textus/infra/store/workflow_queue.rb +54 -0
- data/lib/textus/infra/store.rb +29 -0
- data/lib/textus/ingest.rb +8 -0
- data/lib/textus/lanes/artifact/cache.rb +35 -0
- data/lib/textus/lanes/artifact/handlers.rb +29 -0
- data/lib/textus/lanes/artifact/lifecycle.rb +23 -0
- data/lib/textus/lanes/artifact/verbs.rb +18 -0
- data/lib/textus/lanes/ingest/dedup.rb +17 -0
- data/lib/textus/lanes/ingest/entry_types/asset.rb +45 -0
- data/lib/textus/lanes/ingest/entry_types/link.rb +16 -0
- data/lib/textus/lanes/ingest/entry_types/text.rb +17 -0
- data/lib/textus/lanes/ingest/entry_types.rb +25 -0
- data/lib/textus/lanes/ingest/handlers.rb +54 -0
- data/lib/textus/lanes/ingest/index_rebuilder.rb +13 -0
- data/lib/textus/lanes/ingest/key_builder.rb +33 -0
- data/lib/textus/lanes/ingest/resolver.rb +21 -0
- data/lib/textus/lanes/knowledge/freeform.rb +15 -0
- data/lib/textus/lanes/knowledge/handlers.rb +53 -0
- data/lib/textus/lanes/knowledge/runner.rb +45 -0
- data/lib/textus/lanes/knowledge/verbs.rb +16 -0
- data/lib/textus/lanes/scratchpad/handlers.rb +164 -0
- data/lib/textus/lanes/scratchpad/verbs.rb +73 -0
- data/lib/textus/{gate → protocol}/binder.rb +2 -10
- data/lib/textus/protocol/boot/catalog.rb +34 -0
- data/lib/textus/protocol/boot/context.rb +124 -0
- data/lib/textus/protocol/boot/protocol.rb +33 -0
- data/lib/textus/protocol/boot.rb +42 -0
- data/lib/textus/protocol/builder/domain.rb +17 -0
- data/lib/textus/protocol/builder/infrastructure.rb +17 -0
- data/lib/textus/protocol/builder/runtime.rb +46 -0
- data/lib/textus/protocol/builder.rb +11 -0
- data/lib/textus/protocol/container.rb +22 -0
- data/lib/textus/protocol/diff.rb +170 -0
- data/lib/textus/protocol/entry_constraint.rb +54 -0
- data/lib/textus/protocol/envelope.rb +70 -0
- data/lib/textus/protocol/format/base.rb +80 -0
- data/lib/textus/protocol/format/bash.rb +10 -0
- data/lib/textus/protocol/format/javascript.rb +10 -0
- data/lib/textus/protocol/format/json.rb +82 -0
- data/lib/textus/protocol/format/markdown.rb +53 -0
- data/lib/textus/protocol/format/python.rb +10 -0
- data/lib/textus/protocol/format/ruby.rb +10 -0
- data/lib/textus/protocol/format/script.rb +55 -0
- data/lib/textus/protocol/format/text.rb +48 -0
- data/lib/textus/protocol/format/yaml.rb +105 -0
- data/lib/textus/protocol/format.rb +73 -0
- data/lib/textus/protocol/freshness/ttl_evaluator.rb +61 -0
- data/lib/textus/protocol/gate.rb +61 -0
- data/lib/textus/protocol/handlers/command_context.rb +19 -0
- data/lib/textus/protocol/handlers/concern.rb +15 -0
- data/lib/textus/protocol/handlers/ops/audit_filter.rb +37 -0
- data/lib/textus/protocol/handlers/ops/bulk_planner.rb +38 -0
- data/lib/textus/protocol/handlers/ops/data_mv.rb +49 -0
- data/lib/textus/protocol/handlers/ops/git_blame.rb +65 -0
- data/lib/textus/protocol/handlers/ops/pulse_coordinator.rb +37 -0
- data/lib/textus/protocol/handlers/ops/source_expander.rb +41 -0
- data/lib/textus/protocol/handlers/query_context.rb +41 -0
- data/lib/textus/protocol/handlers/read.rb +67 -0
- data/lib/textus/protocol/handlers/system.rb +93 -0
- data/lib/textus/protocol/handlers/write.rb +57 -0
- data/lib/textus/protocol/init.rb +143 -0
- data/lib/textus/protocol/key/grammar.rb +35 -0
- data/lib/textus/protocol/key/matching.rb +23 -0
- data/lib/textus/protocol/key/path.rb +23 -0
- data/lib/textus/protocol/key.rb +25 -0
- data/lib/textus/protocol/lane.rb +12 -0
- data/lib/textus/{store/geometry.rb → protocol/layout.rb} +32 -22
- data/lib/textus/protocol/links/resolver.rb +33 -0
- data/lib/textus/protocol/links/uri_rewriter.rb +30 -0
- data/lib/textus/protocol/links.rb +10 -0
- data/lib/textus/protocol/manifest/data.rb +90 -0
- data/lib/textus/protocol/manifest/entry/base.rb +95 -0
- data/lib/textus/protocol/manifest/entry/leaf.rb +19 -0
- data/lib/textus/protocol/manifest/entry/nested.rb +19 -0
- data/lib/textus/protocol/manifest/entry/parser.rb +71 -0
- data/lib/textus/protocol/manifest/entry/publish.rb +209 -0
- data/lib/textus/protocol/manifest/entry.rb +10 -0
- data/lib/textus/protocol/manifest/policy/publish_target.rb +36 -0
- data/lib/textus/protocol/manifest/policy.rb +69 -0
- data/lib/textus/protocol/manifest/resolver.rb +156 -0
- data/lib/textus/protocol/manifest/schema/contract.rb +53 -0
- data/lib/textus/protocol/manifest/schema/validator.rb +52 -0
- data/lib/textus/protocol/manifest/schema.rb +40 -0
- data/lib/textus/protocol/manifest.rb +62 -0
- data/lib/textus/protocol/produce/render/context.rb +43 -0
- data/lib/textus/protocol/produce/render.rb +44 -0
- data/lib/textus/protocol/schema/registry.rb +44 -0
- data/lib/textus/protocol/schema/tools.rb +104 -0
- data/lib/textus/protocol/schema.rb +117 -0
- data/lib/textus/protocol/session/bridge.rb +11 -0
- data/lib/textus/protocol/session/context.rb +5 -0
- data/lib/textus/protocol/session.rb +87 -0
- data/lib/textus/protocol/store_engine/delete.rb +37 -0
- data/lib/textus/protocol/store_engine/move.rb +109 -0
- data/lib/textus/protocol/store_engine/pipeline.rb +61 -0
- data/lib/textus/protocol/store_engine/put.rb +104 -0
- data/lib/textus/protocol/store_engine.rb +86 -0
- data/lib/textus/protocol/v4.rb +25 -0
- data/lib/textus/protocol/verb_registry/arg_spec.rb +19 -0
- data/lib/textus/protocol/verb_registry/core_verbs.rb +164 -0
- data/lib/textus/protocol/verb_registry/verb_spec.rb +42 -0
- data/lib/textus/protocol/verb_registry.rb +42 -0
- data/lib/textus/surface/cli/group/{rule.rb → web.rb} +2 -2
- data/lib/textus/surface/cli/runner.rb +25 -25
- data/lib/textus/surface/cli/sources.rb +1 -3
- data/lib/textus/surface/cli/verb/get.rb +3 -6
- data/lib/textus/surface/cli/verb/init.rb +1 -1
- data/lib/textus/surface/cli/verb/put.rb +8 -6
- data/lib/textus/surface/cli/verb/web_serve.rb +22 -0
- data/lib/textus/surface/cli.rb +25 -6
- data/lib/textus/surface/dispatch.rb +17 -0
- data/lib/textus/surface/mcp/adapters/mcp_adapter.rb +28 -0
- data/lib/textus/surface/mcp/catalog.rb +26 -62
- data/lib/textus/surface/mcp/cursor_manager.rb +22 -0
- data/lib/textus/surface/mcp/drift_annotation.rb +19 -0
- data/lib/textus/surface/mcp/errors.rb +0 -10
- data/lib/textus/surface/mcp/server.rb +46 -46
- data/lib/textus/surface/watcher.rb +18 -12
- data/lib/textus/surface/web.rb +50 -0
- data/lib/textus/value/call.rb +1 -1
- data/lib/textus/{core → value}/duration.rb +1 -4
- data/lib/textus/value/etag.rb +7 -7
- data/lib/textus/value/payload.rb +7 -0
- data/lib/textus/version.rb +1 -1
- data/lib/textus/workflow/consumer.rb +39 -0
- data/lib/textus/workflow/dsl/lifecycle.rb +32 -0
- data/lib/textus/workflow/dsl/pattern_matcher.rb +20 -0
- data/lib/textus/workflow/dsl/step_builder.rb +56 -0
- data/lib/textus/workflow/dsl.rb +111 -21
- data/lib/textus/workflow/event_emitter.rb +21 -0
- data/lib/textus/workflow/publisher.rb +59 -0
- data/lib/textus/workflow/registry.rb +31 -8
- data/lib/textus/workflow/runner.rb +25 -61
- data/lib/textus/workflow/scheduler.rb +45 -0
- data/lib/textus/workflow/step_executor.rb +78 -0
- data/lib/textus/workflow/step_helpers.rb +102 -0
- data/lib/textus/workflow.rb +2 -5
- data/lib/textus.rb +16 -80
- metadata +167 -183
- data/SPEC.md +0 -908
- data/docs/architecture/README.md +0 -273
- data/docs/reference/conventions.md +0 -138
- data/lib/textus/action/accept.rb +0 -46
- data/lib/textus/action/audit.rb +0 -94
- data/lib/textus/action/base.rb +0 -42
- data/lib/textus/action/blame.rb +0 -79
- data/lib/textus/action/boot.rb +0 -15
- data/lib/textus/action/data_mv.rb +0 -58
- data/lib/textus/action/deps.rb +0 -19
- data/lib/textus/action/doctor.rb +0 -17
- data/lib/textus/action/drain.rb +0 -31
- data/lib/textus/action/enqueue.rb +0 -37
- data/lib/textus/action/get.rb +0 -34
- data/lib/textus/action/ingest.rb +0 -199
- data/lib/textus/action/jobs.rb +0 -27
- data/lib/textus/action/key_delete.rb +0 -26
- data/lib/textus/action/key_delete_prefix.rb +0 -35
- data/lib/textus/action/key_mv.rb +0 -122
- data/lib/textus/action/key_mv_prefix.rb +0 -48
- data/lib/textus/action/list.rb +0 -28
- data/lib/textus/action/propose.rb +0 -42
- data/lib/textus/action/published.rb +0 -22
- data/lib/textus/action/pulse.rb +0 -49
- data/lib/textus/action/put.rb +0 -38
- data/lib/textus/action/rdeps.rb +0 -24
- data/lib/textus/action/reject.rb +0 -28
- data/lib/textus/action/rule_explain.rb +0 -81
- data/lib/textus/action/rule_lint.rb +0 -62
- data/lib/textus/action/rule_list.rb +0 -38
- data/lib/textus/action/schema_envelope.rb +0 -22
- data/lib/textus/action/uid.rb +0 -19
- data/lib/textus/action/where.rb +0 -21
- data/lib/textus/boot.rb +0 -202
- data/lib/textus/contract/arg.rb +0 -10
- data/lib/textus/contract/dsl.rb +0 -88
- data/lib/textus/contract/spec.rb +0 -25
- data/lib/textus/contract.rb +0 -12
- data/lib/textus/core/freshness/evaluator.rb +0 -150
- data/lib/textus/core/freshness/verdict.rb +0 -34
- data/lib/textus/core/freshness.rb +0 -11
- data/lib/textus/core/retention/sweep.rb +0 -57
- data/lib/textus/core/retention.rb +0 -11
- data/lib/textus/core/sentinel.rb +0 -30
- data/lib/textus/doctor/check/audit_log.rb +0 -34
- data/lib/textus/doctor/check/generator_drift.rb +0 -29
- data/lib/textus/doctor/check/illegal_keys.rb +0 -60
- data/lib/textus/doctor/check/manifest_files.rb +0 -25
- data/lib/textus/doctor/check/notebook_sources.rb +0 -50
- data/lib/textus/doctor/check/orphaned_publish_targets.rb +0 -35
- data/lib/textus/doctor/check/proposal_targets.rb +0 -45
- data/lib/textus/doctor/check/protocol_version.rb +0 -47
- data/lib/textus/doctor/check/publish_tree_index_overlap.rb +0 -48
- data/lib/textus/doctor/check/raw_asset_paths.rb +0 -50
- data/lib/textus/doctor/check/rule_ambiguity.rb +0 -49
- data/lib/textus/doctor/check/schema_parse_error.rb +0 -28
- data/lib/textus/doctor/check/schema_violations.rb +0 -28
- data/lib/textus/doctor/check/schemas.rb +0 -26
- data/lib/textus/doctor/check/sentinels.rb +0 -60
- data/lib/textus/doctor/check/stale_reviewed_stamp.rb +0 -54
- data/lib/textus/doctor/check/templates.rb +0 -29
- data/lib/textus/doctor/check/unowned_schema_fields.rb +0 -40
- data/lib/textus/doctor/check.rb +0 -41
- data/lib/textus/doctor/validator.rb +0 -93
- data/lib/textus/doctor.rb +0 -54
- data/lib/textus/format/base.rb +0 -49
- data/lib/textus/format/json.rb +0 -102
- data/lib/textus/format/markdown.rb +0 -80
- data/lib/textus/format/shared.rb +0 -17
- data/lib/textus/format/text.rb +0 -55
- data/lib/textus/format/yaml.rb +0 -125
- data/lib/textus/format.rb +0 -46
- data/lib/textus/gate/auth.rb +0 -212
- data/lib/textus/gate.rb +0 -92
- data/lib/textus/init.rb +0 -157
- data/lib/textus/jobs.rb +0 -9
- data/lib/textus/key/distance.rb +0 -55
- data/lib/textus/key/grammar.rb +0 -33
- data/lib/textus/key/matching.rb +0 -24
- data/lib/textus/key/path.rb +0 -28
- data/lib/textus/manifest/capabilities.rb +0 -29
- data/lib/textus/manifest/data.rb +0 -102
- data/lib/textus/manifest/entry/base.rb +0 -105
- data/lib/textus/manifest/entry/ignore_matcher.rb +0 -46
- data/lib/textus/manifest/entry/leaf.rb +0 -17
- data/lib/textus/manifest/entry/nested.rb +0 -37
- data/lib/textus/manifest/entry/parser.rb +0 -99
- data/lib/textus/manifest/entry/produced.rb +0 -36
- data/lib/textus/manifest/entry/publish/mode.rb +0 -45
- data/lib/textus/manifest/entry/publish/none.rb +0 -14
- data/lib/textus/manifest/entry/publish/subtree_mirror.rb +0 -73
- data/lib/textus/manifest/entry/publish/template.rb +0 -16
- data/lib/textus/manifest/entry/publish/to_paths.rb +0 -76
- data/lib/textus/manifest/entry/publish/tree.rb +0 -50
- data/lib/textus/manifest/entry/publish.rb +0 -45
- data/lib/textus/manifest/entry/validators/format_matrix.rb +0 -21
- data/lib/textus/manifest/entry/validators/ignore.rb +0 -28
- data/lib/textus/manifest/entry/validators/publish.rb +0 -30
- data/lib/textus/manifest/entry/validators.rb +0 -18
- data/lib/textus/manifest/entry.rb +0 -8
- data/lib/textus/manifest/policy/matcher.rb +0 -51
- data/lib/textus/manifest/policy/publish_target.rb +0 -34
- data/lib/textus/manifest/policy/react.rb +0 -30
- data/lib/textus/manifest/policy/retention.rb +0 -29
- data/lib/textus/manifest/policy/source.rb +0 -30
- data/lib/textus/manifest/policy.rb +0 -95
- data/lib/textus/manifest/resolver.rb +0 -118
- data/lib/textus/manifest/rules.rb +0 -86
- data/lib/textus/manifest/schema/contract.rb +0 -61
- data/lib/textus/manifest/schema/keys.rb +0 -90
- data/lib/textus/manifest/schema/semantics/cross_field.rb +0 -53
- data/lib/textus/manifest/schema/semantics/invariants.rb +0 -125
- data/lib/textus/manifest/schema/semantics/migration.rb +0 -83
- data/lib/textus/manifest/schema/semantics.rb +0 -27
- data/lib/textus/manifest/schema/validator.rb +0 -48
- data/lib/textus/manifest/schema/vocabulary.rb +0 -25
- data/lib/textus/manifest/schema.rb +0 -30
- data/lib/textus/manifest.rb +0 -65
- data/lib/textus/meta.rb +0 -54
- data/lib/textus/port/audit_log.rb +0 -268
- data/lib/textus/port/build_lock.rb +0 -64
- data/lib/textus/port/clock.rb +0 -10
- data/lib/textus/port/publisher.rb +0 -60
- data/lib/textus/port/sentinel_store.rb +0 -83
- data/lib/textus/port/storage/file_stat.rb +0 -19
- data/lib/textus/port/storage/file_store.rb +0 -26
- data/lib/textus/port/store.rb +0 -93
- data/lib/textus/port/watcher_lock.rb +0 -48
- data/lib/textus/produce/engine.rb +0 -50
- data/lib/textus/produce/render.rb +0 -20
- data/lib/textus/schema/tools.rb +0 -115
- data/lib/textus/schema.rb +0 -100
- data/lib/textus/schemas.rb +0 -54
- data/lib/textus/store/compositor.rb +0 -34
- data/lib/textus/store/container.rb +0 -43
- data/lib/textus/store/cursor.rb +0 -26
- data/lib/textus/store/envelope/reader.rb +0 -43
- data/lib/textus/store/envelope/writer.rb +0 -195
- data/lib/textus/store/index/builder.rb +0 -74
- data/lib/textus/store/index/lookup.rb +0 -60
- data/lib/textus/store/jobs/base.rb +0 -13
- data/lib/textus/store/jobs/index.rb +0 -15
- data/lib/textus/store/jobs/materialize.rb +0 -15
- data/lib/textus/store/jobs/plan.rb +0 -11
- data/lib/textus/store/jobs/planner.rb +0 -104
- data/lib/textus/store/jobs/queue.rb +0 -154
- data/lib/textus/store/jobs/registry.rb +0 -19
- data/lib/textus/store/jobs/retention.rb +0 -50
- data/lib/textus/store/jobs/sweep.rb +0 -21
- data/lib/textus/store/jobs/worker.rb +0 -64
- data/lib/textus/store/session.rb +0 -37
- data/lib/textus/store.rb +0 -99
- data/lib/textus/surface/cli/verb/doctor.rb +0 -19
- data/lib/textus/surface/cli/verb/schema_diff.rb +0 -17
- data/lib/textus/surface/cli/verb/schema_init.rb +0 -21
- data/lib/textus/surface/cli/verb/schema_migrate.rb +0 -21
- data/lib/textus/surface/mcp.rb +0 -8
- data/lib/textus/surface/projector.rb +0 -27
- data/lib/textus/surface/role_scope.rb +0 -34
- data/lib/textus/value/command.rb +0 -16
- data/lib/textus/value/envelope.rb +0 -89
- data/lib/textus/value/result.rb +0 -26
- data/lib/textus/workflow/collector.rb +0 -27
- data/lib/textus/workflow/context.rb +0 -5
- data/lib/textus/workflow/loader.rb +0 -17
- data/lib/textus/workflow/pattern.rb +0 -18
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Textus
|
|
4
|
-
module Action
|
|
5
|
-
class KeyMvPrefix < Base
|
|
6
|
-
verb :key_mv_prefix
|
|
7
|
-
summary "Bulk-rename every leaf key under from_prefix to to_prefix. Dry-run returns a Plan; apply with dry_run: false."
|
|
8
|
-
surfaces :cli, :mcp
|
|
9
|
-
cli "key mv-prefix"
|
|
10
|
-
arg :from_prefix, String, required: true, positional: true,
|
|
11
|
-
description: "dotted prefix whose leaf keys are renamed"
|
|
12
|
-
arg :to_prefix, String, required: true, positional: true,
|
|
13
|
-
description: "dotted prefix the keys are renamed to"
|
|
14
|
-
arg :dry_run, :boolean, default: false,
|
|
15
|
-
description: "when true, returns the planned moves without applying them; defaults " \
|
|
16
|
-
"to false, so omitting it applies the rename immediately"
|
|
17
|
-
view { |v, _i| v.to_h }
|
|
18
|
-
|
|
19
|
-
def self.call(container:, call:, from_prefix:, to_prefix:, dry_run: false)
|
|
20
|
-
return Failure(code: :usage_error, message: "from_prefix and to_prefix required") if from_prefix.nil? || to_prefix.nil?
|
|
21
|
-
|
|
22
|
-
leaves = Textus::Action::List.leaf_keys(container: container, prefix: from_prefix)
|
|
23
|
-
|
|
24
|
-
if leaves.include?(from_prefix)
|
|
25
|
-
return Failure(code: :usage_error,
|
|
26
|
-
message: "from_prefix '#{from_prefix}' is itself a leaf — use `mv` to rename a single key")
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
warnings = []
|
|
30
|
-
warnings << "no keys under #{from_prefix}" if leaves.empty?
|
|
31
|
-
|
|
32
|
-
steps = leaves.map do |old_key|
|
|
33
|
-
tail = old_key.delete_prefix("#{from_prefix}.")
|
|
34
|
-
new_key = "#{to_prefix}.#{tail}"
|
|
35
|
-
{ "op" => "mv", "from" => old_key, "to" => new_key }
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
plan = Textus::Store::Jobs::Plan.new(steps: steps, warnings: warnings)
|
|
39
|
-
return Success(plan) if dry_run
|
|
40
|
-
|
|
41
|
-
steps.each do |step|
|
|
42
|
-
Value::Result.unwrap(Textus::Action::KeyMv.call(container: container, call: call, old_key: step["from"], new_key: step["to"]))
|
|
43
|
-
end
|
|
44
|
-
Success(plan)
|
|
45
|
-
end
|
|
46
|
-
end
|
|
47
|
-
end
|
|
48
|
-
end
|
data/lib/textus/action/list.rb
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Textus
|
|
4
|
-
module Action
|
|
5
|
-
class List < Base
|
|
6
|
-
verb :list
|
|
7
|
-
summary "List keys filtered by lane and/or prefix."
|
|
8
|
-
surfaces :cli, :mcp
|
|
9
|
-
arg :prefix, String,
|
|
10
|
-
description: "restrict to keys starting with this dotted prefix, e.g. 'knowledge.runbooks'"
|
|
11
|
-
arg :lane, String,
|
|
12
|
-
description: "restrict to one lane by name (see `boot` lanes); combine with prefix to narrow further"
|
|
13
|
-
view(:cli) { |rows| { "entries" => rows } }
|
|
14
|
-
|
|
15
|
-
def self.call(container:, call: nil, prefix: nil, lane: nil) # rubocop:disable Lint/UnusedMethodArgument
|
|
16
|
-
manifest = container.manifest
|
|
17
|
-
rows = manifest.resolver.enumerate(prefix: prefix)
|
|
18
|
-
rows = rows.select { |row| row[:manifest_entry].lane == lane } if lane
|
|
19
|
-
Success(rows.map { |row| { "key" => row[:key], "lane" => row[:manifest_entry].lane, "path" => row[:path] } })
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
def self.leaf_keys(container:, prefix: nil, lane: nil)
|
|
23
|
-
rows = Value::Result.unwrap(call(container: container, prefix: prefix, lane: lane))
|
|
24
|
-
rows.map { |row| row.is_a?(Hash) ? (row["key"] || row[:key]) : row }
|
|
25
|
-
end
|
|
26
|
-
end
|
|
27
|
-
end
|
|
28
|
-
end
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Textus
|
|
4
|
-
module Action
|
|
5
|
-
class Propose < Base
|
|
6
|
-
verb :propose
|
|
7
|
-
summary "Write a proposal to the role's propose_lane. Auto-prefixes the key."
|
|
8
|
-
surfaces :cli, :mcp
|
|
9
|
-
cli_stdin :json
|
|
10
|
-
arg :key, String, required: true, positional: true,
|
|
11
|
-
description: "key relative to propose_lane, e.g. 'decisions.feature-x'"
|
|
12
|
-
arg :meta, Hash, required: false, wire_name: :_meta,
|
|
13
|
-
description: "frontmatter; reads back as `_meta` from `get`. Include a 'proposal:' block naming the target_key"
|
|
14
|
-
arg :body, String,
|
|
15
|
-
description: "markdown/text payload for markdown-format entries; omit (use `content`) for json/yaml entries. Do not send both"
|
|
16
|
-
arg :content, Hash,
|
|
17
|
-
description: "structured payload for json/yaml-format entries; omit (use `body`) for markdown entries. Do not send both"
|
|
18
|
-
view { |env, _i| env.to_h_for_wire }
|
|
19
|
-
|
|
20
|
-
def self.call(container:, call:, key:, meta: nil, body: nil, content: nil)
|
|
21
|
-
zone = container.manifest.policy.propose_lane_for(call.role)
|
|
22
|
-
unless zone
|
|
23
|
-
return Failure(code: :propose_forbidden,
|
|
24
|
-
message: "role '#{call.role}' has no writable propose_lane",
|
|
25
|
-
details: { "role" => call.role })
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
mentry = container.manifest.resolver.resolve("#{zone}.#{key}").entry
|
|
29
|
-
Success(container.compositor.write(
|
|
30
|
-
"#{zone}.#{key}",
|
|
31
|
-
mentry: mentry,
|
|
32
|
-
payload: Textus::Store::Envelope::Writer::Payload.new(
|
|
33
|
-
meta: meta || {},
|
|
34
|
-
body: body,
|
|
35
|
-
content: content,
|
|
36
|
-
),
|
|
37
|
-
call: call,
|
|
38
|
-
))
|
|
39
|
-
end
|
|
40
|
-
end
|
|
41
|
-
end
|
|
42
|
-
end
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Textus
|
|
4
|
-
module Action
|
|
5
|
-
class Published < Base
|
|
6
|
-
verb :published
|
|
7
|
-
summary "List all entries that declare a publish_to target."
|
|
8
|
-
surfaces :cli
|
|
9
|
-
cli "published"
|
|
10
|
-
|
|
11
|
-
def args
|
|
12
|
-
{}
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
def self.call(container:, **)
|
|
16
|
-
Success(container.manifest.data.entries.reject { |entry| entry.publish_to.empty? }.map do |entry|
|
|
17
|
-
{ "key" => entry.key, "publish_to" => entry.publish_to }
|
|
18
|
-
end)
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
end
|
|
22
|
-
end
|
data/lib/textus/action/pulse.rb
DELETED
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require "time"
|
|
4
|
-
|
|
5
|
-
module Textus
|
|
6
|
-
module Action
|
|
7
|
-
class Pulse < Base
|
|
8
|
-
verb :pulse
|
|
9
|
-
summary "Delta since cursor — changed entries, pending proposals, index freshness."
|
|
10
|
-
surfaces :cli, :mcp
|
|
11
|
-
arg :since, Integer, session_default: :cursor,
|
|
12
|
-
description: "audit seq to diff from; defaults to the session cursor"
|
|
13
|
-
|
|
14
|
-
def self.call(container:, call:, since: nil, **)
|
|
15
|
-
manifest = container.manifest
|
|
16
|
-
audit_log = container.audit_log
|
|
17
|
-
root = container.root
|
|
18
|
-
since ||= Textus::Store::Cursor.new(root: root, role: call.role).read
|
|
19
|
-
|
|
20
|
-
changed = Value::Result.unwrap(Textus::Action::Audit.call(container: container, seq_since: since))
|
|
21
|
-
|
|
22
|
-
result = {
|
|
23
|
-
"cursor" => audit_log.latest_seq,
|
|
24
|
-
"changed" => changed,
|
|
25
|
-
"pending_review" => review_keys(manifest, container),
|
|
26
|
-
"contract_etag" => Textus::Value::Etag.for_contract(root),
|
|
27
|
-
"index_etag" => index_etag(container),
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
Textus::Store::Cursor.new(root: root, role: call.role).write(result["cursor"])
|
|
31
|
-
Success(result)
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
def self.review_keys(manifest, container)
|
|
35
|
-
queue = manifest.policy.queue_lane
|
|
36
|
-
return [] unless queue
|
|
37
|
-
|
|
38
|
-
Textus::Action::List.leaf_keys(container: container, lane: queue)
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
def self.index_etag(container)
|
|
42
|
-
path = container.manifest.resolver.resolve("artifacts.system.index").path
|
|
43
|
-
File.exist?(path) ? container.file_store.etag(path) : nil
|
|
44
|
-
rescue Textus::Error
|
|
45
|
-
nil
|
|
46
|
-
end
|
|
47
|
-
end
|
|
48
|
-
end
|
|
49
|
-
end
|
data/lib/textus/action/put.rb
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Textus
|
|
4
|
-
module Action
|
|
5
|
-
class Put < Base
|
|
6
|
-
verb :put
|
|
7
|
-
summary "Create or update an entry. Schema-validated. Returns {uid, etag}."
|
|
8
|
-
surfaces :cli, :mcp
|
|
9
|
-
arg :key, String, required: true, positional: true,
|
|
10
|
-
description: "dotted entry key, e.g. 'knowledge.project'; must resolve to a zone the role may write"
|
|
11
|
-
arg :meta, Hash, required: false, wire_name: :_meta,
|
|
12
|
-
description: "frontmatter; reads back as `_meta` from `get`. Schema-validated — call `schema KEY` first"
|
|
13
|
-
arg :body, String,
|
|
14
|
-
description: "markdown/text payload for markdown-format entries; omit (use `content`) for json/yaml entries. Do not send both"
|
|
15
|
-
arg :content, Hash,
|
|
16
|
-
description: "structured payload for json/yaml-format entries; omit (use `body`) for markdown entries. Do not send both"
|
|
17
|
-
arg :if_etag, String,
|
|
18
|
-
description: "optimistic-concurrency guard: the etag you last read; the write is rejected if the entry changed since"
|
|
19
|
-
view { |env| { "uid" => env.uid, "etag" => env.etag } }
|
|
20
|
-
|
|
21
|
-
def self.call(container:, call:, key:, meta: nil, body: nil, content: nil, if_etag: nil) # rubocop:disable Metrics/ParameterLists
|
|
22
|
-
Textus::Manifest::Data.validate_key!(key)
|
|
23
|
-
mentry = container.manifest.resolver.resolve(key).entry
|
|
24
|
-
Success(container.compositor.write(
|
|
25
|
-
key,
|
|
26
|
-
mentry: mentry,
|
|
27
|
-
payload: Textus::Store::Envelope::Writer::Payload.new(
|
|
28
|
-
meta: meta,
|
|
29
|
-
body: body,
|
|
30
|
-
content: content,
|
|
31
|
-
),
|
|
32
|
-
if_etag: if_etag,
|
|
33
|
-
call: call,
|
|
34
|
-
))
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
end
|
|
38
|
-
end
|
data/lib/textus/action/rdeps.rb
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Textus
|
|
4
|
-
module Action
|
|
5
|
-
class Rdeps < Base
|
|
6
|
-
verb :rdeps
|
|
7
|
-
summary "List the derived entries that depend on a key (reverse deps / impact set)."
|
|
8
|
-
surfaces :cli, :mcp
|
|
9
|
-
arg :key, String, required: true, positional: true,
|
|
10
|
-
description: "dotted key whose dependents (what would be stranded if it moved) you want"
|
|
11
|
-
|
|
12
|
-
def self.call(container:, key:, **)
|
|
13
|
-
manifest = container.manifest
|
|
14
|
-
rdeps = manifest.data.entries.each_with_object([]) do |entry, acc|
|
|
15
|
-
next unless entry.external?
|
|
16
|
-
|
|
17
|
-
sources = Array(entry.source&.sources).compact
|
|
18
|
-
acc << entry.key if sources.any? { |source| source == key || key.start_with?("#{source}.") }
|
|
19
|
-
end
|
|
20
|
-
Success({ "key" => key, "rdeps" => rdeps })
|
|
21
|
-
end
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
end
|
data/lib/textus/action/reject.rb
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Textus
|
|
4
|
-
module Action
|
|
5
|
-
class Reject < Base
|
|
6
|
-
verb :reject
|
|
7
|
-
summary "discard a queued proposal without applying it"
|
|
8
|
-
surfaces :cli, :mcp
|
|
9
|
-
cli "reject"
|
|
10
|
-
arg :pending_key, String, required: true, positional: true, description: "the queued proposal's key"
|
|
11
|
-
|
|
12
|
-
def self.call(container:, call:, pending_key:)
|
|
13
|
-
mentry = container.manifest.resolver.resolve(pending_key).entry
|
|
14
|
-
unless mentry.in_proposal_lane?(container.manifest.policy)
|
|
15
|
-
return Failure(code: :proposal_error, message: "reject: '#{pending_key}' is not in a proposal zone (zone=#{mentry.lane})")
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
env = container.compositor.read(pending_key)
|
|
19
|
-
parsed = proposal_from(env, key: pending_key)
|
|
20
|
-
return parsed if parsed.is_a?(Dry::Monads::Result::Failure)
|
|
21
|
-
|
|
22
|
-
target_key = parsed[:target_key]
|
|
23
|
-
container.compositor.delete(pending_key, mentry: mentry, call: call)
|
|
24
|
-
Success("protocol" => Textus::PROTOCOL, "rejected" => pending_key, "target_key" => target_key)
|
|
25
|
-
end
|
|
26
|
-
end
|
|
27
|
-
end
|
|
28
|
-
end
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Textus
|
|
4
|
-
module Action
|
|
5
|
-
class RuleExplain < Base
|
|
6
|
-
verb :rule_explain
|
|
7
|
-
summary "Effective rules for a key. Lean {lifecycle, guard} by default; detail: true adds matched blocks + guard predicates."
|
|
8
|
-
surfaces :cli, :mcp
|
|
9
|
-
cli "rule explain"
|
|
10
|
-
arg :key, String, required: true, positional: true,
|
|
11
|
-
description: "dotted key whose effective rules you want (lifecycle ttl/action, write guard, ...)"
|
|
12
|
-
arg :detail, :boolean,
|
|
13
|
-
description: "defaults false: lean {lifecycle, guard}. detail: true adds matched blocks + guard predicates per transition."
|
|
14
|
-
view(:cli) { |r| { "verb" => "rule_explain" }.merge(r.transform_keys(&:to_s)) }
|
|
15
|
-
|
|
16
|
-
def self.call(container:, call:, key:, detail: nil) # rubocop:disable Lint/UnusedMethodArgument
|
|
17
|
-
manifest = container.manifest
|
|
18
|
-
Success(detail ? explain(manifest, key) : effective(manifest, key))
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
REGISTRY = Textus::Manifest::Schema::FIELD_REGISTRY
|
|
22
|
-
LEAN_FIELDS = REGISTRY.select { |_, m| m[:in_rule_explain].include?(:lean) }.keys.freeze
|
|
23
|
-
DETAIL_FIELDS = REGISTRY.select { |_, m| m[:in_rule_explain].include?(:detail) }.keys.freeze
|
|
24
|
-
EFFECTIVE_FIELDS = DETAIL_FIELDS.select { |f| REGISTRY[f][:policy_class] }.freeze
|
|
25
|
-
|
|
26
|
-
def self.effective(manifest, key)
|
|
27
|
-
set = manifest.rules.for(key)
|
|
28
|
-
LEAN_FIELDS.each_with_object({}) do |field, out|
|
|
29
|
-
value = set.public_send(field)
|
|
30
|
-
out[field.to_s] = lean_value(field, value) unless value.nil?
|
|
31
|
-
end
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
def self.lean_value(field, value)
|
|
35
|
-
case field
|
|
36
|
-
when :retention
|
|
37
|
-
retention_hash(value, string_keys: true)
|
|
38
|
-
when :react
|
|
39
|
-
value.to_h
|
|
40
|
-
else
|
|
41
|
-
value
|
|
42
|
-
end
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
def self.explain(manifest, key)
|
|
46
|
-
matching = manifest.rules.explain(key)
|
|
47
|
-
winners = manifest.rules.for(key)
|
|
48
|
-
{
|
|
49
|
-
key: key,
|
|
50
|
-
matched_blocks: matching.map do |block|
|
|
51
|
-
{ match: block.match }.merge(DETAIL_FIELDS.to_h { |f| [f, !block.public_send(f).nil?] })
|
|
52
|
-
end,
|
|
53
|
-
effective: EFFECTIVE_FIELDS.to_h { |f| [f, effective_value(f, winners.public_send(f))] },
|
|
54
|
-
guards: Textus::Gate::Auth::FLOOR.keys.to_h do |action|
|
|
55
|
-
floor = Textus::Gate::Auth::FLOOR.fetch(action, [])
|
|
56
|
-
rule = Array(manifest.rules.for(key).guard&.dig(action.to_s))
|
|
57
|
-
[action, { floor: floor, rule: rule }]
|
|
58
|
-
end,
|
|
59
|
-
}
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
def self.effective_value(field, value)
|
|
63
|
-
return nil if value.nil?
|
|
64
|
-
|
|
65
|
-
case field
|
|
66
|
-
when :retention
|
|
67
|
-
retention_hash(value, string_keys: false)
|
|
68
|
-
when :react
|
|
69
|
-
value.to_h
|
|
70
|
-
else
|
|
71
|
-
value
|
|
72
|
-
end
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
def self.retention_hash(retention, string_keys:)
|
|
76
|
-
h = { ttl_seconds: retention.ttl_seconds, action: retention.action }
|
|
77
|
-
string_keys ? h.transform_keys(&:to_s) : h
|
|
78
|
-
end
|
|
79
|
-
end
|
|
80
|
-
end
|
|
81
|
-
end
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require "yaml"
|
|
4
|
-
|
|
5
|
-
module Textus
|
|
6
|
-
module Action
|
|
7
|
-
class RuleLint < Base
|
|
8
|
-
verb :rule_lint
|
|
9
|
-
summary "Diff candidate manifest YAML's rules against the live manifest. No writes."
|
|
10
|
-
surfaces :cli, :mcp
|
|
11
|
-
cli "rule lint"
|
|
12
|
-
arg :candidate_yaml, String, required: true, wire_name: :against, source: :file,
|
|
13
|
-
description: "path to candidate manifest YAML; its `rules:` block is diffed against the live manifest"
|
|
14
|
-
view { |v, _i| v.to_h }
|
|
15
|
-
|
|
16
|
-
def self.call(container:, call:, candidate_yaml:) # rubocop:disable Lint/UnusedMethodArgument
|
|
17
|
-
root = container.root
|
|
18
|
-
live_rules = current_rules(root)
|
|
19
|
-
candidate_result = parse_candidate(candidate_yaml)
|
|
20
|
-
return candidate_result if candidate_result.is_a?(Dry::Monads::Result::Failure)
|
|
21
|
-
|
|
22
|
-
candidate_rules = candidate_result
|
|
23
|
-
|
|
24
|
-
live_by_match = live_rules.to_h { |rule| [rule["match"], rule] }
|
|
25
|
-
candidate_by_match = candidate_rules.to_h { |rule| [rule["match"], rule] }
|
|
26
|
-
|
|
27
|
-
steps = (candidate_by_match.keys - live_by_match.keys).map do |match|
|
|
28
|
-
{ "op" => "add_rule", "match" => match, "rule" => candidate_by_match[match] }
|
|
29
|
-
end
|
|
30
|
-
(live_by_match.keys - candidate_by_match.keys).each do |match|
|
|
31
|
-
steps << { "op" => "remove_rule", "match" => match }
|
|
32
|
-
end
|
|
33
|
-
(live_by_match.keys & candidate_by_match.keys).each do |match|
|
|
34
|
-
next if live_by_match[match] == candidate_by_match[match]
|
|
35
|
-
|
|
36
|
-
steps << {
|
|
37
|
-
"op" => "change_rule",
|
|
38
|
-
"match" => match,
|
|
39
|
-
"from" => live_by_match[match],
|
|
40
|
-
"to" => candidate_by_match[match],
|
|
41
|
-
}
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
Success(Textus::Store::Jobs::Plan.new(steps: steps, warnings: []))
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
def self.current_rules(root)
|
|
48
|
-
raw = YAML.safe_load_file(File.join(root, "manifest.yaml"), permitted_classes: [Symbol], aliases: false)
|
|
49
|
-
Array(raw["rules"])
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
def self.parse_candidate(yaml_text)
|
|
53
|
-
raw = YAML.safe_load(yaml_text, permitted_classes: [Symbol], aliases: false)
|
|
54
|
-
return Failure(code: :usage_error, message: "candidate is not a YAML mapping") unless raw.is_a?(Hash)
|
|
55
|
-
|
|
56
|
-
Array(raw["rules"])
|
|
57
|
-
rescue Psych::Exception => e
|
|
58
|
-
Failure(code: :usage_error, message: "candidate YAML parse error: #{e.message}")
|
|
59
|
-
end
|
|
60
|
-
end
|
|
61
|
-
end
|
|
62
|
-
end
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Textus
|
|
4
|
-
module Action
|
|
5
|
-
class RuleList < Base
|
|
6
|
-
verb :rule_list
|
|
7
|
-
summary "List every rule block in the manifest."
|
|
8
|
-
surfaces :cli
|
|
9
|
-
cli "rule list"
|
|
10
|
-
view(:cli) { |policies| { "verb" => "rule_list", "policies" => policies } }
|
|
11
|
-
|
|
12
|
-
def self.call(container:, call:, **_options) # rubocop:disable Lint/UnusedMethodArgument
|
|
13
|
-
manifest = container.manifest
|
|
14
|
-
Success(manifest.rules.blocks.map do |block|
|
|
15
|
-
row = { "match" => block.match }
|
|
16
|
-
LIST_FIELDS.each do |field|
|
|
17
|
-
value = block.public_send(field)
|
|
18
|
-
row[field.to_s] = serialize(field, value) unless value.nil?
|
|
19
|
-
end
|
|
20
|
-
row
|
|
21
|
-
end)
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
LIST_FIELDS = Textus::Manifest::Schema::FIELD_REGISTRY.select { |_, m| m[:in_rule_list] }.keys.freeze
|
|
25
|
-
|
|
26
|
-
def self.serialize(field, value)
|
|
27
|
-
case field
|
|
28
|
-
when :retention
|
|
29
|
-
{ "ttl_seconds" => value.ttl_seconds, "action" => value.action.to_s }
|
|
30
|
-
when :react
|
|
31
|
-
value.to_h
|
|
32
|
-
else
|
|
33
|
-
value
|
|
34
|
-
end
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
end
|
|
38
|
-
end
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Textus
|
|
4
|
-
module Action
|
|
5
|
-
class SchemaEnvelope < Base
|
|
6
|
-
verb :schema_show
|
|
7
|
-
summary "Return the schema (field shape) for an entry's family, by key."
|
|
8
|
-
surfaces :cli, :mcp
|
|
9
|
-
cli "schema show"
|
|
10
|
-
arg :key, String, required: true, positional: true,
|
|
11
|
-
description: "any key in the family whose schema you want; returns required/optional fields and their types"
|
|
12
|
-
|
|
13
|
-
def self.call(container:, key:, **)
|
|
14
|
-
manifest = container.manifest
|
|
15
|
-
schemas = container.schemas
|
|
16
|
-
mentry = manifest.resolver.resolve(key).entry
|
|
17
|
-
schema = schemas.fetch_or_nil(mentry.schema)
|
|
18
|
-
Success({ "protocol" => Textus::PROTOCOL, "key" => key, "schema_ref" => mentry.schema, "schema" => schema&.to_h })
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
end
|
|
22
|
-
end
|
data/lib/textus/action/uid.rb
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Textus
|
|
4
|
-
module Action
|
|
5
|
-
class Uid < Base
|
|
6
|
-
verb :uid
|
|
7
|
-
summary "Return the stable UID of an entry without reading its body."
|
|
8
|
-
surfaces :cli
|
|
9
|
-
cli "key uid"
|
|
10
|
-
arg :key, String, required: true, positional: true, description: "entry key"
|
|
11
|
-
view(:cli) { |uid, inputs| { "key" => inputs[:key], "uid" => uid } }
|
|
12
|
-
|
|
13
|
-
def self.call(container:, call:, key:)
|
|
14
|
-
envelope = Value::Result.unwrap(Textus::Action::Get.call(container: container, call: call, key: key))
|
|
15
|
-
Success(envelope.uid)
|
|
16
|
-
end
|
|
17
|
-
end
|
|
18
|
-
end
|
|
19
|
-
end
|
data/lib/textus/action/where.rb
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Textus
|
|
4
|
-
module Action
|
|
5
|
-
class Where < Base
|
|
6
|
-
verb :where
|
|
7
|
-
summary "Resolve a key to its zone, owner, and path without reading the body."
|
|
8
|
-
surfaces :cli, :mcp
|
|
9
|
-
arg :key, String, required: true, positional: true,
|
|
10
|
-
description: "dotted key to locate (returns zone, owner, path; does not read content)"
|
|
11
|
-
|
|
12
|
-
def self.call(container:, key:, call: nil) # rubocop:disable Lint/UnusedMethodArgument
|
|
13
|
-
manifest = container.manifest
|
|
14
|
-
res = manifest.resolver.resolve(key)
|
|
15
|
-
mentry = res.entry
|
|
16
|
-
path = res.path
|
|
17
|
-
Success({ "protocol" => Textus::PROTOCOL, "key" => key, "lane" => mentry.lane, "owner" => mentry.owner, "path" => path })
|
|
18
|
-
end
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
end
|