* TODO [2012-03-21 Wed] ri: perjelas status metadata utk arg, example, link, ... dan common propertiesnya

  istilah argument spec diganti jadi argument metadata? demikian juga link, ... jadi tag links itu adalah array of link metadata.
  
  properties common to all metadata (this include argument, link, example, ...):
  v, entity_version, default_lang, summary, description, tags, links
  
  properties for function metadata (function, ): name (pindah ke sini dari
  common), examples, ...
  
  atau buang aja "name"? selama ini name dipake buat apa ya? utk tau canonical
  name dari sebuah function doang?
  
  UPDATE sekarang juga ada tag metadata.

* TODO [2012-03-21 Wed] ri: default_lang dari arg spec (return spec, example spec, link spec, ...) mengikuti default_lang dari metadata?

  contoh:
  

      {default_lang=>"id_ID",
          ...
          args => {
              arg1 => {
                  summary => "in Indonesian or english?",
                  ...
              },
              ...
          },
          return => {
              summary => "in Indonesian or english?",
          },
          example => [
              {summary => "in Indoneisan? in English?",
               ...
              },
              ...
          ],
          links => [
              {summary => "in Indoneisan? in English?",
               ...
              },
              ...
          ],
      }
  
  jika mengikuti, maka saat melakukan translation (di langprop
  Perinci::Object::Metadata misalnya) kita harus menyertakan parent metadata.
  
  saat ini yang sederhananya sih kita selalu mengeset default_lang di spec ybs,
  agar tidak terjadi ambiguitas.
  

* TODO ri: test streaming output interface

  - result meta: streaming=>1, result payload coderef
  - output format can be text (direct dump) or (later) streaming yaml/json array
  - ATAU, ikuti PSGI, instead of enveloped result, return a coderef. this allows
    for delayed response. we can return the enveloped result later the coderef is
    called.
  - kita seharusnya membiasakan menggunakan ini:
  

      envres($res)->success
  
  instead of
  

      $res->[0] == 200
  
  karena dengan yang pertama, kode kita jadi otomatis bisa dipakai walaupun $res
  adalah coderef.
  
  wrapper juga bisa otomatis wrap-kan envres(). jadi:
  

      $res = foo(...)
      die $res->errmsg unless $res->success; # "404 - Not found\n"
      $ct = $res->payload;
      $ud = $res->meta->{undo_data};
  

* WISHLIST [2012-02-05 Sun] ri: function: retry property: conditional retry

  - depends on args or result matching a certain schema, whatever. needs real use cases first.

* TODO [2012-02-05 Sun] ri: versioning utk 3rd party properties?
* TODO [2012-01-20 Fri] ri: PROP.alt.output.FOO

  - membedakan antara summary utk command-line vs summary utk POD vs ...

* TODO [2012-01-20 Fri] ri: func: protocol/standard (or function) to operate on multiple items

  mis: ada func, arg-nya salah satunya x, dan sisanya y, z. kita ingin melakukan
  func() utk x1, x2, x3, x4.
  

      multi('func', items=>{x=>[x1, x2, x3, x4]}, args=>{y=>Y, z=>Z})
  
  hasilnya nanti: X jika semua status sama X. 200 jika gak ada yang gagal atau ada
  yang berhasil. jika gagal semua dan beda2x, statusnya 500? semua enveloped
  result akan dikumpulkan dan direturn di extra->{results}. ada juga opsi utk
  randomize, max_fail, max_success.
  

* TODO [2012-01-20 Fri] ri: func: protocol/standard to pass a single argument to multiple function

  - kebalikannya multi-items. mungkin namanya serial-func?
  - pass result to next function, so it's like f(g(h(i(j)))).
  - bisa ada kode utk evaluate each step, early exit/bail, jump... (seperti
    Sub::Spec::Runner dong). tapi, dibutuhkan atau gak?

