atif-sql 0.2.0__py3-none-any.whl

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.
Files changed (164) hide show
  1. atif_analytics/__init__.py +9 -0
  2. atif_analytics/application/__init__.py +3 -0
  3. atif_analytics/application/analyze.py +158 -0
  4. atif_analytics/application/prompts.py +750 -0
  5. atif_analytics/application/use_cases/__init__.py +3 -0
  6. atif_analytics/application/use_cases/_shared.py +264 -0
  7. atif_analytics/application/use_cases/classify.py +430 -0
  8. atif_analytics/application/use_cases/conflicts.py +448 -0
  9. atif_analytics/application/use_cases/friction.py +634 -0
  10. atif_analytics/application/use_cases/perceived.py +451 -0
  11. atif_analytics/domain/__init__.py +3 -0
  12. atif_analytics/domain/authorship.py +166 -0
  13. atif_analytics/domain/config.py +30 -0
  14. atif_analytics/domain/costs.py +50 -0
  15. atif_analytics/domain/friction.py +117 -0
  16. atif_analytics/domain/layout.py +94 -0
  17. atif_analytics/domain/models.py +385 -0
  18. atif_analytics/domain/ports.py +100 -0
  19. atif_analytics/domain/transcript.py +359 -0
  20. atif_analytics/infrastructure/__init__.py +3 -0
  21. atif_analytics/infrastructure/corpus_reader.py +546 -0
  22. atif_analytics/infrastructure/parquet_cache.py +186 -0
  23. atif_analytics/infrastructure/settings.py +114 -0
  24. atif_analytics/infrastructure/sqlite_state/__init__.py +3 -0
  25. atif_analytics/infrastructure/sqlite_state/checkpointer.py +326 -0
  26. atif_analytics/infrastructure/sqlite_state/retry_queue.py +296 -0
  27. atif_analytics/py.typed +0 -0
  28. atif_cli/__init__.py +3 -0
  29. atif_cli/__main__.py +8 -0
  30. atif_cli/app.py +2459 -0
  31. atif_cli/converter_adapter.py +151 -0
  32. atif_cli/corpus.py +409 -0
  33. atif_cli/cron.py +311 -0
  34. atif_cli/duck_errors.py +97 -0
  35. atif_cli/embed_lake.py +101 -0
  36. atif_cli/errors.py +89 -0
  37. atif_cli/lake.py +373 -0
  38. atif_cli/lake_sessions.py +270 -0
  39. atif_cli/output.py +297 -0
  40. atif_cli/py.typed +0 -0
  41. atif_converter/__init__.py +3 -0
  42. atif_converter/application/__init__.py +3 -0
  43. atif_converter/application/convert_and_audit.py +294 -0
  44. atif_converter/application/convert_codex.py +210 -0
  45. atif_converter/domain/__init__.py +9 -0
  46. atif_converter/domain/agents.py +40 -0
  47. atif_converter/domain/atif/__init__.py +55 -0
  48. atif_converter/domain/atif/agent.py +37 -0
  49. atif_converter/domain/atif/content.py +161 -0
  50. atif_converter/domain/atif/final_metrics.py +45 -0
  51. atif_converter/domain/atif/metrics.py +49 -0
  52. atif_converter/domain/atif/observation.py +21 -0
  53. atif_converter/domain/atif/observation_result.py +47 -0
  54. atif_converter/domain/atif/step.py +144 -0
  55. atif_converter/domain/atif/subagent_trajectory_ref.py +90 -0
  56. atif_converter/domain/atif/tool_call.py +36 -0
  57. atif_converter/domain/atif/trajectory.py +211 -0
  58. atif_converter/domain/atif/trajectory_validator.py +299 -0
  59. atif_converter/domain/blobs.py +510 -0
  60. atif_converter/domain/claude_code_conversion.py +1077 -0
  61. atif_converter/domain/codex_conversion.py +1036 -0
  62. atif_converter/domain/codex_edges.py +192 -0
  63. atif_converter/domain/codex_enrichment.py +419 -0
  64. atif_converter/domain/codex_fidelity.py +124 -0
  65. atif_converter/domain/codex_nested_calls.py +165 -0
  66. atif_converter/domain/edges.py +113 -0
  67. atif_converter/domain/enrichment.py +412 -0
  68. atif_converter/domain/errors.py +60 -0
  69. atif_converter/domain/fidelity.py +171 -0
  70. atif_converter/domain/model_prices.json +8538 -0
  71. atif_converter/domain/pricing.py +790 -0
  72. atif_converter/domain/result_signals.py +774 -0
  73. atif_converter/domain/schema_version.py +90 -0
  74. atif_converter/domain/session_events.py +408 -0
  75. atif_converter/infrastructure/__init__.py +3 -0
  76. atif_converter/infrastructure/census.py +89 -0
  77. atif_converter/infrastructure/claude_code_converter.py +127 -0
  78. atif_converter/infrastructure/codex_adapter.py +132 -0
  79. atif_converter/infrastructure/codex_census.py +100 -0
  80. atif_converter/infrastructure/codex_converter.py +82 -0
  81. atif_converter/infrastructure/harbor_adapter.py +187 -0
  82. atif_converter/infrastructure/raw_records.py +426 -0
  83. atif_converter/infrastructure/source_archive.py +154 -0
  84. atif_converter/py.typed +0 -0
  85. atif_corpus/__init__.py +13 -0
  86. atif_corpus/application/__init__.py +7 -0
  87. atif_corpus/application/materialize.py +1826 -0
  88. atif_corpus/domain/__init__.py +9 -0
  89. atif_corpus/domain/agents.py +33 -0
  90. atif_corpus/domain/generation.py +34 -0
  91. atif_corpus/domain/layout.py +168 -0
  92. atif_corpus/domain/ports.py +175 -0
  93. atif_corpus/domain/session_id.py +68 -0
  94. atif_corpus/domain/sessions.py +228 -0
  95. atif_corpus/domain/slug.py +72 -0
  96. atif_corpus/domain/source_layout.py +143 -0
  97. atif_corpus/domain/watermark.py +76 -0
  98. atif_corpus/infrastructure/__init__.py +7 -0
  99. atif_corpus/infrastructure/atomic.py +266 -0
  100. atif_corpus/infrastructure/compress_artifacts.py +161 -0
  101. atif_corpus/infrastructure/fake_converter.py +174 -0
  102. atif_corpus/infrastructure/scanner.py +316 -0
  103. atif_corpus/infrastructure/settings.py +130 -0
  104. atif_corpus/infrastructure/source_archive.py +202 -0
  105. atif_corpus/py.typed +0 -0
  106. atif_duck/__init__.py +43 -0
  107. atif_duck/domain/__init__.py +32 -0
  108. atif_duck/domain/artifacts.py +66 -0
  109. atif_duck/domain/authorship.py +165 -0
  110. atif_duck/domain/catalog.py +626 -0
  111. atif_duck/domain/columnar.py +149 -0
  112. atif_duck/domain/embedding_guard.py +88 -0
  113. atif_duck/domain/examples.py +265 -0
  114. atif_duck/domain/lake.py +427 -0
  115. atif_duck/domain/lake_sessions.py +97 -0
  116. atif_duck/domain/raw_readers.py +140 -0
  117. atif_duck/domain/session_id.py +69 -0
  118. atif_duck/domain/sql_literal.py +50 -0
  119. atif_duck/infrastructure/__init__.py +34 -0
  120. atif_duck/infrastructure/analytics.py +469 -0
  121. atif_duck/infrastructure/authorship.py +139 -0
  122. atif_duck/infrastructure/columnar.py +641 -0
  123. atif_duck/infrastructure/lake.py +1383 -0
  124. atif_duck/infrastructure/lake_sessions.py +194 -0
  125. atif_duck/infrastructure/lake_settings.py +63 -0
  126. atif_duck/infrastructure/lake_steps.py +225 -0
  127. atif_duck/infrastructure/projections.py +221 -0
  128. atif_duck/infrastructure/registry.py +2194 -0
  129. atif_duck/infrastructure/stored_artifacts.py +115 -0
  130. atif_duck/py.typed +0 -0
  131. atif_embed/__init__.py +12 -0
  132. atif_embed/application/__init__.py +3 -0
  133. atif_embed/application/embed.py +293 -0
  134. atif_embed/application/prune.py +80 -0
  135. atif_embed/domain/__init__.py +3 -0
  136. atif_embed/domain/discovery.py +70 -0
  137. atif_embed/domain/embedding_guard.py +83 -0
  138. atif_embed/domain/errors.py +94 -0
  139. atif_embed/domain/ports.py +223 -0
  140. atif_embed/domain/sql_literal.py +49 -0
  141. atif_embed/domain/text_stamp.py +71 -0
  142. atif_embed/infrastructure/__init__.py +3 -0
  143. atif_embed/infrastructure/cohere_bedrock.py +433 -0
  144. atif_embed/infrastructure/corpus_text_rows.py +273 -0
  145. atif_embed/infrastructure/gemma_local.py +355 -0
  146. atif_embed/infrastructure/lake_text_rows.py +203 -0
  147. atif_embed/infrastructure/lance_store.py +440 -0
  148. atif_embed/infrastructure/providers.py +30 -0
  149. atif_embed/infrastructure/settings.py +154 -0
  150. atif_embed/py.typed +0 -0
  151. atif_models/__init__.py +14 -0
  152. atif_models/domain/__init__.py +9 -0
  153. atif_models/domain/ports.py +143 -0
  154. atif_models/domain/registry.py +151 -0
  155. atif_models/domain/schema.py +109 -0
  156. atif_models/infrastructure/__init__.py +8 -0
  157. atif_models/infrastructure/openai_bedrock.py +314 -0
  158. atif_models/infrastructure/settings.py +85 -0
  159. atif_models/py.typed +0 -0
  160. atif_sql-0.2.0.dist-info/METADATA +272 -0
  161. atif_sql-0.2.0.dist-info/RECORD +164 -0
  162. atif_sql-0.2.0.dist-info/WHEEL +4 -0
  163. atif_sql-0.2.0.dist-info/entry_points.txt +2 -0
  164. atif_sql-0.2.0.dist-info/licenses/LICENSE +202 -0
