Головна / Статті / Практичні поради: ваш Terraform Agent, ймовірно, помиляється наполовину часу

Практичні поради: ваш Terraform Agent, ймовірно, помиляється наполовину часу

Покрокове керівництво з практичних нотаток: ваш Terraform Agent, ймовірно, помиляється наполовину часу: контракти, перевірки та слоти для коду для команд, які використовують цю схему.

3334 слів

Наступні примітки описують практичний підхід до вирішення проблеми „Ваш Terraform Agent, ймовірно, помиляється наполовину часу“. Увага зосереджена на контрактах, перевірках та шаблонах коду, а не на мотиваційних аспектах. Під час етапу огляду спочатку запишіть контракт: необхідні вхідні дані, сигнал про успіх та те, що відбувається у разі часткової невдачі. Цей перелік допоможе зберегти чесність пізніших змін у коді. Розглядайте цей етап як контракт між вхідними даними та перевіреними результатами. Призначте назви елементам, визначте критерії успіху та не допускайте беззвучного часткового виконання завдань.

agent/       the deepagents Terraform agent, its tools, prompts, and skills
eval/        the verifier, 38 tasks with Rego policies, and the benchmark
optimizer/   the DSPy program, metric, and GEPA compile

Агент, якого ми використовуємо, працює найкраще, коли його розглядають як вимірювану поверхню. Запишіть один ідеальний приклад роботи, один випадок збою та примітки щодо скасування змін перед розширенням обсягу завдань. Записуйте час виконання та витрати на токени чи запити поруч із функціональними результатами. Чітке бачення витрат заздалегідь запобігає несподіваним рахункам під час переходу від демо-версії до спільних середовищ. Тримайте стан графа простим та типованим. Вкладені структури приховують інформацію про те, який вузол заповнив яке поле, що призводить до порушення послідовності виконання після перерв.

from deepagents import create_deep_agent

agent = create_deep_agent(
    model="openrouter:openai/gpt-5.6-luna",
    tools=[provider_schema, write_terraform, validate_config],
    system_prompt=SYSTEM_PROMPT,
    skills=["./agent/skills"],     # SKILL.md — the thing we'll optimize
)

Як насправді виглядає збій