* TODO [2012-01-20 Fri] ri: func: protocol/standard for callback/"background" and progress report/query

  - http already has this standard, the 202 = accepted status code. it means: "The
    request has been accepted for processing, but the processing has not been
    completed. Its purpose is to allow a server to accept a request for some other
    process (perhaps a batch-oriented process that is only run once per day)
    without requiring that the user agent's connection to the server persist until
    the process is completed. The entity returned with this response SHOULD
    include an indication of the request's current status and either a pointer to
    a status monitor or some estimate of when the user can expect the request to
    be fulfilled."
  - so protocol should be like this:
    + first invocation: f1(arg1=>1, arg2=>2, ...) => [202, "Accepted", undef,
      {-async_job_id=>123, -async_estimated=>unix_timestamp,
      -async_started=>unix_timestamp, -async_completed=>10%}]
    + second invocation is to ask for status: f1(arg1=>1, arg2=>2, ...,
      -async_job_id=>123). exact arguments not needed, especially if large, job id
      should be unique. function should return [202 (still? or perhaps 220 or
      whatever), "In Progress", {-async_job_id=>123, -async_estimated=>...,
      -async_started=>..., -async_completed=>
  - first invocation can also set callback function (a URI?)
  - second (third, ...) invocation can remove callback, change callback, add
    callbacks
  - after job is finished? and client not know yet since callback not defined,
    server waits until client comes again. [20x, "Already Done", ...]
  - if job is gone/cancelled/failed, also report this...
  - UPDATE [2012-10-24 Wed]: utk progress sudah pake Progress::Any.

* TODO [2012-01-20 Fri] ri: func: protocol/standard: undo: what if args are large?

  they get passed around with each do/check_undo/undo/redo, and currently and
  stored in undo storage.

* TODO [2012-01-20 Fri] ri: func: protocol/standard for redirection

  - much like HTTP 3xx redirection
  - "contact this URL instead, don't execute me"

* TODO [2012-01-20 Fri] ri: func: protocol/standard for encrypting URI parameter

  - for example, callback function (specified in URI) contains sensitive
    information (cc number, special ID or generated key, new/generated password,
    etc)
  - perlu gitu? URI kan bisa kita panggil lewat https:// dan argument-nya kita
    POST. gak semua harus disebutkan di URI string.

* IDEA ri: a new args_as: cmdish


      1, 2, 3, -foo => bar,
  tujuannya supaya bisa mirip seperti di cmdline (getopt::long), bisa mix antara
  positional arg dan named, named menggunakan prefix -WORD.

* IDEA [2012-06-16 Sat] ri, periswrap: crash logger [#C]
* IDEA [2012-06-15 Fri] ri: function: caching/memoization (using CHI) + wrapper implementation

  - key / argumen(-argumen) yg dipake jadi cache keys
  - kriteria caching (max 6 jam, sehari sekali, dsb)
  - selain cache hasil, juga versi yg seperti once-daily, skip running jika masih
    "cached"

* TODO [2012-06-04 Mon] ri, periswrap: metadata property for locking/one instance only (or two ...?)

  - memanfaatkan transaction database

* TODO [2012-08-14 Tue] ri: undo: selection, repeat (ctrl-y)

  - ini perlu ada selevel di atas ri::tx::Undo, karena menyangkut selection.
  - fungsi yg ingin participate perlu support feature: selection
    (menerima/mengenali selection).
  - [2] end-user invokes command: $something->call (?) ($f, $selection) [ini ada undo
    list-nya, atau cuma 1 aja?]
  - ini nanti translates ke $txm->call($f or $other_f, $args) (one, or one or more?)
  - txm perlu save selection? atau minimal save description (di summary/name?)
    agar user tahu.
  - kalau user ingin undo, bisa melihat undo history dari $txm.
  - kalau user ingin repeat dengan selection lain, melihat history dari [2].
  
  jadi kayaknya cuma sesimpel kita mengesave 1 tindakan (nama fungsi) aja yang
  support selection.

* IDEA [2012-07-28 Sat] ri: arg spec: cmdline_src (or src) dari ENV <-- tapi ini harusnya dihandle oleh config secara lebih umum

  - walaupun src bisa override that dan customize, mis nama env tidak sama dengna
    nama arg.
  - berguna untuk password misalnya

* TODO [2013-10-15 Sel] ri: per-arg examples? [#C]

  - if we want to be more example-oriented, this is probably a good idea. user
    bisa melihat contoh yang relevan aja yg berkaitan dengan arg tsb. apalagi jika
    fungsinya kompleks dengan banyak argumen. tapi, sebetulnya bisa aja sih
    digabung di function-level examples, kita bisa filter kok hanya memperlihatkan
    example yg mention a certain argument.
  - bisa juga kita terapkan begini di pericmd: untuk --help (short help), kita
    tampilkan semua examples di satu section Examples. di --help --verbose
    (verbose help) kita bisa tampilkan example di tiap arg.
  - jadi, saat ini gw cenderung tetap tidak menambah spec Rinci, examples cukup
    satu property aja, kita bisa pilah2x sendiri saat menampilkannya.

* IDEA [2013-09-03 Tue] ri: specify metadata dalam bentuk grammar yg lebih manusiawi, seperti "bnf" atau docopt

  contoh dalam python:
  

      def somefunc(...):
         """
         Do some stuff.
  :

         args:
           - foo (str*): some summary blah
           - bar (str*): some summary blah
           - baz (array*[str*]): blah blah blah
  :

         Returns (str*): blah
         """
  
  gw gak terlalu suka ya. readable sih iya, pretty juga. tapi limited. dan yet
  another limited language. i prefer writing directly in data structure. tetep
  readable kok.
  
  sebagai perbandingan, ini docopt (dari manpage modul perl Docopt):
  

      Naval Fate.
  :

      Usage:
          naval_fate ship new <name>...
          naval_fate ship <name> move <x> <y> [--speed=<kn>]
          naval_fate ship shoot <x> <y>
          naval_fate mine (set|remove) <x> <y> [--moored|--drifting]
          naval_fate -h | --help
          naval_fate --version
  :

      Options:
          -h --help     Show this screen.
          --version     Show version.
          --speed=<kn>  Speed in knots [default: 10].
          --moored      Moored (anchored) mine.
          --drifting    Drifting mine.
  

* TODO [2013-07-15 Mon] ri: wrapper or type: tipe integer for number of seconds (time period)

  di periwrap convert string seperti '1 day' atau '2.5 day' menjadi seconds.
  
  tapi bagaimana dg month? sebetulnya tidak persis sama lho.
  
  atau ada pilihan utk diconvert ke real period kayak DateTime. tergantung
  fungsinya pengen apa.
  
  some helper for completion? misalnya normal range adalah 1000-2000s, maka kalo
  ada 1<tab> pilihannya lebih ke hour/day (gak ada pilihan decade atau
  year/century misalnya).

* TODO [2013-07-15 Mon] ri: wrapper or type: tipe unix time (sub dari int)

  bisa convert '2013-12-31' atau 'dec 31, 2013' jadi epoch.
  
  ada pilihan utk convert ke unix epoch atau DateTime object.
  
  some helper utk completion.

* TODO [2013-07-15 Mon] ri: wrapper or helper: unit utk ukuran

  mis: int/float bisa ditambah k/KB/m/MB/...
  
  fungsi menerima hasilnya dalam bentuk sudah bytes.
  
  ada juga originalnya dipass dalam special variables.

* TODO [2012-11-09 Fri] ri: spesifikasi utk result metadata, utk spanel API, fungsi2 perlu bisa state bahwa array yg dikembalikan adalah tabel atau list of objects

  contoh, list-accounts atau list-services mengembalikan daftar akun dan servis
  dalam bentuk AoH. perlu bisa express bahwa ini adalah array of objects or items.
  dan utk tiap item ada action yang bisa dilakukan. tapi ini ga usah
  tampil/mengotori.
  
  barangkali:
  

       [200, "OK",
        [
          {name=>"http", title=>"Web server (Apache)", port=>80, status=>"running"},
          {name=>"httpproxy", title=>"Web proxy (Squid)", port=>[2138, 8080], status=>"stopped"},
          {name=>"pop3d", title=>"POP3 daemon (dovecot)", port=>110, status=>"disabled"},
        ],
        {items => [
           {actions => [{function => 'stop_service', args => {service=>'http'}, xtitle=>'Stop'}, # function otomatis di-qualify sesuai si caller
                        {function => 'Spanel::API::service::restart_service', args => {service=>'http'}, xtitle=>'Restart'},], },
           {actions => [{function => 'Spanel::API::service::start_service', args => {service=>'http'}, xtitle=>'Restart'}], },
         ]}
       ]
  
  generate item_actions perlu dienable dulu lewat some special argument. dan ada
  pilihan language juga? atau title itu gak usah, di level UI aja (gw cenderung ke
  sini).
  
  UPDATE: sometimes ini perlu dilakukan oleh wrapper atau middleware periahs,
  supaya orthogonal, separation of concern. misalnya, list-services memberikan
  pilihan start & stop tergantung apakah servis saat ini sedang stopped atau
  started. tapi gimana dengan permission? ini perlu difilter lagi di level di luar
  fungsi.
  
  barangkali tiap fungsi perlu diberi metadata, dia act on which entity/object,
  butuh permission bit apa aja, contoh:
  
   $SPEC{start_service} = {
      ...
      tags => ['perm::service.modify', 'item-type::service', 'item-id-arg::service', 'action-type::change-state', 'final-state::running',
   }
  
  dan nanti list_services mengembalikan result metadata sbb:
  
   {items => [
       {id => 'http'}, # isinya cuma item id aja, ini
       {id => 'httpproxy'},
       {id => 'pop3d'},
    ]}
  
  lalu wrapper atau middleware setelah call akan mencari semua fungsi yang match
  dengan tag ini. tapi bagaimana filtering jika udah start gak perlu fungsi start
  lagi, dsb. mungkin si fungsi bisa ngasih hint, mis:
  
   {item_type => 'service',
    items => [
       {id => 'http', state => 'running'}, # isinya cuma item id aja, ini
       {id => 'httpproxy', state => 'stopped'},
       {id => 'pop3d', state => 'disabled'},
    ]}
  
  lalu nanti wrapper perlu mencari semua fungsi yang punya tag: item-type::service
  (atau semua package yang item-type::service). lalu filter out semua yang tag-nya
  final-state::$state sama dengan si state). lalu baru nanti filter lagi dengan
  permission.

* TODO [2013-12-19 Thu] periahs, ri: beri informasi rate-limiting di riap, riap HTTP, spanel-sendmail, spanel-smtpd...

  - biar user tau, berapa lagi limitnya dalam 1 jam dan 24 jam
  - DONE utk spanel-smtpd (tapi baru di log akses doang, mestinya di http header
    jg kan ya, utk memberitahu user)
  - ref:
  - biasanya utk implementasinya (utk API calls) pake redis, pake mysql gitu berat
    di write-nya, ini sangat write intensive soalnya (per request).
  - http status jika over: 429 (too many requests). 503 (service unavailable)
    kayaknya kurang pas.
  - di twitter: 350/hour. google compute: 50k/day, 20/sec.
  - utk header http yg diberikan ke klien, github/vimeo pake x-ratelimit-limit &
    x-ratelimit-remaining. twitter pake x-rate-limit-{limit,remaining,reset} (yg
    reset adalah waktu sebelum limitnya direset). imgur pake
    x-ratelimit-user{limit,remaining,reset} dan
    x-ratelimit-client{limit,remaining}.

* IDEA [2014-03-27 Thu] ri: result: specify that result returns a list of records (a table) and specify its summary

  - supaya kita bisa create result metadata format_options utk formatting

* IDEA [2014-03-14 Fri] ri: func: args: property to allow skipping documentation of an argument (in cmdline and/or pod and/or wrapped meta [for api])
* IDEA [2012-07-23 Mon] ri: func: arg spec: max_size utk cmdline_src = stdin/stdin_or_files, max_items (utk mencegah slurp terlalu besar)
* TODO [2015-03-07 Sab] ri: args_groups: rel=req_one_of

  - untuk require one of. ini gak bisa diimplement di per-arg 'req' property.
  - kalo req_all, bisa, tinggal set req=1 aja di semua arg
  - bagaimana jika ingin req any 2 (or 3, ...) of ?

* TODO [2015-03-04 Wed] ri: x.schema.entity should've just been schema's type

  - it's just types actually

* IDEA [2015-03-01 Sun] ri: formalize x.schema.entity as entity?

  - or schema.entity? schema_entity?

* TODO [2015-02-07 Sab] pwp-ri: Add notes from 'args_groups' func prop & 'deps' arg spec prop
* BUG [2015-01-07 Wed] pwp-ri, pleg: can't build because pwp-ri inserts OPTIONS POD section to bin/perl-example-die even though it should not (it's not a Getopt::Long::Complete or Perinci::CmdLine script)
* TODO [2014-12-19 Jum] ri: add perisprop-validation to use perl code to validate.

  in the POD, add note that this is only when needed. we still encourage 'schema'
  property instead.

* IDEA [2015-01-06 Tue] periswrap, ri: args_as => 'scalar+hash' or 'hash+list'

  often we have one scalar main argument (or a list of arguments) but also have
  other arguments as options (though they are optional). examples:
  

      kill PID1, PID2, ...
      kill {signal=>'KILL'}, PID1, PID2, ...
  :

      module_path($module)
      module_path({find_pod=>1}, $module)
      module_path($module, {find_pod=>1, find_pmc=>1})
  
  this will make the simple case simpler (e.g. instead of
  module_path(module=>$module) which is to be honest a bit less DRY.
  
  the main argument(s) must be declared req=>1, pos=>0, (and greedy=>1 for list).

* TODO [2015-01-03 Sat] testri: Add option -l (like prove)?
* IDEA [2014-11-28 Fri] ri: summary.alt.{plural,singular,singplural}

  - sama seperti pasangan summary.alt.{pos,neg,posneg}
  - opsi --arrayofstr (mis: --file) menggunakan summary singular.
    --arrayofstr-json menggunakan summary plural (atau summary aja, jika gak ada).
  - log ::
    + [2014-12-02 Sel] implemented in peris2cliospec

* IDEA [2014-11-22 Sab] ri: per-arg examples [#C]

  contoh:

      exclude_dist => {
          summary => 'Exclude all modules of a dist',
          schema => ['array*' => of => 'str*'],
          examples => [
              # bisa pake argv atau args, seperti function's examples:
              {
                  argv => [qw/--exclude-dist Foo::Bar --exclude-dist Baz-Qux/],
                  summary => 'Blah',
              },
              # bisa juga cuma specify value
              {
                  value => ['Foo::Bar', 'Baz-Qux'],
                  summary => 'Blah',
              },
          ],
      }
  
  nanti yang value bisa disediakan untuk --exclude-dist juga utk
  --exclude-dist-json.

* IDEA [2014-11-22 Sab] pwp-ri: OPTIONS for script: show example for each arg

  - nah ini gw agak2x torn between naruh di function's examples atau di arg spec?
  - kalo user ingin naruh per-arg examples juga harusnya diperbolehkan.
  - perlu ada modul utk process/display examples, karena dipake juga selain di
    POD, di pericmd --help.

* IDEA [2014-11-22 Sab] pwp-ri: OPTIONS for script: show See <other_arg> from arg's links.
* IDEA [2014-11-01 Sat] ri, periga-argv, pericmd: suppress accepting --foo-json/--foo-yaml even though arg is array etc

  contoh, gw ingin accept file sebagai --file F1 --file F2 saja, gak mau user bisa
  --file-json '["F1","F2"]'. terutama utk array of simple scalar, gw hanya ingin
  itu.
  
  tentu saja kita bisa matikan per_arg_json, per_arg_yaml. mungkin perlu ada
  per-arg optionnya. dan belum ada cara utk specify ini dari pericmd.

* IDEA [2014-04-04 Fri] pericmd, ri: how to specify default is dry_run?

  - so, to actually do stuffs, cmd --nodry-run, or func(-dry_run=>0).

* IDEA [2014-09-21 Sun] ri: ideas for rinci async
* IDEA [2014-08-15 Fri] ri: cmdline: untuk fungsi yang return bool status false/true, ada opsi utk set exit code non-zero jika false


      result => {
          schema => 'bool',
      }
  

       % check-palindrome foo; # dan exit 1
       Not a palindrome
       % check-palindrome apa; # exit 0
       Palindrome
  
  instead of:
  

       % check-palindrome foo; # exit 0, karena [200,"OK",0]
       0
       % check-palindrome apa; # exit 0, karena [200,"OK",1]
       1
  
  bisa juga di result metadata sih, tapi gw sedikit lebih prefer di function
  metadata, mis:
  

      x.perinci.cmdline.whatever => 1

* IDEA [2014-08-15 Fri] ri: cmdline: result metadata prop: text to display instead of result

  contoh, fungsi seperti check_palindrome() kalo dipake di perl baiknya return
  bool:
  

       check_palindrome("foo"); # -> 0
       check_palindrome("apa"); # -> 1
  
  tapi cmdline enaknya show nicer message and status kali ya (seperti grep, supaya
  skrip shell bisa do something accordingly)?
  

       % check-palindrome foo; # dan exit 1
       Not a palindrome
       % check-palindrome apa; # exit 0
       Palindrome
  
  instead of:
  

       % check-palindrome foo; # exit 0, karena [200,"OK",0]
       0
       % check-palindrome apa; # exit 0, karena [200,"OK",1]
       1
  
  tadinya gw berpikir result metadata seperti ini:
  

       [200, "OK", $is_palindrome, {"cmdline.result" => ($is_palindrome ? "Palindrome" : "Not a palindrome")}]
  
  sementara kalo mau melakukan hal ini, bisa menggunakan "cara manual":
  

       if ($args{-cmdline}) { # running under CLI
           return ...;
       } else {
           return ...;
       }

* TODO [2014-12-16 Tue] dzp-ri-absfmeta, pwp-ri, shcompgen, app-genbashcompleter: recognize NO_PERICMD_SCRIPT tag
* TODO [2014-11-22 Sab] peris2clidocdata, ri: provide category sorting options

  - kategori tertentu yang lebih penting bisa ditampilkan di awal, gak harus
    selalu alfabetikal. contoh di fatten:
  

      Debugging options
      Module selection options
      Options
      Output options
  
    sebaiknya (other terakhir, output duluan baru module selection, dsb):
  

      Output options
      Debugging options
      Module selection options
      Other options
  
  - demikian juga opsi tertentu contoh di fatten:

      --stripper
      --no-stripper-comment
      --no-stripper-pod
      --no-stripper-ws
  
    harusnya (opsi --stripper dulu dong ya disebutkan, baru )
  
    ini bisa pakai links misalnya, jadi stripper_comment, stripper_pod,
    stripper_ws kan link ke 'stripper'. pakai sorting berdasarkan dependency.

* TODO [2014-11-22 Sab] pwp-ri: OPTIONS for script: tweak: default jika pendek inline

  instead of selalu menampilkan verbatim paragraph:
  
   Default:
  
    "-"
  
  jika default pendek dan tidak mengandung karakter "<<" atau ">>", inlinekan aja.
  
   Default: C<<"-">>.
  
  dan jika default berupa string yang tidak mengandung 'karakter aneh', gak usah
  pake quote (gak usah didump sekalian):
  
   Default: C<->.
   Default: C</usr/bin/perl>
   Default: C<foo bar>
  

* TODO [2014-11-22 Sab] pwp-ri: OPTIONS for script: tweak: 'in' jika pendek (atau jika berupa list of scalars dengan bukan karakter aneh)

  - tanpa quotes
  - dan sort?
  - ini nanti dipake juga saat produce html/web-based help