atif_duck/__init__.py ADDED
@@ -0,0 +1,43 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+
3
+ """atif-duck: DuckDB views over the materialized ATIF corpus.
4
+
5
+ Layered: ``infrastructure`` (DuckDB registry) > ``domain`` (static
6
+ view/macro catalog). ``register(con, corpus_root)`` wires a connection to a
7
+ CONTRACT-shaped corpus (``<root>/sessions/<id>/{trajectory.json,
8
+ edges.jsonl, loss_report.json, meta.json}``) and exposes the core query
9
+ surface: the views in :data:`VIEW_NAMES` (sessions / steps / messages /
10
+ tool_calls / user_steps / human_turns / session_outcomes / ...) plus the
11
+ macros in :data:`MACRO_NAMES`. The v2
12
+ analytics surface (``ANALYTICS_VIEW_NAMES``,
13
+ ``ANALYTICS_MACRO_SIGNATURES``) registers separately and needs
14
+ ``atif-sql analyze`` to have run.
15
+ """
16
+
17
+ from atif_duck.domain.catalog import (
18
+ DEFAULT_PRICING,
19
+ MACRO_NAMES,
20
+ MACRO_SIGNATURES,
21
+ VIEW_NAMES,
22
+ VIEW_SCHEMA,
23
+ )
24
+ from atif_duck.infrastructure.registry import (
25
+ RawSources,
26
+ register,
27
+ register_macros,
28
+ register_raw,
29
+ register_views,
30
+ )
31
+
32
+ __all__ = [
33
+ "DEFAULT_PRICING",
34
+ "MACRO_NAMES",
35
+ "MACRO_SIGNATURES",
36
+ "VIEW_NAMES",
37
+ "VIEW_SCHEMA",
38
+ "RawSources",
39
+ "register",
40
+ "register_macros",
41
+ "register_raw",
42
+ "register_views",
43
+ ]
@@ -0,0 +1,32 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+
3
+ """Domain layer: the static view/macro catalog for atif-duck.
4
+
5
+ Pure value objects — no duckdb import, no I/O. The catalog is the
6
+ agent-facing contract (`atif-sql schema` answers from here in <50ms with
7
+ zero DuckDB bind cost); drift against the actual DDL is caught by the
8
+ tests in ``tests/test_duck_views.py``.
9
+ """
10
+
11
+ from atif_duck.domain.catalog import (
12
+ DEFAULT_PRICING,
13
+ DESCRIPTIONS,
14
+ MACRO_NAMES,
15
+ MACRO_SIGNATURES,
16
+ TABLE_MACRO_NAMES,
17
+ VIEW_NAMES,
18
+ VIEW_SCHEMA,
19
+ )
20
+ from atif_duck.domain.examples import ExampleQuery, build_examples
21
+
22
+ __all__ = [
23
+ "DEFAULT_PRICING",
24
+ "DESCRIPTIONS",
25
+ "MACRO_NAMES",
26
+ "MACRO_SIGNATURES",
27
+ "TABLE_MACRO_NAMES",
28
+ "VIEW_NAMES",
29
+ "VIEW_SCHEMA",
30
+ "ExampleQuery",
31
+ "build_examples",
32
+ ]
@@ -0,0 +1,66 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+
3
+ """How the per-session JSON artifacts are stored: their names and their compression.
4
+
5
+ Three of the artifacts a session directory holds are the bulk of a corpus's
6
+ bytes: ``trajectory.json`` (the ATIF document), ``edges.jsonl`` and
7
+ ``session_events.jsonl``. materialize stores each of them zstd-compressed,
8
+ as ``<name>.zst``, and a corpus written before that keeps the plain file until
9
+ ``atif-sql corpus slim`` compresses it. Either spelling holds the same bytes
10
+ once decompressed, so every reader resolves the stored file per session
11
+ (:func:`stored_names`, the compressed one first) and nothing else about it
12
+ changes. ``meta.json`` and ``loss_report.json`` stay plain: they're small, and
13
+ ``meta.json`` is what the corpus writer and every reader check first.
14
+
15
+ A path a view reports (``sessions.trajectory_path``) names the logical
16
+ artifact, ``<session>/trajectory.json``, whichever spelling is on disk, so a
17
+ row reads the same before and after a corpus is slimmed.
18
+
19
+ atif-corpus writes these names and carries the twin constants; the cross-package
20
+ pin lives in atif-cli's tests, the one package that may import both.
21
+
22
+ Pure constants: no filesystem access.
23
+ """
24
+
25
+ from __future__ import annotations
26
+
27
+ #: The ATIF document.
28
+ TRAJECTORY_JSON: str = "trajectory.json"
29
+ #: One line per raw transcript record.
30
+ EDGES_JSONL: str = "edges.jsonl"
31
+ #: One line per kept non-message record.
32
+ SESSION_EVENTS_JSONL: str = "session_events.jsonl"
33
+ #: The completion marker every reader gates on (always plain).
34
+ META_JSON: str = "meta.json"
35
+ #: The fidelity report (always plain).
36
+ LOSS_REPORT_JSON: str = "loss_report.json"
37
+
38
+ #: The suffix a compressed artifact carries after its logical name.
39
+ COMPRESSED_SUFFIX: str = ".zst"
40
+
41
+ #: The artifacts materialize stores compressed.
42
+ COMPRESSED_ARTIFACTS: tuple[str, ...] = (TRAJECTORY_JSON, EDGES_JSONL, SESSION_EVENTS_JSONL)
43
+
44
+
45
+ def stored_names(name: str) -> tuple[str, ...]:
46
+ """The file names ``name`` may be stored under, in the order a reader tries them.
47
+
48
+ The compressed spelling comes first: a session caught between ``corpus
49
+ slim`` writing ``<name>.zst`` and removing ``<name>`` holds both, with the
50
+ same content, and either answer is right.
51
+ """
52
+ if name in COMPRESSED_ARTIFACTS:
53
+ return (f"{name}{COMPRESSED_SUFFIX}", name)
54
+ return (name,)
55
+
56
+
57
+ __all__ = [
58
+ "COMPRESSED_ARTIFACTS",
59
+ "COMPRESSED_SUFFIX",
60
+ "EDGES_JSONL",
61
+ "LOSS_REPORT_JSON",
62
+ "META_JSON",
63
+ "SESSION_EVENTS_JSONL",
64
+ "TRAJECTORY_JSON",
65
+ "stored_names",
66
+ ]
@@ -0,0 +1,165 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+
3
+ """Who wrote a user-role step: the ``author`` rule table and its SQL form.
4
+
5
+ Claude Code and Codex deliver a lot of machine-written text in the USER role:
6
+ Stop hook feedback, ``<task-notification>`` blocks, retry and continuation
7
+ nudges, skill bodies, slash-command wrappers, image metadata from a screenshot
8
+ the agent read, and the prompts of automated review sessions. Counted as
9
+ user turns they drown the human ones (on a busy agent corpus about half of
10
+ the main-chain user steps were machine-written), so every analytics reader
11
+ classifies a user step first and treats only ``human`` as the user
12
+ speaking.
13
+
14
+ The classification is a PREFIX match over the message with leading
15
+ whitespace stripped, first rule wins, in :data:`AUTHOR_PREFIX_RULES` order.
16
+ Prefixes only, so the SQL macro (``starts_with``) and the Python twin
17
+ (``str.startswith``) cannot disagree on a regex dialect. An empty message is
18
+ ``harness``: nothing a human typed. One rule sits outside the text: a step the
19
+ converter flagged ``is_compact_summary`` is ``harness`` whatever it says
20
+ (``user_steps.author`` and the Python twin both apply it; the bare
21
+ ``step_author`` macro sees only source and text).
22
+
23
+ This table is the ONE definition. atif-analytics may not import atif-duck
24
+ (independence contract), so ``atif_analytics.domain.authorship`` carries a
25
+ twin of the two tuples below, and ``tests/test_authorship_twin_pin.py`` reads
26
+ that twin as source text and fails on any difference (the ``session_id``
27
+ precedent).
28
+
29
+ Pure domain module: stdlib only, no duckdb.
30
+ """
31
+
32
+ from __future__ import annotations
33
+
34
+ from atif_duck.domain.sql_literal import SqlFragment, sql_literal
35
+
36
+ #: The author labels, in the order the docs list them.
37
+ AUTHOR_VALUES: tuple[str, ...] = (
38
+ "human",
39
+ "stop_hook",
40
+ "task_notification",
41
+ "harness",
42
+ "audit_prompt",
43
+ )
44
+
45
+ #: Characters stripped from the left of a message before matching.
46
+ AUTHOR_STRIP_CHARS: str = " \t\r\n"
47
+
48
+ #: ``(author, prefix)``, first match wins. Every prefix was read off real
49
+ #: Claude Code and Codex corpora in September 2026 as a most-common opening of
50
+ #: user-role steps; the comment beside each says what writes it.
51
+ AUTHOR_PREFIX_RULES: tuple[tuple[str, str], ...] = (
52
+ # An automated review session: a hook that audits another agent's turn
53
+ # opens a fresh session whose whole content is its prompt and a verdict.
54
+ ("audit_prompt", "You are auditing an agent turn"),
55
+ # Claude Code Stop / SubagentStop hooks that blocked the agent's stop.
56
+ ("stop_hook", "Stop hook feedback"),
57
+ ("stop_hook", "SubagentStop hook feedback"),
58
+ # Background task completion notices.
59
+ ("task_notification", "<task-notification>"),
60
+ ("task_notification", "[SYSTEM NOTIFICATION"),
61
+ # Claude Code bookkeeping: interrupts, continuation and retry nudges,
62
+ # compaction summaries, skill bodies, image metadata for a screenshot the
63
+ # agent read, workflow-computed tasks, reminders and hook output.
64
+ ("harness", "[Request interrupted"),
65
+ ("harness", "Continue from where you left off"),
66
+ ("harness", "Your previous attempt hit a transient"),
67
+ ("harness", "This session is being continued from a previous conversation"),
68
+ ("harness", "Base directory for this skill:"),
69
+ ("harness", "[Image: original "),
70
+ ("harness", '{"type": "image"'),
71
+ ("harness", "[Workflow harness"),
72
+ ("harness", "[structured-output-enforce]"),
73
+ ("harness", "<system-reminder>"),
74
+ ("harness", "<user-prompt-submit-hook>"),
75
+ ("harness", "UserPromptSubmit operation blocked by hook"),
76
+ ("harness", "<fork-boilerplate>"),
77
+ ("harness", "Another Claude session sent a message"),
78
+ ("harness", "The coordinator sent a message"),
79
+ # Slash-command and local-shell wrappers.
80
+ ("harness", "<command-name>"),
81
+ ("harness", "<command-message>"),
82
+ ("harness", "<command-args>"),
83
+ ("harness", "<local-command-stdout>"),
84
+ ("harness", "<local-command-stderr>"),
85
+ ("harness", "<local-command-caveat>"),
86
+ ("harness", "Caveat: The messages below were generated"),
87
+ ("harness", "<bash-input>"),
88
+ ("harness", "<bash-stdout>"),
89
+ ("harness", "<bash-stderr>"),
90
+ # Codex CLI context injections.
91
+ ("harness", "<environment_context>"),
92
+ ("harness", "<codex_internal_context"),
93
+ ("harness", "<user_instructions>"),
94
+ ("harness", "# AGENTS.md instructions"),
95
+ ("harness", "<turn_aborted>"),
96
+ ("harness", "The following is the Codex agent history"),
97
+ )
98
+
99
+ #: Prefixes that mark an interrupted turn (``session_outcomes.interrupts``).
100
+ #: Both are also ``harness`` rules above, so an interrupt never counts as a
101
+ #: human turn.
102
+ INTERRUPT_PREFIXES: tuple[str, ...] = ("[Request interrupted", "<turn_aborted>")
103
+
104
+
105
+ #: ``ltrim`` argument naming :data:`AUTHOR_STRIP_CHARS` by code point (space,
106
+ #: tab, CR, LF); ``test_authorship.py`` pins the two against each other.
107
+ _STRIP_CHARS_SQL = "chr(32) || chr(9) || chr(13) || chr(10)"
108
+
109
+ #: The stripped message inside the ``step_author(src, msg)`` macro body.
110
+ _MACRO_MSG_STRIPPED = f"ltrim(msg, {_STRIP_CHARS_SQL})"
111
+
112
+ #: The stripped ``message`` column, for predicates over ``steps`` rows.
113
+ _COLUMN_MSG_STRIPPED = f"ltrim(message, {_STRIP_CHARS_SQL})"
114
+
115
+
116
+ def _author_arms() -> SqlFragment:
117
+ """One ``WHEN starts_with(...) THEN '<author>'`` arm per rule, in order."""
118
+ return SqlFragment(
119
+ "\n".join(
120
+ f" WHEN starts_with({_MACRO_MSG_STRIPPED}, {sql_literal(prefix)}) "
121
+ f"THEN {sql_literal(author)}"
122
+ for author, prefix in AUTHOR_PREFIX_RULES
123
+ )
124
+ )
125
+
126
+
127
+ def _step_author_case() -> SqlFragment:
128
+ """The ``CASE`` expression behind the ``step_author(src, msg)`` macro.
129
+
130
+ ``NULL`` for a step whose source is not ``user``; otherwise ``harness`` for
131
+ an empty message, the first matching rule's author, and ``human`` when
132
+ nothing matches.
133
+ """
134
+ return SqlFragment(
135
+ "CASE\n WHEN src IS DISTINCT FROM 'user' THEN NULL\n"
136
+ f" WHEN msg IS NULL OR {_MACRO_MSG_STRIPPED} = '' THEN 'harness'\n"
137
+ f"{_author_arms()}\n ELSE 'human'\nEND"
138
+ )
139
+
140
+
141
+ def _interrupt_predicate() -> SqlFragment:
142
+ """``starts_with`` over :data:`INTERRUPT_PREFIXES` for the ``message`` column."""
143
+ return SqlFragment(
144
+ "("
145
+ + " OR ".join(
146
+ f"starts_with({_COLUMN_MSG_STRIPPED}, {sql_literal(prefix)})"
147
+ for prefix in INTERRUPT_PREFIXES
148
+ )
149
+ + ")"
150
+ )
151
+
152
+
153
+ #: The macro body and the interrupt test, rendered once from the tables above.
154
+ STEP_AUTHOR_CASE_SQL: SqlFragment = _step_author_case()
155
+ INTERRUPT_PREDICATE_SQL: SqlFragment = _interrupt_predicate()
156
+
157
+
158
+ __all__ = [
159
+ "AUTHOR_PREFIX_RULES",
160
+ "AUTHOR_STRIP_CHARS",
161
+ "AUTHOR_VALUES",
162
+ "INTERRUPT_PREDICATE_SQL",
163
+ "INTERRUPT_PREFIXES",
164
+ "STEP_AUTHOR_CASE_SQL",
165
+ ]