Сценарій збою «What» працює найкраще, коли його розглядають як вимірювану поверхню. Збережіть один ідеальний запис, один випадок збою та примітку про скасування змін перед розширенням обсягу. Тримайте конфігурацію окремо від коду додатку. Файли середовища, сховища конфіденційних даних та флаги функцій мають знаходитися в одному місці, де оператори можуть їх перевіряти, не читаючи весь граф. Тримайте стан графа простим та типованим. Вкладені блоки приховують інформацію про те, який вузол записав яке поле, що ускладнює продовження роботи після перерв.

  encryption {
    kms_key_name = var.encryption_key_name
  }

  lifecycle_rules {
    ...
$ tofu validate

Error: Missing required argument
  on main.tf line 18, in resource "google_storage_bucket" "terraform_state":
The argument "default_kms_key_name" is required, but no definition was found.

Error: Unsupported argument
  on main.tf line 19, in resource "google_storage_bucket" "terraform_state":
An argument named "kms_key_name" is not expected here.

Error: Unsupported block type
  on main.tf line 22, in resource "google_storage_bucket" "terraform_state":
Blocks of type "lifecycle_rules" are not expected here. Did you mean
"lifecycle_rule"?
$ uv run python -m agent.run --task eval/tasks/backend-var-interpolation.json

task      backend-var-interpolation (opentofu)
model     openai/gpt-5.6-luna  engine=deepagents
files     main.tf, variables.tf
tools     {'write_terraform': 2, 'validate_config': 1, 'validate_pass': 1}
elapsed   56602ms

Оцінювач перед фреймворком: Terraform оцінює власну роботу

The A Scorer Before a stage працює найкраще, коли його розглядають як вимірювану поверхню. Збережіть один ідеальний запис, один випадок збою та примітку про скасування дій перед розширенням обсягу. Документуйте як успішний, так і відновлювальний шляхи. Повторні спроби, людський контроль та обробка некоректних повідомлень є частиною продукту, а не етапом подальшої оптимізації. Зберігайте стан графа у простому та типованому вигляді. Вкладені структури приховують інформацію про те, який вузол заповнив яке поле, і ускладнюють продовження роботи після перерв. The A Scorer Before a stage працює найкраще, коли його розглядають як вимірювану поверхню. Збережіть один ідеальний запис, один випадок збою та примітку про скасування дій перед розширенням обсягу. Розглядайте цей етап як контракт між вхідними даними та перевіреними результатами. Позначте всі елементи, визначте критерії успіху та не допускайте мовчазного часткового завершення роботи.

package main
import rego.v1

deny contains "bucket must use a customer-managed KMS key" if {
    some name
    bucket := input.resource.google_storage_bucket[name][_]
    not bucket.encryption
}
$ cd eval/tasks && ./check_policies.sh
  ...
  ✓ vpc-subnet-firewall              good=0 bad=2

✅ 38/38 policies verified in both directions

Впровадження DSPy

На етапі впровадження DSPy необхідно спочатку визначити вхідні дані, відповідального за крок та критерії завершення, перш ніж змінювати код. Оператори мають мати можливість перезапустити крок з відомої точки контролю, не намагаючись вгадати прихований стан. Записуйте час виконання та витрати на токени або запити поруч із функціональними результатами. Чітке відображення витрат заздалегідь запобігає несподіваним рахункам під час переходу з демо-середовища у спільні. Встановлюйте людське схвалення для кроків, які витрачають гроші або змінюють дані в продакшені. Підключення під час компіляції не є гарантією повності бізнес-функціоналу.

uv add dspy
uv sync

Етап 1: Програмування

На етапі програмування Фази 1 необхідно визначити вхідні дані, відповідальну особу за кожен крок та критерії завершення перед зміною коду. Оператори повинні мати можливість перезапустити крок з відомої точки контролю, не намагаючись визначити прихований стан. Конфігурацію слід тримати окремо від коду додатку. Файли середовища, сховища конфіденційних даних та флаги функцій мають знаходитися в одному місці, де оператори можуть їх перевіряти, не читаючи весь код. Необхідно передбачити людське схвалення для операцій, які призводять до витрат грошей чи змінюють дані у продакшені. Підключення на етапі компіляції не є гарантією повноти бізнес-функціоналу.

import dspy

class AuthorConfiguration(dspy.Signature):
    """Write a complete, valid Infrastructure-as-Code configuration."""

    request: str = dspy.InputField(
        desc="What the user wants built, in natural language."
    )
    target: str = dspy.InputField(
        desc="Which dialect to target: 'terraform' or 'opentofu'. These have "
             "diverged — code targeting the wrong one will fail validation."
    )
    config: str = dspy.OutputField(
        desc="The complete configuration as fenced HCL blocks. Start each block "
             "with a comment naming its file, e.g. '# main.tf'."
    )
dspy.inspect_history(n=1)
System message:

Your input fields are:
1. `request` (str): What the user wants built, in natural language.
2. `target` (str): Which dialect to target: 'terraform' or 'opentofu'. ...
Your output fields are:
1. `config` (str): The complete configuration as fenced HCL blocks. ...

[[ ## request ## ]]
{request}

[[ ## target ## ]]
{target}

[[ ## config ## ]]
{config}

In adhering to this structure, your objective is:
        Write a complete, valid Infrastructure-as-Code configuration ...
generate = dspy.Predict(AuthorConfiguration)             # one shot
generate = dspy.ChainOfThought(AuthorConfiguration)      # reason first
generate = dspy.ReAct(AuthorConfiguration, tools=[...])  # run a tool loop
from agent.tools import make_tools            # the deployed agent's tools

class TerraformAuthoringAgent(dspy.Module):
    def __init__(self, seed_instruction: str):
        super().__init__()
        # Seed the SIGNATURE before constructing ReAct, so DSPy appends its
        # tool protocol to your instruction instead of replacing it.
        seeded = AuthorConfiguration.with_instructions(seed_instruction)
        lc_tools = make_tools(work_dir, binary="terraform", stats={})
        self.react = dspy.ReAct(
            seeded,
            tools=[dspy.Tool(t.func, name=t.name, desc=t.description)
                   for t in lc_tools.values()],
            max_iters=10,
        )

    def forward(self, request: str, target: str = "terraform"):
        return self.react(request=request, target=target)

Фаза 2: Оцінка

На етапі оцінки другої фази необхідно визначити вхідні дані, відповідальну особу за кожен крок та критерії завершення перед зміною коду. Оператори повинні мати можливість знову виконати крок з відомої точки контролю, не намагаючись вгадати прихований стан. Необхідно документувати як шлях успішного виконання, так і шлях відновлення. Повторні спроби, людський контроль та обробка некоректних повідомлень є частиною продукту, а не етапом подальшої доробки. Встановлюйте людське схвалення для тих кроків, які призводять до витрат грошей чи змінюють дані у продакшені. Компіляційне підключення елементів не є гарантією повноти функціоналу продукту. На етапі оцінки другої фази необхідно визначити вхідні дані, відповідальну особу за кожен крок та критерії завершення перед зміною коду. Оператори повинні мати можливість знову виконати крок з відомої точки контролю, не намагаючись вгадати прихований стан. Розглядайте цей етап як контракт між вхідними даними та перевіреними результатами. Називайте всі елементи, визначайте критерії успіху та не допускайте безповідомного часткового завершення роботи.

dataset = [
    dspy.Example(
        task_id=t["id"],
        request=t["prompt"],
        target=t["target"],
        rego=t["rego"],                # path to this task's policy
    ).with_inputs("request", "target")
    for t in tasks
]
def verify_metric(example, prediction, trace=None, pred_name=None, pred_trace=None):
    """Score with the SAME verifier that produces our benchmark numbers."""
    result = verify(
        config_dir=materialise(prediction.config),
        policy_dir=example.rego,
        target=example.target,
    )

    # Job 1 — bootstrapping (trace is set): a strict bool. Only outputs that
    # FULLY pass may become worked examples.
    if trace is not None:
        return result.passed

    # Job 2 — reflective optimization (pred_name is set): score AND feedback.
    # GEPA reads the text to understand *why* a candidate failed.
    if pred_name is not None:
        return dspy.Prediction(score=result.score, feedback=format_failures(result))

    # Job 3 — plain evaluation: a float.
    return result.score
evaluate = dspy.Evaluate(devset=valset, metric=verify_metric,
                         num_threads=8, display_table=True)
evaluate(program)
Average Metric: 0.59 / 3 (19.6%): 100%|██████████| 3/3 [01:16<00:00, 25.60s/it]
INFO dspy.evaluate.evaluate: Average Metric: 0.5882 / 3 (19.6%)
WARNING dspy.evaluate.evaluate: Skipping table display since `pandas` is not installed.

Етап 3: Оптимізація

Під час роботи над етапом оптимізації спочатку запишіть умови контракту: необхідні вхідні дані, сигнал про успіх та те, що відбувається у разі часткової невдачі. Такий перелік допомагає зберігати чесність пізніших змін у коді. Записуйте час виконання та витрати на токени або запити поруч із функціональними результатами. Чітке бачення витрат заздалегідь запобігає несподіваним рахункам, коли процес переходить від демо-середовища до спільних середовищ. Робіть контрольні позначки після дорогих кроків. Функція відновлення не повинна знову стягувати плату за один і той самий виклик LLM, коли оператор перезапускає пізнішу ланку.

gepa = dspy.GEPA(
    metric=verify_metric,
    max_metric_calls=150,
    reflection_lm=dspy.LM("openrouter/openai/gpt-5.6-luna", max_tokens=16000),
    num_threads=8,
    track_stats=True,
)

compiled = gepa.compile(student=program, trainset=trainset, valset=valset)
compiled.save("compiled_state.json", save_program=False)

Робочий процес продовжує оплачуватися після оптимізації

Під час роботи над етапом оплати за робочий процес спочатку запишіть умови контракту: необхідні вхідні дані, сигнал про успіх та те, що відбувається у разі часткової невдачі. Такий перелік допомагає зберігати чесність пізніших змін у коді. Тримайте конфігурацію окремо від коду додатку. Файли середовища, сховища конфіденційних даних та флаги функцій мають знаходитися в одному місці, де оператори можуть їх перевіряти, не читаючи весь алгоритм. Робіть контрольні пункти після дорогих кроків. Функція відновлення не повинна знову стягувати плату за один і той самий виклик LLM, коли оператор перезапускає пізнішу ланку.

robust = dspy.Refine(module=program, N=3, reward_fn=verify_metric, threshold=1.0)
program.set_lm(dspy.LM("openrouter/qwen/qwen3-coder-30b-a3b-instruct"))
evaluate(program)

Чесний результат

Під час роботи над етапом «Чесний результат» спочатку запишіть умови використання: необхідні дані вхіду, сигнал про успіх та те, що відбувається у разі часткової невдачі. Цей перелік допомагає зберігати чесність подальших змін у коді. Одночасно задокументуйте шлях успішного виконання та шлях відновлення. Повторні спроби, людський контроль та обробка некоректних повідомлень є частиною продукту, а не етапом подальшої доробки. Робіть контрольні пункти після дорогих кроків. Система відновлення не повинна знову стягувати плату за той самий виклик ШІ, коли оператор намагається виконати наступний етап. Під час роботи над етапом «Чесний результат» спочатку запишіть умови використання: необхідні дані вхіду, сигнал про успіх та те, що відбувається у разі часткової невдачі. Цей перелік допомагає зберігати чесність подальших змін у коді. Розглядайте цей етап як угоду між даними вхіду та перевіреними результатами. Позначте всі елементи, визначте критерії успіху та не допускайте безповідомного часткового завершення роботи.

Висновок

Етап висновків працює найкраще, якщо його розглядати як вимірювану поверхню. Запишіть один ідеальний результат, один випадок збою та примітку про скасування змін перед розширенням обсягу роботи. Записуйте час виконання та витрати на токени чи запити поруч із функціональними результатами. Візуалізація витрат заздалегідь запобігає несподіваним рахункам під час переходу від демо-середовища до спільних середовищ. Тримайте стан графа простим та типованим. Вкладені блоки приховують інформацію про те, який вузол заповнив яке поле, і ускладнюють продовження роботи після перерв.

Чек-лист операцій

На етапі чек-листу операцій необхідно визначити вхідні дані, відповідальну особу за крок та критерії завершення перед зміною коду. Оператори повинні мати можливість перезапустити крок з відомої точки контролю, не здогадуючись про прихований стан. Краще використовувати невеликі, перевірювані одиниці коду замість об’ємних скриптів. Якщо крок зазнає невдачі, причина має вказувати на конкретну відповідальність, а не на заплутану послідовність дій.

Необхідно отримувати людське схвалення для операцій, які спричиняють витрати грошей чи змінюють дані виробництва. Підключення під час компіляції не є гарантією повноти бізнес-процесу.

Напишіть короткий посібник: як змінювати ключі, як спорожнювати чергу, як скасовувати останні операції вставки даних.

Розглядайте цей етап як контракт між вхідними даними та перевіреними результатами. Позначте всі елементи, визначте критерії успіху та не допускайте мовчазного часткового виконання завдань.

Необхідно отримувати людське схвалення для операцій, які спричиняють витрати грошей чи змінюють дані виробництва. Підключення під час компіляції не є гарантією повноти бізнес-процесу.

Перш ніж підвищувати рівень складності системи, заморозьте версії, створіть остаточний запис для критичного шляху виконання та підтвердьте кроки скасування змін. У спільних середовищах необхідні обмеження на швидкість виконання операцій, перевірки прав доступу та чіткий власник для зміни секретних даних. Віддавайте перевагу надійності перед креативними одноразовими демонстраціями.

Примітка до пакету c9e85f3f670f: не включайте ключі постачальників у репозиторій, встановіть ліміт токенів на кожну сесію та зберігайте транскрипції поруч із фіксами для оцінки, щоб подальша заміна моделей залишалася порівнянною.

Під час роботи над етапом 0 примітки щодо посилення безпеки спочатку запишіть контракт: необхідні вхідні дані, сигнал про успіх та те, що відбувається при частковій невдачі. Цей перелік допомагає зберігати чесність у подальших змінах коду. Зберігайте конфігурацію окремо від коду додатку. Файли середовища, сховища секретів та флаги функцій мають знаходитися в одному місці, яке оператори можуть перевіряти, не читаючи весь код.

Деталь посилення безпеки 0/880: вимірюйте час виконання, клас помилки та витрату токенів для цієї примітки, а потім вирішуйте, чи залишити зміни, ґрунтуючись на фіксованому наборі питань, а не на індивідуальних спостереженнях.

Етап 1 процедури зміцнення найкраще функціонує, якщо його розглядати як вимірювану поверхню. Збережіть один ідеальний зразок виконання, один випадок збою та запис про скасування змін перед розширенням обсягу роботи. Віддавайте перевагу невеликим, тестованим одиницям перед складними скриптами. Коли якийсь крок зазнає невдачі, причина має вказувати на конкретну відповідальність, а не на заплутану послідовність дій.

Деталь зміцнення 1/880: виміряйте час виконання, клас помилки та кількість витрачених токенів для цього запису, а потім вирішіть, чи залишити зміни, ґрунтуючись на фіксованому наборі питань, а не на окремих прикладах.

Для другого етапу процедури зміцнення необхідно визначити вхідні дані, відповідальну особу за крок та критерії завершення перед зміною коду. Оператори повинні мати можливість перезапустити крок з відомої точки контролю, не здогадуючись про прихований стан системи. Поруч із функціональними результатами слід записувати час виконання та витрати на токени або запити. Чітке бачення витрат заздалегідь запобігає несподіваним рахункам під час переходу з демо-середовища у спільні середовища.

Деталь зміцнення 2/880: вимірюйте час виконання, клас помилок та витрати на токени для цього етапу, а потім вирішуйте, чи залишити зміни, ґрунтуючись на фіксованому наборі питань, а не на індивідуальних спостереженнях.

Під час виконання третього етапу додаткових заходів зпрочнення спочатку запишіть умови контракту: необхідні вхідні дані, сигнал про успіх та те, що відбувається у разі часткової невдачі. Цей перелік допомагає зберігати чесність пізніших змін у коді. Документуйте як шлях успішної роботи, так і шлях відновлення одночасно. Повторні спроби, людський контроль та обробка некоректних повідомлень є частиною продукту, а не етапом подальшої доробки.

Деталі заходу зпрочнення 3/880: вимірюйте час виконання, клас помилки та кількість витрачених токенів для цього заходу, а потім вирішуйте, чи зберегти зміни, ґрунтуючись на фіксованому наборі критеріїв, а не на окремих випадках.

Четвертий етап додаткових заходів зпрочнення працює найкраще, якщо його розглядати як вимірювану поверхню. Збережіть один ідеальний запис виконання, один випадок невдачі та запис про скасування змін перед розширенням обсягу роботи. Розглядайте цей етап як контракт між вхідними даними та перевіреними результатами. Позначте всі елементи, визначте критерії успіху та не допускайте мовчазного часткового завершення роботи.

Деталь посилення безпеки 4/880: виміряйте час виконання, клас помилки та кількість витрачених токенів для цього запису, а потім вирішіть, чи залишити зміни, ґрунтуючись на фіксованому наборі питань, а не на окремих випадках.

На стадії 5 запису про посилення безпеки необхідно визначити вхідні дані, власника кроку та критерії завершення перед зміною коду. Оператори повинні мати можливість перезапустити крок з відомої точки контролю, не здогадуючись про прихований стан. Зберігайте конфігурацію окремо від коду додатку. Файли середовища, сховища секретів та флаги функцій мають знаходитися в одному місці, яке оператори можуть перевірити, не читаючи весь код.

Деталь посилення безпеки 5/880: виміряйте час виконання, клас помилки та кількість витрачених токенів для цього запису, а потім вирішіть, чи залишити зміни, ґрунтуючись на фіксованому наборі питань, а не на окремих випадках.

Під час виконання 6-го етапу інструкцій з посилення безпеки спочатку запишіть умови контракту: необхідні вхідні дані, сигнал про успіх та те, що відбувається у разі часткової невдачі. Такий перелік допомагає зберігати чесність пізніших змін у коді. Краще використовувати невеликі, перевірювані одиниці коду замість об’ємних скриптів. Коли якийсь крок зазнає невдачі, причина має вказувати на конкретну відповідальність, а не на складну систему взаємозв’язків.

Деталь посилення безпеки 6/880: вимірюйте час виконання, клас помилки та кількість витрачених токенів для цього етапу, а потім вирішуйте, чи залишити зміни, ґрунтуючись на фіксованому наборі критеріїв, а не на індивідуальних спостереженнях.

7-й етап інструкцій з посилення безпеки найкраще працює, якщо його розглядати як вимірювану поверхню. Збережіть один ідеальний зразок виконання, один випадок невдачі та запис про скасування змін перед розширенням обсягу роботи. Записуйте час виконання та витрати на токени чи запити поруч із функціональними результатами. Чітке бачення витрат заздалегідь запобігає несподіваним витратам під час переходу з демо-середовища до спільних середовищ.

Деталь посилення безпеки 7/880: виміряйте час виконання, клас помилки та кількість витрачених токенів для цього запису, а потім вирішіть, чи залишити зміни, ґрунтуючись на фіксованому наборі питань, а не на окремих випадках.

На 8-му етапі додатку посилення безпеки визначте вхідні дані, відповідальну особу за крок та критерії завершення перед зміною коду. Оператори повинні мати можливість перезапустити крок з відомої точки контролю, не здогадуючись про прихований стан. Документуйте як успішний, так і відновлювальний сценарії. Повторні спроби, людський контроль та обробка некоректних повідомлень є частиною продукту, а не етапом подальшої оптимізації.

Деталь посилення безпеки 8/880: виміряйте час виконання, клас помилки та кількість витрачених токенів для цього запису, а потім вирішіть, чи залишити зміни, ґрунтуючись на фіксованому наборі питань, а не на окремих випадках.

Під час виконання етапу 9 інструкцій з посилення безпеки спочатку запишіть угоду: необхідні вхідні дані, сигнал про успіх та те, що відбувається у разі часткової невдачі. Цей перелік допомагає зберігати чесність пізніших змін у коді. Розглядайте цей етап як угоду між вхідними даними та перевіреними результатами. Дайте назви елементам, визначте критерії успіху та не допускайте мовчазного часткового виконання завдань.

Деталь посилення безпеки 9/880: вимірюйте час виконання, клас помилки та кількість витрачених ресурсів для цього етапу, а потім вирішуйте, чи залишити зміни, ґрунтуючись на фіксованому наборі питань, а не на індивідуальних спостереженнях.

Етап 10 інструкцій з посилення безпеки найкраще працює, якщо його розглядати як вимірювану поверхню. Збережіть один ідеальний зразок роботи, один випадок невдачі та запис про скасування змін перед розширенням обсягу роботи. Тримайте конфігурацію окремо від коду програми. Файли середовища, сховища секретних даних та флаги функцій мають знаходитися в одному місці, де оператори можуть їх перевіряти, не читаючи весь код.

Деталь посилення безпеки 10/880: виміряйте час виконання, клас помилки та кількість витрачених токенів для цього запису, а потім вирішіть, чи залишити зміни, ґрунтуючись на фіксованому наборі питань, а не на окремих випадках.

На етапі 11 процесу посилення безпеки необхідно визначити вхідні дані, відповідальну особу та критерії завершення перед зміною коду. Оператори повинні мати можливість перезапустити крок з відомої точки контролю, не здогадуючись про прихований стан. Краще використовувати невеликі, перевірювані одиниці коду замість об’ємних скриптів. Якщо крок зазнає невдачі, причина має вказувати на конкретну відповідальність, а не на складну структуру обробки даних.

Деталь посилення безпеки 11/880: виміряйте час виконання, клас помилки та кількість витрачених токенів для цього запису, а потім вирішіть, чи залишити зміни, ґрунтуючись на фіксованому наборі питань, а не на окремих випадках.

Під час виконання 12-го етапу процедури зміцнення спочатку запишіть умови контракту: необхідні вхідні дані, сигнал про успіх та те, що відбувається у разі часткової невдачі. Такий перелік допомагає зберігати чесність пізніших змін у коді. Поруч із функціональними результатами задокументуйте час виконання та витрати на токени або запити. Чітке бачення витрат заздалегідь запобігає несподіваним рахункам під час переходу з демо-середовища до спільних.

Деталь зміцнення 12/880: виміряйте час виконання, клас помилки та витрати на токени для цього етапу, а потім вирішіть, чи залишити зміну, ґрунтуючись на фіксованому наборі питань, а не на індивідуальних спостереженнях.

13-й етап процедури зміцнення найкраще працює, якщо його розглядати як вимірювану поверхню. Збережіть один ідеальний запис виконання, один випадок невдачі та запис про скасування змін перед розширенням обсягу роботи. Документуйте як успішний, так і відновлювальний сценарії. Повторні спроби, людські контролі та обробка некоректних повідомлень є частиною продукту, а не етапом подальшої доробки.

Деталь посилення безпеки 13/880: виміряйте час виконання, клас помилки та кількість витрачених токенів для цього запису, а потім вирішіть, чи залишити зміни, ґрунтуючись на фіксованому наборі питань, а не на окремих випадках.

На етапі 14 процесу посилення безпеки необхідно визначити вхідні дані, відповідальну особу та критерії завершення перед зміною коду. Оператори повинні мати можливість знову виконати цей крок, починаючи з відомої точки контролю, без необхідності здогадуватися про прихований стан. Вважайте цей етап контрактом між вхідними даними та перевіреними результатами. Позначте всі елементи, визначте критерії успіху та не допускайте мовчазного часткового завершення роботи.

Деталь посилення безпеки 14/880: виміряйте час виконання, клас помилки та кількість витрачених токенів для цього запису, а потім вирішіть, чи залишити зміни, ґрунтуючись на фіксованому наборі питань, а не на окремих випадках.